| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510245112451224513245142451524516245172451824519245202452124522245232452424525245262452724528245292453024531245322453324534245352453624537245382453924540245412454224543245442454524546245472454824549245502455124552245532455424555245562455724558245592456024561245622456324564245652456624567245682456924570245712457224573245742457524576245772457824579245802458124582245832458424585245862458724588245892459024591245922459324594245952459624597245982459924600246012460224603246042460524606246072460824609246102461124612246132461424615246162461724618246192462024621246222462324624246252462624627246282462924630246312463224633246342463524636246372463824639246402464124642246432464424645246462464724648246492465024651246522465324654246552465624657246582465924660246612466224663246642466524666246672466824669246702467124672246732467424675246762467724678246792468024681246822468324684246852468624687246882468924690246912469224693246942469524696246972469824699247002470124702247032470424705247062470724708247092471024711247122471324714247152471624717247182471924720247212472224723247242472524726247272472824729247302473124732247332473424735247362473724738247392474024741247422474324744247452474624747247482474924750247512475224753247542475524756247572475824759247602476124762247632476424765247662476724768247692477024771247722477324774247752477624777247782477924780247812478224783247842478524786247872478824789247902479124792247932479424795247962479724798247992480024801248022480324804248052480624807248082480924810248112481224813248142481524816248172481824819248202482124822248232482424825248262482724828248292483024831248322483324834248352483624837248382483924840248412484224843248442484524846248472484824849248502485124852248532485424855248562485724858248592486024861248622486324864248652486624867248682486924870248712487224873248742487524876248772487824879248802488124882248832488424885248862488724888248892489024891248922489324894248952489624897248982489924900249012490224903249042490524906249072490824909249102491124912249132491424915249162491724918249192492024921249222492324924249252492624927249282492924930249312493224933249342493524936249372493824939249402494124942249432494424945249462494724948249492495024951249522495324954249552495624957249582495924960249612496224963249642496524966249672496824969249702497124972249732497424975249762497724978249792498024981249822498324984249852498624987249882498924990249912499224993249942499524996249972499824999250002500125002250032500425005250062500725008250092501025011250122501325014250152501625017250182501925020250212502225023250242502525026250272502825029250302503125032250332503425035250362503725038250392504025041250422504325044250452504625047250482504925050250512505225053250542505525056250572505825059250602506125062250632506425065250662506725068250692507025071250722507325074250752507625077250782507925080250812508225083250842508525086250872508825089250902509125092250932509425095250962509725098250992510025101251022510325104251052510625107251082510925110251112511225113251142511525116251172511825119251202512125122251232512425125251262512725128251292513025131251322513325134251352513625137251382513925140251412514225143251442514525146251472514825149251502515125152251532515425155251562515725158251592516025161251622516325164251652516625167251682516925170251712517225173251742517525176251772517825179251802518125182251832518425185251862518725188251892519025191251922519325194251952519625197251982519925200252012520225203252042520525206252072520825209252102521125212252132521425215252162521725218252192522025221252222522325224252252522625227252282522925230252312523225233252342523525236252372523825239252402524125242252432524425245252462524725248252492525025251252522525325254252552525625257252582525925260252612526225263252642526525266252672526825269252702527125272252732527425275252762527725278252792528025281252822528325284252852528625287252882528925290252912529225293252942529525296252972529825299253002530125302253032530425305253062530725308253092531025311253122531325314253152531625317253182531925320253212532225323253242532525326253272532825329253302533125332253332533425335253362533725338253392534025341253422534325344253452534625347253482534925350253512535225353253542535525356253572535825359253602536125362253632536425365253662536725368253692537025371253722537325374253752537625377253782537925380253812538225383253842538525386253872538825389253902539125392253932539425395253962539725398253992540025401254022540325404254052540625407254082540925410254112541225413254142541525416254172541825419254202542125422254232542425425254262542725428254292543025431254322543325434254352543625437254382543925440254412544225443254442544525446254472544825449254502545125452254532545425455254562545725458254592546025461254622546325464254652546625467254682546925470254712547225473254742547525476254772547825479254802548125482254832548425485254862548725488254892549025491254922549325494254952549625497254982549925500255012550225503255042550525506255072550825509255102551125512255132551425515255162551725518255192552025521255222552325524255252552625527255282552925530255312553225533255342553525536255372553825539255402554125542255432554425545255462554725548255492555025551255522555325554255552555625557255582555925560255612556225563255642556525566255672556825569255702557125572255732557425575255762557725578255792558025581255822558325584255852558625587255882558925590255912559225593255942559525596255972559825599256002560125602256032560425605256062560725608256092561025611256122561325614256152561625617256182561925620256212562225623256242562525626256272562825629256302563125632256332563425635256362563725638256392564025641256422564325644256452564625647256482564925650256512565225653256542565525656256572565825659256602566125662256632566425665256662566725668256692567025671256722567325674256752567625677256782567925680256812568225683256842568525686256872568825689256902569125692256932569425695256962569725698256992570025701257022570325704257052570625707257082570925710257112571225713257142571525716257172571825719257202572125722257232572425725257262572725728257292573025731257322573325734257352573625737257382573925740257412574225743257442574525746257472574825749257502575125752257532575425755257562575725758257592576025761257622576325764257652576625767257682576925770257712577225773257742577525776257772577825779257802578125782257832578425785257862578725788257892579025791257922579325794257952579625797257982579925800258012580225803258042580525806258072580825809258102581125812258132581425815258162581725818258192582025821258222582325824258252582625827258282582925830258312583225833258342583525836258372583825839258402584125842258432584425845258462584725848258492585025851258522585325854258552585625857258582585925860258612586225863258642586525866258672586825869258702587125872258732587425875258762587725878258792588025881258822588325884258852588625887258882588925890258912589225893258942589525896258972589825899259002590125902259032590425905259062590725908259092591025911259122591325914259152591625917259182591925920259212592225923259242592525926259272592825929259302593125932259332593425935259362593725938259392594025941259422594325944259452594625947259482594925950259512595225953259542595525956259572595825959259602596125962259632596425965259662596725968259692597025971259722597325974259752597625977259782597925980259812598225983259842598525986259872598825989259902599125992259932599425995259962599725998259992600026001260022600326004260052600626007260082600926010260112601226013260142601526016260172601826019260202602126022260232602426025260262602726028260292603026031260322603326034260352603626037260382603926040260412604226043260442604526046260472604826049260502605126052260532605426055260562605726058260592606026061260622606326064260652606626067260682606926070260712607226073260742607526076260772607826079260802608126082260832608426085260862608726088260892609026091260922609326094260952609626097260982609926100261012610226103261042610526106261072610826109261102611126112261132611426115261162611726118261192612026121261222612326124261252612626127261282612926130261312613226133261342613526136261372613826139261402614126142261432614426145261462614726148261492615026151261522615326154261552615626157261582615926160261612616226163261642616526166261672616826169261702617126172261732617426175261762617726178261792618026181261822618326184261852618626187261882618926190261912619226193261942619526196261972619826199262002620126202262032620426205262062620726208262092621026211262122621326214262152621626217262182621926220262212622226223262242622526226262272622826229262302623126232262332623426235262362623726238262392624026241262422624326244262452624626247262482624926250262512625226253262542625526256262572625826259262602626126262262632626426265262662626726268262692627026271262722627326274262752627626277262782627926280262812628226283262842628526286262872628826289262902629126292262932629426295262962629726298262992630026301263022630326304263052630626307263082630926310263112631226313263142631526316263172631826319263202632126322263232632426325263262632726328263292633026331263322633326334263352633626337263382633926340263412634226343263442634526346263472634826349263502635126352263532635426355263562635726358263592636026361263622636326364263652636626367263682636926370263712637226373263742637526376263772637826379263802638126382263832638426385263862638726388263892639026391263922639326394263952639626397263982639926400264012640226403264042640526406264072640826409264102641126412264132641426415264162641726418264192642026421264222642326424264252642626427264282642926430264312643226433264342643526436264372643826439264402644126442264432644426445264462644726448264492645026451264522645326454264552645626457264582645926460264612646226463264642646526466264672646826469264702647126472264732647426475264762647726478264792648026481264822648326484264852648626487264882648926490264912649226493264942649526496264972649826499265002650126502265032650426505265062650726508265092651026511265122651326514265152651626517265182651926520265212652226523265242652526526265272652826529265302653126532265332653426535265362653726538265392654026541265422654326544265452654626547265482654926550265512655226553265542655526556265572655826559265602656126562265632656426565265662656726568265692657026571265722657326574265752657626577265782657926580265812658226583265842658526586265872658826589265902659126592265932659426595265962659726598265992660026601266022660326604266052660626607266082660926610266112661226613266142661526616266172661826619266202662126622266232662426625266262662726628266292663026631266322663326634266352663626637266382663926640266412664226643266442664526646266472664826649266502665126652266532665426655266562665726658266592666026661266622666326664266652666626667266682666926670266712667226673266742667526676266772667826679266802668126682266832668426685266862668726688266892669026691266922669326694266952669626697266982669926700267012670226703267042670526706267072670826709267102671126712267132671426715267162671726718267192672026721267222672326724267252672626727267282672926730267312673226733267342673526736267372673826739267402674126742267432674426745267462674726748267492675026751267522675326754267552675626757267582675926760267612676226763267642676526766267672676826769267702677126772267732677426775267762677726778267792678026781267822678326784267852678626787267882678926790267912679226793267942679526796267972679826799268002680126802268032680426805268062680726808268092681026811268122681326814268152681626817268182681926820268212682226823268242682526826268272682826829268302683126832268332683426835268362683726838268392684026841268422684326844268452684626847268482684926850268512685226853268542685526856268572685826859268602686126862268632686426865268662686726868268692687026871268722687326874268752687626877268782687926880268812688226883268842688526886268872688826889268902689126892268932689426895268962689726898268992690026901269022690326904269052690626907269082690926910269112691226913269142691526916269172691826919269202692126922269232692426925269262692726928269292693026931269322693326934269352693626937269382693926940269412694226943269442694526946269472694826949269502695126952269532695426955269562695726958269592696026961269622696326964269652696626967269682696926970269712697226973269742697526976269772697826979269802698126982269832698426985269862698726988269892699026991269922699326994269952699626997269982699927000270012700227003270042700527006270072700827009270102701127012270132701427015270162701727018270192702027021270222702327024270252702627027270282702927030270312703227033270342703527036270372703827039270402704127042270432704427045270462704727048270492705027051270522705327054270552705627057270582705927060270612706227063270642706527066270672706827069270702707127072270732707427075270762707727078270792708027081270822708327084270852708627087270882708927090270912709227093270942709527096270972709827099271002710127102271032710427105271062710727108271092711027111271122711327114271152711627117271182711927120271212712227123271242712527126271272712827129271302713127132271332713427135271362713727138271392714027141271422714327144271452714627147271482714927150271512715227153271542715527156271572715827159271602716127162271632716427165271662716727168271692717027171271722717327174271752717627177271782717927180271812718227183271842718527186271872718827189271902719127192271932719427195271962719727198271992720027201272022720327204272052720627207272082720927210272112721227213272142721527216272172721827219272202722127222272232722427225272262722727228272292723027231272322723327234272352723627237272382723927240272412724227243272442724527246272472724827249272502725127252272532725427255272562725727258272592726027261272622726327264272652726627267272682726927270272712727227273272742727527276272772727827279272802728127282272832728427285272862728727288272892729027291272922729327294272952729627297272982729927300273012730227303273042730527306273072730827309273102731127312273132731427315273162731727318273192732027321273222732327324273252732627327273282732927330273312733227333273342733527336273372733827339273402734127342273432734427345273462734727348273492735027351273522735327354273552735627357273582735927360273612736227363273642736527366273672736827369273702737127372273732737427375273762737727378273792738027381273822738327384273852738627387273882738927390273912739227393273942739527396273972739827399274002740127402274032740427405274062740727408274092741027411274122741327414274152741627417274182741927420274212742227423274242742527426274272742827429274302743127432274332743427435274362743727438274392744027441274422744327444274452744627447274482744927450274512745227453274542745527456274572745827459274602746127462274632746427465274662746727468274692747027471274722747327474274752747627477274782747927480274812748227483274842748527486274872748827489274902749127492274932749427495274962749727498274992750027501275022750327504275052750627507275082750927510275112751227513275142751527516275172751827519275202752127522275232752427525275262752727528275292753027531275322753327534275352753627537275382753927540275412754227543275442754527546275472754827549275502755127552275532755427555275562755727558275592756027561275622756327564275652756627567275682756927570275712757227573275742757527576275772757827579275802758127582275832758427585275862758727588275892759027591275922759327594275952759627597275982759927600276012760227603276042760527606276072760827609276102761127612276132761427615276162761727618276192762027621276222762327624276252762627627276282762927630276312763227633276342763527636276372763827639276402764127642276432764427645276462764727648276492765027651276522765327654276552765627657276582765927660276612766227663276642766527666276672766827669276702767127672276732767427675276762767727678276792768027681276822768327684276852768627687276882768927690276912769227693276942769527696276972769827699277002770127702277032770427705277062770727708277092771027711277122771327714277152771627717277182771927720277212772227723277242772527726277272772827729277302773127732277332773427735277362773727738277392774027741277422774327744277452774627747277482774927750277512775227753277542775527756277572775827759277602776127762277632776427765277662776727768277692777027771277722777327774277752777627777277782777927780277812778227783277842778527786277872778827789277902779127792277932779427795277962779727798277992780027801278022780327804278052780627807278082780927810278112781227813278142781527816278172781827819278202782127822278232782427825278262782727828278292783027831278322783327834278352783627837278382783927840278412784227843278442784527846278472784827849278502785127852278532785427855278562785727858278592786027861278622786327864278652786627867278682786927870278712787227873278742787527876278772787827879278802788127882278832788427885278862788727888278892789027891278922789327894278952789627897278982789927900279012790227903279042790527906279072790827909279102791127912279132791427915279162791727918279192792027921279222792327924279252792627927279282792927930279312793227933279342793527936279372793827939279402794127942279432794427945279462794727948279492795027951279522795327954279552795627957279582795927960279612796227963279642796527966279672796827969279702797127972279732797427975279762797727978279792798027981279822798327984279852798627987279882798927990279912799227993279942799527996279972799827999280002800128002280032800428005280062800728008280092801028011280122801328014280152801628017280182801928020280212802228023280242802528026280272802828029280302803128032280332803428035280362803728038280392804028041280422804328044280452804628047280482804928050280512805228053280542805528056280572805828059280602806128062280632806428065280662806728068280692807028071280722807328074280752807628077280782807928080280812808228083280842808528086280872808828089280902809128092280932809428095280962809728098280992810028101281022810328104281052810628107281082810928110281112811228113281142811528116281172811828119281202812128122281232812428125281262812728128281292813028131281322813328134281352813628137281382813928140281412814228143281442814528146281472814828149281502815128152281532815428155281562815728158281592816028161281622816328164281652816628167281682816928170281712817228173281742817528176281772817828179281802818128182281832818428185281862818728188281892819028191281922819328194281952819628197281982819928200282012820228203282042820528206282072820828209282102821128212282132821428215282162821728218282192822028221282222822328224282252822628227282282822928230282312823228233282342823528236282372823828239282402824128242282432824428245282462824728248282492825028251282522825328254282552825628257282582825928260282612826228263282642826528266282672826828269282702827128272282732827428275282762827728278282792828028281282822828328284282852828628287282882828928290282912829228293282942829528296282972829828299283002830128302283032830428305283062830728308283092831028311283122831328314283152831628317283182831928320283212832228323283242832528326283272832828329283302833128332283332833428335283362833728338283392834028341283422834328344283452834628347283482834928350283512835228353283542835528356283572835828359283602836128362283632836428365283662836728368283692837028371283722837328374283752837628377283782837928380283812838228383283842838528386283872838828389283902839128392283932839428395283962839728398283992840028401284022840328404284052840628407284082840928410284112841228413284142841528416284172841828419284202842128422284232842428425284262842728428284292843028431284322843328434284352843628437284382843928440284412844228443284442844528446284472844828449284502845128452284532845428455284562845728458284592846028461284622846328464284652846628467284682846928470284712847228473284742847528476284772847828479284802848128482284832848428485284862848728488284892849028491284922849328494284952849628497284982849928500285012850228503285042850528506285072850828509285102851128512285132851428515285162851728518285192852028521285222852328524285252852628527285282852928530285312853228533285342853528536285372853828539285402854128542285432854428545285462854728548285492855028551285522855328554285552855628557285582855928560285612856228563285642856528566285672856828569285702857128572285732857428575285762857728578285792858028581285822858328584285852858628587285882858928590285912859228593285942859528596285972859828599286002860128602286032860428605286062860728608286092861028611286122861328614286152861628617286182861928620286212862228623286242862528626286272862828629286302863128632286332863428635286362863728638286392864028641286422864328644286452864628647286482864928650286512865228653286542865528656286572865828659286602866128662286632866428665286662866728668286692867028671286722867328674286752867628677286782867928680286812868228683286842868528686286872868828689286902869128692286932869428695286962869728698286992870028701287022870328704287052870628707287082870928710287112871228713287142871528716287172871828719287202872128722287232872428725287262872728728287292873028731287322873328734287352873628737287382873928740287412874228743287442874528746287472874828749287502875128752287532875428755287562875728758287592876028761287622876328764287652876628767287682876928770287712877228773287742877528776287772877828779287802878128782287832878428785287862878728788287892879028791287922879328794287952879628797287982879928800288012880228803288042880528806288072880828809288102881128812288132881428815288162881728818288192882028821288222882328824288252882628827288282882928830288312883228833288342883528836288372883828839288402884128842288432884428845288462884728848288492885028851288522885328854288552885628857288582885928860288612886228863288642886528866288672886828869288702887128872288732887428875288762887728878288792888028881288822888328884288852888628887288882888928890288912889228893288942889528896288972889828899289002890128902289032890428905289062890728908289092891028911289122891328914289152891628917289182891928920289212892228923289242892528926289272892828929289302893128932289332893428935289362893728938289392894028941289422894328944289452894628947289482894928950289512895228953289542895528956289572895828959289602896128962289632896428965289662896728968289692897028971289722897328974289752897628977289782897928980289812898228983289842898528986289872898828989289902899128992289932899428995289962899728998289992900029001290022900329004290052900629007290082900929010290112901229013290142901529016290172901829019290202902129022290232902429025290262902729028290292903029031290322903329034290352903629037290382903929040290412904229043290442904529046290472904829049290502905129052290532905429055290562905729058290592906029061290622906329064290652906629067290682906929070290712907229073290742907529076290772907829079290802908129082290832908429085290862908729088290892909029091290922909329094290952909629097290982909929100291012910229103291042910529106291072910829109291102911129112291132911429115291162911729118291192912029121291222912329124291252912629127291282912929130291312913229133291342913529136291372913829139291402914129142291432914429145291462914729148291492915029151291522915329154291552915629157291582915929160291612916229163291642916529166291672916829169291702917129172291732917429175291762917729178291792918029181291822918329184291852918629187291882918929190291912919229193291942919529196291972919829199292002920129202292032920429205292062920729208292092921029211292122921329214292152921629217292182921929220292212922229223292242922529226292272922829229292302923129232292332923429235292362923729238292392924029241292422924329244292452924629247292482924929250292512925229253292542925529256292572925829259292602926129262292632926429265292662926729268292692927029271292722927329274292752927629277292782927929280292812928229283292842928529286292872928829289292902929129292292932929429295292962929729298292992930029301293022930329304293052930629307293082930929310293112931229313293142931529316293172931829319293202932129322293232932429325293262932729328293292933029331293322933329334293352933629337293382933929340293412934229343293442934529346293472934829349293502935129352293532935429355293562935729358293592936029361293622936329364293652936629367293682936929370293712937229373293742937529376293772937829379293802938129382293832938429385293862938729388293892939029391293922939329394293952939629397293982939929400294012940229403294042940529406294072940829409294102941129412294132941429415294162941729418294192942029421294222942329424294252942629427294282942929430294312943229433294342943529436294372943829439294402944129442294432944429445294462944729448294492945029451294522945329454294552945629457294582945929460294612946229463294642946529466294672946829469294702947129472294732947429475294762947729478294792948029481294822948329484294852948629487294882948929490294912949229493294942949529496294972949829499295002950129502295032950429505295062950729508295092951029511295122951329514295152951629517295182951929520295212952229523295242952529526295272952829529295302953129532295332953429535295362953729538295392954029541295422954329544295452954629547295482954929550295512955229553295542955529556295572955829559295602956129562295632956429565295662956729568295692957029571295722957329574295752957629577295782957929580295812958229583295842958529586295872958829589295902959129592295932959429595295962959729598295992960029601296022960329604296052960629607296082960929610296112961229613296142961529616296172961829619296202962129622296232962429625296262962729628296292963029631296322963329634296352963629637296382963929640296412964229643296442964529646296472964829649296502965129652296532965429655296562965729658296592966029661296622966329664296652966629667296682966929670296712967229673296742967529676296772967829679296802968129682296832968429685296862968729688296892969029691296922969329694296952969629697296982969929700297012970229703297042970529706297072970829709297102971129712297132971429715297162971729718297192972029721297222972329724297252972629727297282972929730297312973229733297342973529736297372973829739297402974129742297432974429745297462974729748297492975029751297522975329754297552975629757297582975929760297612976229763297642976529766297672976829769297702977129772297732977429775297762977729778297792978029781297822978329784297852978629787297882978929790297912979229793297942979529796297972979829799298002980129802298032980429805298062980729808298092981029811298122981329814298152981629817298182981929820298212982229823298242982529826298272982829829298302983129832298332983429835298362983729838298392984029841298422984329844298452984629847298482984929850298512985229853298542985529856298572985829859298602986129862298632986429865298662986729868298692987029871298722987329874298752987629877298782987929880298812988229883298842988529886298872988829889298902989129892298932989429895298962989729898298992990029901299022990329904299052990629907299082990929910299112991229913299142991529916299172991829919299202992129922299232992429925299262992729928299292993029931299322993329934299352993629937299382993929940299412994229943299442994529946299472994829949299502995129952299532995429955299562995729958299592996029961299622996329964299652996629967299682996929970299712997229973299742997529976299772997829979299802998129982299832998429985299862998729988299892999029991299922999329994299952999629997299982999930000300013000230003300043000530006300073000830009300103001130012300133001430015300163001730018300193002030021300223002330024300253002630027300283002930030300313003230033300343003530036300373003830039300403004130042300433004430045300463004730048300493005030051300523005330054300553005630057300583005930060300613006230063300643006530066300673006830069300703007130072300733007430075300763007730078300793008030081300823008330084300853008630087300883008930090300913009230093300943009530096300973009830099301003010130102301033010430105301063010730108301093011030111301123011330114301153011630117301183011930120301213012230123301243012530126301273012830129301303013130132301333013430135301363013730138301393014030141301423014330144301453014630147301483014930150301513015230153301543015530156301573015830159301603016130162301633016430165301663016730168301693017030171301723017330174301753017630177301783017930180301813018230183301843018530186301873018830189301903019130192301933019430195301963019730198301993020030201302023020330204302053020630207302083020930210302113021230213302143021530216302173021830219302203022130222302233022430225302263022730228302293023030231302323023330234302353023630237302383023930240302413024230243302443024530246302473024830249302503025130252302533025430255302563025730258302593026030261302623026330264302653026630267302683026930270302713027230273302743027530276302773027830279302803028130282302833028430285302863028730288302893029030291302923029330294302953029630297302983029930300303013030230303303043030530306303073030830309303103031130312303133031430315303163031730318303193032030321303223032330324303253032630327303283032930330303313033230333303343033530336303373033830339303403034130342303433034430345303463034730348303493035030351303523035330354303553035630357303583035930360303613036230363303643036530366303673036830369303703037130372303733037430375303763037730378303793038030381303823038330384303853038630387303883038930390303913039230393303943039530396303973039830399304003040130402304033040430405304063040730408304093041030411304123041330414304153041630417304183041930420304213042230423304243042530426304273042830429304303043130432304333043430435304363043730438304393044030441304423044330444304453044630447304483044930450304513045230453304543045530456304573045830459304603046130462304633046430465304663046730468304693047030471304723047330474304753047630477304783047930480304813048230483304843048530486304873048830489304903049130492304933049430495304963049730498304993050030501305023050330504305053050630507305083050930510305113051230513305143051530516305173051830519305203052130522305233052430525305263052730528305293053030531305323053330534305353053630537305383053930540305413054230543305443054530546305473054830549305503055130552305533055430555305563055730558305593056030561305623056330564305653056630567305683056930570305713057230573305743057530576305773057830579305803058130582305833058430585305863058730588305893059030591305923059330594305953059630597305983059930600306013060230603306043060530606306073060830609306103061130612306133061430615306163061730618306193062030621306223062330624306253062630627306283062930630306313063230633306343063530636306373063830639306403064130642306433064430645306463064730648306493065030651306523065330654306553065630657306583065930660306613066230663306643066530666306673066830669306703067130672306733067430675306763067730678306793068030681306823068330684306853068630687306883068930690306913069230693306943069530696306973069830699307003070130702307033070430705307063070730708307093071030711307123071330714307153071630717307183071930720307213072230723307243072530726307273072830729307303073130732307333073430735307363073730738307393074030741307423074330744307453074630747307483074930750307513075230753307543075530756307573075830759307603076130762307633076430765307663076730768307693077030771307723077330774307753077630777307783077930780307813078230783307843078530786307873078830789307903079130792307933079430795307963079730798307993080030801308023080330804308053080630807308083080930810308113081230813308143081530816308173081830819308203082130822308233082430825308263082730828308293083030831308323083330834308353083630837308383083930840308413084230843308443084530846308473084830849308503085130852308533085430855308563085730858308593086030861308623086330864308653086630867308683086930870308713087230873308743087530876308773087830879308803088130882308833088430885308863088730888308893089030891308923089330894308953089630897308983089930900309013090230903309043090530906309073090830909309103091130912309133091430915309163091730918309193092030921309223092330924309253092630927309283092930930309313093230933309343093530936309373093830939309403094130942309433094430945309463094730948309493095030951309523095330954309553095630957309583095930960309613096230963309643096530966309673096830969309703097130972309733097430975309763097730978309793098030981309823098330984309853098630987309883098930990309913099230993309943099530996309973099830999310003100131002310033100431005310063100731008310093101031011310123101331014310153101631017310183101931020310213102231023310243102531026310273102831029310303103131032310333103431035310363103731038310393104031041310423104331044310453104631047310483104931050310513105231053310543105531056310573105831059310603106131062310633106431065310663106731068310693107031071310723107331074310753107631077310783107931080310813108231083310843108531086310873108831089310903109131092310933109431095310963109731098310993110031101311023110331104311053110631107311083110931110311113111231113311143111531116311173111831119311203112131122311233112431125311263112731128311293113031131311323113331134311353113631137311383113931140311413114231143311443114531146311473114831149311503115131152311533115431155311563115731158311593116031161311623116331164311653116631167311683116931170311713117231173311743117531176311773117831179311803118131182311833118431185311863118731188311893119031191311923119331194311953119631197311983119931200312013120231203312043120531206312073120831209312103121131212312133121431215312163121731218312193122031221312223122331224312253122631227312283122931230312313123231233312343123531236312373123831239312403124131242312433124431245312463124731248312493125031251312523125331254312553125631257312583125931260312613126231263312643126531266312673126831269312703127131272312733127431275312763127731278312793128031281312823128331284312853128631287312883128931290312913129231293312943129531296312973129831299313003130131302313033130431305313063130731308313093131031311313123131331314313153131631317313183131931320313213132231323313243132531326313273132831329313303133131332313333133431335313363133731338313393134031341313423134331344313453134631347313483134931350313513135231353313543135531356313573135831359313603136131362313633136431365313663136731368313693137031371313723137331374313753137631377313783137931380313813138231383313843138531386313873138831389313903139131392313933139431395313963139731398313993140031401314023140331404314053140631407314083140931410314113141231413314143141531416314173141831419314203142131422314233142431425314263142731428314293143031431314323143331434314353143631437314383143931440314413144231443314443144531446314473144831449314503145131452314533145431455314563145731458314593146031461314623146331464314653146631467314683146931470314713147231473314743147531476314773147831479314803148131482314833148431485314863148731488314893149031491314923149331494314953149631497314983149931500315013150231503315043150531506315073150831509315103151131512315133151431515315163151731518315193152031521315223152331524315253152631527315283152931530315313153231533315343153531536315373153831539315403154131542315433154431545315463154731548315493155031551315523155331554315553155631557315583155931560315613156231563315643156531566315673156831569315703157131572315733157431575315763157731578315793158031581315823158331584315853158631587315883158931590315913159231593315943159531596315973159831599316003160131602316033160431605316063160731608316093161031611316123161331614316153161631617316183161931620316213162231623316243162531626316273162831629316303163131632316333163431635316363163731638316393164031641316423164331644316453164631647316483164931650316513165231653316543165531656316573165831659316603166131662316633166431665316663166731668316693167031671316723167331674316753167631677316783167931680316813168231683316843168531686316873168831689316903169131692316933169431695316963169731698316993170031701317023170331704317053170631707317083170931710317113171231713317143171531716317173171831719317203172131722317233172431725317263172731728317293173031731317323173331734317353173631737317383173931740317413174231743317443174531746317473174831749317503175131752317533175431755317563175731758317593176031761317623176331764317653176631767317683176931770317713177231773317743177531776317773177831779317803178131782317833178431785317863178731788317893179031791317923179331794317953179631797317983179931800318013180231803318043180531806318073180831809318103181131812318133181431815318163181731818318193182031821318223182331824318253182631827318283182931830318313183231833318343183531836318373183831839318403184131842318433184431845318463184731848318493185031851318523185331854318553185631857318583185931860318613186231863318643186531866318673186831869318703187131872318733187431875318763187731878318793188031881318823188331884318853188631887318883188931890318913189231893318943189531896318973189831899319003190131902319033190431905319063190731908319093191031911319123191331914319153191631917319183191931920319213192231923319243192531926319273192831929319303193131932319333193431935319363193731938319393194031941319423194331944319453194631947319483194931950319513195231953319543195531956319573195831959319603196131962319633196431965319663196731968319693197031971319723197331974319753197631977319783197931980319813198231983319843198531986319873198831989319903199131992319933199431995319963199731998319993200032001320023200332004320053200632007320083200932010320113201232013320143201532016320173201832019320203202132022320233202432025320263202732028320293203032031320323203332034320353203632037320383203932040320413204232043320443204532046320473204832049320503205132052320533205432055320563205732058320593206032061320623206332064320653206632067320683206932070320713207232073320743207532076320773207832079320803208132082320833208432085320863208732088320893209032091320923209332094320953209632097320983209932100321013210232103321043210532106321073210832109321103211132112321133211432115321163211732118321193212032121321223212332124321253212632127321283212932130321313213232133321343213532136321373213832139321403214132142321433214432145321463214732148321493215032151321523215332154321553215632157321583215932160321613216232163321643216532166321673216832169321703217132172321733217432175321763217732178321793218032181321823218332184321853218632187321883218932190321913219232193321943219532196321973219832199322003220132202322033220432205322063220732208322093221032211322123221332214322153221632217322183221932220322213222232223322243222532226322273222832229322303223132232322333223432235322363223732238322393224032241322423224332244322453224632247322483224932250322513225232253322543225532256322573225832259322603226132262322633226432265322663226732268322693227032271322723227332274322753227632277322783227932280322813228232283322843228532286322873228832289322903229132292322933229432295322963229732298322993230032301323023230332304323053230632307323083230932310323113231232313323143231532316323173231832319323203232132322323233232432325323263232732328323293233032331323323233332334323353233632337323383233932340323413234232343323443234532346323473234832349323503235132352323533235432355323563235732358323593236032361323623236332364323653236632367323683236932370323713237232373323743237532376323773237832379323803238132382323833238432385323863238732388323893239032391323923239332394323953239632397323983239932400324013240232403324043240532406324073240832409324103241132412324133241432415324163241732418324193242032421324223242332424324253242632427324283242932430324313243232433324343243532436324373243832439324403244132442324433244432445324463244732448324493245032451324523245332454324553245632457324583245932460324613246232463324643246532466324673246832469324703247132472324733247432475324763247732478324793248032481324823248332484324853248632487324883248932490324913249232493324943249532496324973249832499325003250132502325033250432505325063250732508325093251032511325123251332514325153251632517325183251932520325213252232523325243252532526325273252832529325303253132532325333253432535325363253732538325393254032541325423254332544325453254632547325483254932550325513255232553325543255532556325573255832559325603256132562325633256432565325663256732568325693257032571325723257332574325753257632577325783257932580325813258232583325843258532586325873258832589325903259132592325933259432595325963259732598325993260032601326023260332604326053260632607326083260932610326113261232613326143261532616326173261832619326203262132622326233262432625326263262732628326293263032631326323263332634326353263632637326383263932640326413264232643326443264532646326473264832649326503265132652326533265432655326563265732658326593266032661326623266332664326653266632667326683266932670326713267232673326743267532676326773267832679326803268132682326833268432685326863268732688326893269032691326923269332694326953269632697326983269932700327013270232703327043270532706327073270832709327103271132712327133271432715327163271732718327193272032721327223272332724327253272632727327283272932730327313273232733327343273532736327373273832739327403274132742327433274432745327463274732748327493275032751327523275332754327553275632757327583275932760327613276232763327643276532766327673276832769327703277132772327733277432775327763277732778327793278032781327823278332784327853278632787327883278932790327913279232793327943279532796327973279832799328003280132802328033280432805328063280732808328093281032811328123281332814328153281632817328183281932820328213282232823328243282532826328273282832829328303283132832328333283432835328363283732838328393284032841328423284332844328453284632847328483284932850328513285232853328543285532856328573285832859328603286132862328633286432865328663286732868328693287032871328723287332874328753287632877328783287932880328813288232883328843288532886328873288832889328903289132892328933289432895328963289732898328993290032901329023290332904329053290632907329083290932910329113291232913329143291532916329173291832919329203292132922329233292432925329263292732928329293293032931329323293332934329353293632937329383293932940329413294232943329443294532946329473294832949329503295132952329533295432955329563295732958329593296032961329623296332964329653296632967329683296932970329713297232973329743297532976329773297832979329803298132982329833298432985329863298732988329893299032991329923299332994329953299632997329983299933000330013300233003330043300533006330073300833009330103301133012330133301433015330163301733018330193302033021330223302333024330253302633027330283302933030330313303233033330343303533036330373303833039330403304133042330433304433045330463304733048330493305033051330523305333054330553305633057330583305933060330613306233063330643306533066330673306833069330703307133072330733307433075330763307733078330793308033081330823308333084330853308633087330883308933090330913309233093330943309533096330973309833099331003310133102331033310433105331063310733108331093311033111331123311333114331153311633117331183311933120331213312233123331243312533126331273312833129331303313133132331333313433135331363313733138331393314033141331423314333144331453314633147331483314933150331513315233153331543315533156331573315833159331603316133162331633316433165331663316733168331693317033171331723317333174331753317633177331783317933180331813318233183331843318533186331873318833189331903319133192331933319433195331963319733198331993320033201332023320333204332053320633207332083320933210332113321233213332143321533216332173321833219332203322133222332233322433225332263322733228332293323033231332323323333234332353323633237332383323933240332413324233243332443324533246332473324833249332503325133252332533325433255332563325733258332593326033261332623326333264332653326633267332683326933270332713327233273332743327533276332773327833279332803328133282332833328433285332863328733288332893329033291332923329333294332953329633297332983329933300333013330233303333043330533306333073330833309333103331133312333133331433315333163331733318333193332033321333223332333324333253332633327333283332933330333313333233333333343333533336333373333833339333403334133342333433334433345333463334733348333493335033351333523335333354333553335633357333583335933360333613336233363333643336533366333673336833369333703337133372333733337433375333763337733378333793338033381333823338333384333853338633387333883338933390333913339233393333943339533396333973339833399334003340133402334033340433405334063340733408334093341033411334123341333414334153341633417334183341933420334213342233423334243342533426334273342833429334303343133432334333343433435334363343733438334393344033441334423344333444334453344633447334483344933450334513345233453334543345533456334573345833459334603346133462334633346433465334663346733468334693347033471334723347333474334753347633477334783347933480334813348233483334843348533486334873348833489334903349133492334933349433495334963349733498334993350033501335023350333504335053350633507335083350933510335113351233513335143351533516335173351833519335203352133522335233352433525335263352733528335293353033531335323353333534335353353633537335383353933540335413354233543335443354533546335473354833549335503355133552335533355433555335563355733558335593356033561335623356333564335653356633567335683356933570335713357233573335743357533576335773357833579335803358133582335833358433585335863358733588335893359033591335923359333594335953359633597335983359933600336013360233603336043360533606336073360833609336103361133612336133361433615336163361733618336193362033621336223362333624336253362633627336283362933630336313363233633336343363533636336373363833639336403364133642336433364433645336463364733648336493365033651336523365333654336553365633657336583365933660336613366233663336643366533666336673366833669336703367133672336733367433675336763367733678336793368033681336823368333684336853368633687336883368933690336913369233693336943369533696336973369833699337003370133702337033370433705337063370733708337093371033711337123371333714337153371633717337183371933720337213372233723337243372533726337273372833729337303373133732337333373433735337363373733738337393374033741337423374333744337453374633747337483374933750337513375233753337543375533756337573375833759337603376133762337633376433765337663376733768337693377033771337723377333774337753377633777337783377933780337813378233783337843378533786337873378833789337903379133792337933379433795337963379733798337993380033801338023380333804338053380633807338083380933810338113381233813338143381533816338173381833819338203382133822338233382433825338263382733828338293383033831338323383333834338353383633837338383383933840338413384233843338443384533846338473384833849338503385133852338533385433855338563385733858338593386033861338623386333864338653386633867338683386933870338713387233873338743387533876338773387833879338803388133882338833388433885338863388733888338893389033891338923389333894338953389633897338983389933900339013390233903339043390533906339073390833909339103391133912339133391433915339163391733918339193392033921339223392333924339253392633927339283392933930339313393233933339343393533936339373393833939339403394133942339433394433945339463394733948339493395033951339523395333954339553395633957339583395933960339613396233963339643396533966339673396833969339703397133972339733397433975339763397733978339793398033981339823398333984339853398633987339883398933990339913399233993339943399533996339973399833999340003400134002340033400434005340063400734008340093401034011340123401334014340153401634017340183401934020340213402234023340243402534026340273402834029340303403134032340333403434035340363403734038340393404034041340423404334044340453404634047340483404934050340513405234053340543405534056340573405834059340603406134062340633406434065340663406734068340693407034071340723407334074340753407634077340783407934080340813408234083340843408534086340873408834089340903409134092340933409434095340963409734098340993410034101341023410334104341053410634107341083410934110341113411234113341143411534116341173411834119341203412134122341233412434125341263412734128341293413034131341323413334134341353413634137341383413934140341413414234143341443414534146341473414834149341503415134152341533415434155341563415734158341593416034161341623416334164341653416634167341683416934170341713417234173341743417534176341773417834179341803418134182341833418434185341863418734188341893419034191341923419334194341953419634197341983419934200342013420234203342043420534206342073420834209342103421134212342133421434215342163421734218342193422034221342223422334224342253422634227342283422934230342313423234233342343423534236342373423834239342403424134242342433424434245342463424734248342493425034251342523425334254342553425634257342583425934260342613426234263342643426534266342673426834269342703427134272342733427434275342763427734278342793428034281342823428334284342853428634287342883428934290342913429234293342943429534296342973429834299343003430134302343033430434305343063430734308343093431034311343123431334314343153431634317343183431934320343213432234323343243432534326343273432834329343303433134332343333433434335343363433734338343393434034341343423434334344343453434634347343483434934350343513435234353343543435534356343573435834359343603436134362343633436434365343663436734368343693437034371343723437334374343753437634377343783437934380343813438234383343843438534386343873438834389343903439134392343933439434395343963439734398343993440034401344023440334404344053440634407344083440934410344113441234413344143441534416344173441834419344203442134422344233442434425344263442734428344293443034431344323443334434344353443634437344383443934440344413444234443344443444534446344473444834449344503445134452344533445434455344563445734458344593446034461344623446334464344653446634467344683446934470344713447234473344743447534476344773447834479344803448134482344833448434485344863448734488344893449034491344923449334494344953449634497344983449934500345013450234503345043450534506345073450834509345103451134512345133451434515345163451734518345193452034521345223452334524345253452634527345283452934530345313453234533345343453534536345373453834539345403454134542345433454434545345463454734548345493455034551345523455334554345553455634557345583455934560345613456234563345643456534566345673456834569345703457134572345733457434575345763457734578345793458034581345823458334584345853458634587345883458934590345913459234593345943459534596345973459834599346003460134602346033460434605346063460734608346093461034611346123461334614346153461634617346183461934620346213462234623346243462534626346273462834629346303463134632346333463434635346363463734638346393464034641346423464334644346453464634647346483464934650346513465234653346543465534656346573465834659346603466134662346633466434665346663466734668346693467034671346723467334674346753467634677346783467934680346813468234683346843468534686346873468834689346903469134692346933469434695346963469734698346993470034701347023470334704347053470634707347083470934710347113471234713347143471534716347173471834719347203472134722347233472434725347263472734728347293473034731347323473334734347353473634737347383473934740347413474234743347443474534746347473474834749347503475134752347533475434755347563475734758347593476034761347623476334764347653476634767347683476934770347713477234773347743477534776347773477834779347803478134782347833478434785347863478734788347893479034791347923479334794347953479634797347983479934800348013480234803348043480534806348073480834809348103481134812348133481434815348163481734818348193482034821348223482334824348253482634827348283482934830348313483234833348343483534836348373483834839348403484134842348433484434845348463484734848348493485034851348523485334854348553485634857348583485934860348613486234863348643486534866348673486834869348703487134872348733487434875348763487734878348793488034881348823488334884348853488634887348883488934890348913489234893348943489534896348973489834899349003490134902349033490434905349063490734908349093491034911349123491334914349153491634917349183491934920349213492234923349243492534926349273492834929349303493134932349333493434935349363493734938349393494034941349423494334944349453494634947349483494934950349513495234953349543495534956349573495834959349603496134962349633496434965349663496734968349693497034971349723497334974349753497634977349783497934980349813498234983349843498534986349873498834989349903499134992349933499434995349963499734998349993500035001350023500335004350053500635007350083500935010350113501235013350143501535016350173501835019350203502135022350233502435025350263502735028350293503035031350323503335034350353503635037350383503935040350413504235043350443504535046350473504835049350503505135052350533505435055350563505735058350593506035061350623506335064350653506635067350683506935070350713507235073350743507535076350773507835079350803508135082350833508435085350863508735088350893509035091350923509335094350953509635097350983509935100351013510235103351043510535106351073510835109351103511135112351133511435115351163511735118351193512035121351223512335124351253512635127351283512935130351313513235133351343513535136351373513835139351403514135142351433514435145351463514735148351493515035151351523515335154351553515635157351583515935160351613516235163351643516535166351673516835169351703517135172351733517435175351763517735178351793518035181351823518335184351853518635187351883518935190351913519235193351943519535196351973519835199352003520135202352033520435205352063520735208352093521035211352123521335214352153521635217352183521935220352213522235223352243522535226352273522835229352303523135232352333523435235352363523735238352393524035241352423524335244352453524635247352483524935250352513525235253352543525535256352573525835259352603526135262352633526435265352663526735268352693527035271352723527335274352753527635277352783527935280352813528235283352843528535286352873528835289352903529135292352933529435295352963529735298352993530035301353023530335304353053530635307353083530935310353113531235313353143531535316353173531835319353203532135322353233532435325353263532735328353293533035331353323533335334353353533635337353383533935340353413534235343353443534535346353473534835349353503535135352353533535435355353563535735358353593536035361353623536335364353653536635367353683536935370353713537235373353743537535376353773537835379353803538135382353833538435385353863538735388353893539035391353923539335394353953539635397353983539935400354013540235403354043540535406354073540835409354103541135412354133541435415354163541735418354193542035421354223542335424354253542635427354283542935430354313543235433354343543535436354373543835439354403544135442354433544435445354463544735448354493545035451354523545335454354553545635457354583545935460354613546235463354643546535466354673546835469354703547135472354733547435475354763547735478354793548035481354823548335484354853548635487354883548935490354913549235493354943549535496354973549835499355003550135502355033550435505355063550735508355093551035511355123551335514355153551635517355183551935520355213552235523355243552535526355273552835529355303553135532355333553435535355363553735538355393554035541355423554335544355453554635547355483554935550355513555235553355543555535556355573555835559355603556135562355633556435565355663556735568355693557035571355723557335574355753557635577355783557935580355813558235583355843558535586355873558835589355903559135592355933559435595355963559735598355993560035601356023560335604356053560635607356083560935610356113561235613356143561535616356173561835619356203562135622356233562435625356263562735628356293563035631356323563335634356353563635637356383563935640356413564235643356443564535646356473564835649356503565135652356533565435655356563565735658356593566035661356623566335664356653566635667356683566935670356713567235673356743567535676356773567835679356803568135682356833568435685356863568735688356893569035691356923569335694356953569635697356983569935700357013570235703357043570535706357073570835709357103571135712357133571435715357163571735718357193572035721357223572335724357253572635727357283572935730357313573235733357343573535736357373573835739357403574135742357433574435745357463574735748357493575035751357523575335754357553575635757357583575935760357613576235763357643576535766357673576835769357703577135772357733577435775357763577735778357793578035781357823578335784357853578635787357883578935790357913579235793357943579535796357973579835799358003580135802358033580435805358063580735808358093581035811358123581335814358153581635817358183581935820358213582235823358243582535826358273582835829358303583135832358333583435835358363583735838358393584035841358423584335844358453584635847358483584935850358513585235853358543585535856358573585835859358603586135862358633586435865358663586735868358693587035871358723587335874358753587635877358783587935880358813588235883358843588535886358873588835889358903589135892358933589435895358963589735898358993590035901359023590335904359053590635907359083590935910359113591235913359143591535916359173591835919359203592135922359233592435925359263592735928359293593035931359323593335934359353593635937359383593935940359413594235943359443594535946359473594835949359503595135952359533595435955359563595735958359593596035961359623596335964359653596635967359683596935970359713597235973359743597535976359773597835979359803598135982359833598435985359863598735988359893599035991359923599335994359953599635997359983599936000360013600236003360043600536006360073600836009360103601136012360133601436015360163601736018360193602036021360223602336024360253602636027360283602936030360313603236033360343603536036360373603836039360403604136042360433604436045360463604736048360493605036051360523605336054360553605636057360583605936060360613606236063360643606536066360673606836069360703607136072360733607436075360763607736078360793608036081360823608336084360853608636087360883608936090360913609236093360943609536096360973609836099361003610136102361033610436105361063610736108361093611036111361123611336114361153611636117361183611936120361213612236123361243612536126361273612836129361303613136132361333613436135361363613736138361393614036141361423614336144361453614636147361483614936150361513615236153361543615536156361573615836159361603616136162361633616436165361663616736168361693617036171361723617336174361753617636177361783617936180361813618236183361843618536186361873618836189361903619136192361933619436195361963619736198361993620036201362023620336204362053620636207362083620936210362113621236213362143621536216362173621836219362203622136222362233622436225362263622736228362293623036231362323623336234362353623636237362383623936240362413624236243362443624536246362473624836249362503625136252362533625436255362563625736258362593626036261362623626336264362653626636267362683626936270362713627236273362743627536276362773627836279362803628136282362833628436285362863628736288362893629036291362923629336294362953629636297362983629936300363013630236303363043630536306363073630836309363103631136312363133631436315363163631736318363193632036321363223632336324363253632636327363283632936330363313633236333363343633536336363373633836339363403634136342363433634436345363463634736348363493635036351363523635336354363553635636357363583635936360363613636236363363643636536366363673636836369363703637136372363733637436375363763637736378363793638036381363823638336384363853638636387363883638936390363913639236393363943639536396363973639836399364003640136402364033640436405364063640736408364093641036411364123641336414364153641636417364183641936420364213642236423364243642536426364273642836429364303643136432364333643436435364363643736438364393644036441364423644336444364453644636447364483644936450364513645236453364543645536456364573645836459364603646136462364633646436465364663646736468364693647036471364723647336474364753647636477364783647936480364813648236483364843648536486364873648836489364903649136492364933649436495364963649736498364993650036501365023650336504365053650636507365083650936510365113651236513365143651536516365173651836519365203652136522365233652436525365263652736528365293653036531365323653336534365353653636537365383653936540365413654236543365443654536546365473654836549365503655136552365533655436555365563655736558365593656036561365623656336564365653656636567365683656936570365713657236573365743657536576365773657836579365803658136582365833658436585365863658736588365893659036591365923659336594365953659636597365983659936600366013660236603366043660536606366073660836609366103661136612366133661436615366163661736618366193662036621366223662336624366253662636627366283662936630366313663236633366343663536636366373663836639366403664136642366433664436645366463664736648366493665036651366523665336654366553665636657366583665936660366613666236663366643666536666366673666836669366703667136672366733667436675366763667736678366793668036681366823668336684366853668636687366883668936690366913669236693366943669536696366973669836699367003670136702367033670436705367063670736708367093671036711367123671336714367153671636717367183671936720367213672236723367243672536726367273672836729367303673136732367333673436735367363673736738367393674036741367423674336744367453674636747367483674936750367513675236753367543675536756367573675836759367603676136762367633676436765367663676736768367693677036771367723677336774367753677636777367783677936780367813678236783367843678536786367873678836789367903679136792367933679436795367963679736798367993680036801368023680336804368053680636807368083680936810368113681236813368143681536816368173681836819368203682136822368233682436825368263682736828368293683036831368323683336834368353683636837368383683936840368413684236843368443684536846368473684836849368503685136852368533685436855368563685736858368593686036861368623686336864368653686636867368683686936870368713687236873368743687536876368773687836879368803688136882368833688436885368863688736888368893689036891368923689336894368953689636897368983689936900369013690236903369043690536906369073690836909369103691136912369133691436915369163691736918369193692036921369223692336924369253692636927369283692936930369313693236933369343693536936369373693836939369403694136942369433694436945369463694736948369493695036951369523695336954369553695636957369583695936960369613696236963369643696536966369673696836969369703697136972369733697436975369763697736978369793698036981369823698336984369853698636987369883698936990369913699236993369943699536996369973699836999370003700137002370033700437005370063700737008370093701037011370123701337014370153701637017370183701937020370213702237023370243702537026370273702837029370303703137032370333703437035370363703737038370393704037041370423704337044370453704637047370483704937050370513705237053370543705537056370573705837059370603706137062370633706437065370663706737068370693707037071370723707337074370753707637077370783707937080370813708237083370843708537086370873708837089370903709137092370933709437095370963709737098370993710037101371023710337104371053710637107371083710937110371113711237113371143711537116371173711837119371203712137122371233712437125371263712737128371293713037131371323713337134371353713637137371383713937140371413714237143371443714537146371473714837149371503715137152371533715437155371563715737158371593716037161371623716337164371653716637167371683716937170371713717237173371743717537176371773717837179371803718137182371833718437185371863718737188371893719037191371923719337194371953719637197371983719937200372013720237203372043720537206372073720837209372103721137212372133721437215372163721737218372193722037221372223722337224372253722637227372283722937230372313723237233372343723537236372373723837239372403724137242372433724437245372463724737248372493725037251372523725337254372553725637257372583725937260372613726237263372643726537266372673726837269372703727137272372733727437275372763727737278372793728037281372823728337284372853728637287372883728937290372913729237293372943729537296372973729837299373003730137302373033730437305373063730737308373093731037311373123731337314373153731637317373183731937320373213732237323373243732537326373273732837329373303733137332373333733437335373363733737338373393734037341373423734337344373453734637347373483734937350373513735237353373543735537356373573735837359373603736137362373633736437365373663736737368373693737037371373723737337374373753737637377373783737937380373813738237383373843738537386373873738837389373903739137392373933739437395373963739737398373993740037401374023740337404374053740637407374083740937410374113741237413374143741537416374173741837419374203742137422374233742437425374263742737428374293743037431374323743337434374353743637437374383743937440374413744237443374443744537446374473744837449374503745137452374533745437455374563745737458374593746037461374623746337464374653746637467374683746937470374713747237473374743747537476374773747837479374803748137482374833748437485374863748737488374893749037491374923749337494374953749637497374983749937500375013750237503375043750537506375073750837509375103751137512375133751437515375163751737518375193752037521375223752337524375253752637527375283752937530375313753237533375343753537536375373753837539375403754137542375433754437545375463754737548375493755037551375523755337554375553755637557375583755937560375613756237563375643756537566375673756837569375703757137572375733757437575375763757737578375793758037581375823758337584375853758637587375883758937590375913759237593375943759537596375973759837599376003760137602376033760437605376063760737608376093761037611376123761337614376153761637617376183761937620376213762237623376243762537626376273762837629376303763137632376333763437635376363763737638376393764037641376423764337644376453764637647376483764937650376513765237653376543765537656376573765837659376603766137662376633766437665376663766737668376693767037671376723767337674376753767637677376783767937680376813768237683376843768537686376873768837689376903769137692376933769437695376963769737698376993770037701377023770337704377053770637707377083770937710377113771237713377143771537716377173771837719377203772137722377233772437725377263772737728377293773037731377323773337734377353773637737377383773937740377413774237743377443774537746377473774837749377503775137752377533775437755377563775737758377593776037761377623776337764377653776637767377683776937770377713777237773377743777537776377773777837779377803778137782377833778437785377863778737788377893779037791377923779337794377953779637797377983779937800378013780237803378043780537806378073780837809378103781137812378133781437815378163781737818378193782037821378223782337824378253782637827378283782937830378313783237833378343783537836378373783837839378403784137842378433784437845378463784737848378493785037851378523785337854378553785637857378583785937860378613786237863378643786537866378673786837869378703787137872378733787437875378763787737878378793788037881378823788337884378853788637887378883788937890378913789237893378943789537896378973789837899379003790137902379033790437905379063790737908379093791037911379123791337914379153791637917379183791937920379213792237923379243792537926379273792837929379303793137932379333793437935379363793737938379393794037941379423794337944379453794637947379483794937950379513795237953379543795537956379573795837959379603796137962379633796437965379663796737968379693797037971379723797337974379753797637977379783797937980379813798237983379843798537986379873798837989379903799137992379933799437995379963799737998379993800038001380023800338004380053800638007380083800938010380113801238013380143801538016380173801838019380203802138022380233802438025380263802738028380293803038031380323803338034380353803638037380383803938040380413804238043380443804538046380473804838049380503805138052380533805438055380563805738058380593806038061380623806338064380653806638067380683806938070380713807238073380743807538076380773807838079380803808138082380833808438085380863808738088380893809038091380923809338094380953809638097380983809938100381013810238103381043810538106381073810838109381103811138112381133811438115381163811738118381193812038121381223812338124381253812638127381283812938130381313813238133381343813538136381373813838139381403814138142381433814438145381463814738148381493815038151381523815338154381553815638157381583815938160381613816238163381643816538166381673816838169381703817138172381733817438175381763817738178381793818038181381823818338184381853818638187381883818938190381913819238193381943819538196381973819838199382003820138202382033820438205382063820738208382093821038211382123821338214382153821638217382183821938220382213822238223382243822538226382273822838229382303823138232382333823438235382363823738238382393824038241382423824338244382453824638247382483824938250382513825238253382543825538256382573825838259382603826138262382633826438265382663826738268382693827038271382723827338274382753827638277382783827938280382813828238283382843828538286382873828838289382903829138292382933829438295382963829738298382993830038301383023830338304383053830638307383083830938310383113831238313383143831538316383173831838319383203832138322383233832438325383263832738328383293833038331383323833338334383353833638337383383833938340383413834238343383443834538346383473834838349383503835138352383533835438355383563835738358383593836038361383623836338364383653836638367383683836938370383713837238373383743837538376383773837838379383803838138382383833838438385383863838738388383893839038391383923839338394383953839638397383983839938400384013840238403384043840538406384073840838409384103841138412384133841438415384163841738418384193842038421384223842338424384253842638427384283842938430384313843238433384343843538436384373843838439384403844138442384433844438445384463844738448384493845038451384523845338454384553845638457384583845938460384613846238463384643846538466384673846838469384703847138472384733847438475384763847738478384793848038481384823848338484384853848638487384883848938490384913849238493384943849538496384973849838499385003850138502385033850438505385063850738508385093851038511385123851338514385153851638517385183851938520385213852238523385243852538526385273852838529385303853138532385333853438535385363853738538385393854038541385423854338544385453854638547385483854938550385513855238553385543855538556385573855838559385603856138562385633856438565385663856738568385693857038571385723857338574385753857638577385783857938580385813858238583385843858538586385873858838589385903859138592385933859438595385963859738598385993860038601386023860338604386053860638607386083860938610386113861238613386143861538616386173861838619386203862138622386233862438625386263862738628386293863038631386323863338634386353863638637386383863938640386413864238643386443864538646386473864838649386503865138652386533865438655386563865738658386593866038661386623866338664386653866638667386683866938670386713867238673386743867538676386773867838679386803868138682386833868438685386863868738688386893869038691386923869338694386953869638697386983869938700387013870238703387043870538706387073870838709387103871138712387133871438715387163871738718387193872038721387223872338724387253872638727387283872938730387313873238733387343873538736387373873838739387403874138742387433874438745387463874738748387493875038751387523875338754387553875638757387583875938760387613876238763387643876538766387673876838769387703877138772387733877438775387763877738778387793878038781387823878338784387853878638787387883878938790387913879238793387943879538796387973879838799388003880138802388033880438805388063880738808388093881038811388123881338814388153881638817388183881938820388213882238823388243882538826388273882838829388303883138832388333883438835388363883738838388393884038841388423884338844388453884638847388483884938850388513885238853388543885538856388573885838859388603886138862388633886438865388663886738868388693887038871388723887338874388753887638877388783887938880388813888238883388843888538886388873888838889388903889138892388933889438895388963889738898388993890038901389023890338904389053890638907389083890938910389113891238913389143891538916389173891838919389203892138922389233892438925389263892738928389293893038931389323893338934389353893638937389383893938940389413894238943389443894538946389473894838949389503895138952389533895438955389563895738958389593896038961389623896338964389653896638967389683896938970389713897238973389743897538976389773897838979389803898138982389833898438985389863898738988389893899038991389923899338994389953899638997389983899939000390013900239003390043900539006390073900839009390103901139012390133901439015390163901739018390193902039021390223902339024390253902639027390283902939030390313903239033390343903539036390373903839039390403904139042390433904439045390463904739048390493905039051390523905339054390553905639057390583905939060390613906239063390643906539066390673906839069390703907139072390733907439075390763907739078390793908039081390823908339084390853908639087390883908939090390913909239093390943909539096390973909839099391003910139102391033910439105391063910739108391093911039111391123911339114391153911639117391183911939120391213912239123391243912539126391273912839129391303913139132391333913439135391363913739138391393914039141391423914339144391453914639147391483914939150391513915239153391543915539156391573915839159391603916139162391633916439165391663916739168391693917039171391723917339174391753917639177391783917939180391813918239183391843918539186391873918839189391903919139192391933919439195391963919739198391993920039201392023920339204392053920639207392083920939210392113921239213392143921539216392173921839219392203922139222392233922439225392263922739228392293923039231392323923339234392353923639237392383923939240392413924239243392443924539246392473924839249392503925139252392533925439255392563925739258392593926039261392623926339264392653926639267392683926939270392713927239273392743927539276392773927839279392803928139282392833928439285392863928739288392893929039291392923929339294392953929639297392983929939300393013930239303393043930539306393073930839309393103931139312393133931439315393163931739318393193932039321393223932339324393253932639327393283932939330393313933239333393343933539336393373933839339393403934139342393433934439345393463934739348393493935039351393523935339354393553935639357393583935939360393613936239363393643936539366393673936839369393703937139372393733937439375393763937739378393793938039381393823938339384393853938639387393883938939390393913939239393393943939539396393973939839399394003940139402394033940439405394063940739408394093941039411394123941339414394153941639417394183941939420394213942239423394243942539426394273942839429394303943139432394333943439435394363943739438394393944039441394423944339444394453944639447394483944939450394513945239453394543945539456394573945839459394603946139462394633946439465394663946739468394693947039471394723947339474394753947639477394783947939480394813948239483394843948539486394873948839489394903949139492394933949439495394963949739498394993950039501395023950339504395053950639507395083950939510395113951239513395143951539516395173951839519395203952139522395233952439525395263952739528395293953039531395323953339534395353953639537395383953939540395413954239543395443954539546395473954839549395503955139552395533955439555395563955739558395593956039561395623956339564395653956639567395683956939570395713957239573395743957539576395773957839579395803958139582395833958439585395863958739588395893959039591395923959339594395953959639597395983959939600396013960239603396043960539606396073960839609396103961139612396133961439615396163961739618396193962039621396223962339624396253962639627396283962939630396313963239633396343963539636396373963839639396403964139642396433964439645396463964739648396493965039651396523965339654396553965639657396583965939660396613966239663396643966539666396673966839669396703967139672396733967439675396763967739678396793968039681396823968339684396853968639687396883968939690396913969239693396943969539696396973969839699397003970139702397033970439705397063970739708397093971039711397123971339714397153971639717397183971939720397213972239723397243972539726397273972839729397303973139732397333973439735397363973739738397393974039741397423974339744397453974639747397483974939750397513975239753397543975539756397573975839759397603976139762397633976439765397663976739768397693977039771397723977339774397753977639777397783977939780397813978239783397843978539786397873978839789397903979139792397933979439795397963979739798397993980039801398023980339804398053980639807398083980939810398113981239813398143981539816398173981839819398203982139822398233982439825398263982739828398293983039831398323983339834398353983639837398383983939840398413984239843398443984539846398473984839849398503985139852398533985439855398563985739858398593986039861398623986339864398653986639867398683986939870398713987239873398743987539876398773987839879398803988139882398833988439885398863988739888398893989039891398923989339894398953989639897398983989939900399013990239903399043990539906399073990839909399103991139912399133991439915399163991739918399193992039921399223992339924399253992639927399283992939930399313993239933399343993539936399373993839939399403994139942399433994439945399463994739948399493995039951399523995339954399553995639957399583995939960399613996239963399643996539966399673996839969399703997139972399733997439975399763997739978399793998039981399823998339984399853998639987399883998939990399913999239993399943999539996399973999839999400004000140002400034000440005400064000740008400094001040011400124001340014400154001640017400184001940020400214002240023400244002540026400274002840029400304003140032400334003440035400364003740038400394004040041400424004340044400454004640047400484004940050400514005240053400544005540056400574005840059400604006140062400634006440065400664006740068400694007040071400724007340074400754007640077400784007940080400814008240083400844008540086400874008840089400904009140092400934009440095400964009740098400994010040101401024010340104401054010640107401084010940110401114011240113401144011540116401174011840119401204012140122401234012440125401264012740128401294013040131401324013340134401354013640137401384013940140401414014240143401444014540146401474014840149401504015140152401534015440155401564015740158401594016040161401624016340164401654016640167401684016940170401714017240173401744017540176401774017840179401804018140182401834018440185401864018740188401894019040191401924019340194401954019640197401984019940200402014020240203402044020540206402074020840209402104021140212402134021440215402164021740218402194022040221402224022340224402254022640227402284022940230402314023240233402344023540236402374023840239402404024140242402434024440245402464024740248402494025040251402524025340254402554025640257402584025940260402614026240263402644026540266402674026840269402704027140272402734027440275402764027740278402794028040281402824028340284402854028640287402884028940290402914029240293402944029540296402974029840299403004030140302403034030440305403064030740308403094031040311403124031340314403154031640317403184031940320403214032240323403244032540326403274032840329403304033140332403334033440335403364033740338403394034040341403424034340344403454034640347403484034940350403514035240353403544035540356403574035840359403604036140362403634036440365403664036740368403694037040371403724037340374403754037640377403784037940380403814038240383403844038540386403874038840389403904039140392403934039440395403964039740398403994040040401404024040340404404054040640407404084040940410404114041240413404144041540416404174041840419404204042140422404234042440425404264042740428404294043040431404324043340434404354043640437404384043940440404414044240443404444044540446404474044840449404504045140452404534045440455404564045740458404594046040461404624046340464404654046640467404684046940470404714047240473404744047540476404774047840479404804048140482404834048440485404864048740488404894049040491404924049340494404954049640497404984049940500405014050240503405044050540506405074050840509405104051140512405134051440515405164051740518405194052040521405224052340524405254052640527405284052940530405314053240533405344053540536405374053840539405404054140542405434054440545405464054740548405494055040551405524055340554405554055640557405584055940560405614056240563405644056540566405674056840569405704057140572405734057440575405764057740578405794058040581405824058340584405854058640587405884058940590405914059240593405944059540596405974059840599406004060140602406034060440605406064060740608406094061040611406124061340614406154061640617406184061940620406214062240623406244062540626406274062840629406304063140632406334063440635406364063740638406394064040641406424064340644406454064640647406484064940650406514065240653406544065540656406574065840659406604066140662406634066440665406664066740668406694067040671406724067340674406754067640677406784067940680406814068240683406844068540686406874068840689406904069140692406934069440695406964069740698406994070040701407024070340704407054070640707407084070940710407114071240713407144071540716407174071840719407204072140722407234072440725407264072740728407294073040731407324073340734407354073640737407384073940740407414074240743407444074540746407474074840749407504075140752407534075440755407564075740758407594076040761407624076340764407654076640767407684076940770407714077240773407744077540776407774077840779407804078140782407834078440785407864078740788407894079040791407924079340794407954079640797407984079940800408014080240803408044080540806408074080840809408104081140812408134081440815408164081740818408194082040821408224082340824408254082640827408284082940830408314083240833408344083540836408374083840839408404084140842408434084440845408464084740848408494085040851408524085340854408554085640857408584085940860408614086240863408644086540866408674086840869408704087140872408734087440875408764087740878408794088040881408824088340884408854088640887408884088940890408914089240893408944089540896408974089840899409004090140902409034090440905409064090740908409094091040911409124091340914409154091640917409184091940920409214092240923409244092540926409274092840929409304093140932409334093440935409364093740938409394094040941409424094340944409454094640947409484094940950409514095240953409544095540956409574095840959409604096140962409634096440965409664096740968409694097040971409724097340974409754097640977409784097940980409814098240983409844098540986409874098840989409904099140992409934099440995409964099740998409994100041001410024100341004410054100641007410084100941010410114101241013410144101541016410174101841019410204102141022410234102441025410264102741028410294103041031410324103341034410354103641037410384103941040410414104241043410444104541046410474104841049410504105141052410534105441055410564105741058410594106041061410624106341064410654106641067410684106941070410714107241073410744107541076410774107841079410804108141082410834108441085410864108741088410894109041091410924109341094410954109641097410984109941100411014110241103411044110541106411074110841109411104111141112411134111441115411164111741118411194112041121411224112341124411254112641127411284112941130411314113241133411344113541136411374113841139411404114141142411434114441145411464114741148411494115041151411524115341154411554115641157411584115941160411614116241163411644116541166411674116841169411704117141172411734117441175411764117741178411794118041181411824118341184411854118641187411884118941190411914119241193411944119541196411974119841199412004120141202412034120441205412064120741208412094121041211412124121341214412154121641217412184121941220412214122241223412244122541226412274122841229412304123141232412334123441235412364123741238412394124041241412424124341244412454124641247412484124941250412514125241253412544125541256412574125841259412604126141262412634126441265412664126741268412694127041271412724127341274412754127641277412784127941280412814128241283412844128541286412874128841289412904129141292412934129441295412964129741298412994130041301413024130341304413054130641307413084130941310413114131241313413144131541316413174131841319413204132141322413234132441325413264132741328413294133041331413324133341334413354133641337413384133941340413414134241343413444134541346413474134841349413504135141352413534135441355413564135741358413594136041361413624136341364413654136641367413684136941370413714137241373413744137541376413774137841379413804138141382413834138441385413864138741388413894139041391413924139341394413954139641397413984139941400414014140241403414044140541406414074140841409414104141141412414134141441415414164141741418414194142041421414224142341424414254142641427414284142941430414314143241433414344143541436414374143841439414404144141442414434144441445414464144741448414494145041451414524145341454414554145641457414584145941460414614146241463414644146541466414674146841469414704147141472414734147441475414764147741478414794148041481414824148341484414854148641487414884148941490414914149241493414944149541496414974149841499415004150141502415034150441505415064150741508415094151041511415124151341514415154151641517415184151941520415214152241523415244152541526415274152841529415304153141532415334153441535415364153741538415394154041541415424154341544415454154641547415484154941550415514155241553415544155541556415574155841559415604156141562415634156441565415664156741568415694157041571415724157341574415754157641577415784157941580415814158241583415844158541586415874158841589415904159141592415934159441595415964159741598415994160041601416024160341604416054160641607416084160941610416114161241613416144161541616416174161841619416204162141622416234162441625416264162741628416294163041631416324163341634416354163641637416384163941640416414164241643416444164541646416474164841649416504165141652416534165441655416564165741658416594166041661416624166341664416654166641667416684166941670416714167241673416744167541676416774167841679416804168141682416834168441685416864168741688416894169041691416924169341694416954169641697416984169941700417014170241703417044170541706417074170841709417104171141712417134171441715417164171741718417194172041721417224172341724417254172641727417284172941730417314173241733417344173541736417374173841739417404174141742417434174441745417464174741748417494175041751417524175341754417554175641757417584175941760417614176241763417644176541766417674176841769417704177141772417734177441775417764177741778417794178041781417824178341784417854178641787417884178941790417914179241793417944179541796417974179841799418004180141802418034180441805418064180741808418094181041811418124181341814418154181641817418184181941820418214182241823418244182541826418274182841829418304183141832418334183441835418364183741838418394184041841418424184341844418454184641847418484184941850418514185241853418544185541856418574185841859418604186141862418634186441865418664186741868418694187041871418724187341874418754187641877418784187941880418814188241883418844188541886418874188841889418904189141892418934189441895418964189741898418994190041901419024190341904419054190641907419084190941910419114191241913419144191541916419174191841919419204192141922419234192441925419264192741928419294193041931419324193341934419354193641937419384193941940419414194241943419444194541946419474194841949419504195141952419534195441955419564195741958419594196041961419624196341964419654196641967419684196941970419714197241973419744197541976419774197841979419804198141982419834198441985419864198741988419894199041991419924199341994419954199641997419984199942000420014200242003420044200542006420074200842009420104201142012420134201442015420164201742018420194202042021420224202342024420254202642027420284202942030420314203242033420344203542036420374203842039420404204142042420434204442045420464204742048420494205042051420524205342054420554205642057420584205942060420614206242063420644206542066420674206842069420704207142072420734207442075420764207742078420794208042081420824208342084420854208642087420884208942090420914209242093420944209542096420974209842099421004210142102421034210442105421064210742108421094211042111421124211342114421154211642117421184211942120421214212242123421244212542126421274212842129421304213142132421334213442135421364213742138421394214042141421424214342144421454214642147421484214942150421514215242153421544215542156421574215842159421604216142162421634216442165421664216742168421694217042171421724217342174421754217642177421784217942180421814218242183421844218542186421874218842189421904219142192421934219442195421964219742198421994220042201422024220342204422054220642207422084220942210422114221242213422144221542216422174221842219422204222142222422234222442225422264222742228422294223042231422324223342234422354223642237422384223942240422414224242243422444224542246422474224842249422504225142252422534225442255422564225742258422594226042261422624226342264422654226642267422684226942270422714227242273422744227542276422774227842279422804228142282422834228442285422864228742288422894229042291422924229342294422954229642297422984229942300423014230242303423044230542306423074230842309423104231142312423134231442315423164231742318423194232042321423224232342324423254232642327423284232942330423314233242333423344233542336423374233842339423404234142342423434234442345423464234742348423494235042351423524235342354423554235642357423584235942360423614236242363423644236542366423674236842369423704237142372423734237442375423764237742378423794238042381423824238342384423854238642387423884238942390423914239242393423944239542396423974239842399424004240142402424034240442405424064240742408424094241042411424124241342414424154241642417424184241942420424214242242423424244242542426424274242842429424304243142432424334243442435424364243742438424394244042441424424244342444424454244642447424484244942450424514245242453424544245542456424574245842459424604246142462424634246442465424664246742468424694247042471424724247342474424754247642477424784247942480424814248242483424844248542486424874248842489424904249142492424934249442495424964249742498424994250042501425024250342504425054250642507425084250942510425114251242513425144251542516425174251842519425204252142522425234252442525425264252742528425294253042531425324253342534425354253642537425384253942540425414254242543425444254542546425474254842549425504255142552425534255442555425564255742558425594256042561425624256342564425654256642567425684256942570425714257242573425744257542576425774257842579425804258142582425834258442585425864258742588425894259042591425924259342594425954259642597425984259942600426014260242603426044260542606426074260842609426104261142612426134261442615426164261742618426194262042621426224262342624426254262642627426284262942630426314263242633426344263542636426374263842639426404264142642426434264442645426464264742648426494265042651426524265342654426554265642657426584265942660426614266242663426644266542666426674266842669426704267142672426734267442675426764267742678426794268042681426824268342684426854268642687426884268942690426914269242693426944269542696426974269842699427004270142702427034270442705427064270742708427094271042711427124271342714427154271642717427184271942720427214272242723427244272542726427274272842729427304273142732427334273442735427364273742738427394274042741427424274342744427454274642747427484274942750427514275242753427544275542756427574275842759427604276142762427634276442765427664276742768427694277042771427724277342774427754277642777427784277942780427814278242783427844278542786427874278842789427904279142792427934279442795427964279742798427994280042801428024280342804428054280642807428084280942810428114281242813428144281542816428174281842819428204282142822428234282442825428264282742828428294283042831428324283342834428354283642837428384283942840428414284242843428444284542846428474284842849428504285142852428534285442855428564285742858428594286042861428624286342864428654286642867428684286942870428714287242873428744287542876428774287842879428804288142882428834288442885428864288742888428894289042891428924289342894428954289642897428984289942900429014290242903429044290542906429074290842909429104291142912429134291442915429164291742918429194292042921429224292342924429254292642927429284292942930429314293242933429344293542936429374293842939429404294142942429434294442945429464294742948429494295042951429524295342954429554295642957429584295942960429614296242963429644296542966429674296842969429704297142972429734297442975429764297742978429794298042981429824298342984429854298642987429884298942990429914299242993429944299542996429974299842999430004300143002430034300443005430064300743008430094301043011430124301343014430154301643017430184301943020430214302243023430244302543026430274302843029430304303143032430334303443035430364303743038430394304043041430424304343044430454304643047430484304943050430514305243053430544305543056430574305843059430604306143062430634306443065430664306743068430694307043071430724307343074430754307643077430784307943080430814308243083430844308543086430874308843089430904309143092430934309443095430964309743098430994310043101431024310343104431054310643107431084310943110431114311243113431144311543116431174311843119431204312143122431234312443125431264312743128431294313043131431324313343134431354313643137431384313943140431414314243143431444314543146431474314843149431504315143152431534315443155431564315743158431594316043161431624316343164431654316643167431684316943170431714317243173431744317543176431774317843179431804318143182431834318443185431864318743188431894319043191431924319343194431954319643197431984319943200432014320243203432044320543206432074320843209432104321143212432134321443215432164321743218432194322043221432224322343224432254322643227432284322943230432314323243233432344323543236432374323843239432404324143242432434324443245432464324743248432494325043251432524325343254432554325643257432584325943260432614326243263432644326543266432674326843269432704327143272432734327443275432764327743278432794328043281432824328343284432854328643287432884328943290432914329243293432944329543296432974329843299433004330143302433034330443305433064330743308433094331043311433124331343314433154331643317433184331943320433214332243323433244332543326433274332843329433304333143332433334333443335433364333743338433394334043341433424334343344433454334643347433484334943350433514335243353433544335543356433574335843359433604336143362433634336443365433664336743368433694337043371433724337343374433754337643377433784337943380433814338243383433844338543386433874338843389433904339143392433934339443395433964339743398433994340043401434024340343404434054340643407434084340943410434114341243413434144341543416434174341843419434204342143422434234342443425434264342743428434294343043431434324343343434434354343643437434384343943440434414344243443434444344543446434474344843449434504345143452434534345443455434564345743458434594346043461434624346343464434654346643467434684346943470434714347243473434744347543476434774347843479434804348143482434834348443485434864348743488434894349043491434924349343494434954349643497434984349943500435014350243503435044350543506435074350843509435104351143512435134351443515435164351743518435194352043521435224352343524435254352643527435284352943530435314353243533435344353543536435374353843539435404354143542435434354443545435464354743548435494355043551435524355343554435554355643557435584355943560435614356243563435644356543566435674356843569435704357143572435734357443575435764357743578435794358043581435824358343584435854358643587435884358943590435914359243593435944359543596435974359843599436004360143602436034360443605436064360743608436094361043611436124361343614436154361643617436184361943620436214362243623436244362543626436274362843629436304363143632436334363443635436364363743638436394364043641436424364343644436454364643647436484364943650436514365243653436544365543656436574365843659436604366143662436634366443665436664366743668436694367043671436724367343674436754367643677436784367943680436814368243683436844368543686436874368843689436904369143692436934369443695436964369743698436994370043701437024370343704437054370643707437084370943710437114371243713437144371543716437174371843719437204372143722437234372443725437264372743728437294373043731437324373343734437354373643737437384373943740437414374243743437444374543746437474374843749437504375143752437534375443755437564375743758437594376043761437624376343764437654376643767437684376943770437714377243773437744377543776437774377843779437804378143782437834378443785437864378743788437894379043791437924379343794437954379643797437984379943800438014380243803438044380543806438074380843809438104381143812438134381443815438164381743818438194382043821438224382343824438254382643827438284382943830438314383243833438344383543836438374383843839438404384143842438434384443845438464384743848438494385043851438524385343854438554385643857438584385943860438614386243863438644386543866438674386843869438704387143872438734387443875438764387743878438794388043881438824388343884438854388643887438884388943890438914389243893438944389543896438974389843899439004390143902439034390443905439064390743908439094391043911439124391343914439154391643917439184391943920439214392243923439244392543926439274392843929439304393143932439334393443935439364393743938439394394043941439424394343944439454394643947439484394943950439514395243953439544395543956439574395843959439604396143962439634396443965439664396743968439694397043971439724397343974439754397643977439784397943980439814398243983439844398543986439874398843989439904399143992439934399443995439964399743998439994400044001440024400344004440054400644007440084400944010440114401244013440144401544016440174401844019440204402144022440234402444025440264402744028440294403044031440324403344034440354403644037440384403944040440414404244043440444404544046440474404844049440504405144052440534405444055440564405744058440594406044061440624406344064440654406644067440684406944070440714407244073440744407544076440774407844079440804408144082440834408444085440864408744088440894409044091440924409344094440954409644097440984409944100441014410244103441044410544106441074410844109441104411144112441134411444115441164411744118441194412044121441224412344124441254412644127441284412944130441314413244133441344413544136441374413844139441404414144142441434414444145441464414744148441494415044151441524415344154441554415644157441584415944160441614416244163441644416544166441674416844169441704417144172441734417444175441764417744178441794418044181441824418344184441854418644187441884418944190441914419244193441944419544196441974419844199442004420144202442034420444205442064420744208442094421044211442124421344214442154421644217442184421944220442214422244223442244422544226442274422844229442304423144232442334423444235442364423744238442394424044241442424424344244442454424644247442484424944250442514425244253442544425544256442574425844259442604426144262442634426444265442664426744268442694427044271442724427344274442754427644277442784427944280442814428244283442844428544286442874428844289442904429144292442934429444295442964429744298442994430044301443024430344304443054430644307443084430944310443114431244313443144431544316443174431844319443204432144322443234432444325443264432744328443294433044331443324433344334443354433644337443384433944340443414434244343443444434544346443474434844349443504435144352443534435444355443564435744358443594436044361443624436344364443654436644367443684436944370443714437244373443744437544376443774437844379443804438144382443834438444385443864438744388443894439044391443924439344394443954439644397443984439944400444014440244403444044440544406444074440844409444104441144412444134441444415444164441744418444194442044421444224442344424444254442644427444284442944430444314443244433444344443544436444374443844439444404444144442444434444444445444464444744448444494445044451444524445344454444554445644457444584445944460444614446244463444644446544466444674446844469444704447144472444734447444475444764447744478444794448044481444824448344484444854448644487444884448944490444914449244493444944449544496444974449844499445004450144502445034450444505445064450744508445094451044511445124451344514445154451644517445184451944520445214452244523445244452544526445274452844529445304453144532445334453444535445364453744538445394454044541445424454344544445454454644547445484454944550445514455244553445544455544556445574455844559445604456144562445634456444565445664456744568445694457044571445724457344574445754457644577445784457944580445814458244583445844458544586445874458844589445904459144592445934459444595445964459744598445994460044601446024460344604446054460644607446084460944610446114461244613446144461544616446174461844619446204462144622446234462444625446264462744628446294463044631446324463344634446354463644637446384463944640446414464244643446444464544646446474464844649446504465144652446534465444655446564465744658446594466044661446624466344664446654466644667446684466944670446714467244673446744467544676446774467844679446804468144682446834468444685446864468744688446894469044691446924469344694446954469644697446984469944700447014470244703447044470544706447074470844709447104471144712447134471444715447164471744718447194472044721447224472344724447254472644727447284472944730447314473244733447344473544736447374473844739447404474144742447434474444745447464474744748447494475044751447524475344754447554475644757447584475944760447614476244763447644476544766447674476844769447704477144772447734477444775447764477744778447794478044781447824478344784447854478644787447884478944790447914479244793447944479544796447974479844799448004480144802448034480444805448064480744808448094481044811448124481344814448154481644817448184481944820448214482244823448244482544826448274482844829448304483144832448334483444835448364483744838448394484044841448424484344844448454484644847448484484944850448514485244853448544485544856448574485844859448604486144862448634486444865448664486744868448694487044871448724487344874448754487644877448784487944880448814488244883448844488544886448874488844889448904489144892448934489444895448964489744898448994490044901449024490344904449054490644907449084490944910449114491244913449144491544916449174491844919449204492144922449234492444925449264492744928449294493044931449324493344934449354493644937449384493944940449414494244943449444494544946449474494844949449504495144952449534495444955449564495744958449594496044961449624496344964449654496644967449684496944970449714497244973449744497544976449774497844979449804498144982449834498444985449864498744988449894499044991449924499344994449954499644997449984499945000450014500245003450044500545006450074500845009450104501145012450134501445015450164501745018450194502045021450224502345024450254502645027450284502945030450314503245033450344503545036450374503845039450404504145042450434504445045450464504745048450494505045051450524505345054450554505645057450584505945060450614506245063450644506545066450674506845069450704507145072450734507445075450764507745078450794508045081450824508345084450854508645087450884508945090450914509245093450944509545096450974509845099451004510145102451034510445105451064510745108451094511045111451124511345114451154511645117451184511945120451214512245123451244512545126451274512845129451304513145132451334513445135451364513745138451394514045141451424514345144451454514645147451484514945150451514515245153451544515545156451574515845159451604516145162451634516445165451664516745168451694517045171451724517345174451754517645177451784517945180451814518245183451844518545186451874518845189451904519145192451934519445195451964519745198451994520045201452024520345204452054520645207452084520945210452114521245213452144521545216452174521845219452204522145222452234522445225452264522745228452294523045231452324523345234452354523645237452384523945240452414524245243452444524545246452474524845249452504525145252452534525445255452564525745258452594526045261452624526345264452654526645267452684526945270452714527245273452744527545276452774527845279452804528145282452834528445285452864528745288452894529045291452924529345294452954529645297452984529945300453014530245303453044530545306453074530845309453104531145312453134531445315453164531745318453194532045321453224532345324453254532645327453284532945330453314533245333453344533545336453374533845339453404534145342453434534445345453464534745348453494535045351453524535345354453554535645357453584535945360453614536245363453644536545366453674536845369453704537145372453734537445375453764537745378453794538045381453824538345384453854538645387453884538945390453914539245393453944539545396453974539845399454004540145402454034540445405454064540745408454094541045411454124541345414454154541645417454184541945420454214542245423454244542545426454274542845429454304543145432454334543445435454364543745438454394544045441454424544345444454454544645447454484544945450454514545245453454544545545456454574545845459454604546145462454634546445465454664546745468454694547045471454724547345474454754547645477454784547945480454814548245483454844548545486454874548845489454904549145492454934549445495454964549745498454994550045501455024550345504455054550645507455084550945510455114551245513455144551545516455174551845519455204552145522455234552445525455264552745528455294553045531455324553345534455354553645537455384553945540455414554245543455444554545546455474554845549455504555145552455534555445555455564555745558455594556045561455624556345564455654556645567455684556945570455714557245573455744557545576455774557845579455804558145582455834558445585455864558745588455894559045591455924559345594455954559645597455984559945600456014560245603456044560545606456074560845609456104561145612456134561445615456164561745618456194562045621456224562345624456254562645627456284562945630456314563245633456344563545636456374563845639456404564145642456434564445645456464564745648456494565045651456524565345654456554565645657456584565945660456614566245663456644566545666456674566845669456704567145672456734567445675456764567745678456794568045681456824568345684456854568645687456884568945690456914569245693456944569545696456974569845699457004570145702457034570445705457064570745708457094571045711457124571345714457154571645717457184571945720457214572245723457244572545726457274572845729457304573145732457334573445735457364573745738457394574045741457424574345744457454574645747457484574945750457514575245753457544575545756457574575845759457604576145762457634576445765457664576745768457694577045771457724577345774457754577645777457784577945780457814578245783457844578545786457874578845789457904579145792457934579445795457964579745798457994580045801458024580345804458054580645807458084580945810458114581245813458144581545816458174581845819458204582145822458234582445825458264582745828458294583045831458324583345834458354583645837458384583945840458414584245843458444584545846458474584845849458504585145852458534585445855458564585745858458594586045861458624586345864458654586645867458684586945870458714587245873458744587545876458774587845879458804588145882458834588445885458864588745888458894589045891458924589345894458954589645897458984589945900459014590245903459044590545906459074590845909459104591145912459134591445915459164591745918459194592045921459224592345924459254592645927459284592945930459314593245933459344593545936459374593845939459404594145942459434594445945459464594745948459494595045951459524595345954459554595645957459584595945960459614596245963459644596545966459674596845969459704597145972459734597445975459764597745978459794598045981459824598345984459854598645987459884598945990459914599245993459944599545996459974599845999460004600146002460034600446005460064600746008460094601046011460124601346014460154601646017460184601946020460214602246023460244602546026460274602846029460304603146032460334603446035460364603746038460394604046041460424604346044460454604646047460484604946050460514605246053460544605546056460574605846059460604606146062460634606446065460664606746068460694607046071460724607346074460754607646077460784607946080460814608246083460844608546086460874608846089460904609146092460934609446095460964609746098460994610046101461024610346104461054610646107461084610946110461114611246113461144611546116461174611846119461204612146122461234612446125461264612746128461294613046131461324613346134461354613646137461384613946140461414614246143461444614546146461474614846149461504615146152461534615446155461564615746158461594616046161461624616346164461654616646167461684616946170461714617246173461744617546176461774617846179461804618146182461834618446185461864618746188461894619046191461924619346194461954619646197461984619946200462014620246203462044620546206462074620846209462104621146212462134621446215462164621746218462194622046221462224622346224462254622646227462284622946230462314623246233462344623546236462374623846239462404624146242462434624446245462464624746248462494625046251462524625346254462554625646257462584625946260462614626246263462644626546266462674626846269462704627146272462734627446275462764627746278462794628046281462824628346284462854628646287462884628946290462914629246293462944629546296462974629846299463004630146302463034630446305463064630746308463094631046311463124631346314463154631646317463184631946320463214632246323463244632546326463274632846329463304633146332463334633446335463364633746338463394634046341463424634346344463454634646347463484634946350463514635246353463544635546356463574635846359463604636146362463634636446365463664636746368463694637046371463724637346374463754637646377463784637946380463814638246383463844638546386463874638846389463904639146392463934639446395463964639746398463994640046401464024640346404464054640646407464084640946410464114641246413464144641546416464174641846419464204642146422464234642446425464264642746428464294643046431464324643346434464354643646437464384643946440464414644246443464444644546446464474644846449464504645146452464534645446455464564645746458464594646046461464624646346464464654646646467464684646946470464714647246473464744647546476464774647846479464804648146482464834648446485464864648746488464894649046491464924649346494464954649646497464984649946500465014650246503465044650546506465074650846509465104651146512465134651446515465164651746518465194652046521465224652346524465254652646527465284652946530465314653246533465344653546536465374653846539465404654146542465434654446545465464654746548465494655046551465524655346554465554655646557465584655946560465614656246563465644656546566465674656846569465704657146572465734657446575465764657746578465794658046581465824658346584465854658646587465884658946590465914659246593465944659546596465974659846599466004660146602466034660446605466064660746608466094661046611466124661346614466154661646617466184661946620466214662246623466244662546626466274662846629466304663146632466334663446635466364663746638466394664046641466424664346644466454664646647466484664946650466514665246653466544665546656466574665846659466604666146662466634666446665466664666746668466694667046671466724667346674466754667646677466784667946680466814668246683466844668546686466874668846689466904669146692466934669446695466964669746698466994670046701467024670346704467054670646707467084670946710467114671246713467144671546716467174671846719467204672146722467234672446725467264672746728467294673046731467324673346734467354673646737467384673946740467414674246743467444674546746467474674846749467504675146752467534675446755467564675746758467594676046761467624676346764467654676646767467684676946770467714677246773467744677546776467774677846779467804678146782467834678446785467864678746788467894679046791467924679346794467954679646797467984679946800468014680246803468044680546806468074680846809468104681146812468134681446815468164681746818468194682046821468224682346824468254682646827468284682946830468314683246833468344683546836468374683846839468404684146842468434684446845468464684746848468494685046851468524685346854468554685646857468584685946860468614686246863468644686546866468674686846869468704687146872468734687446875468764687746878468794688046881468824688346884468854688646887468884688946890468914689246893468944689546896468974689846899469004690146902469034690446905469064690746908469094691046911469124691346914469154691646917469184691946920469214692246923469244692546926469274692846929469304693146932469334693446935469364693746938469394694046941469424694346944469454694646947469484694946950469514695246953469544695546956469574695846959469604696146962469634696446965469664696746968469694697046971469724697346974469754697646977469784697946980469814698246983469844698546986469874698846989469904699146992469934699446995469964699746998469994700047001470024700347004470054700647007470084700947010470114701247013470144701547016470174701847019470204702147022470234702447025470264702747028470294703047031470324703347034470354703647037470384703947040470414704247043470444704547046470474704847049470504705147052470534705447055470564705747058470594706047061470624706347064470654706647067470684706947070470714707247073470744707547076470774707847079470804708147082470834708447085470864708747088470894709047091470924709347094470954709647097470984709947100471014710247103471044710547106471074710847109471104711147112471134711447115471164711747118471194712047121471224712347124471254712647127471284712947130471314713247133471344713547136471374713847139471404714147142471434714447145471464714747148471494715047151471524715347154471554715647157471584715947160471614716247163471644716547166471674716847169471704717147172471734717447175471764717747178471794718047181471824718347184471854718647187471884718947190471914719247193471944719547196471974719847199472004720147202472034720447205472064720747208472094721047211472124721347214472154721647217472184721947220472214722247223472244722547226472274722847229472304723147232472334723447235472364723747238472394724047241472424724347244472454724647247472484724947250472514725247253472544725547256472574725847259472604726147262472634726447265472664726747268472694727047271472724727347274472754727647277472784727947280472814728247283472844728547286472874728847289472904729147292472934729447295472964729747298472994730047301473024730347304473054730647307473084730947310473114731247313473144731547316473174731847319473204732147322473234732447325473264732747328473294733047331473324733347334473354733647337473384733947340473414734247343473444734547346473474734847349473504735147352473534735447355473564735747358473594736047361473624736347364473654736647367473684736947370473714737247373473744737547376473774737847379473804738147382473834738447385473864738747388473894739047391473924739347394473954739647397473984739947400474014740247403474044740547406474074740847409474104741147412474134741447415474164741747418474194742047421474224742347424474254742647427474284742947430474314743247433474344743547436474374743847439474404744147442474434744447445474464744747448474494745047451474524745347454474554745647457474584745947460474614746247463474644746547466474674746847469474704747147472474734747447475474764747747478474794748047481474824748347484474854748647487474884748947490474914749247493474944749547496474974749847499475004750147502475034750447505475064750747508475094751047511475124751347514475154751647517475184751947520475214752247523475244752547526475274752847529475304753147532475334753447535475364753747538475394754047541475424754347544475454754647547475484754947550475514755247553475544755547556475574755847559475604756147562475634756447565475664756747568475694757047571475724757347574475754757647577475784757947580475814758247583475844758547586475874758847589475904759147592475934759447595475964759747598475994760047601476024760347604476054760647607476084760947610476114761247613476144761547616476174761847619476204762147622476234762447625476264762747628476294763047631476324763347634476354763647637476384763947640476414764247643476444764547646476474764847649476504765147652476534765447655476564765747658476594766047661476624766347664476654766647667476684766947670476714767247673476744767547676476774767847679476804768147682476834768447685476864768747688476894769047691476924769347694476954769647697476984769947700477014770247703477044770547706477074770847709477104771147712477134771447715477164771747718477194772047721477224772347724477254772647727477284772947730477314773247733477344773547736477374773847739477404774147742477434774447745477464774747748477494775047751477524775347754477554775647757477584775947760477614776247763477644776547766477674776847769477704777147772477734777447775477764777747778477794778047781477824778347784477854778647787477884778947790477914779247793477944779547796477974779847799478004780147802478034780447805478064780747808478094781047811478124781347814478154781647817478184781947820478214782247823478244782547826478274782847829478304783147832478334783447835478364783747838478394784047841478424784347844478454784647847478484784947850478514785247853478544785547856478574785847859478604786147862478634786447865478664786747868478694787047871478724787347874478754787647877478784787947880478814788247883478844788547886478874788847889478904789147892478934789447895478964789747898478994790047901479024790347904479054790647907479084790947910479114791247913479144791547916479174791847919479204792147922479234792447925479264792747928479294793047931479324793347934479354793647937479384793947940479414794247943479444794547946479474794847949479504795147952479534795447955479564795747958479594796047961479624796347964479654796647967479684796947970479714797247973479744797547976479774797847979479804798147982479834798447985479864798747988479894799047991479924799347994479954799647997479984799948000480014800248003480044800548006480074800848009480104801148012480134801448015480164801748018480194802048021480224802348024480254802648027480284802948030480314803248033480344803548036480374803848039480404804148042480434804448045480464804748048480494805048051480524805348054480554805648057480584805948060480614806248063480644806548066480674806848069480704807148072480734807448075480764807748078480794808048081480824808348084480854808648087480884808948090480914809248093480944809548096480974809848099481004810148102481034810448105481064810748108481094811048111481124811348114481154811648117481184811948120481214812248123481244812548126481274812848129481304813148132481334813448135481364813748138481394814048141481424814348144481454814648147481484814948150481514815248153481544815548156481574815848159481604816148162481634816448165481664816748168481694817048171481724817348174481754817648177481784817948180481814818248183481844818548186481874818848189481904819148192481934819448195481964819748198481994820048201482024820348204482054820648207482084820948210482114821248213482144821548216482174821848219482204822148222482234822448225482264822748228482294823048231482324823348234482354823648237482384823948240482414824248243482444824548246482474824848249482504825148252482534825448255482564825748258482594826048261482624826348264482654826648267482684826948270482714827248273482744827548276482774827848279482804828148282482834828448285482864828748288482894829048291482924829348294482954829648297482984829948300483014830248303483044830548306483074830848309483104831148312483134831448315483164831748318483194832048321483224832348324483254832648327483284832948330483314833248333483344833548336483374833848339483404834148342483434834448345483464834748348483494835048351483524835348354483554835648357483584835948360483614836248363483644836548366483674836848369483704837148372483734837448375483764837748378483794838048381483824838348384483854838648387483884838948390483914839248393483944839548396483974839848399484004840148402484034840448405484064840748408484094841048411484124841348414484154841648417484184841948420484214842248423484244842548426484274842848429484304843148432484334843448435484364843748438484394844048441484424844348444484454844648447484484844948450484514845248453484544845548456484574845848459484604846148462484634846448465484664846748468484694847048471484724847348474484754847648477484784847948480484814848248483484844848548486484874848848489484904849148492484934849448495484964849748498484994850048501485024850348504485054850648507485084850948510485114851248513485144851548516485174851848519485204852148522485234852448525485264852748528485294853048531485324853348534485354853648537485384853948540485414854248543485444854548546485474854848549485504855148552485534855448555485564855748558485594856048561485624856348564485654856648567485684856948570485714857248573485744857548576485774857848579485804858148582485834858448585485864858748588485894859048591485924859348594485954859648597485984859948600486014860248603486044860548606486074860848609486104861148612486134861448615486164861748618486194862048621486224862348624486254862648627486284862948630486314863248633486344863548636486374863848639486404864148642486434864448645486464864748648486494865048651486524865348654486554865648657486584865948660486614866248663486644866548666486674866848669486704867148672486734867448675486764867748678486794868048681486824868348684486854868648687486884868948690486914869248693486944869548696486974869848699487004870148702487034870448705487064870748708487094871048711487124871348714487154871648717487184871948720487214872248723487244872548726487274872848729487304873148732487334873448735487364873748738487394874048741487424874348744487454874648747487484874948750487514875248753487544875548756487574875848759487604876148762487634876448765487664876748768487694877048771487724877348774487754877648777487784877948780487814878248783487844878548786487874878848789487904879148792487934879448795487964879748798487994880048801488024880348804488054880648807488084880948810488114881248813488144881548816488174881848819488204882148822488234882448825488264882748828488294883048831488324883348834488354883648837488384883948840488414884248843488444884548846488474884848849488504885148852488534885448855488564885748858488594886048861488624886348864488654886648867488684886948870488714887248873488744887548876488774887848879488804888148882488834888448885488864888748888488894889048891488924889348894488954889648897488984889948900489014890248903489044890548906489074890848909489104891148912489134891448915489164891748918489194892048921489224892348924489254892648927489284892948930489314893248933489344893548936489374893848939489404894148942489434894448945489464894748948489494895048951489524895348954489554895648957489584895948960489614896248963489644896548966489674896848969489704897148972489734897448975489764897748978489794898048981489824898348984489854898648987489884898948990489914899248993489944899548996489974899848999490004900149002490034900449005490064900749008490094901049011490124901349014490154901649017490184901949020490214902249023490244902549026490274902849029490304903149032490334903449035490364903749038490394904049041490424904349044490454904649047490484904949050490514905249053490544905549056490574905849059490604906149062490634906449065490664906749068490694907049071490724907349074490754907649077490784907949080490814908249083490844908549086490874908849089490904909149092490934909449095490964909749098490994910049101491024910349104491054910649107491084910949110491114911249113491144911549116491174911849119491204912149122491234912449125491264912749128491294913049131491324913349134491354913649137491384913949140491414914249143491444914549146491474914849149491504915149152491534915449155491564915749158491594916049161491624916349164491654916649167491684916949170491714917249173491744917549176491774917849179491804918149182491834918449185491864918749188491894919049191491924919349194491954919649197491984919949200492014920249203492044920549206492074920849209492104921149212492134921449215492164921749218492194922049221492224922349224492254922649227492284922949230492314923249233492344923549236492374923849239492404924149242492434924449245492464924749248492494925049251492524925349254492554925649257492584925949260492614926249263492644926549266492674926849269492704927149272492734927449275492764927749278492794928049281492824928349284492854928649287492884928949290492914929249293492944929549296492974929849299493004930149302493034930449305493064930749308493094931049311493124931349314493154931649317493184931949320493214932249323493244932549326493274932849329493304933149332493334933449335493364933749338493394934049341493424934349344493454934649347493484934949350493514935249353493544935549356493574935849359493604936149362493634936449365493664936749368493694937049371493724937349374493754937649377493784937949380493814938249383493844938549386493874938849389493904939149392493934939449395493964939749398493994940049401494024940349404494054940649407494084940949410494114941249413494144941549416494174941849419494204942149422494234942449425494264942749428494294943049431494324943349434494354943649437494384943949440494414944249443494444944549446494474944849449494504945149452494534945449455494564945749458494594946049461494624946349464494654946649467494684946949470494714947249473494744947549476494774947849479494804948149482494834948449485494864948749488494894949049491494924949349494494954949649497494984949949500495014950249503495044950549506495074950849509495104951149512495134951449515495164951749518495194952049521495224952349524495254952649527495284952949530495314953249533495344953549536495374953849539495404954149542495434954449545495464954749548495494955049551495524955349554495554955649557495584955949560495614956249563495644956549566495674956849569495704957149572495734957449575495764957749578495794958049581495824958349584495854958649587495884958949590495914959249593495944959549596495974959849599496004960149602496034960449605496064960749608496094961049611496124961349614496154961649617496184961949620496214962249623496244962549626496274962849629496304963149632496334963449635496364963749638496394964049641496424964349644496454964649647496484964949650496514965249653496544965549656496574965849659496604966149662496634966449665496664966749668496694967049671496724967349674496754967649677496784967949680496814968249683496844968549686496874968849689496904969149692496934969449695496964969749698496994970049701497024970349704497054970649707497084970949710497114971249713497144971549716497174971849719497204972149722497234972449725497264972749728497294973049731497324973349734497354973649737497384973949740497414974249743497444974549746497474974849749497504975149752497534975449755497564975749758497594976049761497624976349764497654976649767497684976949770497714977249773497744977549776497774977849779497804978149782497834978449785497864978749788497894979049791497924979349794497954979649797497984979949800498014980249803498044980549806498074980849809498104981149812498134981449815498164981749818498194982049821498224982349824498254982649827498284982949830498314983249833498344983549836498374983849839498404984149842498434984449845498464984749848498494985049851498524985349854498554985649857498584985949860498614986249863498644986549866498674986849869498704987149872498734987449875498764987749878498794988049881498824988349884498854988649887498884988949890498914989249893498944989549896498974989849899499004990149902499034990449905499064990749908499094991049911499124991349914499154991649917499184991949920499214992249923499244992549926499274992849929499304993149932499334993449935499364993749938499394994049941499424994349944499454994649947499484994949950499514995249953499544995549956499574995849959499604996149962499634996449965499664996749968499694997049971499724997349974499754997649977499784997949980499814998249983499844998549986499874998849989499904999149992499934999449995499964999749998499995000050001500025000350004500055000650007500085000950010500115001250013500145001550016500175001850019500205002150022500235002450025500265002750028500295003050031500325003350034500355003650037500385003950040500415004250043500445004550046500475004850049500505005150052500535005450055500565005750058500595006050061500625006350064500655006650067500685006950070500715007250073500745007550076500775007850079500805008150082500835008450085500865008750088500895009050091500925009350094500955009650097500985009950100501015010250103501045010550106501075010850109501105011150112501135011450115501165011750118501195012050121501225012350124501255012650127501285012950130501315013250133501345013550136501375013850139501405014150142501435014450145501465014750148501495015050151501525015350154501555015650157501585015950160501615016250163501645016550166501675016850169501705017150172501735017450175501765017750178501795018050181501825018350184501855018650187501885018950190501915019250193501945019550196501975019850199502005020150202502035020450205502065020750208502095021050211502125021350214502155021650217502185021950220502215022250223502245022550226502275022850229502305023150232502335023450235502365023750238502395024050241502425024350244502455024650247502485024950250502515025250253502545025550256502575025850259502605026150262502635026450265502665026750268502695027050271502725027350274502755027650277502785027950280502815028250283502845028550286502875028850289502905029150292502935029450295502965029750298502995030050301503025030350304503055030650307503085030950310503115031250313503145031550316503175031850319503205032150322503235032450325503265032750328503295033050331503325033350334503355033650337503385033950340503415034250343503445034550346503475034850349503505035150352503535035450355503565035750358503595036050361503625036350364503655036650367503685036950370503715037250373503745037550376503775037850379503805038150382503835038450385503865038750388503895039050391503925039350394503955039650397503985039950400504015040250403504045040550406504075040850409504105041150412504135041450415504165041750418504195042050421504225042350424504255042650427504285042950430504315043250433504345043550436504375043850439504405044150442504435044450445504465044750448504495045050451504525045350454504555045650457504585045950460504615046250463504645046550466504675046850469504705047150472504735047450475504765047750478504795048050481504825048350484504855048650487504885048950490504915049250493504945049550496504975049850499505005050150502505035050450505505065050750508505095051050511505125051350514505155051650517505185051950520505215052250523505245052550526505275052850529505305053150532505335053450535505365053750538505395054050541505425054350544505455054650547505485054950550505515055250553505545055550556505575055850559505605056150562505635056450565505665056750568505695057050571505725057350574505755057650577505785057950580505815058250583505845058550586505875058850589505905059150592505935059450595505965059750598505995060050601506025060350604506055060650607506085060950610506115061250613506145061550616506175061850619506205062150622506235062450625506265062750628506295063050631506325063350634506355063650637506385063950640506415064250643506445064550646506475064850649506505065150652506535065450655506565065750658506595066050661506625066350664506655066650667506685066950670506715067250673506745067550676506775067850679506805068150682506835068450685506865068750688506895069050691506925069350694506955069650697506985069950700507015070250703507045070550706507075070850709507105071150712507135071450715507165071750718507195072050721507225072350724507255072650727507285072950730507315073250733507345073550736507375073850739507405074150742507435074450745507465074750748507495075050751507525075350754507555075650757507585075950760507615076250763507645076550766507675076850769507705077150772507735077450775507765077750778507795078050781507825078350784507855078650787507885078950790507915079250793507945079550796507975079850799508005080150802508035080450805508065080750808508095081050811508125081350814508155081650817508185081950820508215082250823508245082550826508275082850829508305083150832508335083450835508365083750838508395084050841508425084350844508455084650847508485084950850508515085250853508545085550856508575085850859508605086150862508635086450865508665086750868508695087050871508725087350874508755087650877508785087950880508815088250883508845088550886508875088850889508905089150892508935089450895508965089750898508995090050901509025090350904509055090650907509085090950910509115091250913509145091550916509175091850919509205092150922509235092450925509265092750928509295093050931509325093350934509355093650937509385093950940509415094250943509445094550946509475094850949509505095150952509535095450955509565095750958509595096050961509625096350964509655096650967509685096950970509715097250973509745097550976509775097850979509805098150982509835098450985509865098750988509895099050991509925099350994509955099650997509985099951000510015100251003510045100551006510075100851009510105101151012510135101451015510165101751018510195102051021510225102351024510255102651027510285102951030510315103251033510345103551036510375103851039510405104151042510435104451045510465104751048510495105051051510525105351054510555105651057510585105951060510615106251063510645106551066510675106851069510705107151072510735107451075510765107751078510795108051081510825108351084510855108651087510885108951090510915109251093510945109551096510975109851099511005110151102511035110451105511065110751108511095111051111511125111351114511155111651117511185111951120511215112251123511245112551126511275112851129511305113151132511335113451135511365113751138511395114051141511425114351144511455114651147511485114951150511515115251153511545115551156511575115851159511605116151162511635116451165511665116751168511695117051171511725117351174511755117651177511785117951180511815118251183511845118551186511875118851189511905119151192511935119451195511965119751198511995120051201512025120351204512055120651207512085120951210512115121251213512145121551216512175121851219512205122151222512235122451225512265122751228512295123051231512325123351234512355123651237512385123951240512415124251243512445124551246512475124851249512505125151252512535125451255512565125751258512595126051261512625126351264512655126651267512685126951270512715127251273512745127551276512775127851279512805128151282512835128451285512865128751288512895129051291512925129351294512955129651297512985129951300513015130251303513045130551306513075130851309513105131151312513135131451315513165131751318513195132051321513225132351324513255132651327513285132951330513315133251333513345133551336513375133851339513405134151342513435134451345513465134751348513495135051351513525135351354513555135651357513585135951360513615136251363513645136551366513675136851369513705137151372513735137451375513765137751378513795138051381513825138351384513855138651387513885138951390513915139251393513945139551396513975139851399514005140151402514035140451405514065140751408514095141051411514125141351414514155141651417514185141951420514215142251423514245142551426514275142851429514305143151432514335143451435514365143751438514395144051441514425144351444514455144651447514485144951450514515145251453514545145551456514575145851459514605146151462514635146451465514665146751468514695147051471514725147351474514755147651477514785147951480514815148251483514845148551486514875148851489514905149151492514935149451495514965149751498514995150051501515025150351504515055150651507515085150951510515115151251513515145151551516515175151851519515205152151522515235152451525515265152751528515295153051531515325153351534515355153651537515385153951540515415154251543515445154551546515475154851549515505155151552515535155451555515565155751558515595156051561515625156351564515655156651567515685156951570515715157251573515745157551576515775157851579515805158151582515835158451585515865158751588515895159051591515925159351594515955159651597515985159951600516015160251603516045160551606516075160851609516105161151612516135161451615516165161751618516195162051621516225162351624516255162651627516285162951630516315163251633516345163551636516375163851639516405164151642516435164451645516465164751648516495165051651516525165351654516555165651657516585165951660516615166251663516645166551666516675166851669516705167151672516735167451675516765167751678516795168051681516825168351684516855168651687516885168951690516915169251693516945169551696516975169851699517005170151702517035170451705517065170751708517095171051711517125171351714517155171651717517185171951720517215172251723517245172551726517275172851729517305173151732517335173451735517365173751738517395174051741517425174351744517455174651747517485174951750517515175251753517545175551756517575175851759517605176151762517635176451765517665176751768517695177051771517725177351774517755177651777517785177951780517815178251783517845178551786517875178851789517905179151792517935179451795517965179751798517995180051801518025180351804518055180651807518085180951810518115181251813518145181551816518175181851819518205182151822518235182451825518265182751828518295183051831518325183351834518355183651837518385183951840518415184251843518445184551846518475184851849518505185151852518535185451855518565185751858518595186051861518625186351864518655186651867518685186951870518715187251873518745187551876518775187851879518805188151882518835188451885518865188751888518895189051891518925189351894518955189651897518985189951900519015190251903519045190551906519075190851909519105191151912519135191451915519165191751918519195192051921519225192351924519255192651927519285192951930519315193251933519345193551936519375193851939519405194151942519435194451945519465194751948519495195051951519525195351954519555195651957519585195951960519615196251963519645196551966519675196851969519705197151972519735197451975519765197751978519795198051981519825198351984519855198651987519885198951990519915199251993519945199551996519975199851999520005200152002520035200452005520065200752008520095201052011520125201352014520155201652017520185201952020520215202252023520245202552026520275202852029520305203152032520335203452035520365203752038520395204052041520425204352044520455204652047520485204952050520515205252053520545205552056520575205852059520605206152062520635206452065520665206752068520695207052071520725207352074520755207652077520785207952080520815208252083520845208552086520875208852089520905209152092520935209452095520965209752098520995210052101521025210352104521055210652107521085210952110521115211252113521145211552116521175211852119521205212152122521235212452125521265212752128521295213052131521325213352134521355213652137521385213952140521415214252143521445214552146521475214852149521505215152152521535215452155521565215752158521595216052161521625216352164521655216652167521685216952170521715217252173521745217552176521775217852179521805218152182521835218452185521865218752188521895219052191521925219352194521955219652197521985219952200522015220252203522045220552206522075220852209522105221152212522135221452215522165221752218522195222052221522225222352224522255222652227522285222952230522315223252233522345223552236522375223852239522405224152242522435224452245522465224752248522495225052251522525225352254522555225652257522585225952260522615226252263522645226552266522675226852269522705227152272522735227452275522765227752278522795228052281522825228352284522855228652287522885228952290522915229252293522945229552296522975229852299523005230152302523035230452305523065230752308523095231052311523125231352314523155231652317523185231952320523215232252323523245232552326523275232852329523305233152332523335233452335523365233752338523395234052341523425234352344523455234652347523485234952350523515235252353523545235552356523575235852359523605236152362523635236452365523665236752368523695237052371523725237352374523755237652377523785237952380523815238252383523845238552386523875238852389523905239152392523935239452395523965239752398523995240052401524025240352404524055240652407524085240952410524115241252413524145241552416524175241852419524205242152422524235242452425524265242752428524295243052431524325243352434524355243652437524385243952440524415244252443524445244552446524475244852449524505245152452524535245452455524565245752458524595246052461524625246352464524655246652467524685246952470524715247252473524745247552476524775247852479524805248152482524835248452485524865248752488524895249052491524925249352494524955249652497524985249952500525015250252503525045250552506525075250852509525105251152512525135251452515525165251752518525195252052521525225252352524525255252652527525285252952530525315253252533525345253552536525375253852539525405254152542525435254452545525465254752548525495255052551525525255352554525555255652557525585255952560525615256252563525645256552566525675256852569525705257152572525735257452575525765257752578525795258052581525825258352584525855258652587525885258952590525915259252593525945259552596525975259852599526005260152602526035260452605526065260752608526095261052611526125261352614526155261652617526185261952620526215262252623526245262552626526275262852629526305263152632526335263452635526365263752638526395264052641526425264352644526455264652647526485264952650526515265252653526545265552656526575265852659526605266152662526635266452665526665266752668526695267052671526725267352674526755267652677526785267952680526815268252683526845268552686526875268852689526905269152692526935269452695526965269752698526995270052701527025270352704527055270652707527085270952710527115271252713527145271552716527175271852719527205272152722527235272452725527265272752728527295273052731527325273352734527355273652737527385273952740527415274252743527445274552746527475274852749527505275152752527535275452755527565275752758527595276052761527625276352764527655276652767527685276952770527715277252773527745277552776527775277852779527805278152782527835278452785527865278752788527895279052791527925279352794527955279652797527985279952800528015280252803528045280552806528075280852809528105281152812528135281452815528165281752818528195282052821528225282352824528255282652827528285282952830528315283252833528345283552836528375283852839528405284152842528435284452845528465284752848528495285052851528525285352854528555285652857528585285952860528615286252863528645286552866528675286852869528705287152872528735287452875528765287752878528795288052881528825288352884528855288652887528885288952890528915289252893528945289552896528975289852899529005290152902529035290452905529065290752908529095291052911529125291352914529155291652917529185291952920529215292252923529245292552926529275292852929529305293152932529335293452935529365293752938529395294052941529425294352944529455294652947529485294952950529515295252953529545295552956529575295852959529605296152962529635296452965529665296752968529695297052971529725297352974529755297652977529785297952980529815298252983529845298552986529875298852989529905299152992529935299452995529965299752998529995300053001530025300353004530055300653007530085300953010530115301253013530145301553016530175301853019530205302153022530235302453025530265302753028530295303053031530325303353034530355303653037530385303953040530415304253043530445304553046530475304853049530505305153052530535305453055530565305753058530595306053061530625306353064530655306653067530685306953070530715307253073530745307553076530775307853079530805308153082530835308453085530865308753088530895309053091530925309353094530955309653097530985309953100531015310253103531045310553106531075310853109531105311153112531135311453115531165311753118531195312053121531225312353124531255312653127531285312953130531315313253133531345313553136531375313853139531405314153142531435314453145531465314753148531495315053151531525315353154531555315653157531585315953160531615316253163531645316553166531675316853169531705317153172531735317453175531765317753178531795318053181531825318353184531855318653187531885318953190531915319253193531945319553196531975319853199532005320153202532035320453205532065320753208532095321053211532125321353214532155321653217532185321953220532215322253223532245322553226532275322853229532305323153232532335323453235532365323753238532395324053241532425324353244532455324653247532485324953250532515325253253532545325553256532575325853259532605326153262532635326453265532665326753268532695327053271532725327353274532755327653277532785327953280532815328253283532845328553286532875328853289532905329153292532935329453295532965329753298532995330053301533025330353304533055330653307533085330953310533115331253313533145331553316533175331853319533205332153322533235332453325533265332753328533295333053331533325333353334533355333653337533385333953340533415334253343533445334553346533475334853349533505335153352533535335453355533565335753358533595336053361533625336353364533655336653367533685336953370533715337253373533745337553376533775337853379533805338153382533835338453385533865338753388533895339053391533925339353394533955339653397533985339953400534015340253403534045340553406534075340853409534105341153412534135341453415534165341753418534195342053421534225342353424534255342653427534285342953430534315343253433534345343553436534375343853439534405344153442534435344453445534465344753448534495345053451534525345353454534555345653457534585345953460534615346253463534645346553466534675346853469534705347153472534735347453475534765347753478534795348053481534825348353484534855348653487534885348953490534915349253493534945349553496534975349853499535005350153502535035350453505535065350753508535095351053511535125351353514535155351653517535185351953520535215352253523535245352553526535275352853529535305353153532535335353453535535365353753538535395354053541535425354353544535455354653547535485354953550535515355253553535545355553556535575355853559535605356153562535635356453565535665356753568535695357053571535725357353574535755357653577535785357953580535815358253583535845358553586535875358853589535905359153592535935359453595535965359753598535995360053601536025360353604536055360653607536085360953610536115361253613536145361553616536175361853619536205362153622536235362453625536265362753628536295363053631536325363353634536355363653637536385363953640536415364253643536445364553646536475364853649536505365153652536535365453655536565365753658536595366053661536625366353664536655366653667536685366953670536715367253673536745367553676536775367853679536805368153682536835368453685536865368753688536895369053691536925369353694536955369653697536985369953700537015370253703537045370553706537075370853709537105371153712537135371453715537165371753718537195372053721537225372353724537255372653727537285372953730537315373253733537345373553736537375373853739537405374153742537435374453745537465374753748537495375053751537525375353754537555375653757537585375953760537615376253763537645376553766537675376853769537705377153772537735377453775537765377753778537795378053781537825378353784537855378653787537885378953790537915379253793537945379553796537975379853799538005380153802538035380453805538065380753808538095381053811538125381353814538155381653817538185381953820538215382253823538245382553826538275382853829538305383153832538335383453835538365383753838538395384053841538425384353844538455384653847538485384953850538515385253853538545385553856538575385853859538605386153862538635386453865538665386753868538695387053871538725387353874538755387653877538785387953880538815388253883538845388553886538875388853889538905389153892538935389453895538965389753898538995390053901539025390353904539055390653907539085390953910539115391253913539145391553916539175391853919539205392153922539235392453925539265392753928539295393053931539325393353934539355393653937539385393953940539415394253943539445394553946539475394853949539505395153952539535395453955539565395753958539595396053961539625396353964539655396653967539685396953970539715397253973539745397553976539775397853979539805398153982539835398453985539865398753988539895399053991539925399353994539955399653997539985399954000540015400254003540045400554006540075400854009540105401154012540135401454015540165401754018540195402054021540225402354024540255402654027540285402954030540315403254033540345403554036540375403854039540405404154042540435404454045540465404754048540495405054051540525405354054540555405654057540585405954060540615406254063540645406554066540675406854069540705407154072540735407454075540765407754078540795408054081540825408354084540855408654087540885408954090540915409254093540945409554096540975409854099541005410154102541035410454105541065410754108541095411054111541125411354114541155411654117541185411954120541215412254123541245412554126541275412854129541305413154132541335413454135541365413754138541395414054141541425414354144541455414654147541485414954150541515415254153541545415554156541575415854159541605416154162541635416454165541665416754168541695417054171541725417354174541755417654177541785417954180541815418254183541845418554186541875418854189541905419154192541935419454195541965419754198541995420054201542025420354204542055420654207542085420954210542115421254213542145421554216542175421854219542205422154222542235422454225542265422754228542295423054231542325423354234542355423654237542385423954240542415424254243542445424554246542475424854249542505425154252542535425454255542565425754258542595426054261542625426354264542655426654267542685426954270542715427254273542745427554276542775427854279542805428154282542835428454285542865428754288542895429054291542925429354294542955429654297542985429954300543015430254303543045430554306543075430854309543105431154312543135431454315543165431754318543195432054321543225432354324543255432654327543285432954330543315433254333543345433554336543375433854339543405434154342543435434454345543465434754348543495435054351543525435354354543555435654357543585435954360543615436254363543645436554366543675436854369543705437154372543735437454375543765437754378543795438054381543825438354384543855438654387543885438954390543915439254393543945439554396543975439854399544005440154402544035440454405544065440754408544095441054411544125441354414544155441654417544185441954420544215442254423544245442554426544275442854429544305443154432544335443454435544365443754438544395444054441544425444354444544455444654447544485444954450544515445254453544545445554456544575445854459544605446154462544635446454465544665446754468544695447054471544725447354474544755447654477544785447954480544815448254483544845448554486544875448854489544905449154492544935449454495544965449754498544995450054501545025450354504545055450654507545085450954510545115451254513545145451554516545175451854519545205452154522545235452454525545265452754528545295453054531545325453354534545355453654537545385453954540545415454254543545445454554546545475454854549545505455154552545535455454555545565455754558545595456054561545625456354564545655456654567545685456954570545715457254573545745457554576545775457854579545805458154582545835458454585545865458754588545895459054591545925459354594545955459654597545985459954600546015460254603546045460554606546075460854609546105461154612546135461454615546165461754618546195462054621546225462354624546255462654627546285462954630546315463254633546345463554636546375463854639546405464154642546435464454645546465464754648546495465054651546525465354654546555465654657546585465954660546615466254663546645466554666546675466854669546705467154672546735467454675546765467754678546795468054681546825468354684546855468654687546885468954690546915469254693546945469554696546975469854699547005470154702547035470454705547065470754708547095471054711547125471354714547155471654717547185471954720547215472254723547245472554726547275472854729547305473154732547335473454735547365473754738547395474054741547425474354744547455474654747547485474954750547515475254753547545475554756547575475854759547605476154762547635476454765547665476754768547695477054771547725477354774547755477654777547785477954780547815478254783547845478554786547875478854789547905479154792547935479454795547965479754798547995480054801548025480354804548055480654807548085480954810548115481254813548145481554816548175481854819548205482154822548235482454825548265482754828548295483054831548325483354834548355483654837548385483954840548415484254843548445484554846548475484854849548505485154852548535485454855548565485754858548595486054861548625486354864548655486654867548685486954870548715487254873548745487554876548775487854879548805488154882548835488454885548865488754888548895489054891548925489354894548955489654897548985489954900549015490254903549045490554906549075490854909549105491154912549135491454915549165491754918549195492054921549225492354924549255492654927549285492954930549315493254933549345493554936549375493854939549405494154942549435494454945549465494754948549495495054951549525495354954549555495654957549585495954960549615496254963549645496554966549675496854969549705497154972549735497454975549765497754978549795498054981549825498354984549855498654987549885498954990549915499254993549945499554996549975499854999550005500155002550035500455005550065500755008550095501055011550125501355014550155501655017550185501955020550215502255023550245502555026550275502855029550305503155032550335503455035550365503755038550395504055041550425504355044550455504655047550485504955050550515505255053550545505555056550575505855059550605506155062550635506455065550665506755068550695507055071550725507355074550755507655077550785507955080550815508255083550845508555086550875508855089550905509155092550935509455095550965509755098550995510055101551025510355104551055510655107551085510955110551115511255113551145511555116551175511855119551205512155122551235512455125551265512755128551295513055131551325513355134551355513655137551385513955140551415514255143551445514555146551475514855149551505515155152551535515455155551565515755158551595516055161551625516355164551655516655167551685516955170551715517255173551745517555176551775517855179551805518155182551835518455185551865518755188551895519055191551925519355194551955519655197551985519955200552015520255203552045520555206552075520855209552105521155212552135521455215552165521755218552195522055221552225522355224552255522655227552285522955230552315523255233552345523555236552375523855239552405524155242552435524455245552465524755248552495525055251552525525355254552555525655257552585525955260552615526255263552645526555266552675526855269552705527155272552735527455275552765527755278552795528055281552825528355284552855528655287552885528955290552915529255293552945529555296552975529855299553005530155302553035530455305553065530755308553095531055311553125531355314553155531655317553185531955320553215532255323553245532555326553275532855329553305533155332553335533455335553365533755338553395534055341553425534355344553455534655347553485534955350553515535255353553545535555356553575535855359553605536155362553635536455365553665536755368553695537055371553725537355374553755537655377553785537955380553815538255383553845538555386553875538855389553905539155392553935539455395553965539755398553995540055401554025540355404554055540655407554085540955410554115541255413554145541555416554175541855419554205542155422554235542455425554265542755428554295543055431554325543355434554355543655437554385543955440554415544255443554445544555446554475544855449554505545155452554535545455455554565545755458554595546055461554625546355464554655546655467554685546955470554715547255473554745547555476554775547855479554805548155482554835548455485554865548755488554895549055491554925549355494554955549655497554985549955500555015550255503555045550555506555075550855509555105551155512555135551455515555165551755518555195552055521555225552355524555255552655527555285552955530555315553255533555345553555536555375553855539555405554155542555435554455545555465554755548555495555055551555525555355554555555555655557555585555955560555615556255563555645556555566555675556855569555705557155572555735557455575555765557755578555795558055581555825558355584555855558655587555885558955590555915559255593555945559555596555975559855599556005560155602556035560455605556065560755608556095561055611556125561355614556155561655617556185561955620556215562255623556245562555626556275562855629556305563155632556335563455635556365563755638556395564055641556425564355644556455564655647556485564955650556515565255653556545565555656556575565855659556605566155662556635566455665556665566755668556695567055671556725567355674556755567655677556785567955680556815568255683556845568555686556875568855689556905569155692556935569455695556965569755698556995570055701557025570355704557055570655707557085570955710557115571255713557145571555716557175571855719557205572155722557235572455725557265572755728557295573055731557325573355734557355573655737557385573955740557415574255743557445574555746557475574855749557505575155752557535575455755557565575755758557595576055761557625576355764557655576655767557685576955770557715577255773557745577555776557775577855779557805578155782557835578455785557865578755788557895579055791557925579355794557955579655797557985579955800558015580255803558045580555806558075580855809558105581155812558135581455815558165581755818558195582055821558225582355824558255582655827558285582955830558315583255833558345583555836558375583855839558405584155842558435584455845558465584755848558495585055851558525585355854558555585655857558585585955860558615586255863558645586555866558675586855869558705587155872558735587455875558765587755878558795588055881558825588355884558855588655887558885588955890558915589255893558945589555896558975589855899559005590155902559035590455905559065590755908559095591055911559125591355914559155591655917559185591955920559215592255923559245592555926559275592855929559305593155932559335593455935559365593755938559395594055941559425594355944559455594655947559485594955950559515595255953559545595555956559575595855959559605596155962559635596455965559665596755968559695597055971559725597355974559755597655977559785597955980559815598255983559845598555986559875598855989559905599155992559935599455995559965599755998559995600056001560025600356004560055600656007560085600956010560115601256013560145601556016560175601856019560205602156022560235602456025560265602756028560295603056031560325603356034560355603656037560385603956040560415604256043560445604556046560475604856049560505605156052560535605456055560565605756058560595606056061560625606356064560655606656067560685606956070560715607256073560745607556076560775607856079560805608156082560835608456085560865608756088560895609056091560925609356094560955609656097560985609956100561015610256103561045610556106561075610856109561105611156112561135611456115561165611756118561195612056121561225612356124561255612656127561285612956130561315613256133561345613556136561375613856139561405614156142561435614456145561465614756148561495615056151561525615356154561555615656157561585615956160561615616256163561645616556166561675616856169561705617156172561735617456175561765617756178561795618056181561825618356184561855618656187561885618956190561915619256193561945619556196561975619856199562005620156202562035620456205562065620756208562095621056211562125621356214562155621656217562185621956220562215622256223562245622556226562275622856229562305623156232562335623456235562365623756238562395624056241562425624356244562455624656247562485624956250562515625256253562545625556256562575625856259562605626156262562635626456265562665626756268562695627056271562725627356274562755627656277562785627956280562815628256283562845628556286562875628856289562905629156292562935629456295562965629756298562995630056301563025630356304563055630656307563085630956310563115631256313563145631556316563175631856319563205632156322563235632456325563265632756328563295633056331563325633356334563355633656337563385633956340563415634256343563445634556346563475634856349563505635156352563535635456355563565635756358563595636056361563625636356364563655636656367563685636956370563715637256373563745637556376563775637856379563805638156382563835638456385563865638756388563895639056391563925639356394563955639656397563985639956400564015640256403564045640556406564075640856409564105641156412564135641456415564165641756418564195642056421564225642356424564255642656427564285642956430564315643256433564345643556436564375643856439564405644156442564435644456445564465644756448564495645056451564525645356454564555645656457564585645956460564615646256463564645646556466564675646856469564705647156472564735647456475564765647756478564795648056481564825648356484564855648656487564885648956490564915649256493564945649556496564975649856499565005650156502565035650456505565065650756508565095651056511565125651356514565155651656517565185651956520565215652256523565245652556526565275652856529565305653156532565335653456535565365653756538565395654056541565425654356544565455654656547565485654956550565515655256553565545655556556565575655856559565605656156562565635656456565565665656756568565695657056571565725657356574565755657656577565785657956580565815658256583565845658556586565875658856589565905659156592565935659456595565965659756598565995660056601566025660356604566055660656607566085660956610566115661256613566145661556616566175661856619566205662156622566235662456625566265662756628566295663056631566325663356634566355663656637566385663956640566415664256643566445664556646566475664856649566505665156652566535665456655566565665756658566595666056661566625666356664566655666656667566685666956670566715667256673566745667556676566775667856679566805668156682566835668456685566865668756688566895669056691566925669356694566955669656697566985669956700567015670256703567045670556706567075670856709567105671156712567135671456715567165671756718567195672056721567225672356724567255672656727567285672956730567315673256733567345673556736567375673856739567405674156742567435674456745567465674756748567495675056751567525675356754567555675656757567585675956760567615676256763567645676556766567675676856769567705677156772567735677456775567765677756778567795678056781567825678356784567855678656787567885678956790567915679256793567945679556796567975679856799568005680156802568035680456805568065680756808568095681056811568125681356814568155681656817568185681956820568215682256823568245682556826568275682856829568305683156832568335683456835568365683756838568395684056841568425684356844568455684656847568485684956850568515685256853568545685556856568575685856859568605686156862568635686456865568665686756868568695687056871568725687356874568755687656877568785687956880568815688256883568845688556886568875688856889568905689156892568935689456895568965689756898568995690056901569025690356904569055690656907569085690956910569115691256913569145691556916569175691856919569205692156922569235692456925569265692756928569295693056931569325693356934569355693656937569385693956940569415694256943569445694556946569475694856949569505695156952569535695456955569565695756958569595696056961569625696356964569655696656967569685696956970569715697256973569745697556976569775697856979569805698156982569835698456985569865698756988569895699056991569925699356994569955699656997569985699957000570015700257003570045700557006570075700857009570105701157012570135701457015570165701757018570195702057021570225702357024570255702657027570285702957030570315703257033570345703557036570375703857039570405704157042570435704457045570465704757048570495705057051570525705357054570555705657057570585705957060570615706257063570645706557066570675706857069570705707157072570735707457075570765707757078570795708057081570825708357084570855708657087570885708957090570915709257093570945709557096570975709857099571005710157102571035710457105571065710757108571095711057111571125711357114571155711657117571185711957120571215712257123571245712557126571275712857129571305713157132571335713457135571365713757138571395714057141571425714357144571455714657147571485714957150571515715257153571545715557156571575715857159571605716157162571635716457165571665716757168571695717057171571725717357174571755717657177571785717957180571815718257183571845718557186571875718857189571905719157192571935719457195571965719757198571995720057201572025720357204572055720657207572085720957210572115721257213572145721557216572175721857219572205722157222572235722457225572265722757228572295723057231572325723357234572355723657237572385723957240572415724257243572445724557246572475724857249572505725157252572535725457255572565725757258572595726057261572625726357264572655726657267572685726957270572715727257273572745727557276572775727857279572805728157282572835728457285572865728757288572895729057291572925729357294572955729657297572985729957300573015730257303573045730557306573075730857309573105731157312573135731457315573165731757318573195732057321573225732357324573255732657327573285732957330573315733257333573345733557336573375733857339573405734157342573435734457345573465734757348573495735057351573525735357354573555735657357573585735957360573615736257363573645736557366573675736857369573705737157372573735737457375573765737757378573795738057381573825738357384573855738657387573885738957390573915739257393573945739557396573975739857399574005740157402574035740457405574065740757408574095741057411574125741357414574155741657417574185741957420574215742257423574245742557426574275742857429574305743157432574335743457435574365743757438574395744057441574425744357444574455744657447574485744957450574515745257453574545745557456574575745857459574605746157462574635746457465574665746757468574695747057471574725747357474574755747657477574785747957480574815748257483574845748557486574875748857489574905749157492574935749457495574965749757498574995750057501575025750357504575055750657507575085750957510575115751257513575145751557516575175751857519575205752157522575235752457525575265752757528575295753057531575325753357534575355753657537575385753957540575415754257543575445754557546575475754857549575505755157552575535755457555575565755757558575595756057561575625756357564575655756657567575685756957570575715757257573575745757557576575775757857579575805758157582575835758457585575865758757588575895759057591575925759357594575955759657597575985759957600576015760257603576045760557606576075760857609576105761157612576135761457615576165761757618576195762057621576225762357624576255762657627576285762957630576315763257633576345763557636576375763857639576405764157642576435764457645576465764757648576495765057651576525765357654576555765657657576585765957660576615766257663576645766557666576675766857669576705767157672576735767457675576765767757678576795768057681576825768357684576855768657687576885768957690576915769257693576945769557696576975769857699577005770157702577035770457705577065770757708577095771057711577125771357714577155771657717577185771957720577215772257723577245772557726577275772857729577305773157732577335773457735577365773757738577395774057741577425774357744577455774657747577485774957750577515775257753577545775557756577575775857759577605776157762577635776457765577665776757768577695777057771577725777357774577755777657777577785777957780577815778257783577845778557786577875778857789577905779157792577935779457795577965779757798577995780057801578025780357804578055780657807578085780957810578115781257813578145781557816578175781857819578205782157822578235782457825578265782757828578295783057831578325783357834578355783657837578385783957840578415784257843578445784557846578475784857849578505785157852578535785457855578565785757858578595786057861578625786357864578655786657867578685786957870578715787257873578745787557876578775787857879578805788157882578835788457885578865788757888578895789057891578925789357894578955789657897578985789957900579015790257903579045790557906579075790857909579105791157912579135791457915579165791757918579195792057921579225792357924579255792657927579285792957930579315793257933579345793557936579375793857939579405794157942579435794457945579465794757948579495795057951579525795357954579555795657957579585795957960579615796257963579645796557966579675796857969579705797157972579735797457975579765797757978579795798057981579825798357984579855798657987579885798957990579915799257993579945799557996579975799857999580005800158002580035800458005580065800758008580095801058011580125801358014580155801658017580185801958020580215802258023580245802558026580275802858029580305803158032580335803458035580365803758038580395804058041580425804358044580455804658047580485804958050580515805258053580545805558056580575805858059580605806158062580635806458065580665806758068580695807058071580725807358074580755807658077580785807958080580815808258083580845808558086580875808858089580905809158092580935809458095580965809758098580995810058101581025810358104581055810658107581085810958110581115811258113581145811558116581175811858119581205812158122581235812458125581265812758128581295813058131581325813358134581355813658137581385813958140581415814258143581445814558146581475814858149581505815158152581535815458155581565815758158581595816058161581625816358164581655816658167581685816958170581715817258173581745817558176581775817858179581805818158182581835818458185581865818758188581895819058191581925819358194581955819658197581985819958200582015820258203582045820558206582075820858209582105821158212582135821458215582165821758218582195822058221582225822358224582255822658227582285822958230582315823258233582345823558236582375823858239582405824158242582435824458245582465824758248582495825058251582525825358254582555825658257582585825958260582615826258263582645826558266582675826858269582705827158272582735827458275582765827758278582795828058281582825828358284582855828658287582885828958290582915829258293582945829558296582975829858299583005830158302583035830458305583065830758308583095831058311583125831358314583155831658317583185831958320583215832258323583245832558326583275832858329583305833158332583335833458335583365833758338583395834058341583425834358344583455834658347583485834958350583515835258353583545835558356583575835858359583605836158362583635836458365583665836758368583695837058371583725837358374583755837658377583785837958380583815838258383583845838558386583875838858389583905839158392583935839458395583965839758398583995840058401584025840358404584055840658407584085840958410584115841258413584145841558416584175841858419584205842158422584235842458425584265842758428584295843058431584325843358434584355843658437584385843958440584415844258443584445844558446584475844858449584505845158452584535845458455584565845758458584595846058461584625846358464584655846658467584685846958470584715847258473584745847558476584775847858479584805848158482584835848458485584865848758488584895849058491584925849358494584955849658497584985849958500585015850258503585045850558506585075850858509585105851158512585135851458515585165851758518585195852058521585225852358524585255852658527585285852958530585315853258533585345853558536585375853858539585405854158542585435854458545585465854758548585495855058551585525855358554585555855658557585585855958560585615856258563585645856558566585675856858569585705857158572585735857458575585765857758578585795858058581585825858358584585855858658587585885858958590585915859258593585945859558596585975859858599586005860158602586035860458605586065860758608586095861058611586125861358614586155861658617586185861958620586215862258623586245862558626586275862858629586305863158632586335863458635586365863758638586395864058641586425864358644586455864658647586485864958650586515865258653586545865558656586575865858659586605866158662586635866458665586665866758668586695867058671586725867358674586755867658677586785867958680586815868258683586845868558686586875868858689586905869158692586935869458695586965869758698586995870058701587025870358704587055870658707587085870958710587115871258713587145871558716587175871858719587205872158722587235872458725587265872758728587295873058731587325873358734587355873658737587385873958740587415874258743587445874558746587475874858749587505875158752587535875458755587565875758758587595876058761587625876358764587655876658767587685876958770587715877258773587745877558776587775877858779587805878158782587835878458785587865878758788587895879058791587925879358794587955879658797587985879958800588015880258803588045880558806588075880858809588105881158812588135881458815588165881758818588195882058821588225882358824588255882658827588285882958830588315883258833588345883558836588375883858839588405884158842588435884458845588465884758848588495885058851588525885358854588555885658857588585885958860588615886258863588645886558866588675886858869588705887158872588735887458875588765887758878588795888058881588825888358884588855888658887588885888958890588915889258893588945889558896588975889858899589005890158902589035890458905589065890758908589095891058911589125891358914589155891658917589185891958920589215892258923589245892558926589275892858929589305893158932589335893458935589365893758938589395894058941589425894358944589455894658947589485894958950589515895258953589545895558956589575895858959589605896158962589635896458965589665896758968589695897058971589725897358974589755897658977589785897958980589815898258983589845898558986589875898858989589905899158992589935899458995589965899758998589995900059001590025900359004590055900659007590085900959010590115901259013590145901559016590175901859019590205902159022590235902459025590265902759028590295903059031590325903359034590355903659037590385903959040590415904259043590445904559046590475904859049590505905159052590535905459055590565905759058590595906059061590625906359064590655906659067590685906959070590715907259073590745907559076590775907859079590805908159082590835908459085590865908759088590895909059091590925909359094590955909659097590985909959100591015910259103591045910559106591075910859109591105911159112591135911459115591165911759118591195912059121591225912359124591255912659127591285912959130591315913259133591345913559136591375913859139591405914159142591435914459145591465914759148591495915059151591525915359154591555915659157591585915959160591615916259163591645916559166591675916859169591705917159172591735917459175591765917759178591795918059181591825918359184591855918659187591885918959190591915919259193591945919559196591975919859199592005920159202592035920459205592065920759208592095921059211592125921359214592155921659217592185921959220592215922259223592245922559226592275922859229592305923159232592335923459235592365923759238592395924059241592425924359244592455924659247592485924959250592515925259253592545925559256592575925859259592605926159262592635926459265592665926759268592695927059271592725927359274592755927659277592785927959280592815928259283592845928559286592875928859289592905929159292592935929459295592965929759298592995930059301593025930359304593055930659307593085930959310593115931259313593145931559316593175931859319593205932159322593235932459325593265932759328593295933059331593325933359334593355933659337593385933959340593415934259343593445934559346593475934859349593505935159352593535935459355593565935759358593595936059361593625936359364593655936659367593685936959370593715937259373593745937559376593775937859379593805938159382593835938459385593865938759388593895939059391593925939359394593955939659397593985939959400594015940259403594045940559406594075940859409594105941159412594135941459415594165941759418594195942059421594225942359424594255942659427594285942959430594315943259433594345943559436594375943859439594405944159442594435944459445594465944759448594495945059451594525945359454594555945659457594585945959460594615946259463594645946559466594675946859469594705947159472594735947459475594765947759478594795948059481594825948359484594855948659487594885948959490594915949259493594945949559496594975949859499595005950159502595035950459505595065950759508595095951059511595125951359514595155951659517595185951959520595215952259523595245952559526595275952859529595305953159532595335953459535595365953759538595395954059541595425954359544595455954659547595485954959550595515955259553595545955559556595575955859559595605956159562595635956459565595665956759568595695957059571595725957359574595755957659577595785957959580595815958259583595845958559586595875958859589595905959159592595935959459595595965959759598595995960059601596025960359604596055960659607596085960959610596115961259613596145961559616596175961859619596205962159622596235962459625596265962759628596295963059631596325963359634596355963659637596385963959640596415964259643596445964559646596475964859649596505965159652596535965459655596565965759658596595966059661596625966359664596655966659667596685966959670596715967259673596745967559676596775967859679596805968159682596835968459685596865968759688596895969059691596925969359694596955969659697596985969959700597015970259703597045970559706597075970859709597105971159712597135971459715597165971759718597195972059721597225972359724597255972659727597285972959730597315973259733597345973559736597375973859739597405974159742597435974459745597465974759748597495975059751597525975359754597555975659757597585975959760597615976259763597645976559766597675976859769597705977159772597735977459775597765977759778597795978059781597825978359784597855978659787597885978959790597915979259793597945979559796597975979859799598005980159802598035980459805598065980759808598095981059811598125981359814598155981659817598185981959820598215982259823598245982559826598275982859829598305983159832598335983459835598365983759838598395984059841598425984359844598455984659847598485984959850598515985259853598545985559856598575985859859598605986159862598635986459865598665986759868598695987059871598725987359874598755987659877598785987959880598815988259883598845988559886598875988859889598905989159892598935989459895598965989759898598995990059901599025990359904599055990659907599085990959910599115991259913599145991559916599175991859919599205992159922599235992459925599265992759928599295993059931599325993359934599355993659937599385993959940599415994259943599445994559946599475994859949599505995159952599535995459955599565995759958599595996059961599625996359964599655996659967599685996959970599715997259973599745997559976599775997859979599805998159982599835998459985599865998759988599895999059991599925999359994599955999659997599985999960000600016000260003600046000560006600076000860009600106001160012600136001460015600166001760018600196002060021600226002360024600256002660027600286002960030600316003260033600346003560036600376003860039600406004160042600436004460045600466004760048600496005060051600526005360054600556005660057600586005960060600616006260063600646006560066600676006860069600706007160072600736007460075600766007760078600796008060081600826008360084600856008660087600886008960090600916009260093600946009560096600976009860099601006010160102601036010460105601066010760108601096011060111601126011360114601156011660117601186011960120601216012260123601246012560126601276012860129601306013160132601336013460135601366013760138601396014060141601426014360144601456014660147601486014960150601516015260153601546015560156601576015860159601606016160162601636016460165601666016760168601696017060171601726017360174601756017660177601786017960180601816018260183601846018560186601876018860189601906019160192601936019460195601966019760198601996020060201602026020360204602056020660207602086020960210602116021260213602146021560216602176021860219602206022160222602236022460225602266022760228602296023060231602326023360234602356023660237602386023960240602416024260243602446024560246602476024860249602506025160252602536025460255602566025760258602596026060261602626026360264602656026660267602686026960270602716027260273602746027560276602776027860279602806028160282602836028460285602866028760288602896029060291602926029360294602956029660297602986029960300603016030260303603046030560306603076030860309603106031160312603136031460315603166031760318603196032060321603226032360324603256032660327603286032960330603316033260333603346033560336603376033860339603406034160342603436034460345603466034760348603496035060351603526035360354603556035660357603586035960360603616036260363603646036560366603676036860369603706037160372603736037460375603766037760378603796038060381603826038360384603856038660387603886038960390603916039260393603946039560396603976039860399604006040160402604036040460405604066040760408604096041060411604126041360414604156041660417604186041960420604216042260423604246042560426604276042860429604306043160432604336043460435604366043760438604396044060441604426044360444604456044660447604486044960450604516045260453604546045560456604576045860459604606046160462604636046460465604666046760468604696047060471604726047360474604756047660477604786047960480604816048260483604846048560486604876048860489604906049160492604936049460495604966049760498604996050060501605026050360504605056050660507605086050960510605116051260513605146051560516605176051860519605206052160522605236052460525605266052760528605296053060531605326053360534605356053660537605386053960540605416054260543605446054560546605476054860549605506055160552605536055460555605566055760558605596056060561605626056360564605656056660567605686056960570605716057260573605746057560576605776057860579605806058160582605836058460585605866058760588605896059060591605926059360594605956059660597605986059960600606016060260603606046060560606606076060860609606106061160612606136061460615606166061760618606196062060621606226062360624606256062660627606286062960630606316063260633606346063560636606376063860639606406064160642606436064460645606466064760648606496065060651606526065360654606556065660657606586065960660606616066260663606646066560666606676066860669606706067160672606736067460675606766067760678606796068060681606826068360684606856068660687606886068960690606916069260693606946069560696606976069860699607006070160702607036070460705607066070760708607096071060711607126071360714607156071660717607186071960720607216072260723607246072560726607276072860729607306073160732607336073460735607366073760738607396074060741607426074360744607456074660747607486074960750607516075260753607546075560756607576075860759607606076160762607636076460765607666076760768607696077060771607726077360774607756077660777607786077960780607816078260783607846078560786607876078860789607906079160792607936079460795607966079760798607996080060801608026080360804608056080660807608086080960810608116081260813608146081560816608176081860819608206082160822608236082460825608266082760828608296083060831608326083360834608356083660837608386083960840608416084260843608446084560846608476084860849608506085160852608536085460855608566085760858608596086060861608626086360864608656086660867608686086960870608716087260873608746087560876608776087860879608806088160882608836088460885608866088760888608896089060891608926089360894608956089660897608986089960900609016090260903609046090560906609076090860909609106091160912609136091460915609166091760918609196092060921609226092360924609256092660927609286092960930609316093260933609346093560936609376093860939609406094160942609436094460945609466094760948609496095060951609526095360954609556095660957609586095960960609616096260963609646096560966609676096860969609706097160972609736097460975609766097760978609796098060981609826098360984609856098660987609886098960990609916099260993609946099560996609976099860999610006100161002610036100461005610066100761008610096101061011610126101361014610156101661017610186101961020610216102261023610246102561026610276102861029610306103161032610336103461035610366103761038610396104061041610426104361044610456104661047610486104961050610516105261053610546105561056610576105861059610606106161062610636106461065610666106761068610696107061071610726107361074610756107661077610786107961080610816108261083610846108561086610876108861089610906109161092610936109461095610966109761098610996110061101611026110361104611056110661107611086110961110611116111261113611146111561116611176111861119611206112161122611236112461125611266112761128611296113061131611326113361134611356113661137611386113961140611416114261143611446114561146611476114861149611506115161152611536115461155611566115761158611596116061161611626116361164611656116661167611686116961170611716117261173611746117561176611776117861179611806118161182611836118461185611866118761188611896119061191611926119361194611956119661197611986119961200612016120261203612046120561206612076120861209612106121161212612136121461215612166121761218612196122061221612226122361224612256122661227612286122961230612316123261233612346123561236612376123861239612406124161242612436124461245612466124761248612496125061251612526125361254612556125661257612586125961260612616126261263612646126561266612676126861269612706127161272612736127461275612766127761278612796128061281612826128361284612856128661287612886128961290612916129261293612946129561296612976129861299613006130161302613036130461305613066130761308613096131061311613126131361314613156131661317613186131961320613216132261323613246132561326613276132861329613306133161332613336133461335613366133761338613396134061341613426134361344613456134661347613486134961350613516135261353613546135561356613576135861359613606136161362613636136461365613666136761368613696137061371613726137361374613756137661377613786137961380613816138261383613846138561386613876138861389613906139161392613936139461395613966139761398613996140061401614026140361404614056140661407614086140961410614116141261413614146141561416614176141861419614206142161422614236142461425614266142761428614296143061431614326143361434614356143661437614386143961440614416144261443614446144561446614476144861449614506145161452614536145461455614566145761458614596146061461614626146361464614656146661467614686146961470614716147261473614746147561476614776147861479614806148161482614836148461485614866148761488614896149061491614926149361494614956149661497614986149961500615016150261503615046150561506615076150861509615106151161512615136151461515615166151761518615196152061521615226152361524615256152661527615286152961530615316153261533615346153561536615376153861539615406154161542615436154461545615466154761548615496155061551615526155361554615556155661557615586155961560615616156261563615646156561566615676156861569615706157161572615736157461575615766157761578615796158061581615826158361584615856158661587615886158961590615916159261593615946159561596615976159861599616006160161602616036160461605616066160761608616096161061611616126161361614616156161661617616186161961620616216162261623616246162561626616276162861629616306163161632616336163461635616366163761638616396164061641616426164361644616456164661647616486164961650616516165261653616546165561656616576165861659616606166161662616636166461665616666166761668616696167061671616726167361674616756167661677616786167961680616816168261683616846168561686616876168861689616906169161692616936169461695616966169761698616996170061701617026170361704617056170661707617086170961710617116171261713617146171561716617176171861719617206172161722617236172461725617266172761728617296173061731617326173361734617356173661737617386173961740617416174261743617446174561746617476174861749617506175161752617536175461755617566175761758617596176061761617626176361764617656176661767617686176961770617716177261773617746177561776617776177861779617806178161782617836178461785617866178761788617896179061791617926179361794617956179661797617986179961800618016180261803618046180561806618076180861809618106181161812618136181461815618166181761818618196182061821618226182361824618256182661827618286182961830618316183261833618346183561836618376183861839618406184161842618436184461845618466184761848618496185061851618526185361854618556185661857618586185961860618616186261863618646186561866618676186861869618706187161872618736187461875618766187761878618796188061881618826188361884618856188661887618886188961890618916189261893618946189561896618976189861899619006190161902619036190461905619066190761908619096191061911619126191361914619156191661917619186191961920619216192261923619246192561926619276192861929619306193161932619336193461935619366193761938619396194061941619426194361944619456194661947619486194961950619516195261953619546195561956619576195861959619606196161962619636196461965619666196761968619696197061971619726197361974619756197661977619786197961980619816198261983619846198561986619876198861989619906199161992619936199461995619966199761998619996200062001620026200362004620056200662007620086200962010620116201262013620146201562016620176201862019620206202162022620236202462025620266202762028620296203062031620326203362034620356203662037620386203962040620416204262043620446204562046620476204862049620506205162052620536205462055620566205762058620596206062061620626206362064620656206662067620686206962070620716207262073620746207562076620776207862079620806208162082620836208462085620866208762088620896209062091620926209362094620956209662097620986209962100621016210262103621046210562106621076210862109621106211162112621136211462115621166211762118621196212062121621226212362124621256212662127621286212962130621316213262133621346213562136621376213862139621406214162142621436214462145621466214762148621496215062151621526215362154621556215662157621586215962160621616216262163621646216562166621676216862169621706217162172621736217462175621766217762178621796218062181621826218362184621856218662187621886218962190621916219262193621946219562196621976219862199622006220162202622036220462205622066220762208622096221062211622126221362214622156221662217622186221962220622216222262223622246222562226622276222862229622306223162232622336223462235622366223762238622396224062241622426224362244622456224662247622486224962250622516225262253622546225562256622576225862259622606226162262622636226462265622666226762268622696227062271622726227362274622756227662277622786227962280622816228262283622846228562286622876228862289622906229162292622936229462295622966229762298622996230062301623026230362304623056230662307623086230962310623116231262313623146231562316623176231862319623206232162322623236232462325623266232762328623296233062331623326233362334623356233662337623386233962340623416234262343623446234562346623476234862349623506235162352623536235462355623566235762358623596236062361623626236362364623656236662367623686236962370623716237262373623746237562376623776237862379623806238162382623836238462385623866238762388623896239062391623926239362394623956239662397623986239962400624016240262403624046240562406624076240862409624106241162412624136241462415624166241762418624196242062421624226242362424624256242662427624286242962430624316243262433624346243562436624376243862439624406244162442624436244462445624466244762448624496245062451624526245362454624556245662457624586245962460624616246262463624646246562466624676246862469624706247162472624736247462475624766247762478624796248062481624826248362484624856248662487624886248962490624916249262493624946249562496624976249862499625006250162502625036250462505625066250762508625096251062511625126251362514625156251662517625186251962520625216252262523625246252562526625276252862529625306253162532625336253462535625366253762538625396254062541625426254362544625456254662547625486254962550625516255262553625546255562556625576255862559625606256162562625636256462565625666256762568625696257062571625726257362574625756257662577625786257962580625816258262583625846258562586625876258862589625906259162592625936259462595625966259762598625996260062601626026260362604626056260662607626086260962610626116261262613626146261562616626176261862619626206262162622626236262462625626266262762628626296263062631626326263362634626356263662637626386263962640626416264262643626446264562646626476264862649626506265162652626536265462655626566265762658626596266062661626626266362664626656266662667626686266962670626716267262673626746267562676626776267862679626806268162682626836268462685626866268762688626896269062691626926269362694626956269662697626986269962700627016270262703627046270562706627076270862709627106271162712627136271462715627166271762718627196272062721627226272362724627256272662727627286272962730627316273262733627346273562736627376273862739627406274162742627436274462745627466274762748627496275062751627526275362754627556275662757627586275962760627616276262763627646276562766627676276862769627706277162772627736277462775627766277762778627796278062781627826278362784627856278662787627886278962790627916279262793627946279562796627976279862799628006280162802628036280462805628066280762808628096281062811628126281362814628156281662817628186281962820628216282262823628246282562826628276282862829628306283162832628336283462835628366283762838628396284062841628426284362844628456284662847628486284962850628516285262853628546285562856628576285862859628606286162862628636286462865628666286762868628696287062871628726287362874628756287662877628786287962880628816288262883628846288562886628876288862889628906289162892628936289462895628966289762898628996290062901629026290362904629056290662907629086290962910629116291262913629146291562916629176291862919629206292162922629236292462925629266292762928629296293062931629326293362934629356293662937629386293962940629416294262943629446294562946629476294862949629506295162952629536295462955629566295762958629596296062961629626296362964629656296662967629686296962970629716297262973629746297562976629776297862979629806298162982629836298462985629866298762988629896299062991629926299362994629956299662997629986299963000630016300263003630046300563006630076300863009630106301163012630136301463015630166301763018630196302063021630226302363024630256302663027630286302963030630316303263033630346303563036630376303863039630406304163042630436304463045630466304763048630496305063051630526305363054630556305663057630586305963060630616306263063630646306563066630676306863069630706307163072630736307463075630766307763078630796308063081630826308363084630856308663087630886308963090630916309263093630946309563096630976309863099631006310163102631036310463105631066310763108631096311063111631126311363114631156311663117631186311963120631216312263123631246312563126631276312863129631306313163132631336313463135631366313763138631396314063141631426314363144631456314663147631486314963150631516315263153631546315563156631576315863159631606316163162631636316463165631666316763168631696317063171631726317363174631756317663177631786317963180631816318263183631846318563186631876318863189631906319163192631936319463195631966319763198631996320063201632026320363204632056320663207632086320963210632116321263213632146321563216632176321863219632206322163222632236322463225632266322763228632296323063231632326323363234632356323663237632386323963240632416324263243632446324563246632476324863249632506325163252632536325463255632566325763258632596326063261632626326363264632656326663267632686326963270632716327263273632746327563276632776327863279632806328163282632836328463285632866328763288632896329063291632926329363294632956329663297632986329963300633016330263303633046330563306633076330863309633106331163312633136331463315633166331763318633196332063321633226332363324633256332663327633286332963330633316333263333633346333563336633376333863339633406334163342633436334463345633466334763348633496335063351633526335363354633556335663357633586335963360633616336263363633646336563366633676336863369633706337163372633736337463375633766337763378633796338063381633826338363384633856338663387633886338963390633916339263393633946339563396633976339863399634006340163402634036340463405634066340763408634096341063411634126341363414634156341663417634186341963420634216342263423634246342563426634276342863429634306343163432634336343463435634366343763438634396344063441634426344363444634456344663447634486344963450634516345263453634546345563456634576345863459634606346163462634636346463465634666346763468634696347063471634726347363474634756347663477634786347963480634816348263483634846348563486634876348863489634906349163492634936349463495634966349763498634996350063501635026350363504635056350663507635086350963510635116351263513635146351563516635176351863519635206352163522635236352463525635266352763528635296353063531635326353363534635356353663537635386353963540635416354263543635446354563546635476354863549635506355163552635536355463555635566355763558635596356063561635626356363564635656356663567635686356963570635716357263573635746357563576635776357863579635806358163582635836358463585635866358763588635896359063591635926359363594635956359663597635986359963600636016360263603636046360563606636076360863609636106361163612636136361463615636166361763618636196362063621636226362363624636256362663627636286362963630636316363263633636346363563636636376363863639636406364163642636436364463645636466364763648636496365063651636526365363654636556365663657636586365963660636616366263663636646366563666636676366863669636706367163672636736367463675636766367763678636796368063681636826368363684636856368663687636886368963690636916369263693636946369563696636976369863699637006370163702637036370463705637066370763708637096371063711637126371363714637156371663717637186371963720637216372263723637246372563726637276372863729637306373163732637336373463735637366373763738637396374063741637426374363744637456374663747637486374963750637516375263753637546375563756637576375863759637606376163762637636376463765637666376763768637696377063771637726377363774637756377663777637786377963780637816378263783637846378563786637876378863789637906379163792637936379463795637966379763798637996380063801638026380363804638056380663807638086380963810638116381263813638146381563816638176381863819638206382163822638236382463825638266382763828638296383063831638326383363834638356383663837638386383963840638416384263843638446384563846638476384863849638506385163852638536385463855638566385763858638596386063861638626386363864638656386663867638686386963870638716387263873638746387563876638776387863879638806388163882638836388463885638866388763888638896389063891638926389363894638956389663897638986389963900639016390263903639046390563906639076390863909639106391163912639136391463915639166391763918639196392063921639226392363924639256392663927639286392963930639316393263933639346393563936639376393863939639406394163942639436394463945639466394763948639496395063951639526395363954639556395663957639586395963960639616396263963639646396563966639676396863969639706397163972639736397463975639766397763978639796398063981639826398363984639856398663987639886398963990639916399263993639946399563996639976399863999640006400164002640036400464005640066400764008640096401064011640126401364014640156401664017640186401964020640216402264023640246402564026640276402864029640306403164032640336403464035640366403764038640396404064041640426404364044640456404664047640486404964050640516405264053640546405564056640576405864059640606406164062640636406464065640666406764068640696407064071640726407364074640756407664077640786407964080640816408264083640846408564086640876408864089640906409164092640936409464095640966409764098640996410064101641026410364104641056410664107641086410964110641116411264113641146411564116641176411864119641206412164122641236412464125641266412764128641296413064131641326413364134641356413664137641386413964140641416414264143641446414564146641476414864149641506415164152641536415464155641566415764158641596416064161641626416364164641656416664167641686416964170641716417264173641746417564176641776417864179641806418164182641836418464185641866418764188641896419064191641926419364194641956419664197641986419964200642016420264203642046420564206642076420864209642106421164212642136421464215642166421764218642196422064221642226422364224642256422664227642286422964230642316423264233642346423564236642376423864239642406424164242642436424464245642466424764248642496425064251642526425364254642556425664257642586425964260642616426264263642646426564266642676426864269642706427164272642736427464275642766427764278642796428064281642826428364284642856428664287642886428964290642916429264293642946429564296642976429864299643006430164302643036430464305643066430764308643096431064311643126431364314643156431664317643186431964320643216432264323643246432564326643276432864329643306433164332643336433464335643366433764338643396434064341643426434364344643456434664347643486434964350643516435264353643546435564356643576435864359643606436164362643636436464365643666436764368643696437064371643726437364374643756437664377643786437964380643816438264383643846438564386643876438864389643906439164392643936439464395643966439764398643996440064401644026440364404644056440664407644086440964410644116441264413644146441564416644176441864419644206442164422644236442464425644266442764428644296443064431644326443364434644356443664437644386443964440644416444264443644446444564446644476444864449644506445164452644536445464455644566445764458644596446064461644626446364464644656446664467644686446964470644716447264473644746447564476644776447864479644806448164482644836448464485644866448764488644896449064491644926449364494644956449664497644986449964500645016450264503645046450564506645076450864509645106451164512645136451464515645166451764518645196452064521645226452364524645256452664527645286452964530645316453264533645346453564536645376453864539645406454164542645436454464545645466454764548645496455064551645526455364554645556455664557645586455964560645616456264563645646456564566645676456864569645706457164572645736457464575645766457764578645796458064581645826458364584645856458664587645886458964590645916459264593645946459564596645976459864599646006460164602646036460464605646066460764608646096461064611646126461364614646156461664617646186461964620646216462264623646246462564626646276462864629646306463164632646336463464635646366463764638646396464064641646426464364644646456464664647646486464964650646516465264653646546465564656646576465864659646606466164662646636466464665646666466764668646696467064671646726467364674646756467664677646786467964680646816468264683646846468564686646876468864689646906469164692646936469464695646966469764698646996470064701647026470364704647056470664707647086470964710647116471264713647146471564716647176471864719647206472164722647236472464725647266472764728647296473064731647326473364734647356473664737647386473964740647416474264743647446474564746647476474864749647506475164752647536475464755647566475764758647596476064761647626476364764647656476664767647686476964770647716477264773647746477564776647776477864779647806478164782647836478464785647866478764788647896479064791647926479364794647956479664797647986479964800648016480264803648046480564806648076480864809648106481164812648136481464815648166481764818648196482064821648226482364824648256482664827648286482964830648316483264833648346483564836648376483864839648406484164842648436484464845648466484764848648496485064851648526485364854648556485664857648586485964860648616486264863648646486564866648676486864869648706487164872648736487464875648766487764878648796488064881648826488364884648856488664887648886488964890648916489264893648946489564896648976489864899649006490164902649036490464905649066490764908649096491064911649126491364914649156491664917649186491964920649216492264923649246492564926649276492864929649306493164932649336493464935649366493764938649396494064941649426494364944649456494664947649486494964950649516495264953649546495564956649576495864959649606496164962649636496464965649666496764968649696497064971649726497364974649756497664977649786497964980649816498264983649846498564986649876498864989649906499164992649936499464995649966499764998649996500065001650026500365004650056500665007650086500965010650116501265013650146501565016650176501865019650206502165022650236502465025650266502765028650296503065031650326503365034650356503665037650386503965040650416504265043650446504565046650476504865049650506505165052650536505465055650566505765058650596506065061650626506365064650656506665067650686506965070650716507265073650746507565076650776507865079650806508165082650836508465085650866508765088650896509065091650926509365094650956509665097650986509965100651016510265103651046510565106651076510865109651106511165112651136511465115651166511765118651196512065121651226512365124651256512665127651286512965130651316513265133651346513565136651376513865139651406514165142651436514465145651466514765148651496515065151651526515365154651556515665157651586515965160651616516265163651646516565166651676516865169651706517165172651736517465175651766517765178651796518065181651826518365184651856518665187651886518965190651916519265193651946519565196651976519865199652006520165202652036520465205652066520765208652096521065211652126521365214652156521665217652186521965220652216522265223652246522565226652276522865229652306523165232652336523465235652366523765238652396524065241652426524365244652456524665247652486524965250652516525265253652546525565256652576525865259652606526165262652636526465265652666526765268652696527065271652726527365274652756527665277652786527965280652816528265283652846528565286652876528865289652906529165292652936529465295652966529765298652996530065301653026530365304653056530665307653086530965310653116531265313653146531565316653176531865319653206532165322653236532465325653266532765328653296533065331653326533365334653356533665337653386533965340653416534265343653446534565346653476534865349653506535165352653536535465355653566535765358653596536065361653626536365364653656536665367653686536965370653716537265373653746537565376653776537865379653806538165382653836538465385653866538765388653896539065391653926539365394653956539665397653986539965400654016540265403654046540565406654076540865409654106541165412654136541465415654166541765418654196542065421654226542365424654256542665427654286542965430654316543265433654346543565436654376543865439654406544165442654436544465445654466544765448654496545065451654526545365454654556545665457654586545965460654616546265463654646546565466654676546865469654706547165472654736547465475654766547765478654796548065481654826548365484654856548665487654886548965490654916549265493654946549565496654976549865499655006550165502655036550465505655066550765508655096551065511655126551365514655156551665517655186551965520655216552265523655246552565526655276552865529655306553165532655336553465535655366553765538655396554065541655426554365544655456554665547655486554965550655516555265553655546555565556655576555865559655606556165562655636556465565655666556765568655696557065571655726557365574655756557665577655786557965580655816558265583655846558565586655876558865589655906559165592655936559465595655966559765598655996560065601656026560365604656056560665607656086560965610656116561265613656146561565616656176561865619656206562165622656236562465625656266562765628656296563065631656326563365634656356563665637656386563965640656416564265643656446564565646656476564865649656506565165652656536565465655656566565765658656596566065661656626566365664656656566665667656686566965670656716567265673656746567565676656776567865679656806568165682656836568465685656866568765688656896569065691656926569365694656956569665697656986569965700657016570265703657046570565706657076570865709657106571165712657136571465715657166571765718657196572065721657226572365724657256572665727657286572965730657316573265733657346573565736657376573865739657406574165742657436574465745657466574765748657496575065751657526575365754657556575665757657586575965760657616576265763657646576565766657676576865769657706577165772657736577465775657766577765778657796578065781657826578365784657856578665787657886578965790657916579265793657946579565796657976579865799658006580165802658036580465805658066580765808658096581065811658126581365814658156581665817658186581965820658216582265823658246582565826658276582865829658306583165832658336583465835658366583765838658396584065841658426584365844658456584665847658486584965850658516585265853658546585565856658576585865859658606586165862658636586465865658666586765868658696587065871658726587365874658756587665877658786587965880658816588265883658846588565886658876588865889658906589165892658936589465895658966589765898658996590065901659026590365904659056590665907659086590965910659116591265913659146591565916659176591865919659206592165922659236592465925659266592765928659296593065931659326593365934659356593665937659386593965940659416594265943659446594565946659476594865949659506595165952659536595465955659566595765958659596596065961659626596365964659656596665967659686596965970659716597265973659746597565976659776597865979659806598165982659836598465985659866598765988659896599065991659926599365994659956599665997659986599966000660016600266003660046600566006660076600866009660106601166012660136601466015660166601766018660196602066021660226602366024660256602666027660286602966030660316603266033660346603566036660376603866039660406604166042660436604466045660466604766048660496605066051660526605366054660556605666057660586605966060660616606266063660646606566066660676606866069660706607166072660736607466075660766607766078660796608066081660826608366084660856608666087660886608966090660916609266093660946609566096660976609866099661006610166102661036610466105661066610766108661096611066111661126611366114661156611666117661186611966120661216612266123661246612566126661276612866129661306613166132661336613466135661366613766138661396614066141661426614366144661456614666147661486614966150661516615266153661546615566156661576615866159661606616166162661636616466165661666616766168661696617066171661726617366174661756617666177661786617966180661816618266183661846618566186661876618866189661906619166192661936619466195661966619766198661996620066201662026620366204662056620666207662086620966210662116621266213662146621566216662176621866219662206622166222662236622466225662266622766228662296623066231662326623366234662356623666237662386623966240662416624266243662446624566246662476624866249662506625166252662536625466255662566625766258662596626066261662626626366264662656626666267662686626966270662716627266273662746627566276662776627866279662806628166282662836628466285662866628766288662896629066291662926629366294662956629666297662986629966300663016630266303663046630566306663076630866309663106631166312663136631466315663166631766318663196632066321663226632366324663256632666327663286632966330663316633266333663346633566336663376633866339663406634166342663436634466345663466634766348663496635066351663526635366354663556635666357663586635966360663616636266363663646636566366663676636866369663706637166372663736637466375663766637766378663796638066381663826638366384663856638666387663886638966390663916639266393663946639566396663976639866399664006640166402664036640466405664066640766408664096641066411664126641366414664156641666417664186641966420664216642266423664246642566426664276642866429664306643166432664336643466435664366643766438664396644066441664426644366444664456644666447664486644966450664516645266453664546645566456664576645866459664606646166462664636646466465664666646766468664696647066471664726647366474664756647666477664786647966480664816648266483664846648566486664876648866489664906649166492664936649466495664966649766498664996650066501665026650366504665056650666507665086650966510665116651266513665146651566516665176651866519665206652166522665236652466525665266652766528665296653066531665326653366534665356653666537665386653966540665416654266543665446654566546665476654866549665506655166552665536655466555665566655766558665596656066561665626656366564665656656666567665686656966570665716657266573665746657566576665776657866579665806658166582665836658466585665866658766588665896659066591665926659366594665956659666597665986659966600666016660266603666046660566606666076660866609666106661166612666136661466615666166661766618666196662066621666226662366624666256662666627666286662966630666316663266633666346663566636666376663866639666406664166642666436664466645666466664766648666496665066651666526665366654666556665666657666586665966660666616666266663666646666566666666676666866669666706667166672666736667466675666766667766678666796668066681666826668366684666856668666687666886668966690666916669266693666946669566696666976669866699667006670166702667036670466705667066670766708667096671066711667126671366714667156671666717667186671966720667216672266723667246672566726667276672866729667306673166732667336673466735667366673766738667396674066741667426674366744667456674666747667486674966750667516675266753667546675566756667576675866759667606676166762667636676466765667666676766768667696677066771667726677366774667756677666777667786677966780667816678266783667846678566786667876678866789667906679166792667936679466795667966679766798667996680066801668026680366804668056680666807668086680966810668116681266813668146681566816668176681866819668206682166822668236682466825668266682766828668296683066831668326683366834668356683666837668386683966840668416684266843668446684566846668476684866849668506685166852668536685466855668566685766858668596686066861668626686366864668656686666867668686686966870668716687266873668746687566876668776687866879668806688166882668836688466885668866688766888668896689066891668926689366894668956689666897668986689966900669016690266903669046690566906669076690866909669106691166912669136691466915669166691766918669196692066921669226692366924669256692666927669286692966930669316693266933669346693566936669376693866939669406694166942669436694466945669466694766948669496695066951669526695366954669556695666957669586695966960669616696266963669646696566966669676696866969669706697166972669736697466975669766697766978669796698066981669826698366984669856698666987669886698966990669916699266993669946699566996669976699866999670006700167002670036700467005670066700767008670096701067011670126701367014670156701667017670186701967020670216702267023670246702567026670276702867029670306703167032670336703467035670366703767038670396704067041670426704367044670456704667047670486704967050670516705267053670546705567056670576705867059670606706167062670636706467065670666706767068670696707067071670726707367074670756707667077670786707967080670816708267083670846708567086670876708867089670906709167092670936709467095670966709767098670996710067101671026710367104671056710667107671086710967110671116711267113671146711567116671176711867119671206712167122671236712467125671266712767128671296713067131671326713367134671356713667137671386713967140671416714267143671446714567146671476714867149671506715167152671536715467155671566715767158671596716067161671626716367164671656716667167671686716967170671716717267173671746717567176671776717867179671806718167182671836718467185671866718767188671896719067191671926719367194671956719667197671986719967200672016720267203672046720567206672076720867209672106721167212672136721467215672166721767218672196722067221672226722367224672256722667227672286722967230672316723267233672346723567236672376723867239672406724167242672436724467245672466724767248672496725067251672526725367254672556725667257672586725967260672616726267263672646726567266672676726867269672706727167272672736727467275672766727767278672796728067281672826728367284672856728667287672886728967290672916729267293672946729567296672976729867299673006730167302673036730467305673066730767308673096731067311673126731367314673156731667317673186731967320673216732267323673246732567326673276732867329673306733167332673336733467335673366733767338673396734067341673426734367344673456734667347673486734967350673516735267353673546735567356673576735867359673606736167362673636736467365673666736767368673696737067371673726737367374673756737667377673786737967380673816738267383673846738567386673876738867389673906739167392673936739467395673966739767398673996740067401674026740367404674056740667407674086740967410674116741267413674146741567416674176741867419674206742167422674236742467425674266742767428674296743067431674326743367434674356743667437674386743967440674416744267443674446744567446674476744867449674506745167452674536745467455674566745767458674596746067461674626746367464674656746667467674686746967470674716747267473674746747567476674776747867479674806748167482674836748467485674866748767488674896749067491674926749367494674956749667497674986749967500675016750267503675046750567506675076750867509675106751167512675136751467515675166751767518675196752067521675226752367524675256752667527675286752967530675316753267533675346753567536675376753867539675406754167542675436754467545675466754767548675496755067551675526755367554675556755667557675586755967560675616756267563675646756567566675676756867569675706757167572675736757467575675766757767578675796758067581675826758367584675856758667587675886758967590675916759267593675946759567596675976759867599676006760167602676036760467605676066760767608676096761067611676126761367614676156761667617676186761967620676216762267623676246762567626676276762867629676306763167632676336763467635676366763767638676396764067641676426764367644676456764667647676486764967650676516765267653676546765567656676576765867659676606766167662676636766467665676666766767668676696767067671676726767367674676756767667677676786767967680676816768267683676846768567686676876768867689676906769167692676936769467695676966769767698676996770067701677026770367704677056770667707677086770967710677116771267713677146771567716677176771867719677206772167722677236772467725677266772767728677296773067731677326773367734677356773667737677386773967740677416774267743677446774567746677476774867749677506775167752677536775467755677566775767758677596776067761677626776367764677656776667767677686776967770677716777267773677746777567776677776777867779677806778167782677836778467785677866778767788677896779067791677926779367794677956779667797677986779967800678016780267803678046780567806678076780867809678106781167812678136781467815678166781767818678196782067821678226782367824678256782667827678286782967830678316783267833678346783567836678376783867839678406784167842678436784467845678466784767848678496785067851678526785367854678556785667857678586785967860678616786267863678646786567866678676786867869678706787167872678736787467875678766787767878678796788067881678826788367884678856788667887678886788967890678916789267893678946789567896678976789867899679006790167902679036790467905679066790767908679096791067911679126791367914679156791667917679186791967920679216792267923679246792567926679276792867929679306793167932679336793467935679366793767938679396794067941679426794367944679456794667947679486794967950679516795267953679546795567956679576795867959679606796167962679636796467965679666796767968679696797067971679726797367974679756797667977679786797967980679816798267983679846798567986679876798867989679906799167992679936799467995679966799767998679996800068001680026800368004680056800668007680086800968010680116801268013680146801568016680176801868019680206802168022680236802468025680266802768028680296803068031680326803368034680356803668037680386803968040680416804268043680446804568046680476804868049680506805168052680536805468055680566805768058680596806068061680626806368064680656806668067680686806968070680716807268073680746807568076680776807868079680806808168082680836808468085680866808768088680896809068091680926809368094680956809668097680986809968100681016810268103681046810568106681076810868109681106811168112681136811468115681166811768118681196812068121681226812368124681256812668127681286812968130681316813268133681346813568136681376813868139681406814168142681436814468145681466814768148681496815068151681526815368154681556815668157681586815968160681616816268163681646816568166681676816868169681706817168172681736817468175681766817768178681796818068181681826818368184681856818668187681886818968190681916819268193681946819568196681976819868199682006820168202682036820468205682066820768208682096821068211682126821368214682156821668217682186821968220682216822268223682246822568226682276822868229682306823168232682336823468235682366823768238682396824068241682426824368244682456824668247682486824968250682516825268253682546825568256682576825868259682606826168262682636826468265682666826768268682696827068271682726827368274682756827668277682786827968280682816828268283682846828568286682876828868289682906829168292682936829468295682966829768298682996830068301683026830368304683056830668307683086830968310683116831268313683146831568316683176831868319683206832168322683236832468325683266832768328683296833068331683326833368334683356833668337683386833968340683416834268343683446834568346683476834868349683506835168352683536835468355683566835768358683596836068361683626836368364683656836668367683686836968370683716837268373683746837568376683776837868379683806838168382683836838468385683866838768388683896839068391683926839368394683956839668397683986839968400684016840268403684046840568406684076840868409684106841168412684136841468415684166841768418684196842068421684226842368424684256842668427684286842968430684316843268433684346843568436684376843868439684406844168442684436844468445684466844768448684496845068451684526845368454684556845668457684586845968460684616846268463684646846568466684676846868469684706847168472684736847468475684766847768478684796848068481684826848368484684856848668487684886848968490684916849268493684946849568496684976849868499685006850168502685036850468505685066850768508685096851068511685126851368514685156851668517685186851968520685216852268523685246852568526685276852868529685306853168532685336853468535685366853768538685396854068541685426854368544685456854668547685486854968550685516855268553685546855568556685576855868559685606856168562685636856468565685666856768568685696857068571685726857368574685756857668577685786857968580685816858268583685846858568586685876858868589685906859168592685936859468595685966859768598685996860068601686026860368604686056860668607686086860968610686116861268613686146861568616686176861868619686206862168622686236862468625686266862768628686296863068631686326863368634686356863668637686386863968640686416864268643686446864568646686476864868649686506865168652686536865468655686566865768658686596866068661686626866368664686656866668667686686866968670686716867268673686746867568676686776867868679686806868168682686836868468685686866868768688686896869068691686926869368694686956869668697686986869968700687016870268703687046870568706687076870868709687106871168712687136871468715687166871768718687196872068721687226872368724687256872668727687286872968730687316873268733687346873568736687376873868739687406874168742687436874468745687466874768748687496875068751687526875368754687556875668757687586875968760687616876268763687646876568766687676876868769687706877168772687736877468775687766877768778687796878068781687826878368784687856878668787687886878968790687916879268793687946879568796687976879868799688006880168802688036880468805688066880768808688096881068811688126881368814688156881668817688186881968820688216882268823688246882568826688276882868829688306883168832688336883468835688366883768838688396884068841688426884368844688456884668847688486884968850688516885268853688546885568856688576885868859688606886168862688636886468865688666886768868688696887068871688726887368874688756887668877688786887968880688816888268883688846888568886688876888868889688906889168892688936889468895688966889768898688996890068901689026890368904689056890668907689086890968910689116891268913689146891568916689176891868919689206892168922689236892468925689266892768928689296893068931689326893368934689356893668937689386893968940689416894268943689446894568946689476894868949689506895168952689536895468955689566895768958689596896068961689626896368964689656896668967689686896968970689716897268973689746897568976689776897868979689806898168982689836898468985689866898768988689896899068991689926899368994689956899668997689986899969000690016900269003690046900569006690076900869009690106901169012690136901469015690166901769018690196902069021690226902369024690256902669027690286902969030690316903269033690346903569036690376903869039690406904169042690436904469045690466904769048690496905069051690526905369054690556905669057690586905969060690616906269063690646906569066690676906869069690706907169072690736907469075690766907769078690796908069081690826908369084690856908669087690886908969090690916909269093690946909569096690976909869099691006910169102691036910469105691066910769108691096911069111691126911369114691156911669117691186911969120691216912269123691246912569126691276912869129691306913169132691336913469135691366913769138691396914069141691426914369144691456914669147691486914969150691516915269153691546915569156691576915869159691606916169162691636916469165691666916769168691696917069171691726917369174691756917669177691786917969180691816918269183691846918569186691876918869189691906919169192691936919469195691966919769198691996920069201692026920369204692056920669207692086920969210692116921269213692146921569216692176921869219692206922169222692236922469225692266922769228692296923069231692326923369234692356923669237692386923969240692416924269243692446924569246692476924869249692506925169252692536925469255692566925769258692596926069261692626926369264692656926669267692686926969270692716927269273692746927569276692776927869279692806928169282692836928469285692866928769288692896929069291692926929369294692956929669297692986929969300693016930269303693046930569306693076930869309693106931169312693136931469315693166931769318693196932069321693226932369324693256932669327693286932969330693316933269333693346933569336693376933869339693406934169342693436934469345693466934769348693496935069351693526935369354693556935669357693586935969360693616936269363693646936569366693676936869369693706937169372693736937469375693766937769378693796938069381693826938369384693856938669387693886938969390693916939269393693946939569396693976939869399694006940169402694036940469405694066940769408694096941069411694126941369414694156941669417694186941969420694216942269423694246942569426694276942869429694306943169432694336943469435694366943769438694396944069441694426944369444694456944669447694486944969450694516945269453694546945569456694576945869459694606946169462694636946469465694666946769468694696947069471694726947369474694756947669477694786947969480694816948269483694846948569486694876948869489694906949169492694936949469495694966949769498694996950069501695026950369504695056950669507695086950969510695116951269513695146951569516695176951869519695206952169522695236952469525695266952769528695296953069531695326953369534695356953669537695386953969540695416954269543695446954569546695476954869549695506955169552695536955469555695566955769558695596956069561695626956369564695656956669567695686956969570695716957269573695746957569576695776957869579695806958169582695836958469585695866958769588695896959069591695926959369594695956959669597695986959969600696016960269603696046960569606696076960869609696106961169612696136961469615696166961769618696196962069621696226962369624696256962669627696286962969630696316963269633696346963569636696376963869639696406964169642696436964469645696466964769648696496965069651696526965369654696556965669657696586965969660696616966269663696646966569666696676966869669696706967169672696736967469675696766967769678696796968069681696826968369684696856968669687696886968969690696916969269693696946969569696696976969869699697006970169702697036970469705697066970769708697096971069711697126971369714697156971669717697186971969720697216972269723697246972569726697276972869729697306973169732697336973469735697366973769738697396974069741697426974369744697456974669747697486974969750697516975269753697546975569756697576975869759697606976169762697636976469765697666976769768697696977069771697726977369774697756977669777697786977969780697816978269783697846978569786697876978869789697906979169792697936979469795697966979769798697996980069801698026980369804698056980669807698086980969810698116981269813698146981569816698176981869819698206982169822698236982469825698266982769828698296983069831698326983369834698356983669837698386983969840698416984269843698446984569846698476984869849698506985169852698536985469855698566985769858698596986069861698626986369864698656986669867698686986969870698716987269873698746987569876698776987869879698806988169882698836988469885698866988769888698896989069891698926989369894698956989669897698986989969900699016990269903699046990569906699076990869909699106991169912699136991469915699166991769918699196992069921699226992369924699256992669927699286992969930699316993269933699346993569936699376993869939699406994169942699436994469945699466994769948699496995069951699526995369954699556995669957699586995969960699616996269963699646996569966699676996869969699706997169972699736997469975699766997769978699796998069981699826998369984699856998669987699886998969990699916999269993699946999569996699976999869999700007000170002700037000470005700067000770008700097001070011700127001370014700157001670017700187001970020700217002270023700247002570026700277002870029700307003170032700337003470035700367003770038700397004070041700427004370044700457004670047700487004970050700517005270053700547005570056700577005870059700607006170062700637006470065700667006770068700697007070071700727007370074700757007670077700787007970080700817008270083700847008570086700877008870089700907009170092700937009470095700967009770098700997010070101701027010370104701057010670107701087010970110701117011270113701147011570116701177011870119701207012170122701237012470125701267012770128701297013070131701327013370134701357013670137701387013970140701417014270143701447014570146701477014870149701507015170152701537015470155701567015770158701597016070161701627016370164701657016670167701687016970170701717017270173701747017570176701777017870179701807018170182701837018470185701867018770188701897019070191701927019370194701957019670197701987019970200702017020270203702047020570206702077020870209702107021170212702137021470215702167021770218702197022070221702227022370224702257022670227702287022970230702317023270233702347023570236702377023870239702407024170242702437024470245702467024770248702497025070251702527025370254702557025670257702587025970260702617026270263702647026570266702677026870269702707027170272702737027470275702767027770278702797028070281702827028370284702857028670287702887028970290702917029270293702947029570296702977029870299703007030170302703037030470305703067030770308703097031070311703127031370314703157031670317703187031970320703217032270323703247032570326703277032870329703307033170332703337033470335703367033770338703397034070341703427034370344703457034670347703487034970350703517035270353703547035570356703577035870359703607036170362703637036470365703667036770368703697037070371703727037370374703757037670377703787037970380703817038270383703847038570386703877038870389703907039170392703937039470395703967039770398703997040070401704027040370404704057040670407704087040970410704117041270413704147041570416704177041870419704207042170422704237042470425704267042770428704297043070431704327043370434704357043670437704387043970440704417044270443704447044570446704477044870449704507045170452704537045470455704567045770458704597046070461704627046370464704657046670467704687046970470704717047270473704747047570476704777047870479704807048170482704837048470485704867048770488704897049070491704927049370494704957049670497704987049970500705017050270503705047050570506705077050870509705107051170512705137051470515705167051770518705197052070521705227052370524705257052670527705287052970530705317053270533705347053570536705377053870539705407054170542705437054470545705467054770548705497055070551705527055370554705557055670557705587055970560705617056270563705647056570566705677056870569705707057170572705737057470575705767057770578705797058070581705827058370584705857058670587705887058970590705917059270593705947059570596705977059870599706007060170602706037060470605706067060770608706097061070611706127061370614706157061670617706187061970620706217062270623706247062570626706277062870629706307063170632706337063470635706367063770638706397064070641706427064370644706457064670647706487064970650706517065270653706547065570656706577065870659706607066170662706637066470665706667066770668706697067070671706727067370674706757067670677706787067970680706817068270683706847068570686706877068870689706907069170692706937069470695706967069770698706997070070701707027070370704707057070670707707087070970710707117071270713707147071570716707177071870719707207072170722707237072470725707267072770728707297073070731707327073370734707357073670737707387073970740707417074270743707447074570746707477074870749707507075170752707537075470755707567075770758707597076070761707627076370764707657076670767707687076970770707717077270773707747077570776707777077870779707807078170782707837078470785707867078770788707897079070791707927079370794707957079670797707987079970800708017080270803708047080570806708077080870809708107081170812708137081470815708167081770818708197082070821708227082370824708257082670827708287082970830708317083270833708347083570836708377083870839708407084170842708437084470845708467084770848708497085070851708527085370854708557085670857708587085970860708617086270863708647086570866708677086870869708707087170872708737087470875708767087770878708797088070881708827088370884708857088670887708887088970890708917089270893708947089570896708977089870899709007090170902709037090470905709067090770908709097091070911709127091370914709157091670917709187091970920709217092270923709247092570926709277092870929709307093170932709337093470935709367093770938709397094070941709427094370944709457094670947709487094970950709517095270953709547095570956709577095870959709607096170962709637096470965709667096770968709697097070971709727097370974709757097670977709787097970980709817098270983709847098570986709877098870989709907099170992709937099470995709967099770998709997100071001710027100371004710057100671007710087100971010710117101271013710147101571016710177101871019710207102171022710237102471025710267102771028710297103071031710327103371034710357103671037710387103971040710417104271043710447104571046710477104871049710507105171052710537105471055710567105771058710597106071061710627106371064710657106671067710687106971070710717107271073710747107571076710777107871079710807108171082710837108471085710867108771088710897109071091710927109371094710957109671097710987109971100711017110271103711047110571106711077110871109711107111171112711137111471115711167111771118711197112071121711227112371124711257112671127711287112971130711317113271133711347113571136711377113871139711407114171142711437114471145711467114771148711497115071151711527115371154711557115671157711587115971160711617116271163711647116571166711677116871169711707117171172711737117471175711767117771178711797118071181711827118371184711857118671187711887118971190711917119271193711947119571196711977119871199712007120171202712037120471205712067120771208712097121071211712127121371214712157121671217712187121971220712217122271223712247122571226712277122871229712307123171232712337123471235712367123771238712397124071241712427124371244712457124671247712487124971250712517125271253712547125571256712577125871259712607126171262712637126471265712667126771268712697127071271712727127371274712757127671277712787127971280712817128271283712847128571286712877128871289712907129171292712937129471295712967129771298712997130071301713027130371304713057130671307713087130971310713117131271313713147131571316713177131871319713207132171322713237132471325713267132771328713297133071331713327133371334713357133671337713387133971340713417134271343713447134571346713477134871349713507135171352713537135471355713567135771358713597136071361713627136371364713657136671367713687136971370713717137271373713747137571376713777137871379713807138171382713837138471385713867138771388713897139071391713927139371394713957139671397713987139971400714017140271403714047140571406714077140871409714107141171412714137141471415714167141771418714197142071421714227142371424714257142671427714287142971430714317143271433714347143571436714377143871439714407144171442714437144471445714467144771448714497145071451714527145371454714557145671457714587145971460714617146271463714647146571466714677146871469714707147171472714737147471475714767147771478714797148071481714827148371484714857148671487714887148971490714917149271493714947149571496714977149871499715007150171502715037150471505715067150771508715097151071511715127151371514715157151671517715187151971520715217152271523715247152571526715277152871529715307153171532715337153471535715367153771538715397154071541715427154371544715457154671547715487154971550715517155271553715547155571556715577155871559715607156171562715637156471565715667156771568715697157071571715727157371574715757157671577715787157971580715817158271583715847158571586715877158871589715907159171592715937159471595715967159771598715997160071601716027160371604716057160671607716087160971610716117161271613716147161571616716177161871619716207162171622716237162471625716267162771628716297163071631716327163371634716357163671637716387163971640716417164271643716447164571646716477164871649716507165171652716537165471655716567165771658716597166071661716627166371664716657166671667716687166971670716717167271673716747167571676716777167871679716807168171682716837168471685716867168771688716897169071691716927169371694716957169671697716987169971700717017170271703717047170571706717077170871709717107171171712717137171471715717167171771718717197172071721717227172371724717257172671727717287172971730717317173271733717347173571736717377173871739717407174171742717437174471745717467174771748717497175071751717527175371754717557175671757717587175971760717617176271763717647176571766717677176871769717707177171772717737177471775717767177771778717797178071781717827178371784717857178671787717887178971790717917179271793717947179571796717977179871799718007180171802718037180471805718067180771808718097181071811718127181371814718157181671817718187181971820718217182271823718247182571826718277182871829718307183171832718337183471835718367183771838718397184071841718427184371844718457184671847718487184971850718517185271853718547185571856718577185871859718607186171862718637186471865718667186771868718697187071871718727187371874718757187671877718787187971880718817188271883718847188571886718877188871889718907189171892718937189471895718967189771898718997190071901719027190371904719057190671907719087190971910719117191271913719147191571916719177191871919719207192171922719237192471925719267192771928719297193071931719327193371934719357193671937719387193971940719417194271943719447194571946719477194871949719507195171952719537195471955719567195771958719597196071961719627196371964719657196671967719687196971970719717197271973719747197571976719777197871979719807198171982719837198471985719867198771988719897199071991719927199371994719957199671997719987199972000720017200272003720047200572006720077200872009720107201172012720137201472015720167201772018720197202072021720227202372024720257202672027720287202972030720317203272033720347203572036720377203872039720407204172042720437204472045720467204772048720497205072051720527205372054720557205672057720587205972060720617206272063720647206572066720677206872069720707207172072720737207472075720767207772078720797208072081720827208372084720857208672087720887208972090720917209272093720947209572096720977209872099721007210172102721037210472105721067210772108721097211072111721127211372114721157211672117721187211972120721217212272123721247212572126721277212872129721307213172132721337213472135721367213772138721397214072141721427214372144721457214672147721487214972150721517215272153721547215572156721577215872159721607216172162721637216472165721667216772168721697217072171721727217372174721757217672177721787217972180721817218272183721847218572186721877218872189721907219172192721937219472195721967219772198721997220072201722027220372204722057220672207722087220972210722117221272213722147221572216722177221872219722207222172222722237222472225722267222772228722297223072231722327223372234722357223672237722387223972240722417224272243722447224572246722477224872249722507225172252722537225472255722567225772258722597226072261722627226372264722657226672267722687226972270722717227272273722747227572276722777227872279722807228172282722837228472285722867228772288722897229072291722927229372294722957229672297722987229972300723017230272303723047230572306723077230872309723107231172312723137231472315723167231772318723197232072321723227232372324723257232672327723287232972330723317233272333723347233572336723377233872339723407234172342723437234472345723467234772348723497235072351723527235372354723557235672357723587235972360723617236272363723647236572366723677236872369723707237172372723737237472375723767237772378723797238072381723827238372384723857238672387723887238972390723917239272393723947239572396723977239872399724007240172402724037240472405724067240772408724097241072411724127241372414724157241672417724187241972420724217242272423724247242572426724277242872429724307243172432724337243472435724367243772438724397244072441724427244372444724457244672447724487244972450724517245272453724547245572456724577245872459724607246172462724637246472465724667246772468724697247072471724727247372474724757247672477724787247972480724817248272483724847248572486724877248872489724907249172492724937249472495724967249772498724997250072501725027250372504725057250672507725087250972510725117251272513725147251572516725177251872519725207252172522725237252472525725267252772528725297253072531725327253372534725357253672537725387253972540725417254272543725447254572546725477254872549725507255172552725537255472555725567255772558725597256072561725627256372564725657256672567725687256972570725717257272573725747257572576725777257872579725807258172582725837258472585725867258772588725897259072591725927259372594725957259672597725987259972600726017260272603726047260572606726077260872609726107261172612726137261472615726167261772618726197262072621726227262372624726257262672627726287262972630726317263272633726347263572636726377263872639726407264172642726437264472645726467264772648726497265072651726527265372654726557265672657726587265972660726617266272663726647266572666726677266872669726707267172672726737267472675726767267772678726797268072681726827268372684726857268672687726887268972690726917269272693726947269572696726977269872699727007270172702727037270472705727067270772708727097271072711727127271372714727157271672717727187271972720727217272272723727247272572726727277272872729727307273172732727337273472735727367273772738727397274072741727427274372744727457274672747727487274972750727517275272753727547275572756727577275872759727607276172762727637276472765727667276772768727697277072771727727277372774727757277672777727787277972780727817278272783727847278572786727877278872789727907279172792727937279472795727967279772798727997280072801728027280372804728057280672807728087280972810728117281272813728147281572816728177281872819728207282172822728237282472825728267282772828728297283072831728327283372834728357283672837728387283972840728417284272843728447284572846728477284872849728507285172852728537285472855728567285772858728597286072861728627286372864728657286672867728687286972870728717287272873728747287572876728777287872879728807288172882728837288472885728867288772888728897289072891728927289372894728957289672897728987289972900729017290272903729047290572906729077290872909729107291172912729137291472915729167291772918729197292072921729227292372924729257292672927729287292972930729317293272933729347293572936729377293872939729407294172942729437294472945729467294772948729497295072951729527295372954729557295672957729587295972960729617296272963729647296572966729677296872969729707297172972729737297472975729767297772978729797298072981729827298372984729857298672987729887298972990729917299272993729947299572996729977299872999730007300173002730037300473005730067300773008730097301073011730127301373014730157301673017730187301973020730217302273023730247302573026730277302873029730307303173032730337303473035730367303773038730397304073041730427304373044730457304673047730487304973050730517305273053730547305573056730577305873059730607306173062730637306473065730667306773068730697307073071730727307373074730757307673077730787307973080730817308273083730847308573086730877308873089730907309173092730937309473095730967309773098730997310073101731027310373104731057310673107731087310973110731117311273113731147311573116731177311873119731207312173122731237312473125731267312773128731297313073131731327313373134731357313673137731387313973140731417314273143731447314573146731477314873149731507315173152731537315473155731567315773158731597316073161731627316373164731657316673167731687316973170731717317273173731747317573176731777317873179731807318173182731837318473185731867318773188731897319073191731927319373194731957319673197731987319973200732017320273203732047320573206732077320873209732107321173212732137321473215732167321773218732197322073221732227322373224732257322673227732287322973230732317323273233732347323573236732377323873239732407324173242732437324473245732467324773248732497325073251732527325373254732557325673257732587325973260732617326273263732647326573266732677326873269732707327173272732737327473275732767327773278732797328073281732827328373284732857328673287732887328973290732917329273293732947329573296732977329873299733007330173302733037330473305733067330773308733097331073311733127331373314733157331673317733187331973320733217332273323733247332573326733277332873329733307333173332733337333473335733367333773338733397334073341733427334373344733457334673347733487334973350733517335273353733547335573356733577335873359733607336173362733637336473365733667336773368733697337073371733727337373374733757337673377733787337973380733817338273383733847338573386733877338873389733907339173392733937339473395733967339773398733997340073401734027340373404734057340673407734087340973410734117341273413734147341573416734177341873419734207342173422734237342473425734267342773428734297343073431734327343373434734357343673437734387343973440734417344273443734447344573446734477344873449734507345173452734537345473455734567345773458734597346073461734627346373464734657346673467734687346973470734717347273473734747347573476734777347873479734807348173482734837348473485734867348773488734897349073491734927349373494734957349673497734987349973500735017350273503735047350573506735077350873509735107351173512735137351473515735167351773518735197352073521735227352373524735257352673527735287352973530735317353273533735347353573536735377353873539735407354173542735437354473545735467354773548735497355073551735527355373554735557355673557735587355973560735617356273563735647356573566735677356873569735707357173572735737357473575735767357773578735797358073581735827358373584735857358673587735887358973590735917359273593735947359573596735977359873599736007360173602736037360473605736067360773608736097361073611736127361373614736157361673617736187361973620736217362273623736247362573626736277362873629736307363173632736337363473635736367363773638736397364073641736427364373644736457364673647736487364973650736517365273653736547365573656736577365873659736607366173662736637366473665736667366773668736697367073671736727367373674736757367673677736787367973680736817368273683736847368573686736877368873689736907369173692736937369473695736967369773698736997370073701737027370373704737057370673707737087370973710737117371273713737147371573716737177371873719737207372173722737237372473725737267372773728737297373073731737327373373734737357373673737737387373973740737417374273743737447374573746737477374873749737507375173752737537375473755737567375773758737597376073761737627376373764737657376673767737687376973770737717377273773737747377573776737777377873779737807378173782737837378473785737867378773788737897379073791737927379373794737957379673797737987379973800738017380273803738047380573806738077380873809738107381173812738137381473815738167381773818738197382073821738227382373824738257382673827738287382973830738317383273833738347383573836738377383873839738407384173842738437384473845738467384773848738497385073851738527385373854738557385673857738587385973860738617386273863738647386573866738677386873869738707387173872738737387473875738767387773878738797388073881738827388373884738857388673887738887388973890738917389273893738947389573896738977389873899739007390173902739037390473905739067390773908739097391073911739127391373914739157391673917739187391973920739217392273923739247392573926739277392873929739307393173932739337393473935739367393773938739397394073941739427394373944739457394673947739487394973950739517395273953739547395573956739577395873959739607396173962739637396473965739667396773968739697397073971739727397373974739757397673977739787397973980739817398273983739847398573986739877398873989739907399173992739937399473995739967399773998739997400074001740027400374004740057400674007740087400974010740117401274013740147401574016740177401874019740207402174022740237402474025740267402774028740297403074031740327403374034740357403674037740387403974040740417404274043740447404574046740477404874049740507405174052740537405474055740567405774058740597406074061740627406374064740657406674067740687406974070740717407274073740747407574076740777407874079740807408174082740837408474085740867408774088740897409074091740927409374094740957409674097740987409974100741017410274103741047410574106741077410874109741107411174112741137411474115741167411774118741197412074121741227412374124741257412674127741287412974130741317413274133741347413574136741377413874139741407414174142741437414474145741467414774148741497415074151741527415374154741557415674157741587415974160741617416274163741647416574166741677416874169741707417174172741737417474175741767417774178741797418074181741827418374184741857418674187741887418974190741917419274193741947419574196741977419874199742007420174202742037420474205742067420774208742097421074211742127421374214742157421674217742187421974220742217422274223742247422574226742277422874229742307423174232742337423474235742367423774238742397424074241742427424374244742457424674247742487424974250742517425274253742547425574256742577425874259742607426174262742637426474265742667426774268742697427074271742727427374274742757427674277742787427974280742817428274283742847428574286742877428874289742907429174292742937429474295742967429774298742997430074301743027430374304743057430674307743087430974310743117431274313743147431574316743177431874319743207432174322743237432474325743267432774328743297433074331743327433374334743357433674337743387433974340743417434274343743447434574346743477434874349743507435174352743537435474355743567435774358743597436074361743627436374364743657436674367743687436974370743717437274373743747437574376743777437874379743807438174382743837438474385743867438774388743897439074391743927439374394743957439674397743987439974400744017440274403744047440574406744077440874409744107441174412744137441474415744167441774418744197442074421744227442374424744257442674427744287442974430744317443274433744347443574436744377443874439744407444174442744437444474445744467444774448744497445074451744527445374454744557445674457744587445974460744617446274463744647446574466744677446874469744707447174472744737447474475744767447774478744797448074481744827448374484744857448674487744887448974490744917449274493744947449574496744977449874499745007450174502745037450474505745067450774508745097451074511745127451374514745157451674517745187451974520745217452274523745247452574526745277452874529745307453174532745337453474535745367453774538745397454074541745427454374544745457454674547745487454974550745517455274553745547455574556745577455874559745607456174562745637456474565745667456774568745697457074571745727457374574745757457674577745787457974580745817458274583745847458574586745877458874589745907459174592745937459474595745967459774598745997460074601746027460374604746057460674607746087460974610746117461274613746147461574616746177461874619746207462174622746237462474625746267462774628746297463074631746327463374634746357463674637746387463974640746417464274643746447464574646746477464874649746507465174652746537465474655746567465774658746597466074661746627466374664746657466674667746687466974670746717467274673746747467574676746777467874679746807468174682746837468474685746867468774688746897469074691746927469374694746957469674697746987469974700747017470274703747047470574706747077470874709747107471174712747137471474715747167471774718747197472074721747227472374724747257472674727747287472974730747317473274733747347473574736747377473874739747407474174742747437474474745747467474774748747497475074751747527475374754747557475674757747587475974760747617476274763747647476574766747677476874769747707477174772747737477474775747767477774778747797478074781747827478374784747857478674787747887478974790747917479274793747947479574796747977479874799748007480174802748037480474805748067480774808748097481074811748127481374814748157481674817748187481974820748217482274823748247482574826748277482874829748307483174832748337483474835748367483774838748397484074841748427484374844748457484674847748487484974850748517485274853748547485574856748577485874859748607486174862748637486474865748667486774868748697487074871748727487374874748757487674877748787487974880748817488274883748847488574886748877488874889748907489174892748937489474895748967489774898748997490074901749027490374904749057490674907749087490974910749117491274913749147491574916749177491874919749207492174922749237492474925749267492774928749297493074931749327493374934749357493674937749387493974940749417494274943749447494574946749477494874949749507495174952749537495474955749567495774958749597496074961749627496374964749657496674967749687496974970749717497274973749747497574976749777497874979749807498174982749837498474985749867498774988749897499074991749927499374994749957499674997749987499975000750017500275003750047500575006750077500875009750107501175012750137501475015750167501775018750197502075021750227502375024750257502675027750287502975030750317503275033750347503575036750377503875039750407504175042750437504475045750467504775048750497505075051750527505375054750557505675057750587505975060750617506275063750647506575066750677506875069750707507175072750737507475075750767507775078750797508075081750827508375084750857508675087750887508975090750917509275093750947509575096750977509875099751007510175102751037510475105751067510775108751097511075111751127511375114751157511675117751187511975120751217512275123751247512575126751277512875129751307513175132751337513475135751367513775138751397514075141751427514375144751457514675147751487514975150751517515275153751547515575156751577515875159751607516175162751637516475165751667516775168751697517075171751727517375174751757517675177751787517975180751817518275183751847518575186751877518875189751907519175192751937519475195751967519775198751997520075201752027520375204752057520675207752087520975210752117521275213752147521575216752177521875219752207522175222752237522475225752267522775228752297523075231752327523375234752357523675237752387523975240752417524275243752447524575246752477524875249752507525175252752537525475255752567525775258752597526075261752627526375264752657526675267752687526975270752717527275273752747527575276752777527875279752807528175282752837528475285752867528775288752897529075291752927529375294752957529675297752987529975300753017530275303753047530575306753077530875309753107531175312753137531475315753167531775318753197532075321753227532375324753257532675327753287532975330753317533275333753347533575336753377533875339753407534175342753437534475345753467534775348753497535075351753527535375354753557535675357753587535975360753617536275363753647536575366753677536875369753707537175372753737537475375753767537775378753797538075381753827538375384753857538675387753887538975390753917539275393753947539575396753977539875399754007540175402754037540475405754067540775408754097541075411754127541375414754157541675417754187541975420754217542275423754247542575426754277542875429754307543175432754337543475435754367543775438754397544075441754427544375444754457544675447754487544975450754517545275453754547545575456754577545875459754607546175462754637546475465754667546775468754697547075471754727547375474754757547675477754787547975480754817548275483754847548575486754877548875489754907549175492754937549475495754967549775498754997550075501755027550375504755057550675507755087550975510755117551275513755147551575516755177551875519755207552175522755237552475525755267552775528755297553075531755327553375534755357553675537755387553975540755417554275543755447554575546755477554875549755507555175552755537555475555755567555775558755597556075561755627556375564755657556675567755687556975570755717557275573755747557575576755777557875579755807558175582755837558475585755867558775588755897559075591755927559375594755957559675597755987559975600756017560275603756047560575606756077560875609756107561175612756137561475615756167561775618756197562075621756227562375624756257562675627756287562975630756317563275633756347563575636756377563875639756407564175642756437564475645756467564775648756497565075651756527565375654756557565675657756587565975660756617566275663756647566575666756677566875669756707567175672756737567475675756767567775678756797568075681756827568375684756857568675687756887568975690756917569275693756947569575696756977569875699757007570175702757037570475705757067570775708757097571075711757127571375714757157571675717757187571975720757217572275723757247572575726757277572875729757307573175732757337573475735757367573775738757397574075741757427574375744757457574675747757487574975750757517575275753757547575575756757577575875759757607576175762757637576475765757667576775768757697577075771757727577375774757757577675777757787577975780757817578275783757847578575786757877578875789757907579175792757937579475795757967579775798757997580075801758027580375804758057580675807758087580975810758117581275813758147581575816758177581875819758207582175822758237582475825758267582775828758297583075831758327583375834758357583675837758387583975840758417584275843758447584575846758477584875849758507585175852758537585475855758567585775858758597586075861758627586375864758657586675867758687586975870758717587275873758747587575876758777587875879758807588175882758837588475885758867588775888758897589075891758927589375894758957589675897758987589975900759017590275903759047590575906759077590875909759107591175912759137591475915759167591775918759197592075921759227592375924759257592675927759287592975930759317593275933759347593575936759377593875939759407594175942759437594475945759467594775948759497595075951759527595375954759557595675957759587595975960759617596275963759647596575966759677596875969759707597175972759737597475975759767597775978759797598075981759827598375984759857598675987759887598975990759917599275993759947599575996759977599875999760007600176002760037600476005760067600776008760097601076011760127601376014760157601676017760187601976020760217602276023760247602576026760277602876029760307603176032760337603476035760367603776038760397604076041760427604376044760457604676047760487604976050760517605276053760547605576056760577605876059760607606176062760637606476065760667606776068760697607076071760727607376074760757607676077760787607976080760817608276083760847608576086760877608876089760907609176092760937609476095760967609776098760997610076101761027610376104761057610676107761087610976110761117611276113761147611576116761177611876119761207612176122761237612476125761267612776128761297613076131761327613376134761357613676137761387613976140761417614276143761447614576146761477614876149761507615176152761537615476155761567615776158761597616076161761627616376164761657616676167761687616976170761717617276173761747617576176761777617876179761807618176182761837618476185761867618776188761897619076191761927619376194761957619676197761987619976200762017620276203762047620576206762077620876209762107621176212762137621476215762167621776218762197622076221762227622376224762257622676227762287622976230762317623276233762347623576236762377623876239762407624176242762437624476245762467624776248762497625076251762527625376254762557625676257762587625976260762617626276263762647626576266762677626876269762707627176272762737627476275762767627776278762797628076281762827628376284762857628676287762887628976290762917629276293762947629576296762977629876299763007630176302763037630476305763067630776308763097631076311763127631376314763157631676317763187631976320763217632276323763247632576326763277632876329763307633176332763337633476335763367633776338763397634076341763427634376344763457634676347763487634976350763517635276353763547635576356763577635876359763607636176362763637636476365763667636776368763697637076371763727637376374763757637676377763787637976380763817638276383763847638576386763877638876389763907639176392763937639476395763967639776398763997640076401764027640376404764057640676407764087640976410764117641276413764147641576416764177641876419764207642176422764237642476425764267642776428764297643076431764327643376434764357643676437764387643976440764417644276443764447644576446764477644876449764507645176452764537645476455764567645776458764597646076461764627646376464764657646676467764687646976470764717647276473764747647576476764777647876479764807648176482764837648476485764867648776488764897649076491764927649376494764957649676497764987649976500765017650276503765047650576506765077650876509765107651176512765137651476515765167651776518765197652076521765227652376524765257652676527765287652976530765317653276533765347653576536765377653876539765407654176542765437654476545765467654776548765497655076551765527655376554765557655676557765587655976560765617656276563765647656576566765677656876569765707657176572765737657476575765767657776578765797658076581765827658376584765857658676587765887658976590765917659276593765947659576596765977659876599766007660176602766037660476605766067660776608766097661076611766127661376614766157661676617766187661976620766217662276623766247662576626766277662876629766307663176632766337663476635766367663776638766397664076641766427664376644766457664676647766487664976650766517665276653766547665576656766577665876659766607666176662766637666476665766667666776668766697667076671766727667376674766757667676677766787667976680766817668276683766847668576686766877668876689766907669176692766937669476695766967669776698766997670076701767027670376704767057670676707767087670976710767117671276713767147671576716767177671876719767207672176722767237672476725767267672776728767297673076731767327673376734767357673676737767387673976740767417674276743767447674576746767477674876749767507675176752767537675476755767567675776758767597676076761767627676376764767657676676767767687676976770767717677276773767747677576776767777677876779767807678176782767837678476785767867678776788767897679076791767927679376794767957679676797767987679976800768017680276803768047680576806768077680876809768107681176812768137681476815768167681776818768197682076821768227682376824768257682676827768287682976830768317683276833768347683576836768377683876839768407684176842768437684476845768467684776848768497685076851768527685376854768557685676857768587685976860768617686276863768647686576866768677686876869768707687176872768737687476875768767687776878768797688076881768827688376884768857688676887768887688976890768917689276893768947689576896768977689876899769007690176902769037690476905769067690776908769097691076911769127691376914769157691676917769187691976920769217692276923769247692576926769277692876929769307693176932769337693476935769367693776938769397694076941769427694376944769457694676947769487694976950769517695276953769547695576956769577695876959769607696176962769637696476965769667696776968769697697076971769727697376974769757697676977769787697976980769817698276983769847698576986769877698876989769907699176992769937699476995769967699776998769997700077001770027700377004770057700677007770087700977010770117701277013770147701577016770177701877019770207702177022770237702477025770267702777028770297703077031770327703377034770357703677037770387703977040770417704277043770447704577046770477704877049770507705177052770537705477055770567705777058770597706077061770627706377064770657706677067770687706977070770717707277073770747707577076770777707877079770807708177082770837708477085770867708777088770897709077091770927709377094770957709677097770987709977100771017710277103771047710577106771077710877109771107711177112771137711477115771167711777118771197712077121771227712377124771257712677127771287712977130771317713277133771347713577136771377713877139771407714177142771437714477145771467714777148771497715077151771527715377154771557715677157771587715977160771617716277163771647716577166771677716877169771707717177172771737717477175771767717777178771797718077181771827718377184771857718677187771887718977190771917719277193771947719577196771977719877199772007720177202772037720477205772067720777208772097721077211772127721377214772157721677217772187721977220772217722277223772247722577226772277722877229772307723177232772337723477235772367723777238772397724077241772427724377244772457724677247772487724977250772517725277253772547725577256772577725877259772607726177262772637726477265772667726777268772697727077271772727727377274772757727677277772787727977280772817728277283772847728577286772877728877289772907729177292772937729477295772967729777298772997730077301773027730377304773057730677307773087730977310773117731277313773147731577316773177731877319773207732177322773237732477325773267732777328773297733077331773327733377334773357733677337773387733977340773417734277343773447734577346773477734877349773507735177352773537735477355773567735777358773597736077361773627736377364773657736677367773687736977370773717737277373773747737577376773777737877379773807738177382773837738477385773867738777388773897739077391773927739377394773957739677397773987739977400774017740277403774047740577406774077740877409774107741177412774137741477415774167741777418774197742077421774227742377424774257742677427774287742977430774317743277433774347743577436774377743877439774407744177442774437744477445774467744777448774497745077451774527745377454774557745677457774587745977460774617746277463774647746577466774677746877469774707747177472774737747477475774767747777478774797748077481774827748377484774857748677487774887748977490774917749277493774947749577496774977749877499775007750177502775037750477505775067750777508775097751077511775127751377514775157751677517775187751977520775217752277523775247752577526775277752877529775307753177532775337753477535775367753777538775397754077541775427754377544775457754677547775487754977550775517755277553775547755577556775577755877559775607756177562775637756477565775667756777568775697757077571775727757377574775757757677577775787757977580775817758277583775847758577586775877758877589775907759177592775937759477595775967759777598775997760077601776027760377604776057760677607776087760977610776117761277613776147761577616776177761877619776207762177622776237762477625776267762777628776297763077631776327763377634776357763677637776387763977640776417764277643776447764577646776477764877649776507765177652776537765477655776567765777658776597766077661776627766377664776657766677667776687766977670776717767277673776747767577676776777767877679776807768177682776837768477685776867768777688776897769077691776927769377694776957769677697776987769977700777017770277703777047770577706777077770877709777107771177712777137771477715777167771777718777197772077721777227772377724777257772677727777287772977730777317773277733777347773577736777377773877739777407774177742777437774477745777467774777748777497775077751777527775377754777557775677757777587775977760777617776277763777647776577766777677776877769777707777177772777737777477775777767777777778777797778077781777827778377784777857778677787777887778977790777917779277793777947779577796777977779877799778007780177802778037780477805778067780777808778097781077811778127781377814778157781677817778187781977820778217782277823778247782577826778277782877829778307783177832778337783477835778367783777838778397784077841778427784377844778457784677847778487784977850778517785277853778547785577856778577785877859778607786177862778637786477865778667786777868778697787077871778727787377874778757787677877778787787977880778817788277883778847788577886778877788877889778907789177892778937789477895778967789777898778997790077901779027790377904779057790677907779087790977910779117791277913779147791577916779177791877919779207792177922779237792477925779267792777928779297793077931779327793377934779357793677937779387793977940779417794277943779447794577946779477794877949779507795177952779537795477955779567795777958779597796077961779627796377964779657796677967779687796977970779717797277973779747797577976779777797877979779807798177982779837798477985779867798777988779897799077991779927799377994779957799677997779987799978000780017800278003780047800578006780077800878009780107801178012780137801478015780167801778018780197802078021780227802378024780257802678027780287802978030780317803278033780347803578036780377803878039780407804178042780437804478045780467804778048780497805078051780527805378054780557805678057780587805978060780617806278063780647806578066780677806878069780707807178072780737807478075780767807778078780797808078081780827808378084780857808678087780887808978090780917809278093780947809578096780977809878099781007810178102781037810478105781067810778108781097811078111781127811378114781157811678117781187811978120781217812278123781247812578126781277812878129781307813178132781337813478135781367813778138781397814078141781427814378144781457814678147781487814978150781517815278153781547815578156781577815878159781607816178162781637816478165781667816778168781697817078171781727817378174781757817678177781787817978180781817818278183781847818578186781877818878189781907819178192781937819478195781967819778198781997820078201782027820378204782057820678207782087820978210782117821278213782147821578216782177821878219782207822178222782237822478225782267822778228782297823078231782327823378234782357823678237782387823978240782417824278243782447824578246782477824878249782507825178252782537825478255782567825778258782597826078261782627826378264782657826678267782687826978270782717827278273782747827578276782777827878279782807828178282782837828478285782867828778288782897829078291782927829378294782957829678297782987829978300783017830278303783047830578306783077830878309783107831178312783137831478315783167831778318783197832078321783227832378324783257832678327783287832978330783317833278333783347833578336783377833878339783407834178342783437834478345783467834778348783497835078351783527835378354783557835678357783587835978360783617836278363783647836578366783677836878369783707837178372783737837478375783767837778378783797838078381783827838378384783857838678387783887838978390783917839278393783947839578396783977839878399784007840178402784037840478405784067840778408784097841078411784127841378414784157841678417784187841978420784217842278423784247842578426784277842878429784307843178432784337843478435784367843778438784397844078441784427844378444784457844678447784487844978450784517845278453784547845578456784577845878459784607846178462784637846478465784667846778468784697847078471784727847378474784757847678477784787847978480784817848278483784847848578486784877848878489784907849178492784937849478495784967849778498784997850078501785027850378504785057850678507785087850978510785117851278513785147851578516785177851878519785207852178522785237852478525785267852778528785297853078531785327853378534785357853678537785387853978540785417854278543785447854578546785477854878549785507855178552785537855478555785567855778558785597856078561785627856378564785657856678567785687856978570785717857278573785747857578576785777857878579785807858178582785837858478585785867858778588785897859078591785927859378594785957859678597785987859978600786017860278603786047860578606786077860878609786107861178612786137861478615786167861778618786197862078621786227862378624786257862678627786287862978630786317863278633786347863578636786377863878639786407864178642786437864478645786467864778648786497865078651786527865378654786557865678657786587865978660786617866278663786647866578666786677866878669786707867178672786737867478675786767867778678786797868078681786827868378684786857868678687786887868978690786917869278693786947869578696786977869878699787007870178702787037870478705787067870778708787097871078711787127871378714787157871678717787187871978720787217872278723787247872578726787277872878729787307873178732787337873478735787367873778738787397874078741787427874378744787457874678747787487874978750787517875278753787547875578756787577875878759787607876178762787637876478765787667876778768787697877078771787727877378774787757877678777787787877978780787817878278783787847878578786787877878878789787907879178792787937879478795787967879778798787997880078801788027880378804788057880678807788087880978810788117881278813788147881578816788177881878819788207882178822788237882478825788267882778828788297883078831788327883378834788357883678837788387883978840788417884278843788447884578846788477884878849788507885178852788537885478855788567885778858788597886078861788627886378864788657886678867788687886978870788717887278873788747887578876788777887878879788807888178882788837888478885788867888778888788897889078891788927889378894788957889678897788987889978900789017890278903789047890578906789077890878909789107891178912789137891478915789167891778918789197892078921789227892378924789257892678927789287892978930789317893278933789347893578936789377893878939789407894178942789437894478945789467894778948789497895078951789527895378954789557895678957789587895978960789617896278963789647896578966789677896878969789707897178972789737897478975789767897778978789797898078981789827898378984789857898678987789887898978990789917899278993789947899578996789977899878999790007900179002790037900479005790067900779008790097901079011790127901379014790157901679017790187901979020790217902279023790247902579026790277902879029790307903179032790337903479035790367903779038790397904079041790427904379044790457904679047790487904979050790517905279053790547905579056790577905879059790607906179062790637906479065790667906779068790697907079071790727907379074790757907679077790787907979080790817908279083790847908579086790877908879089790907909179092790937909479095790967909779098790997910079101791027910379104791057910679107791087910979110791117911279113791147911579116791177911879119791207912179122791237912479125791267912779128791297913079131791327913379134791357913679137791387913979140791417914279143791447914579146791477914879149791507915179152791537915479155791567915779158791597916079161791627916379164791657916679167791687916979170791717917279173791747917579176791777917879179791807918179182791837918479185791867918779188791897919079191791927919379194791957919679197791987919979200792017920279203792047920579206792077920879209792107921179212792137921479215792167921779218792197922079221792227922379224792257922679227792287922979230792317923279233792347923579236792377923879239792407924179242792437924479245792467924779248792497925079251792527925379254792557925679257792587925979260792617926279263792647926579266792677926879269792707927179272792737927479275792767927779278792797928079281792827928379284792857928679287792887928979290792917929279293792947929579296792977929879299793007930179302793037930479305793067930779308793097931079311793127931379314793157931679317793187931979320793217932279323793247932579326793277932879329793307933179332793337933479335793367933779338793397934079341793427934379344793457934679347793487934979350793517935279353793547935579356793577935879359793607936179362793637936479365793667936779368793697937079371793727937379374793757937679377793787937979380793817938279383793847938579386793877938879389793907939179392793937939479395793967939779398793997940079401794027940379404794057940679407794087940979410794117941279413794147941579416794177941879419794207942179422794237942479425794267942779428794297943079431794327943379434794357943679437794387943979440794417944279443794447944579446794477944879449794507945179452794537945479455794567945779458794597946079461794627946379464794657946679467794687946979470794717947279473794747947579476794777947879479794807948179482794837948479485794867948779488794897949079491794927949379494794957949679497794987949979500795017950279503795047950579506795077950879509795107951179512795137951479515795167951779518795197952079521795227952379524795257952679527795287952979530795317953279533795347953579536795377953879539795407954179542795437954479545795467954779548795497955079551795527955379554795557955679557795587955979560795617956279563795647956579566795677956879569795707957179572795737957479575795767957779578795797958079581795827958379584795857958679587795887958979590795917959279593795947959579596795977959879599796007960179602796037960479605796067960779608796097961079611796127961379614796157961679617796187961979620796217962279623796247962579626796277962879629796307963179632796337963479635796367963779638796397964079641796427964379644796457964679647796487964979650796517965279653796547965579656796577965879659796607966179662796637966479665796667966779668796697967079671796727967379674796757967679677796787967979680796817968279683796847968579686796877968879689796907969179692796937969479695796967969779698796997970079701797027970379704797057970679707797087970979710797117971279713797147971579716797177971879719797207972179722797237972479725797267972779728797297973079731797327973379734797357973679737797387973979740797417974279743797447974579746797477974879749797507975179752797537975479755797567975779758797597976079761797627976379764797657976679767797687976979770797717977279773797747977579776797777977879779797807978179782797837978479785797867978779788797897979079791797927979379794797957979679797797987979979800798017980279803798047980579806798077980879809798107981179812798137981479815798167981779818798197982079821798227982379824798257982679827798287982979830798317983279833798347983579836798377983879839798407984179842798437984479845798467984779848798497985079851798527985379854798557985679857798587985979860798617986279863798647986579866798677986879869798707987179872798737987479875798767987779878798797988079881798827988379884798857988679887798887988979890798917989279893798947989579896798977989879899799007990179902799037990479905799067990779908799097991079911799127991379914799157991679917799187991979920799217992279923799247992579926799277992879929799307993179932799337993479935799367993779938799397994079941799427994379944799457994679947799487994979950799517995279953799547995579956799577995879959799607996179962799637996479965799667996779968799697997079971799727997379974799757997679977799787997979980799817998279983799847998579986799877998879989799907999179992799937999479995799967999779998799998000080001800028000380004800058000680007800088000980010800118001280013800148001580016800178001880019800208002180022800238002480025800268002780028800298003080031800328003380034800358003680037800388003980040800418004280043800448004580046800478004880049800508005180052800538005480055800568005780058800598006080061800628006380064800658006680067800688006980070800718007280073800748007580076800778007880079800808008180082800838008480085800868008780088800898009080091800928009380094800958009680097800988009980100801018010280103801048010580106801078010880109801108011180112801138011480115801168011780118801198012080121801228012380124801258012680127801288012980130801318013280133801348013580136801378013880139801408014180142801438014480145801468014780148801498015080151801528015380154801558015680157801588015980160801618016280163801648016580166801678016880169801708017180172801738017480175801768017780178801798018080181801828018380184801858018680187801888018980190801918019280193801948019580196801978019880199802008020180202802038020480205802068020780208802098021080211802128021380214802158021680217802188021980220802218022280223802248022580226802278022880229802308023180232802338023480235802368023780238802398024080241802428024380244802458024680247802488024980250802518025280253802548025580256802578025880259802608026180262802638026480265802668026780268802698027080271802728027380274802758027680277802788027980280802818028280283802848028580286802878028880289802908029180292802938029480295802968029780298802998030080301803028030380304803058030680307803088030980310803118031280313803148031580316803178031880319803208032180322803238032480325803268032780328803298033080331803328033380334803358033680337803388033980340803418034280343803448034580346803478034880349803508035180352803538035480355803568035780358803598036080361803628036380364803658036680367803688036980370803718037280373803748037580376803778037880379803808038180382803838038480385803868038780388803898039080391803928039380394803958039680397803988039980400804018040280403804048040580406804078040880409804108041180412804138041480415804168041780418804198042080421804228042380424804258042680427804288042980430804318043280433804348043580436804378043880439804408044180442804438044480445804468044780448804498045080451804528045380454804558045680457804588045980460804618046280463804648046580466804678046880469804708047180472804738047480475804768047780478804798048080481804828048380484804858048680487804888048980490804918049280493804948049580496804978049880499805008050180502805038050480505805068050780508805098051080511805128051380514805158051680517805188051980520805218052280523805248052580526805278052880529805308053180532805338053480535805368053780538805398054080541805428054380544805458054680547805488054980550805518055280553805548055580556805578055880559805608056180562805638056480565805668056780568805698057080571805728057380574805758057680577805788057980580805818058280583805848058580586805878058880589805908059180592805938059480595805968059780598805998060080601806028060380604806058060680607806088060980610806118061280613806148061580616806178061880619806208062180622806238062480625806268062780628806298063080631806328063380634806358063680637806388063980640806418064280643806448064580646806478064880649806508065180652806538065480655806568065780658806598066080661806628066380664806658066680667806688066980670806718067280673806748067580676806778067880679806808068180682806838068480685806868068780688806898069080691806928069380694806958069680697806988069980700807018070280703807048070580706807078070880709807108071180712807138071480715807168071780718807198072080721807228072380724807258072680727807288072980730807318073280733807348073580736807378073880739807408074180742807438074480745807468074780748807498075080751807528075380754807558075680757807588075980760807618076280763807648076580766807678076880769807708077180772807738077480775807768077780778807798078080781807828078380784807858078680787807888078980790807918079280793807948079580796807978079880799808008080180802808038080480805808068080780808808098081080811808128081380814808158081680817808188081980820808218082280823808248082580826808278082880829808308083180832808338083480835808368083780838808398084080841808428084380844808458084680847808488084980850808518085280853808548085580856808578085880859808608086180862808638086480865808668086780868808698087080871808728087380874808758087680877808788087980880808818088280883808848088580886808878088880889808908089180892808938089480895808968089780898808998090080901809028090380904809058090680907809088090980910809118091280913809148091580916809178091880919809208092180922809238092480925809268092780928809298093080931809328093380934809358093680937809388093980940809418094280943809448094580946809478094880949809508095180952809538095480955809568095780958809598096080961809628096380964809658096680967809688096980970809718097280973809748097580976809778097880979809808098180982809838098480985809868098780988809898099080991809928099380994809958099680997809988099981000810018100281003810048100581006810078100881009810108101181012810138101481015810168101781018810198102081021810228102381024810258102681027810288102981030810318103281033810348103581036810378103881039810408104181042810438104481045810468104781048810498105081051810528105381054810558105681057810588105981060810618106281063810648106581066810678106881069810708107181072810738107481075810768107781078810798108081081810828108381084810858108681087810888108981090810918109281093810948109581096810978109881099811008110181102811038110481105811068110781108811098111081111811128111381114811158111681117811188111981120811218112281123811248112581126811278112881129811308113181132811338113481135811368113781138811398114081141811428114381144811458114681147811488114981150811518115281153811548115581156811578115881159811608116181162811638116481165811668116781168811698117081171811728117381174811758117681177811788117981180811818118281183811848118581186811878118881189811908119181192811938119481195811968119781198811998120081201812028120381204812058120681207812088120981210812118121281213812148121581216812178121881219812208122181222812238122481225812268122781228812298123081231812328123381234812358123681237812388123981240812418124281243812448124581246812478124881249812508125181252812538125481255812568125781258812598126081261812628126381264812658126681267812688126981270812718127281273812748127581276812778127881279812808128181282812838128481285812868128781288812898129081291812928129381294812958129681297812988129981300813018130281303813048130581306813078130881309813108131181312813138131481315813168131781318813198132081321813228132381324813258132681327813288132981330813318133281333813348133581336813378133881339813408134181342813438134481345813468134781348813498135081351813528135381354813558135681357813588135981360813618136281363813648136581366813678136881369813708137181372813738137481375813768137781378813798138081381813828138381384813858138681387813888138981390813918139281393813948139581396813978139881399814008140181402814038140481405814068140781408814098141081411814128141381414814158141681417814188141981420814218142281423814248142581426814278142881429814308143181432814338143481435814368143781438814398144081441814428144381444814458144681447814488144981450814518145281453814548145581456814578145881459814608146181462814638146481465814668146781468814698147081471814728147381474814758147681477814788147981480814818148281483814848148581486814878148881489814908149181492814938149481495814968149781498814998150081501815028150381504815058150681507815088150981510815118151281513815148151581516815178151881519815208152181522815238152481525815268152781528815298153081531815328153381534815358153681537815388153981540815418154281543815448154581546815478154881549815508155181552815538155481555815568155781558815598156081561815628156381564815658156681567815688156981570815718157281573815748157581576815778157881579815808158181582815838158481585815868158781588815898159081591815928159381594815958159681597815988159981600816018160281603816048160581606816078160881609816108161181612816138161481615816168161781618816198162081621816228162381624816258162681627816288162981630816318163281633816348163581636816378163881639816408164181642816438164481645816468164781648816498165081651816528165381654816558165681657816588165981660816618166281663816648166581666816678166881669816708167181672816738167481675816768167781678816798168081681816828168381684816858168681687816888168981690816918169281693816948169581696816978169881699817008170181702817038170481705817068170781708817098171081711817128171381714817158171681717817188171981720817218172281723817248172581726817278172881729817308173181732817338173481735817368173781738817398174081741817428174381744817458174681747817488174981750817518175281753817548175581756817578175881759817608176181762817638176481765817668176781768817698177081771817728177381774817758177681777817788177981780817818178281783817848178581786817878178881789817908179181792817938179481795817968179781798817998180081801818028180381804818058180681807818088180981810818118181281813818148181581816818178181881819818208182181822818238182481825818268182781828818298183081831818328183381834818358183681837818388183981840818418184281843818448184581846818478184881849818508185181852818538185481855818568185781858818598186081861818628186381864818658186681867818688186981870818718187281873818748187581876818778187881879818808188181882818838188481885818868188781888818898189081891818928189381894818958189681897818988189981900819018190281903819048190581906819078190881909819108191181912819138191481915819168191781918819198192081921819228192381924819258192681927819288192981930819318193281933819348193581936819378193881939819408194181942819438194481945819468194781948819498195081951819528195381954819558195681957819588195981960819618196281963819648196581966819678196881969819708197181972819738197481975819768197781978819798198081981819828198381984819858198681987819888198981990819918199281993819948199581996819978199881999820008200182002820038200482005820068200782008820098201082011820128201382014820158201682017820188201982020820218202282023820248202582026820278202882029820308203182032820338203482035820368203782038820398204082041820428204382044820458204682047820488204982050820518205282053820548205582056820578205882059820608206182062820638206482065820668206782068820698207082071820728207382074820758207682077820788207982080820818208282083820848208582086820878208882089820908209182092820938209482095820968209782098820998210082101821028210382104821058210682107821088210982110821118211282113821148211582116821178211882119821208212182122821238212482125821268212782128821298213082131821328213382134821358213682137821388213982140821418214282143821448214582146821478214882149821508215182152821538215482155821568215782158821598216082161821628216382164821658216682167821688216982170821718217282173821748217582176821778217882179821808218182182821838218482185821868218782188821898219082191821928219382194821958219682197821988219982200822018220282203822048220582206822078220882209822108221182212822138221482215822168221782218822198222082221822228222382224822258222682227822288222982230822318223282233822348223582236822378223882239822408224182242822438224482245822468224782248822498225082251822528225382254822558225682257822588225982260822618226282263822648226582266822678226882269822708227182272822738227482275822768227782278822798228082281822828228382284822858228682287822888228982290822918229282293822948229582296822978229882299823008230182302823038230482305823068230782308823098231082311823128231382314823158231682317823188231982320823218232282323823248232582326823278232882329823308233182332823338233482335823368233782338823398234082341823428234382344823458234682347823488234982350823518235282353823548235582356823578235882359823608236182362823638236482365823668236782368823698237082371823728237382374823758237682377823788237982380823818238282383823848238582386823878238882389823908239182392823938239482395823968239782398823998240082401824028240382404824058240682407824088240982410824118241282413824148241582416824178241882419824208242182422824238242482425824268242782428824298243082431824328243382434824358243682437824388243982440824418244282443824448244582446824478244882449824508245182452824538245482455824568245782458824598246082461824628246382464824658246682467824688246982470824718247282473824748247582476824778247882479824808248182482824838248482485824868248782488824898249082491824928249382494824958249682497824988249982500825018250282503825048250582506825078250882509825108251182512825138251482515825168251782518825198252082521825228252382524825258252682527825288252982530825318253282533825348253582536825378253882539825408254182542825438254482545825468254782548825498255082551825528255382554825558255682557825588255982560825618256282563825648256582566825678256882569825708257182572825738257482575825768257782578825798258082581825828258382584825858258682587825888258982590825918259282593825948259582596825978259882599826008260182602826038260482605826068260782608826098261082611826128261382614826158261682617826188261982620826218262282623826248262582626826278262882629826308263182632826338263482635826368263782638826398264082641826428264382644826458264682647826488264982650826518265282653826548265582656826578265882659826608266182662826638266482665826668266782668826698267082671826728267382674826758267682677826788267982680826818268282683826848268582686826878268882689826908269182692826938269482695826968269782698826998270082701827028270382704827058270682707827088270982710827118271282713827148271582716827178271882719827208272182722827238272482725827268272782728827298273082731827328273382734827358273682737827388273982740827418274282743827448274582746827478274882749827508275182752827538275482755827568275782758827598276082761827628276382764827658276682767827688276982770827718277282773827748277582776827778277882779827808278182782827838278482785827868278782788827898279082791827928279382794827958279682797827988279982800828018280282803828048280582806828078280882809828108281182812828138281482815828168281782818828198282082821828228282382824828258282682827828288282982830828318283282833828348283582836828378283882839828408284182842828438284482845828468284782848828498285082851828528285382854828558285682857828588285982860828618286282863828648286582866828678286882869828708287182872828738287482875828768287782878828798288082881828828288382884828858288682887828888288982890828918289282893828948289582896828978289882899829008290182902829038290482905829068290782908829098291082911829128291382914829158291682917829188291982920829218292282923829248292582926829278292882929829308293182932829338293482935829368293782938829398294082941829428294382944829458294682947829488294982950829518295282953829548295582956829578295882959829608296182962829638296482965829668296782968829698297082971829728297382974829758297682977829788297982980829818298282983829848298582986829878298882989829908299182992829938299482995829968299782998829998300083001830028300383004830058300683007830088300983010830118301283013830148301583016830178301883019830208302183022830238302483025830268302783028830298303083031830328303383034830358303683037830388303983040830418304283043830448304583046830478304883049830508305183052830538305483055830568305783058830598306083061830628306383064830658306683067830688306983070830718307283073830748307583076830778307883079830808308183082830838308483085830868308783088830898309083091830928309383094830958309683097830988309983100831018310283103831048310583106831078310883109831108311183112831138311483115831168311783118831198312083121831228312383124831258312683127831288312983130831318313283133831348313583136831378313883139831408314183142831438314483145831468314783148831498315083151831528315383154831558315683157831588315983160831618316283163831648316583166831678316883169831708317183172831738317483175831768317783178831798318083181831828318383184831858318683187831888318983190831918319283193831948319583196831978319883199832008320183202832038320483205832068320783208832098321083211832128321383214832158321683217832188321983220832218322283223832248322583226832278322883229832308323183232832338323483235832368323783238832398324083241832428324383244832458324683247832488324983250832518325283253832548325583256832578325883259832608326183262832638326483265832668326783268832698327083271832728327383274832758327683277832788327983280832818328283283832848328583286832878328883289832908329183292832938329483295832968329783298832998330083301833028330383304833058330683307833088330983310833118331283313833148331583316833178331883319833208332183322833238332483325833268332783328833298333083331833328333383334833358333683337833388333983340833418334283343833448334583346833478334883349833508335183352833538335483355833568335783358833598336083361833628336383364833658336683367833688336983370833718337283373833748337583376833778337883379833808338183382833838338483385833868338783388833898339083391833928339383394833958339683397833988339983400834018340283403834048340583406834078340883409834108341183412834138341483415834168341783418834198342083421834228342383424834258342683427834288342983430834318343283433834348343583436834378343883439834408344183442834438344483445834468344783448834498345083451834528345383454834558345683457834588345983460834618346283463834648346583466834678346883469834708347183472834738347483475834768347783478834798348083481834828348383484834858348683487834888348983490834918349283493834948349583496834978349883499835008350183502835038350483505835068350783508835098351083511835128351383514835158351683517835188351983520835218352283523835248352583526835278352883529835308353183532835338353483535835368353783538835398354083541835428354383544835458354683547835488354983550835518355283553835548355583556835578355883559835608356183562835638356483565835668356783568835698357083571835728357383574835758357683577835788357983580835818358283583835848358583586835878358883589835908359183592835938359483595835968359783598835998360083601836028360383604836058360683607836088360983610836118361283613836148361583616836178361883619836208362183622836238362483625836268362783628836298363083631836328363383634836358363683637836388363983640836418364283643836448364583646836478364883649836508365183652836538365483655836568365783658836598366083661836628366383664836658366683667836688366983670836718367283673836748367583676836778367883679836808368183682836838368483685836868368783688836898369083691836928369383694836958369683697836988369983700837018370283703837048370583706837078370883709837108371183712837138371483715837168371783718837198372083721837228372383724837258372683727837288372983730837318373283733837348373583736837378373883739837408374183742837438374483745837468374783748837498375083751837528375383754837558375683757837588375983760837618376283763837648376583766837678376883769837708377183772837738377483775837768377783778837798378083781837828378383784837858378683787837888378983790837918379283793837948379583796837978379883799838008380183802838038380483805838068380783808838098381083811838128381383814838158381683817838188381983820838218382283823838248382583826838278382883829838308383183832838338383483835838368383783838838398384083841838428384383844838458384683847838488384983850838518385283853838548385583856838578385883859838608386183862838638386483865838668386783868838698387083871838728387383874838758387683877838788387983880838818388283883838848388583886838878388883889838908389183892838938389483895838968389783898838998390083901839028390383904839058390683907839088390983910839118391283913839148391583916839178391883919839208392183922839238392483925839268392783928839298393083931839328393383934839358393683937839388393983940839418394283943839448394583946839478394883949839508395183952839538395483955839568395783958839598396083961839628396383964839658396683967839688396983970839718397283973839748397583976839778397883979839808398183982839838398483985839868398783988839898399083991839928399383994839958399683997839988399984000840018400284003840048400584006840078400884009840108401184012840138401484015840168401784018840198402084021840228402384024840258402684027840288402984030840318403284033840348403584036840378403884039840408404184042840438404484045840468404784048840498405084051840528405384054840558405684057840588405984060840618406284063840648406584066840678406884069840708407184072840738407484075840768407784078840798408084081840828408384084840858408684087840888408984090840918409284093840948409584096840978409884099841008410184102841038410484105841068410784108841098411084111841128411384114841158411684117841188411984120841218412284123841248412584126841278412884129841308413184132841338413484135841368413784138841398414084141841428414384144841458414684147841488414984150841518415284153841548415584156841578415884159841608416184162841638416484165841668416784168841698417084171841728417384174841758417684177841788417984180841818418284183841848418584186841878418884189841908419184192841938419484195841968419784198841998420084201842028420384204842058420684207842088420984210842118421284213842148421584216842178421884219842208422184222842238422484225842268422784228842298423084231842328423384234842358423684237842388423984240842418424284243842448424584246842478424884249842508425184252842538425484255842568425784258842598426084261842628426384264842658426684267842688426984270842718427284273842748427584276842778427884279842808428184282842838428484285842868428784288842898429084291842928429384294842958429684297842988429984300843018430284303843048430584306843078430884309843108431184312843138431484315843168431784318843198432084321843228432384324843258432684327843288432984330843318433284333843348433584336843378433884339843408434184342843438434484345843468434784348843498435084351843528435384354843558435684357843588435984360843618436284363843648436584366843678436884369843708437184372843738437484375843768437784378843798438084381843828438384384843858438684387843888438984390843918439284393843948439584396843978439884399844008440184402844038440484405844068440784408844098441084411844128441384414844158441684417844188441984420844218442284423844248442584426844278442884429844308443184432844338443484435844368443784438844398444084441844428444384444844458444684447844488444984450844518445284453844548445584456844578445884459844608446184462844638446484465844668446784468844698447084471844728447384474844758447684477844788447984480844818448284483844848448584486844878448884489844908449184492844938449484495844968449784498844998450084501845028450384504845058450684507845088450984510845118451284513845148451584516845178451884519845208452184522845238452484525845268452784528845298453084531845328453384534845358453684537845388453984540845418454284543845448454584546845478454884549845508455184552845538455484555845568455784558845598456084561845628456384564845658456684567845688456984570845718457284573845748457584576845778457884579845808458184582845838458484585845868458784588845898459084591845928459384594845958459684597845988459984600846018460284603846048460584606846078460884609846108461184612846138461484615846168461784618846198462084621846228462384624846258462684627846288462984630846318463284633846348463584636846378463884639846408464184642846438464484645846468464784648846498465084651846528465384654846558465684657846588465984660846618466284663846648466584666846678466884669846708467184672846738467484675846768467784678846798468084681846828468384684846858468684687846888468984690846918469284693846948469584696846978469884699847008470184702847038470484705847068470784708847098471084711847128471384714847158471684717847188471984720847218472284723847248472584726847278472884729847308473184732847338473484735847368473784738847398474084741847428474384744847458474684747847488474984750847518475284753847548475584756847578475884759847608476184762847638476484765847668476784768847698477084771847728477384774847758477684777847788477984780847818478284783847848478584786847878478884789847908479184792847938479484795847968479784798847998480084801848028480384804848058480684807848088480984810848118481284813848148481584816848178481884819848208482184822848238482484825848268482784828848298483084831848328483384834848358483684837848388483984840848418484284843848448484584846848478484884849848508485184852848538485484855848568485784858848598486084861848628486384864848658486684867848688486984870848718487284873848748487584876848778487884879848808488184882848838488484885848868488784888848898489084891848928489384894848958489684897848988489984900849018490284903849048490584906849078490884909849108491184912849138491484915849168491784918849198492084921849228492384924849258492684927849288492984930849318493284933849348493584936849378493884939849408494184942849438494484945849468494784948849498495084951849528495384954849558495684957849588495984960849618496284963849648496584966849678496884969849708497184972849738497484975849768497784978849798498084981849828498384984849858498684987849888498984990849918499284993849948499584996849978499884999850008500185002850038500485005850068500785008850098501085011850128501385014850158501685017850188501985020850218502285023850248502585026850278502885029850308503185032850338503485035850368503785038850398504085041850428504385044850458504685047850488504985050850518505285053850548505585056850578505885059850608506185062850638506485065850668506785068850698507085071850728507385074850758507685077850788507985080850818508285083850848508585086850878508885089850908509185092850938509485095850968509785098850998510085101851028510385104851058510685107851088510985110851118511285113851148511585116851178511885119851208512185122851238512485125851268512785128851298513085131851328513385134851358513685137851388513985140851418514285143851448514585146851478514885149851508515185152851538515485155851568515785158851598516085161851628516385164851658516685167851688516985170851718517285173851748517585176851778517885179851808518185182851838518485185851868518785188851898519085191851928519385194851958519685197851988519985200852018520285203852048520585206852078520885209852108521185212852138521485215852168521785218852198522085221852228522385224852258522685227852288522985230852318523285233852348523585236852378523885239852408524185242852438524485245852468524785248852498525085251852528525385254852558525685257852588525985260852618526285263852648526585266852678526885269852708527185272852738527485275852768527785278852798528085281852828528385284852858528685287852888528985290852918529285293852948529585296852978529885299853008530185302853038530485305853068530785308853098531085311853128531385314853158531685317853188531985320853218532285323853248532585326853278532885329853308533185332853338533485335853368533785338853398534085341853428534385344853458534685347853488534985350853518535285353853548535585356853578535885359853608536185362853638536485365853668536785368853698537085371853728537385374853758537685377853788537985380853818538285383853848538585386853878538885389853908539185392853938539485395853968539785398853998540085401854028540385404854058540685407854088540985410854118541285413854148541585416854178541885419854208542185422854238542485425854268542785428854298543085431854328543385434854358543685437854388543985440854418544285443854448544585446854478544885449854508545185452854538545485455854568545785458854598546085461854628546385464854658546685467854688546985470854718547285473854748547585476854778547885479854808548185482854838548485485854868548785488854898549085491854928549385494854958549685497854988549985500855018550285503855048550585506855078550885509855108551185512855138551485515855168551785518855198552085521855228552385524855258552685527855288552985530855318553285533855348553585536855378553885539855408554185542855438554485545855468554785548855498555085551855528555385554855558555685557855588555985560855618556285563855648556585566855678556885569855708557185572855738557485575855768557785578855798558085581855828558385584855858558685587855888558985590855918559285593855948559585596855978559885599856008560185602856038560485605856068560785608856098561085611856128561385614856158561685617856188561985620856218562285623856248562585626856278562885629856308563185632856338563485635856368563785638856398564085641856428564385644856458564685647856488564985650856518565285653856548565585656856578565885659856608566185662856638566485665856668566785668856698567085671856728567385674856758567685677856788567985680856818568285683856848568585686856878568885689856908569185692856938569485695856968569785698856998570085701857028570385704857058570685707857088570985710857118571285713857148571585716857178571885719857208572185722857238572485725857268572785728857298573085731857328573385734857358573685737857388573985740857418574285743857448574585746857478574885749857508575185752857538575485755857568575785758857598576085761857628576385764857658576685767857688576985770857718577285773857748577585776857778577885779857808578185782857838578485785857868578785788857898579085791857928579385794857958579685797857988579985800858018580285803858048580585806858078580885809858108581185812858138581485815858168581785818858198582085821858228582385824858258582685827858288582985830858318583285833858348583585836858378583885839858408584185842858438584485845858468584785848858498585085851858528585385854858558585685857858588585985860858618586285863858648586585866858678586885869858708587185872858738587485875858768587785878858798588085881858828588385884858858588685887858888588985890858918589285893858948589585896858978589885899859008590185902859038590485905859068590785908859098591085911859128591385914859158591685917859188591985920859218592285923859248592585926859278592885929859308593185932859338593485935859368593785938859398594085941859428594385944859458594685947859488594985950859518595285953859548595585956859578595885959859608596185962859638596485965859668596785968859698597085971859728597385974859758597685977859788597985980859818598285983859848598585986859878598885989859908599185992859938599485995859968599785998859998600086001860028600386004860058600686007860088600986010860118601286013860148601586016860178601886019860208602186022860238602486025860268602786028860298603086031860328603386034860358603686037860388603986040860418604286043860448604586046860478604886049860508605186052860538605486055860568605786058860598606086061860628606386064860658606686067860688606986070860718607286073860748607586076860778607886079860808608186082860838608486085860868608786088860898609086091860928609386094860958609686097860988609986100861018610286103861048610586106861078610886109861108611186112861138611486115861168611786118861198612086121861228612386124861258612686127861288612986130861318613286133861348613586136861378613886139861408614186142861438614486145861468614786148861498615086151861528615386154861558615686157861588615986160861618616286163861648616586166861678616886169861708617186172861738617486175861768617786178861798618086181861828618386184861858618686187861888618986190861918619286193861948619586196861978619886199862008620186202862038620486205862068620786208862098621086211862128621386214862158621686217862188621986220862218622286223862248622586226862278622886229862308623186232862338623486235862368623786238862398624086241862428624386244862458624686247862488624986250862518625286253862548625586256862578625886259862608626186262862638626486265862668626786268862698627086271862728627386274862758627686277862788627986280862818628286283862848628586286862878628886289862908629186292862938629486295862968629786298862998630086301863028630386304863058630686307863088630986310863118631286313863148631586316863178631886319863208632186322863238632486325863268632786328863298633086331863328633386334863358633686337863388633986340863418634286343863448634586346863478634886349863508635186352863538635486355863568635786358863598636086361863628636386364863658636686367863688636986370863718637286373863748637586376863778637886379863808638186382863838638486385863868638786388863898639086391863928639386394863958639686397863988639986400864018640286403864048640586406864078640886409864108641186412864138641486415864168641786418864198642086421864228642386424864258642686427864288642986430864318643286433864348643586436864378643886439864408644186442864438644486445864468644786448864498645086451864528645386454864558645686457864588645986460864618646286463864648646586466864678646886469864708647186472864738647486475864768647786478864798648086481864828648386484864858648686487864888648986490864918649286493864948649586496864978649886499865008650186502865038650486505865068650786508865098651086511865128651386514865158651686517865188651986520865218652286523865248652586526865278652886529865308653186532865338653486535865368653786538865398654086541865428654386544865458654686547865488654986550865518655286553865548655586556865578655886559865608656186562865638656486565865668656786568865698657086571865728657386574865758657686577865788657986580865818658286583865848658586586865878658886589865908659186592865938659486595865968659786598865998660086601866028660386604866058660686607866088660986610866118661286613866148661586616866178661886619866208662186622866238662486625866268662786628866298663086631866328663386634866358663686637866388663986640866418664286643866448664586646866478664886649866508665186652866538665486655866568665786658866598666086661866628666386664866658666686667866688666986670866718667286673866748667586676866778667886679866808668186682866838668486685866868668786688866898669086691866928669386694866958669686697866988669986700867018670286703867048670586706867078670886709867108671186712867138671486715867168671786718867198672086721867228672386724867258672686727867288672986730867318673286733867348673586736867378673886739867408674186742867438674486745867468674786748867498675086751867528675386754867558675686757867588675986760867618676286763867648676586766867678676886769867708677186772867738677486775867768677786778867798678086781867828678386784867858678686787867888678986790867918679286793867948679586796867978679886799868008680186802868038680486805868068680786808868098681086811868128681386814868158681686817868188681986820868218682286823868248682586826868278682886829868308683186832868338683486835868368683786838868398684086841868428684386844868458684686847868488684986850868518685286853868548685586856868578685886859868608686186862868638686486865868668686786868868698687086871868728687386874868758687686877868788687986880868818688286883868848688586886868878688886889868908689186892868938689486895868968689786898868998690086901869028690386904869058690686907869088690986910869118691286913869148691586916869178691886919869208692186922869238692486925869268692786928869298693086931869328693386934869358693686937869388693986940869418694286943869448694586946869478694886949869508695186952869538695486955869568695786958869598696086961869628696386964869658696686967869688696986970869718697286973869748697586976869778697886979869808698186982869838698486985869868698786988869898699086991869928699386994869958699686997869988699987000870018700287003870048700587006870078700887009870108701187012870138701487015870168701787018870198702087021870228702387024870258702687027870288702987030870318703287033870348703587036870378703887039870408704187042870438704487045870468704787048870498705087051870528705387054870558705687057870588705987060870618706287063870648706587066870678706887069870708707187072870738707487075870768707787078870798708087081870828708387084870858708687087870888708987090870918709287093870948709587096870978709887099871008710187102871038710487105871068710787108871098711087111871128711387114871158711687117871188711987120871218712287123871248712587126871278712887129871308713187132871338713487135871368713787138871398714087141871428714387144871458714687147871488714987150871518715287153871548715587156871578715887159871608716187162871638716487165871668716787168871698717087171871728717387174871758717687177871788717987180871818718287183871848718587186871878718887189871908719187192871938719487195871968719787198871998720087201872028720387204872058720687207872088720987210872118721287213872148721587216872178721887219872208722187222872238722487225872268722787228872298723087231872328723387234872358723687237872388723987240872418724287243872448724587246872478724887249872508725187252872538725487255872568725787258872598726087261872628726387264872658726687267872688726987270872718727287273872748727587276872778727887279872808728187282872838728487285872868728787288872898729087291872928729387294872958729687297872988729987300873018730287303873048730587306873078730887309873108731187312873138731487315873168731787318873198732087321873228732387324873258732687327873288732987330873318733287333873348733587336873378733887339873408734187342873438734487345873468734787348873498735087351873528735387354873558735687357873588735987360873618736287363873648736587366873678736887369873708737187372873738737487375873768737787378873798738087381873828738387384873858738687387873888738987390873918739287393873948739587396873978739887399874008740187402874038740487405874068740787408874098741087411874128741387414874158741687417874188741987420874218742287423874248742587426874278742887429874308743187432874338743487435874368743787438874398744087441874428744387444874458744687447874488744987450874518745287453874548745587456874578745887459874608746187462874638746487465874668746787468874698747087471874728747387474874758747687477874788747987480874818748287483874848748587486874878748887489874908749187492874938749487495874968749787498874998750087501875028750387504875058750687507875088750987510875118751287513875148751587516875178751887519875208752187522875238752487525875268752787528875298753087531875328753387534875358753687537875388753987540875418754287543875448754587546875478754887549875508755187552875538755487555875568755787558875598756087561875628756387564875658756687567875688756987570875718757287573875748757587576875778757887579875808758187582875838758487585875868758787588875898759087591875928759387594875958759687597875988759987600876018760287603876048760587606876078760887609876108761187612876138761487615876168761787618876198762087621876228762387624876258762687627876288762987630876318763287633876348763587636876378763887639876408764187642876438764487645876468764787648876498765087651876528765387654876558765687657876588765987660876618766287663876648766587666876678766887669876708767187672876738767487675876768767787678876798768087681876828768387684876858768687687876888768987690876918769287693876948769587696876978769887699877008770187702877038770487705877068770787708877098771087711877128771387714877158771687717877188771987720877218772287723877248772587726877278772887729877308773187732877338773487735877368773787738877398774087741877428774387744877458774687747877488774987750877518775287753877548775587756877578775887759877608776187762877638776487765877668776787768877698777087771877728777387774877758777687777877788777987780877818778287783877848778587786877878778887789877908779187792877938779487795877968779787798877998780087801878028780387804878058780687807878088780987810878118781287813878148781587816878178781887819878208782187822878238782487825878268782787828878298783087831878328783387834878358783687837878388783987840878418784287843878448784587846878478784887849878508785187852878538785487855878568785787858878598786087861878628786387864878658786687867878688786987870878718787287873878748787587876878778787887879878808788187882878838788487885878868788787888878898789087891878928789387894878958789687897878988789987900879018790287903879048790587906879078790887909879108791187912879138791487915879168791787918879198792087921879228792387924879258792687927879288792987930879318793287933879348793587936879378793887939879408794187942879438794487945879468794787948879498795087951879528795387954879558795687957879588795987960879618796287963879648796587966879678796887969879708797187972879738797487975879768797787978879798798087981879828798387984879858798687987879888798987990879918799287993879948799587996879978799887999880008800188002880038800488005880068800788008880098801088011880128801388014880158801688017880188801988020880218802288023880248802588026880278802888029880308803188032880338803488035880368803788038880398804088041880428804388044880458804688047880488804988050880518805288053880548805588056880578805888059880608806188062880638806488065880668806788068880698807088071880728807388074880758807688077880788807988080880818808288083880848808588086880878808888089880908809188092880938809488095880968809788098880998810088101881028810388104881058810688107881088810988110881118811288113881148811588116881178811888119881208812188122881238812488125881268812788128881298813088131881328813388134881358813688137881388813988140881418814288143881448814588146881478814888149881508815188152881538815488155881568815788158881598816088161881628816388164881658816688167881688816988170881718817288173881748817588176881778817888179881808818188182881838818488185881868818788188881898819088191881928819388194881958819688197881988819988200882018820288203882048820588206882078820888209882108821188212882138821488215882168821788218882198822088221882228822388224882258822688227882288822988230882318823288233882348823588236882378823888239882408824188242882438824488245882468824788248882498825088251882528825388254882558825688257882588825988260882618826288263882648826588266882678826888269882708827188272882738827488275882768827788278882798828088281882828828388284882858828688287882888828988290882918829288293882948829588296882978829888299883008830188302883038830488305883068830788308883098831088311883128831388314883158831688317883188831988320883218832288323883248832588326883278832888329883308833188332883338833488335883368833788338883398834088341883428834388344883458834688347883488834988350883518835288353883548835588356883578835888359883608836188362883638836488365883668836788368883698837088371883728837388374883758837688377883788837988380883818838288383883848838588386883878838888389883908839188392883938839488395883968839788398883998840088401884028840388404884058840688407884088840988410884118841288413884148841588416884178841888419884208842188422884238842488425884268842788428884298843088431884328843388434884358843688437884388843988440884418844288443884448844588446884478844888449884508845188452884538845488455884568845788458884598846088461884628846388464884658846688467884688846988470884718847288473884748847588476884778847888479884808848188482884838848488485884868848788488884898849088491884928849388494884958849688497884988849988500885018850288503885048850588506885078850888509885108851188512885138851488515885168851788518885198852088521885228852388524885258852688527885288852988530885318853288533885348853588536885378853888539885408854188542885438854488545885468854788548885498855088551885528855388554885558855688557885588855988560885618856288563885648856588566885678856888569885708857188572885738857488575885768857788578885798858088581885828858388584885858858688587885888858988590885918859288593885948859588596885978859888599886008860188602886038860488605886068860788608886098861088611886128861388614886158861688617886188861988620886218862288623886248862588626886278862888629886308863188632886338863488635886368863788638886398864088641886428864388644886458864688647886488864988650886518865288653886548865588656886578865888659886608866188662886638866488665886668866788668886698867088671886728867388674886758867688677886788867988680886818868288683886848868588686886878868888689886908869188692886938869488695886968869788698886998870088701887028870388704887058870688707887088870988710887118871288713887148871588716887178871888719887208872188722887238872488725887268872788728887298873088731887328873388734887358873688737887388873988740887418874288743887448874588746887478874888749887508875188752887538875488755887568875788758887598876088761887628876388764887658876688767887688876988770887718877288773887748877588776887778877888779887808878188782887838878488785887868878788788887898879088791887928879388794887958879688797887988879988800888018880288803888048880588806888078880888809888108881188812888138881488815888168881788818888198882088821888228882388824888258882688827888288882988830888318883288833888348883588836888378883888839888408884188842888438884488845888468884788848888498885088851888528885388854888558885688857888588885988860888618886288863888648886588866888678886888869888708887188872888738887488875888768887788878888798888088881888828888388884888858888688887888888888988890888918889288893888948889588896888978889888899889008890188902889038890488905889068890788908889098891088911889128891388914889158891688917889188891988920889218892288923889248892588926889278892888929889308893188932889338893488935889368893788938889398894088941889428894388944889458894688947889488894988950889518895288953889548895588956889578895888959889608896188962889638896488965889668896788968889698897088971889728897388974889758897688977889788897988980889818898288983889848898588986889878898888989889908899188992889938899488995889968899788998889998900089001890028900389004890058900689007890088900989010890118901289013890148901589016890178901889019890208902189022890238902489025890268902789028890298903089031890328903389034890358903689037890388903989040890418904289043890448904589046890478904889049890508905189052890538905489055890568905789058890598906089061890628906389064890658906689067890688906989070890718907289073890748907589076890778907889079890808908189082890838908489085890868908789088890898909089091890928909389094890958909689097890988909989100891018910289103891048910589106891078910889109891108911189112891138911489115891168911789118891198912089121891228912389124891258912689127891288912989130891318913289133891348913589136891378913889139891408914189142891438914489145891468914789148891498915089151891528915389154891558915689157891588915989160891618916289163891648916589166891678916889169891708917189172891738917489175891768917789178891798918089181891828918389184891858918689187891888918989190891918919289193891948919589196891978919889199892008920189202892038920489205892068920789208892098921089211892128921389214892158921689217892188921989220892218922289223892248922589226892278922889229892308923189232892338923489235892368923789238892398924089241892428924389244892458924689247892488924989250892518925289253892548925589256892578925889259892608926189262892638926489265892668926789268892698927089271892728927389274892758927689277892788927989280892818928289283892848928589286892878928889289892908929189292892938929489295892968929789298892998930089301893028930389304893058930689307893088930989310893118931289313893148931589316893178931889319893208932189322893238932489325893268932789328893298933089331893328933389334893358933689337893388933989340893418934289343893448934589346893478934889349893508935189352893538935489355893568935789358893598936089361893628936389364893658936689367893688936989370893718937289373893748937589376893778937889379893808938189382893838938489385893868938789388893898939089391893928939389394893958939689397893988939989400894018940289403894048940589406894078940889409894108941189412894138941489415894168941789418894198942089421894228942389424894258942689427894288942989430894318943289433894348943589436894378943889439894408944189442894438944489445894468944789448894498945089451894528945389454894558945689457894588945989460894618946289463894648946589466894678946889469894708947189472894738947489475894768947789478894798948089481894828948389484894858948689487894888948989490894918949289493894948949589496894978949889499895008950189502895038950489505895068950789508895098951089511895128951389514895158951689517895188951989520895218952289523895248952589526895278952889529895308953189532895338953489535895368953789538895398954089541895428954389544895458954689547895488954989550895518955289553895548955589556895578955889559895608956189562895638956489565895668956789568895698957089571895728957389574895758957689577895788957989580895818958289583895848958589586895878958889589895908959189592895938959489595895968959789598895998960089601896028960389604896058960689607896088960989610896118961289613896148961589616896178961889619896208962189622896238962489625896268962789628896298963089631896328963389634896358963689637896388963989640896418964289643896448964589646896478964889649896508965189652896538965489655896568965789658896598966089661896628966389664896658966689667896688966989670896718967289673896748967589676896778967889679896808968189682896838968489685896868968789688896898969089691896928969389694896958969689697896988969989700897018970289703897048970589706897078970889709897108971189712897138971489715897168971789718897198972089721897228972389724897258972689727897288972989730897318973289733897348973589736897378973889739897408974189742897438974489745897468974789748897498975089751897528975389754897558975689757897588975989760897618976289763897648976589766897678976889769897708977189772897738977489775897768977789778897798978089781897828978389784897858978689787897888978989790897918979289793897948979589796897978979889799898008980189802898038980489805898068980789808898098981089811898128981389814898158981689817898188981989820898218982289823898248982589826898278982889829898308983189832898338983489835898368983789838898398984089841898428984389844898458984689847898488984989850898518985289853898548985589856898578985889859898608986189862898638986489865898668986789868898698987089871898728987389874898758987689877898788987989880898818988289883898848988589886898878988889889898908989189892898938989489895898968989789898898998990089901899028990389904899058990689907899088990989910899118991289913899148991589916899178991889919899208992189922899238992489925899268992789928899298993089931899328993389934899358993689937899388993989940899418994289943899448994589946899478994889949899508995189952899538995489955899568995789958899598996089961899628996389964899658996689967899688996989970899718997289973899748997589976899778997889979899808998189982899838998489985899868998789988899898999089991899928999389994899958999689997899988999990000900019000290003900049000590006900079000890009900109001190012900139001490015900169001790018900199002090021900229002390024900259002690027900289002990030900319003290033900349003590036900379003890039900409004190042900439004490045900469004790048900499005090051900529005390054900559005690057900589005990060900619006290063900649006590066900679006890069900709007190072900739007490075900769007790078900799008090081900829008390084900859008690087900889008990090900919009290093900949009590096900979009890099901009010190102901039010490105901069010790108901099011090111901129011390114901159011690117901189011990120901219012290123901249012590126901279012890129901309013190132901339013490135901369013790138901399014090141901429014390144901459014690147901489014990150901519015290153901549015590156901579015890159901609016190162901639016490165901669016790168901699017090171901729017390174901759017690177901789017990180901819018290183901849018590186901879018890189901909019190192901939019490195901969019790198901999020090201902029020390204902059020690207902089020990210902119021290213902149021590216902179021890219902209022190222902239022490225902269022790228902299023090231902329023390234902359023690237902389023990240902419024290243902449024590246902479024890249902509025190252902539025490255902569025790258902599026090261902629026390264902659026690267902689026990270902719027290273902749027590276902779027890279902809028190282902839028490285902869028790288902899029090291902929029390294902959029690297902989029990300903019030290303903049030590306903079030890309903109031190312903139031490315903169031790318903199032090321903229032390324903259032690327903289032990330903319033290333903349033590336903379033890339903409034190342903439034490345903469034790348903499035090351903529035390354903559035690357903589035990360903619036290363903649036590366903679036890369903709037190372903739037490375903769037790378903799038090381903829038390384903859038690387903889038990390903919039290393903949039590396903979039890399904009040190402904039040490405904069040790408904099041090411904129041390414904159041690417904189041990420904219042290423904249042590426904279042890429904309043190432904339043490435904369043790438904399044090441904429044390444904459044690447904489044990450904519045290453904549045590456904579045890459904609046190462904639046490465904669046790468904699047090471904729047390474904759047690477904789047990480904819048290483904849048590486904879048890489904909049190492904939049490495904969049790498904999050090501905029050390504905059050690507905089050990510905119051290513905149051590516905179051890519905209052190522905239052490525905269052790528905299053090531905329053390534905359053690537905389053990540905419054290543905449054590546905479054890549905509055190552905539055490555905569055790558905599056090561905629056390564905659056690567905689056990570905719057290573905749057590576905779057890579905809058190582905839058490585905869058790588905899059090591905929059390594905959059690597905989059990600906019060290603906049060590606906079060890609906109061190612906139061490615906169061790618906199062090621906229062390624906259062690627906289062990630906319063290633906349063590636906379063890639906409064190642906439064490645906469064790648906499065090651906529065390654906559065690657906589065990660906619066290663906649066590666906679066890669906709067190672906739067490675906769067790678906799068090681906829068390684906859068690687906889068990690906919069290693906949069590696906979069890699907009070190702907039070490705907069070790708907099071090711907129071390714907159071690717907189071990720907219072290723907249072590726907279072890729907309073190732907339073490735907369073790738907399074090741907429074390744907459074690747907489074990750907519075290753907549075590756907579075890759907609076190762907639076490765907669076790768907699077090771907729077390774907759077690777907789077990780907819078290783907849078590786907879078890789907909079190792907939079490795907969079790798907999080090801908029080390804908059080690807908089080990810908119081290813908149081590816908179081890819908209082190822908239082490825908269082790828908299083090831908329083390834908359083690837908389083990840908419084290843908449084590846908479084890849908509085190852908539085490855908569085790858908599086090861908629086390864908659086690867908689086990870908719087290873908749087590876908779087890879908809088190882908839088490885908869088790888908899089090891908929089390894908959089690897908989089990900909019090290903909049090590906909079090890909909109091190912909139091490915909169091790918909199092090921909229092390924909259092690927909289092990930909319093290933909349093590936909379093890939909409094190942909439094490945909469094790948909499095090951909529095390954909559095690957909589095990960909619096290963909649096590966909679096890969909709097190972909739097490975909769097790978909799098090981909829098390984909859098690987909889098990990909919099290993909949099590996909979099890999910009100191002910039100491005910069100791008910099101091011910129101391014910159101691017910189101991020910219102291023910249102591026910279102891029910309103191032910339103491035910369103791038910399104091041910429104391044910459104691047910489104991050910519105291053910549105591056910579105891059910609106191062910639106491065910669106791068910699107091071910729107391074910759107691077910789107991080910819108291083910849108591086910879108891089910909109191092910939109491095910969109791098910999110091101911029110391104911059110691107911089110991110911119111291113911149111591116911179111891119911209112191122911239112491125911269112791128911299113091131911329113391134911359113691137911389113991140911419114291143911449114591146911479114891149911509115191152911539115491155911569115791158911599116091161911629116391164911659116691167911689116991170911719117291173911749117591176911779117891179911809118191182911839118491185911869118791188911899119091191911929119391194911959119691197911989119991200912019120291203912049120591206912079120891209912109121191212912139121491215912169121791218912199122091221912229122391224912259122691227912289122991230912319123291233912349123591236912379123891239912409124191242912439124491245912469124791248912499125091251912529125391254912559125691257912589125991260912619126291263912649126591266912679126891269912709127191272912739127491275912769127791278912799128091281912829128391284912859128691287912889128991290912919129291293912949129591296912979129891299913009130191302913039130491305913069130791308913099131091311913129131391314913159131691317913189131991320913219132291323913249132591326913279132891329913309133191332913339133491335913369133791338913399134091341913429134391344913459134691347913489134991350913519135291353913549135591356913579135891359913609136191362913639136491365913669136791368913699137091371913729137391374913759137691377913789137991380913819138291383913849138591386913879138891389913909139191392913939139491395913969139791398913999140091401914029140391404914059140691407914089140991410914119141291413914149141591416914179141891419914209142191422914239142491425914269142791428914299143091431914329143391434914359143691437914389143991440914419144291443914449144591446914479144891449914509145191452914539145491455914569145791458914599146091461914629146391464914659146691467914689146991470914719147291473914749147591476914779147891479914809148191482914839148491485914869148791488914899149091491914929149391494914959149691497914989149991500915019150291503915049150591506915079150891509915109151191512915139151491515915169151791518915199152091521915229152391524915259152691527915289152991530915319153291533915349153591536915379153891539915409154191542915439154491545915469154791548915499155091551915529155391554915559155691557915589155991560915619156291563915649156591566915679156891569915709157191572915739157491575915769157791578915799158091581915829158391584915859158691587915889158991590915919159291593915949159591596915979159891599916009160191602916039160491605916069160791608916099161091611916129161391614916159161691617916189161991620916219162291623916249162591626916279162891629916309163191632916339163491635916369163791638916399164091641916429164391644916459164691647916489164991650916519165291653916549165591656916579165891659916609166191662916639166491665916669166791668916699167091671916729167391674916759167691677916789167991680916819168291683916849168591686916879168891689916909169191692916939169491695916969169791698916999170091701917029170391704917059170691707917089170991710917119171291713917149171591716917179171891719917209172191722917239172491725917269172791728917299173091731917329173391734917359173691737917389173991740917419174291743917449174591746917479174891749917509175191752917539175491755917569175791758917599176091761917629176391764917659176691767917689176991770917719177291773917749177591776917779177891779917809178191782917839178491785917869178791788917899179091791917929179391794917959179691797917989179991800918019180291803918049180591806918079180891809918109181191812918139181491815918169181791818918199182091821918229182391824918259182691827918289182991830918319183291833918349183591836918379183891839918409184191842918439184491845918469184791848918499185091851918529185391854918559185691857918589185991860918619186291863918649186591866918679186891869918709187191872918739187491875918769187791878918799188091881918829188391884918859188691887918889188991890918919189291893918949189591896918979189891899919009190191902919039190491905919069190791908919099191091911919129191391914919159191691917919189191991920919219192291923919249192591926919279192891929919309193191932919339193491935919369193791938919399194091941919429194391944919459194691947919489194991950919519195291953919549195591956919579195891959919609196191962919639196491965919669196791968919699197091971919729197391974919759197691977919789197991980919819198291983919849198591986919879198891989919909199191992919939199491995919969199791998919999200092001920029200392004920059200692007920089200992010920119201292013920149201592016920179201892019920209202192022920239202492025920269202792028920299203092031920329203392034920359203692037920389203992040920419204292043920449204592046920479204892049920509205192052920539205492055920569205792058920599206092061920629206392064920659206692067920689206992070920719207292073920749207592076920779207892079920809208192082920839208492085920869208792088920899209092091920929209392094920959209692097920989209992100921019210292103921049210592106921079210892109921109211192112921139211492115921169211792118921199212092121921229212392124921259212692127921289212992130921319213292133921349213592136921379213892139921409214192142921439214492145921469214792148921499215092151921529215392154921559215692157921589215992160921619216292163921649216592166921679216892169921709217192172921739217492175921769217792178921799218092181921829218392184921859218692187921889218992190921919219292193921949219592196921979219892199922009220192202922039220492205922069220792208922099221092211922129221392214922159221692217922189221992220922219222292223922249222592226922279222892229922309223192232922339223492235922369223792238922399224092241922429224392244922459224692247922489224992250922519225292253922549225592256922579225892259922609226192262922639226492265922669226792268922699227092271922729227392274922759227692277922789227992280922819228292283922849228592286922879228892289922909229192292922939229492295922969229792298922999230092301923029230392304923059230692307923089230992310923119231292313923149231592316923179231892319923209232192322923239232492325923269232792328923299233092331923329233392334923359233692337923389233992340923419234292343923449234592346923479234892349923509235192352923539235492355923569235792358923599236092361923629236392364923659236692367923689236992370923719237292373923749237592376923779237892379923809238192382923839238492385923869238792388923899239092391923929239392394923959239692397923989239992400924019240292403924049240592406924079240892409924109241192412924139241492415924169241792418924199242092421924229242392424924259242692427924289242992430924319243292433924349243592436924379243892439924409244192442924439244492445924469244792448924499245092451924529245392454924559245692457924589245992460924619246292463924649246592466924679246892469924709247192472924739247492475924769247792478924799248092481924829248392484924859248692487924889248992490924919249292493924949249592496924979249892499925009250192502925039250492505925069250792508925099251092511925129251392514925159251692517925189251992520925219252292523925249252592526925279252892529925309253192532925339253492535925369253792538925399254092541925429254392544925459254692547925489254992550925519255292553925549255592556925579255892559925609256192562925639256492565925669256792568925699257092571925729257392574925759257692577925789257992580925819258292583925849258592586925879258892589925909259192592925939259492595925969259792598925999260092601926029260392604926059260692607926089260992610926119261292613926149261592616926179261892619926209262192622926239262492625926269262792628926299263092631926329263392634926359263692637926389263992640926419264292643926449264592646926479264892649926509265192652926539265492655926569265792658926599266092661926629266392664926659266692667926689266992670926719267292673926749267592676926779267892679926809268192682926839268492685926869268792688926899269092691926929269392694926959269692697926989269992700927019270292703927049270592706927079270892709927109271192712927139271492715927169271792718927199272092721927229272392724927259272692727927289272992730927319273292733927349273592736927379273892739927409274192742927439274492745927469274792748927499275092751927529275392754927559275692757927589275992760927619276292763927649276592766927679276892769927709277192772927739277492775927769277792778927799278092781927829278392784927859278692787927889278992790927919279292793927949279592796927979279892799928009280192802928039280492805928069280792808928099281092811928129281392814928159281692817928189281992820928219282292823928249282592826928279282892829928309283192832928339283492835928369283792838928399284092841928429284392844928459284692847928489284992850928519285292853928549285592856928579285892859928609286192862928639286492865928669286792868928699287092871928729287392874928759287692877928789287992880928819288292883928849288592886928879288892889928909289192892928939289492895928969289792898928999290092901929029290392904929059290692907929089290992910929119291292913929149291592916929179291892919929209292192922929239292492925929269292792928929299293092931929329293392934929359293692937929389293992940929419294292943929449294592946929479294892949929509295192952929539295492955929569295792958929599296092961929629296392964929659296692967929689296992970929719297292973929749297592976929779297892979929809298192982929839298492985929869298792988929899299092991929929299392994929959299692997929989299993000930019300293003930049300593006930079300893009930109301193012930139301493015930169301793018930199302093021930229302393024930259302693027930289302993030930319303293033930349303593036930379303893039930409304193042930439304493045930469304793048930499305093051930529305393054930559305693057930589305993060930619306293063930649306593066930679306893069930709307193072930739307493075930769307793078930799308093081930829308393084930859308693087930889308993090930919309293093930949309593096930979309893099931009310193102931039310493105931069310793108931099311093111931129311393114931159311693117931189311993120931219312293123931249312593126931279312893129931309313193132931339313493135931369313793138931399314093141931429314393144931459314693147931489314993150931519315293153931549315593156931579315893159931609316193162931639316493165931669316793168931699317093171931729317393174931759317693177931789317993180931819318293183931849318593186931879318893189931909319193192931939319493195931969319793198931999320093201932029320393204932059320693207932089320993210932119321293213932149321593216932179321893219932209322193222932239322493225932269322793228932299323093231932329323393234932359323693237932389323993240932419324293243932449324593246932479324893249932509325193252932539325493255932569325793258932599326093261932629326393264932659326693267932689326993270932719327293273932749327593276932779327893279932809328193282932839328493285932869328793288932899329093291932929329393294932959329693297932989329993300933019330293303933049330593306933079330893309933109331193312933139331493315933169331793318933199332093321933229332393324933259332693327933289332993330933319333293333933349333593336933379333893339933409334193342933439334493345933469334793348933499335093351933529335393354933559335693357933589335993360933619336293363933649336593366933679336893369933709337193372933739337493375933769337793378933799338093381933829338393384933859338693387933889338993390933919339293393933949339593396933979339893399934009340193402934039340493405934069340793408934099341093411934129341393414934159341693417934189341993420934219342293423934249342593426934279342893429934309343193432934339343493435934369343793438934399344093441934429344393444934459344693447934489344993450934519345293453934549345593456934579345893459934609346193462934639346493465934669346793468934699347093471934729347393474934759347693477934789347993480934819348293483934849348593486934879348893489934909349193492934939349493495934969349793498934999350093501935029350393504935059350693507935089350993510935119351293513935149351593516935179351893519935209352193522935239352493525935269352793528935299353093531935329353393534935359353693537935389353993540935419354293543935449354593546935479354893549935509355193552935539355493555935569355793558935599356093561935629356393564935659356693567935689356993570935719357293573935749357593576935779357893579935809358193582935839358493585935869358793588935899359093591935929359393594935959359693597935989359993600936019360293603936049360593606936079360893609936109361193612936139361493615936169361793618936199362093621936229362393624936259362693627936289362993630936319363293633936349363593636936379363893639936409364193642936439364493645936469364793648936499365093651936529365393654936559365693657936589365993660936619366293663936649366593666936679366893669936709367193672936739367493675936769367793678936799368093681936829368393684936859368693687936889368993690936919369293693936949369593696936979369893699937009370193702937039370493705937069370793708937099371093711937129371393714937159371693717937189371993720937219372293723937249372593726937279372893729937309373193732937339373493735937369373793738937399374093741937429374393744937459374693747937489374993750937519375293753937549375593756937579375893759937609376193762937639376493765937669376793768937699377093771937729377393774937759377693777937789377993780937819378293783937849378593786937879378893789937909379193792937939379493795937969379793798937999380093801938029380393804938059380693807938089380993810938119381293813938149381593816938179381893819938209382193822938239382493825938269382793828938299383093831938329383393834938359383693837938389383993840938419384293843938449384593846938479384893849938509385193852938539385493855938569385793858938599386093861938629386393864938659386693867938689386993870938719387293873938749387593876938779387893879938809388193882938839388493885938869388793888938899389093891938929389393894938959389693897938989389993900939019390293903939049390593906939079390893909939109391193912939139391493915939169391793918939199392093921939229392393924939259392693927939289392993930939319393293933939349393593936939379393893939939409394193942939439394493945939469394793948939499395093951939529395393954939559395693957939589395993960939619396293963939649396593966939679396893969939709397193972939739397493975939769397793978939799398093981939829398393984939859398693987939889398993990939919399293993939949399593996939979399893999940009400194002940039400494005940069400794008940099401094011940129401394014940159401694017940189401994020940219402294023940249402594026940279402894029940309403194032940339403494035940369403794038940399404094041940429404394044940459404694047940489404994050940519405294053940549405594056940579405894059940609406194062940639406494065940669406794068940699407094071940729407394074940759407694077940789407994080940819408294083940849408594086940879408894089940909409194092940939409494095940969409794098940999410094101941029410394104941059410694107941089410994110941119411294113941149411594116941179411894119941209412194122941239412494125941269412794128941299413094131941329413394134941359413694137941389413994140941419414294143941449414594146941479414894149941509415194152941539415494155941569415794158941599416094161941629416394164941659416694167941689416994170941719417294173941749417594176941779417894179941809418194182941839418494185941869418794188941899419094191941929419394194941959419694197941989419994200942019420294203942049420594206942079420894209942109421194212942139421494215942169421794218942199422094221942229422394224942259422694227942289422994230942319423294233942349423594236942379423894239942409424194242942439424494245942469424794248942499425094251942529425394254942559425694257942589425994260942619426294263942649426594266942679426894269942709427194272942739427494275942769427794278942799428094281942829428394284942859428694287942889428994290942919429294293942949429594296942979429894299943009430194302943039430494305943069430794308943099431094311943129431394314943159431694317943189431994320943219432294323943249432594326943279432894329943309433194332943339433494335943369433794338943399434094341943429434394344943459434694347943489434994350943519435294353943549435594356943579435894359943609436194362943639436494365943669436794368943699437094371943729437394374943759437694377943789437994380943819438294383943849438594386943879438894389943909439194392943939439494395943969439794398943999440094401944029440394404944059440694407944089440994410944119441294413944149441594416944179441894419944209442194422944239442494425944269442794428944299443094431944329443394434944359443694437944389443994440944419444294443944449444594446944479444894449944509445194452944539445494455944569445794458944599446094461944629446394464944659446694467944689446994470944719447294473944749447594476944779447894479944809448194482944839448494485944869448794488944899449094491944929449394494944959449694497944989449994500945019450294503945049450594506945079450894509945109451194512945139451494515945169451794518945199452094521945229452394524945259452694527945289452994530945319453294533945349453594536945379453894539945409454194542945439454494545945469454794548945499455094551945529455394554945559455694557945589455994560945619456294563945649456594566945679456894569945709457194572945739457494575945769457794578945799458094581945829458394584945859458694587945889458994590945919459294593945949459594596945979459894599946009460194602946039460494605946069460794608946099461094611946129461394614946159461694617946189461994620946219462294623946249462594626946279462894629946309463194632946339463494635946369463794638946399464094641946429464394644946459464694647946489464994650946519465294653946549465594656946579465894659946609466194662946639466494665946669466794668946699467094671946729467394674946759467694677946789467994680946819468294683946849468594686946879468894689946909469194692946939469494695946969469794698946999470094701947029470394704947059470694707947089470994710947119471294713947149471594716947179471894719947209472194722947239472494725947269472794728947299473094731947329473394734947359473694737947389473994740947419474294743947449474594746947479474894749947509475194752947539475494755947569475794758947599476094761947629476394764947659476694767947689476994770947719477294773947749477594776947779477894779947809478194782947839478494785947869478794788947899479094791947929479394794947959479694797947989479994800948019480294803948049480594806948079480894809948109481194812948139481494815948169481794818948199482094821948229482394824948259482694827948289482994830948319483294833948349483594836948379483894839948409484194842948439484494845948469484794848948499485094851948529485394854948559485694857948589485994860948619486294863948649486594866948679486894869948709487194872948739487494875948769487794878948799488094881948829488394884948859488694887948889488994890948919489294893948949489594896948979489894899949009490194902949039490494905949069490794908949099491094911949129491394914949159491694917949189491994920949219492294923949249492594926949279492894929949309493194932949339493494935949369493794938949399494094941949429494394944949459494694947949489494994950949519495294953949549495594956949579495894959949609496194962949639496494965949669496794968949699497094971949729497394974949759497694977949789497994980949819498294983949849498594986949879498894989949909499194992949939499494995949969499794998949999500095001950029500395004950059500695007950089500995010950119501295013950149501595016950179501895019950209502195022950239502495025950269502795028950299503095031950329503395034950359503695037950389503995040950419504295043950449504595046950479504895049950509505195052950539505495055950569505795058950599506095061950629506395064950659506695067950689506995070950719507295073950749507595076950779507895079950809508195082950839508495085950869508795088950899509095091950929509395094950959509695097950989509995100951019510295103951049510595106951079510895109951109511195112951139511495115951169511795118951199512095121951229512395124951259512695127951289512995130951319513295133951349513595136951379513895139951409514195142951439514495145951469514795148951499515095151951529515395154951559515695157951589515995160951619516295163951649516595166951679516895169951709517195172951739517495175951769517795178951799518095181951829518395184951859518695187951889518995190951919519295193951949519595196951979519895199952009520195202952039520495205952069520795208952099521095211952129521395214952159521695217952189521995220952219522295223952249522595226952279522895229952309523195232952339523495235952369523795238952399524095241952429524395244952459524695247952489524995250952519525295253952549525595256952579525895259952609526195262952639526495265952669526795268952699527095271952729527395274952759527695277952789527995280952819528295283952849528595286952879528895289952909529195292952939529495295952969529795298952999530095301953029530395304953059530695307953089530995310953119531295313953149531595316953179531895319953209532195322953239532495325953269532795328953299533095331953329533395334953359533695337953389533995340953419534295343953449534595346953479534895349953509535195352953539535495355953569535795358953599536095361953629536395364953659536695367953689536995370953719537295373953749537595376953779537895379953809538195382953839538495385953869538795388953899539095391953929539395394953959539695397953989539995400954019540295403954049540595406954079540895409954109541195412954139541495415954169541795418954199542095421954229542395424954259542695427954289542995430954319543295433954349543595436954379543895439954409544195442954439544495445954469544795448954499545095451954529545395454954559545695457954589545995460954619546295463954649546595466954679546895469954709547195472954739547495475954769547795478954799548095481954829548395484954859548695487954889548995490954919549295493954949549595496954979549895499955009550195502955039550495505955069550795508955099551095511955129551395514955159551695517955189551995520955219552295523955249552595526955279552895529955309553195532955339553495535955369553795538955399554095541955429554395544955459554695547955489554995550955519555295553955549555595556955579555895559955609556195562955639556495565955669556795568955699557095571955729557395574955759557695577955789557995580955819558295583955849558595586955879558895589955909559195592955939559495595955969559795598955999560095601956029560395604956059560695607956089560995610956119561295613956149561595616956179561895619956209562195622956239562495625956269562795628956299563095631956329563395634956359563695637956389563995640956419564295643956449564595646956479564895649956509565195652956539565495655956569565795658956599566095661956629566395664956659566695667956689566995670956719567295673956749567595676956779567895679956809568195682956839568495685956869568795688956899569095691956929569395694956959569695697956989569995700957019570295703957049570595706957079570895709957109571195712957139571495715957169571795718957199572095721957229572395724957259572695727957289572995730957319573295733957349573595736957379573895739957409574195742957439574495745957469574795748957499575095751957529575395754957559575695757957589575995760957619576295763957649576595766957679576895769957709577195772957739577495775957769577795778957799578095781957829578395784957859578695787957889578995790957919579295793957949579595796957979579895799958009580195802958039580495805958069580795808958099581095811958129581395814958159581695817958189581995820958219582295823958249582595826958279582895829958309583195832958339583495835958369583795838958399584095841958429584395844958459584695847958489584995850958519585295853958549585595856958579585895859958609586195862958639586495865958669586795868958699587095871958729587395874958759587695877958789587995880958819588295883958849588595886958879588895889958909589195892958939589495895958969589795898958999590095901959029590395904959059590695907959089590995910959119591295913959149591595916959179591895919959209592195922959239592495925959269592795928959299593095931959329593395934959359593695937959389593995940959419594295943959449594595946959479594895949959509595195952959539595495955959569595795958959599596095961959629596395964959659596695967959689596995970959719597295973959749597595976959779597895979959809598195982959839598495985959869598795988959899599095991959929599395994959959599695997959989599996000960019600296003960049600596006960079600896009960109601196012960139601496015960169601796018960199602096021960229602396024960259602696027960289602996030960319603296033960349603596036960379603896039960409604196042960439604496045960469604796048960499605096051960529605396054960559605696057960589605996060960619606296063960649606596066960679606896069960709607196072960739607496075960769607796078960799608096081960829608396084960859608696087960889608996090960919609296093960949609596096960979609896099961009610196102961039610496105961069610796108961099611096111961129611396114961159611696117961189611996120961219612296123961249612596126961279612896129961309613196132961339613496135961369613796138961399614096141961429614396144961459614696147961489614996150961519615296153961549615596156961579615896159961609616196162961639616496165961669616796168961699617096171961729617396174961759617696177961789617996180961819618296183961849618596186961879618896189961909619196192961939619496195961969619796198961999620096201962029620396204962059620696207962089620996210962119621296213962149621596216962179621896219962209622196222962239622496225962269622796228962299623096231962329623396234962359623696237962389623996240962419624296243962449624596246962479624896249962509625196252962539625496255962569625796258962599626096261962629626396264962659626696267962689626996270962719627296273962749627596276962779627896279962809628196282962839628496285962869628796288962899629096291962929629396294962959629696297962989629996300963019630296303963049630596306963079630896309963109631196312963139631496315963169631796318963199632096321963229632396324963259632696327963289632996330963319633296333963349633596336963379633896339963409634196342963439634496345963469634796348963499635096351963529635396354963559635696357963589635996360963619636296363963649636596366963679636896369963709637196372963739637496375963769637796378963799638096381963829638396384963859638696387963889638996390963919639296393963949639596396963979639896399964009640196402964039640496405964069640796408964099641096411964129641396414964159641696417964189641996420964219642296423964249642596426964279642896429964309643196432964339643496435964369643796438964399644096441964429644396444964459644696447964489644996450964519645296453964549645596456964579645896459964609646196462964639646496465964669646796468964699647096471964729647396474964759647696477964789647996480964819648296483964849648596486964879648896489964909649196492964939649496495964969649796498964999650096501965029650396504965059650696507965089650996510965119651296513965149651596516965179651896519965209652196522965239652496525965269652796528965299653096531965329653396534965359653696537965389653996540965419654296543965449654596546965479654896549965509655196552965539655496555965569655796558965599656096561965629656396564965659656696567965689656996570965719657296573965749657596576965779657896579965809658196582965839658496585965869658796588965899659096591965929659396594965959659696597965989659996600966019660296603966049660596606966079660896609966109661196612966139661496615966169661796618966199662096621966229662396624966259662696627966289662996630966319663296633966349663596636966379663896639966409664196642966439664496645966469664796648966499665096651966529665396654966559665696657966589665996660966619666296663966649666596666966679666896669966709667196672966739667496675966769667796678966799668096681966829668396684966859668696687966889668996690966919669296693966949669596696966979669896699967009670196702967039670496705967069670796708967099671096711967129671396714967159671696717967189671996720967219672296723967249672596726967279672896729967309673196732967339673496735967369673796738967399674096741967429674396744967459674696747967489674996750967519675296753967549675596756967579675896759967609676196762967639676496765967669676796768967699677096771967729677396774967759677696777967789677996780967819678296783967849678596786967879678896789967909679196792967939679496795967969679796798967999680096801968029680396804968059680696807968089680996810968119681296813968149681596816968179681896819968209682196822968239682496825968269682796828968299683096831968329683396834968359683696837968389683996840968419684296843968449684596846968479684896849968509685196852968539685496855968569685796858968599686096861968629686396864968659686696867968689686996870968719687296873968749687596876968779687896879968809688196882968839688496885968869688796888968899689096891968929689396894968959689696897968989689996900969019690296903969049690596906969079690896909969109691196912969139691496915969169691796918969199692096921969229692396924969259692696927969289692996930969319693296933969349693596936969379693896939969409694196942969439694496945969469694796948969499695096951969529695396954969559695696957969589695996960969619696296963969649696596966969679696896969969709697196972969739697496975969769697796978969799698096981969829698396984969859698696987969889698996990969919699296993969949699596996969979699896999970009700197002970039700497005970069700797008970099701097011970129701397014970159701697017970189701997020970219702297023970249702597026970279702897029970309703197032970339703497035970369703797038970399704097041970429704397044970459704697047970489704997050970519705297053970549705597056970579705897059970609706197062970639706497065970669706797068970699707097071970729707397074970759707697077970789707997080970819708297083970849708597086970879708897089970909709197092970939709497095970969709797098970999710097101971029710397104971059710697107971089710997110971119711297113971149711597116971179711897119971209712197122971239712497125971269712797128971299713097131971329713397134971359713697137971389713997140971419714297143971449714597146971479714897149971509715197152971539715497155971569715797158971599716097161971629716397164971659716697167971689716997170971719717297173971749717597176971779717897179971809718197182971839718497185971869718797188971899719097191971929719397194971959719697197971989719997200972019720297203972049720597206972079720897209972109721197212972139721497215972169721797218972199722097221972229722397224972259722697227972289722997230972319723297233972349723597236972379723897239972409724197242972439724497245972469724797248972499725097251972529725397254972559725697257972589725997260972619726297263972649726597266972679726897269972709727197272972739727497275972769727797278972799728097281972829728397284972859728697287972889728997290972919729297293972949729597296972979729897299973009730197302973039730497305973069730797308973099731097311973129731397314973159731697317973189731997320973219732297323973249732597326973279732897329973309733197332973339733497335973369733797338973399734097341973429734397344973459734697347973489734997350973519735297353973549735597356973579735897359973609736197362973639736497365973669736797368973699737097371973729737397374973759737697377973789737997380973819738297383973849738597386973879738897389973909739197392973939739497395973969739797398973999740097401974029740397404974059740697407974089740997410974119741297413974149741597416974179741897419974209742197422974239742497425974269742797428974299743097431974329743397434974359743697437974389743997440974419744297443974449744597446974479744897449974509745197452974539745497455974569745797458974599746097461974629746397464974659746697467974689746997470974719747297473974749747597476974779747897479974809748197482974839748497485974869748797488974899749097491974929749397494974959749697497974989749997500975019750297503975049750597506975079750897509975109751197512975139751497515975169751797518975199752097521975229752397524975259752697527975289752997530975319753297533975349753597536975379753897539975409754197542975439754497545975469754797548975499755097551975529755397554975559755697557975589755997560975619756297563975649756597566975679756897569975709757197572975739757497575975769757797578975799758097581975829758397584975859758697587975889758997590975919759297593975949759597596975979759897599976009760197602976039760497605976069760797608976099761097611976129761397614976159761697617976189761997620976219762297623976249762597626976279762897629976309763197632976339763497635976369763797638976399764097641976429764397644976459764697647976489764997650976519765297653976549765597656976579765897659976609766197662976639766497665976669766797668976699767097671976729767397674976759767697677976789767997680976819768297683976849768597686976879768897689976909769197692976939769497695976969769797698976999770097701977029770397704977059770697707977089770997710977119771297713977149771597716977179771897719977209772197722977239772497725977269772797728977299773097731977329773397734977359773697737977389773997740977419774297743977449774597746977479774897749977509775197752977539775497755977569775797758977599776097761977629776397764977659776697767977689776997770977719777297773977749777597776977779777897779977809778197782977839778497785977869778797788977899779097791977929779397794977959779697797977989779997800978019780297803978049780597806978079780897809978109781197812978139781497815978169781797818978199782097821978229782397824978259782697827978289782997830978319783297833978349783597836978379783897839978409784197842978439784497845978469784797848978499785097851978529785397854978559785697857978589785997860978619786297863978649786597866978679786897869978709787197872978739787497875978769787797878978799788097881978829788397884978859788697887978889788997890978919789297893978949789597896978979789897899979009790197902979039790497905979069790797908979099791097911979129791397914979159791697917979189791997920979219792297923979249792597926979279792897929979309793197932979339793497935979369793797938979399794097941979429794397944979459794697947979489794997950979519795297953979549795597956979579795897959979609796197962979639796497965979669796797968979699797097971979729797397974979759797697977979789797997980 | diff -Nur linux-3.11.10.orig/arch/arm/configs/bcmrpi_cutdown_defconfig linux-3.11.10/arch/arm/configs/bcmrpi_cutdown_defconfig--- linux-3.11.10.orig/arch/arm/configs/bcmrpi_cutdown_defconfig	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/configs/bcmrpi_cutdown_defconfig	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,503 @@+CONFIG_EXPERIMENTAL=y+# CONFIG_LOCALVERSION_AUTO is not set+CONFIG_SYSVIPC=y+CONFIG_POSIX_MQUEUE=y+CONFIG_IKCONFIG=y+CONFIG_IKCONFIG_PROC=y+# CONFIG_UID16 is not set+# CONFIG_KALLSYMS is not set+CONFIG_EMBEDDED=y+# CONFIG_VM_EVENT_COUNTERS is not set+# CONFIG_COMPAT_BRK is not set+CONFIG_SLAB=y+CONFIG_MODULES=y+CONFIG_MODULE_UNLOAD=y+CONFIG_MODVERSIONS=y+CONFIG_MODULE_SRCVERSION_ALL=y+# CONFIG_BLK_DEV_BSG is not set+CONFIG_ARCH_BCM2708=y+CONFIG_NO_HZ=y+CONFIG_HIGH_RES_TIMERS=y+CONFIG_AEABI=y+CONFIG_ZBOOT_ROM_TEXT=0x0+CONFIG_ZBOOT_ROM_BSS=0x0+CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rootwait"+CONFIG_CPU_IDLE=y+CONFIG_VFP=y+CONFIG_BINFMT_MISC=m+CONFIG_NET=y+CONFIG_PACKET=y+CONFIG_UNIX=y+CONFIG_XFRM_USER=y+CONFIG_NET_KEY=m+CONFIG_INET=y+CONFIG_IP_MULTICAST=y+CONFIG_IP_PNP=y+CONFIG_IP_PNP_DHCP=y+CONFIG_IP_PNP_RARP=y+CONFIG_SYN_COOKIES=y+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set+# CONFIG_INET_XFRM_MODE_TUNNEL is not set+# CONFIG_INET_XFRM_MODE_BEET is not set+# CONFIG_INET_LRO is not set+# CONFIG_INET_DIAG is not set+# CONFIG_IPV6 is not set+CONFIG_NET_PKTGEN=m+CONFIG_IRDA=m+CONFIG_IRLAN=m+CONFIG_IRCOMM=m+CONFIG_IRDA_ULTRA=y+CONFIG_IRDA_CACHE_LAST_LSAP=y+CONFIG_IRDA_FAST_RR=y+CONFIG_IRTTY_SIR=m+CONFIG_KINGSUN_DONGLE=m+CONFIG_KSDAZZLE_DONGLE=m+CONFIG_KS959_DONGLE=m+CONFIG_USB_IRDA=m+CONFIG_SIGMATEL_FIR=m+CONFIG_MCS_FIR=m+CONFIG_BT=m+CONFIG_BT_L2CAP=y+CONFIG_BT_SCO=y+CONFIG_BT_RFCOMM=m+CONFIG_BT_RFCOMM_TTY=y+CONFIG_BT_BNEP=m+CONFIG_BT_BNEP_MC_FILTER=y+CONFIG_BT_BNEP_PROTO_FILTER=y+CONFIG_BT_HIDP=m+CONFIG_BT_HCIBTUSB=m+CONFIG_BT_HCIBCM203X=m+CONFIG_BT_HCIBPA10X=m+CONFIG_BT_HCIBFUSB=m+CONFIG_BT_HCIVHCI=m+CONFIG_BT_MRVL=m+CONFIG_BT_MRVL_SDIO=m+CONFIG_BT_ATH3K=m+CONFIG_CFG80211=m+CONFIG_MAC80211=m+CONFIG_MAC80211_RC_PID=y+CONFIG_MAC80211_MESH=y+CONFIG_WIMAX=m+CONFIG_NET_9P=m+CONFIG_NFC=m+CONFIG_NFC_PN533=m+CONFIG_DEVTMPFS=y+CONFIG_BLK_DEV_LOOP=y+CONFIG_BLK_DEV_CRYPTOLOOP=m+CONFIG_BLK_DEV_NBD=m+CONFIG_BLK_DEV_RAM=y+CONFIG_CDROM_PKTCDVD=m+CONFIG_MISC_DEVICES=y+CONFIG_SCSI=y+# CONFIG_SCSI_PROC_FS is not set+CONFIG_BLK_DEV_SD=m+CONFIG_BLK_DEV_SR=m+CONFIG_SCSI_MULTI_LUN=y+# CONFIG_SCSI_LOWLEVEL is not set+CONFIG_NETDEVICES=y+CONFIG_TUN=m+CONFIG_PHYLIB=m+CONFIG_MDIO_BITBANG=m+CONFIG_NET_ETHERNET=y+# CONFIG_NETDEV_1000 is not set+# CONFIG_NETDEV_10000 is not set+CONFIG_LIBERTAS_THINFIRM=m+CONFIG_LIBERTAS_THINFIRM_USB=m+CONFIG_AT76C50X_USB=m+CONFIG_USB_ZD1201=m+CONFIG_USB_NET_RNDIS_WLAN=m+CONFIG_RTL8187=m+CONFIG_MAC80211_HWSIM=m+CONFIG_ATH_COMMON=m+CONFIG_ATH9K=m+CONFIG_ATH9K_HTC=m+CONFIG_CARL9170=m+CONFIG_B43=m+CONFIG_B43LEGACY=m+CONFIG_HOSTAP=m+CONFIG_IWM=m+CONFIG_LIBERTAS=m+CONFIG_LIBERTAS_USB=m+CONFIG_LIBERTAS_SDIO=m+CONFIG_P54_COMMON=m+CONFIG_P54_USB=m+CONFIG_RT2X00=m+CONFIG_RT2500USB=m+CONFIG_RT73USB=m+CONFIG_RT2800USB=m+CONFIG_RT2800USB_RT53XX=y+CONFIG_RTL8192CU=m+CONFIG_WL1251=m+CONFIG_WL12XX_MENU=m+CONFIG_ZD1211RW=m+CONFIG_MWIFIEX=m+CONFIG_MWIFIEX_SDIO=m+CONFIG_WIMAX_I2400M_USB=m+CONFIG_USB_CATC=m+CONFIG_USB_KAWETH=m+CONFIG_USB_PEGASUS=m+CONFIG_USB_RTL8150=m+CONFIG_USB_USBNET=y+CONFIG_USB_NET_AX8817X=m+CONFIG_USB_NET_CDCETHER=m+CONFIG_USB_NET_CDC_EEM=m+CONFIG_USB_NET_DM9601=m+CONFIG_USB_NET_SMSC75XX=m+CONFIG_USB_NET_SMSC95XX=y+CONFIG_USB_NET_GL620A=m+CONFIG_USB_NET_NET1080=m+CONFIG_USB_NET_PLUSB=m+CONFIG_USB_NET_MCS7830=m+CONFIG_USB_NET_CDC_SUBSET=m+CONFIG_USB_ALI_M5632=y+CONFIG_USB_AN2720=y+CONFIG_USB_KC2190=y+# CONFIG_USB_NET_ZAURUS is not set+CONFIG_USB_NET_CX82310_ETH=m+CONFIG_USB_NET_KALMIA=m+CONFIG_USB_NET_INT51X1=m+CONFIG_USB_IPHETH=m+CONFIG_USB_SIERRA_NET=m+CONFIG_USB_VL600=m+CONFIG_PPP=m+CONFIG_PPP_ASYNC=m+CONFIG_PPP_SYNC_TTY=m+CONFIG_PPP_DEFLATE=m+CONFIG_PPP_BSDCOMP=m+CONFIG_SLIP=m+CONFIG_SLIP_COMPRESSED=y+CONFIG_NETCONSOLE=m+CONFIG_INPUT_POLLDEV=m+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set+CONFIG_INPUT_JOYDEV=m+CONFIG_INPUT_EVDEV=m+# CONFIG_INPUT_KEYBOARD is not set+# CONFIG_INPUT_MOUSE is not set+CONFIG_INPUT_MISC=y+CONFIG_INPUT_AD714X=m+CONFIG_INPUT_ATI_REMOTE=m+CONFIG_INPUT_ATI_REMOTE2=m+CONFIG_INPUT_KEYSPAN_REMOTE=m+CONFIG_INPUT_POWERMATE=m+CONFIG_INPUT_YEALINK=m+CONFIG_INPUT_CM109=m+CONFIG_INPUT_UINPUT=m+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m+CONFIG_INPUT_ADXL34X=m+CONFIG_INPUT_CMA3000=m+CONFIG_SERIO=m+CONFIG_SERIO_RAW=m+CONFIG_GAMEPORT=m+CONFIG_GAMEPORT_NS558=m+CONFIG_GAMEPORT_L4=m+CONFIG_VT_HW_CONSOLE_BINDING=y+# CONFIG_LEGACY_PTYS is not set+# CONFIG_DEVKMEM is not set+CONFIG_SERIAL_AMBA_PL011=y+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y+# CONFIG_HW_RANDOM is not set+CONFIG_RAW_DRIVER=y+CONFIG_GPIO_SYSFS=y+# CONFIG_HWMON is not set+CONFIG_WATCHDOG=y+CONFIG_BCM2708_WDT=m+# CONFIG_MFD_SUPPORT is not set+CONFIG_FB=y+CONFIG_FB_BCM2708=y+CONFIG_FRAMEBUFFER_CONSOLE=y+CONFIG_LOGO=y+# CONFIG_LOGO_LINUX_MONO is not set+# CONFIG_LOGO_LINUX_VGA16 is not set+CONFIG_SOUND=y+CONFIG_SND=m+CONFIG_SND_SEQUENCER=m+CONFIG_SND_SEQ_DUMMY=m+CONFIG_SND_MIXER_OSS=m+CONFIG_SND_PCM_OSS=m+CONFIG_SND_SEQUENCER_OSS=y+CONFIG_SND_HRTIMER=m+CONFIG_SND_DUMMY=m+CONFIG_SND_ALOOP=m+CONFIG_SND_VIRMIDI=m+CONFIG_SND_MTPAV=m+CONFIG_SND_SERIAL_U16550=m+CONFIG_SND_MPU401=m+CONFIG_SND_BCM2835=m+CONFIG_SND_USB_AUDIO=m+CONFIG_SND_USB_UA101=m+CONFIG_SND_USB_CAIAQ=m+CONFIG_SND_USB_6FIRE=m+CONFIG_SOUND_PRIME=m+CONFIG_HID_PID=y+CONFIG_USB_HIDDEV=y+CONFIG_HID_A4TECH=m+CONFIG_HID_ACRUX=m+CONFIG_HID_APPLE=m+CONFIG_HID_BELKIN=m+CONFIG_HID_CHERRY=m+CONFIG_HID_CHICONY=m+CONFIG_HID_CYPRESS=m+CONFIG_HID_DRAGONRISE=m+CONFIG_HID_EMS_FF=m+CONFIG_HID_ELECOM=m+CONFIG_HID_EZKEY=m+CONFIG_HID_HOLTEK=m+CONFIG_HID_KEYTOUCH=m+CONFIG_HID_KYE=m+CONFIG_HID_UCLOGIC=m+CONFIG_HID_WALTOP=m+CONFIG_HID_GYRATION=m+CONFIG_HID_TWINHAN=m+CONFIG_HID_KENSINGTON=m+CONFIG_HID_LCPOWER=m+CONFIG_HID_LOGITECH=m+CONFIG_HID_MAGICMOUSE=m+CONFIG_HID_MICROSOFT=m+CONFIG_HID_MONTEREY=m+CONFIG_HID_MULTITOUCH=m+CONFIG_HID_NTRIG=m+CONFIG_HID_ORTEK=m+CONFIG_HID_PANTHERLORD=m+CONFIG_HID_PETALYNX=m+CONFIG_HID_PICOLCD=m+CONFIG_HID_QUANTA=m+CONFIG_HID_ROCCAT=m+CONFIG_HID_SAMSUNG=m+CONFIG_HID_SONY=m+CONFIG_HID_SPEEDLINK=m+CONFIG_HID_SUNPLUS=m+CONFIG_HID_GREENASIA=m+CONFIG_HID_SMARTJOYPLUS=m+CONFIG_HID_TOPSEED=m+CONFIG_HID_THRUSTMASTER=m+CONFIG_HID_WACOM=m+CONFIG_HID_WIIMOTE=m+CONFIG_HID_ZEROPLUS=m+CONFIG_HID_ZYDACRON=m+CONFIG_USB=y+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y+CONFIG_USB_MON=m+CONFIG_USB_DWCOTG=y+CONFIG_USB_STORAGE=y+CONFIG_USB_STORAGE_REALTEK=m+CONFIG_USB_STORAGE_DATAFAB=m+CONFIG_USB_STORAGE_FREECOM=m+CONFIG_USB_STORAGE_ISD200=m+CONFIG_USB_STORAGE_USBAT=m+CONFIG_USB_STORAGE_SDDR09=m+CONFIG_USB_STORAGE_SDDR55=m+CONFIG_USB_STORAGE_JUMPSHOT=m+CONFIG_USB_STORAGE_ALAUDA=m+CONFIG_USB_STORAGE_ONETOUCH=m+CONFIG_USB_STORAGE_KARMA=m+CONFIG_USB_STORAGE_CYPRESS_ATACB=m+CONFIG_USB_STORAGE_ENE_UB6250=m+CONFIG_USB_UAS=m+CONFIG_USB_LIBUSUAL=y+CONFIG_USB_MDC800=m+CONFIG_USB_MICROTEK=m+CONFIG_USB_SERIAL=m+CONFIG_USB_SERIAL_GENERIC=y+CONFIG_USB_SERIAL_AIRCABLE=m+CONFIG_USB_SERIAL_ARK3116=m+CONFIG_USB_SERIAL_BELKIN=m+CONFIG_USB_SERIAL_CH341=m+CONFIG_USB_SERIAL_WHITEHEAT=m+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m+CONFIG_USB_SERIAL_CP210X=m+CONFIG_USB_SERIAL_CYPRESS_M8=m+CONFIG_USB_SERIAL_EMPEG=m+CONFIG_USB_SERIAL_FTDI_SIO=m+CONFIG_USB_SERIAL_FUNSOFT=m+CONFIG_USB_SERIAL_VISOR=m+CONFIG_USB_SERIAL_IPAQ=m+CONFIG_USB_SERIAL_IR=m+CONFIG_USB_SERIAL_EDGEPORT=m+CONFIG_USB_SERIAL_EDGEPORT_TI=m+CONFIG_USB_SERIAL_GARMIN=m+CONFIG_USB_SERIAL_IPW=m+CONFIG_USB_SERIAL_IUU=m+CONFIG_USB_SERIAL_KEYSPAN_PDA=m+CONFIG_USB_SERIAL_KEYSPAN=m+CONFIG_USB_SERIAL_KLSI=m+CONFIG_USB_SERIAL_KOBIL_SCT=m+CONFIG_USB_SERIAL_MCT_U232=m+CONFIG_USB_SERIAL_MOS7720=m+CONFIG_USB_SERIAL_MOS7840=m+CONFIG_USB_SERIAL_MOTOROLA=m+CONFIG_USB_SERIAL_NAVMAN=m+CONFIG_USB_SERIAL_PL2303=m+CONFIG_USB_SERIAL_OTI6858=m+CONFIG_USB_SERIAL_QCAUX=m+CONFIG_USB_SERIAL_QUALCOMM=m+CONFIG_USB_SERIAL_SPCP8X5=m+CONFIG_USB_SERIAL_HP4X=m+CONFIG_USB_SERIAL_SAFE=m+CONFIG_USB_SERIAL_SIEMENS_MPI=m+CONFIG_USB_SERIAL_SIERRAWIRELESS=m+CONFIG_USB_SERIAL_SYMBOL=m+CONFIG_USB_SERIAL_TI=m+CONFIG_USB_SERIAL_CYBERJACK=m+CONFIG_USB_SERIAL_XIRCOM=m+CONFIG_USB_SERIAL_OPTION=m+CONFIG_USB_SERIAL_OMNINET=m+CONFIG_USB_SERIAL_OPTICON=m+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m+CONFIG_USB_SERIAL_ZIO=m+CONFIG_USB_SERIAL_SSU100=m+CONFIG_USB_SERIAL_DEBUG=m+CONFIG_USB_EMI62=m+CONFIG_USB_EMI26=m+CONFIG_USB_ADUTUX=m+CONFIG_USB_SEVSEG=m+CONFIG_USB_RIO500=m+CONFIG_USB_LEGOTOWER=m+CONFIG_USB_LCD=m+CONFIG_USB_LED=m+CONFIG_USB_CYPRESS_CY7C63=m+CONFIG_USB_CYTHERM=m+CONFIG_USB_IDMOUSE=m+CONFIG_USB_FTDI_ELAN=m+CONFIG_USB_APPLEDISPLAY=m+CONFIG_USB_LD=m+CONFIG_USB_TRANCEVIBRATOR=m+CONFIG_USB_IOWARRIOR=m+CONFIG_USB_TEST=m+CONFIG_USB_ISIGHTFW=m+CONFIG_USB_YUREX=m+CONFIG_MMC=y+CONFIG_MMC_SDHCI=y+CONFIG_MMC_SDHCI_PLTFM=y+CONFIG_MMC_SDHCI_BCM2708=y+CONFIG_MMC_SDHCI_BCM2708_DMA=y+CONFIG_LEDS_GPIO=y+CONFIG_LEDS_TRIGGER_TIMER=m+CONFIG_LEDS_TRIGGER_HEARTBEAT=m+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m+CONFIG_UIO=m+CONFIG_UIO_PDRV=m+CONFIG_UIO_PDRV_GENIRQ=m+# CONFIG_IOMMU_SUPPORT is not set+CONFIG_EXT4_FS=y+CONFIG_EXT4_FS_POSIX_ACL=y+CONFIG_EXT4_FS_SECURITY=y+CONFIG_REISERFS_FS=m+CONFIG_REISERFS_FS_XATTR=y+CONFIG_REISERFS_FS_POSIX_ACL=y+CONFIG_REISERFS_FS_SECURITY=y+CONFIG_JFS_FS=m+CONFIG_JFS_POSIX_ACL=y+CONFIG_JFS_SECURITY=y+CONFIG_XFS_FS=m+CONFIG_XFS_QUOTA=y+CONFIG_XFS_POSIX_ACL=y+CONFIG_XFS_RT=y+CONFIG_GFS2_FS=m+CONFIG_OCFS2_FS=m+CONFIG_BTRFS_FS=m+CONFIG_BTRFS_FS_POSIX_ACL=y+CONFIG_NILFS2_FS=m+CONFIG_AUTOFS4_FS=y+CONFIG_FUSE_FS=m+CONFIG_CUSE=m+CONFIG_FSCACHE=y+CONFIG_CACHEFILES=y+CONFIG_ISO9660_FS=m+CONFIG_JOLIET=y+CONFIG_ZISOFS=y+CONFIG_UDF_FS=m+CONFIG_MSDOS_FS=y+CONFIG_VFAT_FS=y+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"+CONFIG_NTFS_FS=m+CONFIG_TMPFS=y+CONFIG_TMPFS_POSIX_ACL=y+CONFIG_CONFIGFS_FS=y+CONFIG_SQUASHFS=m+CONFIG_SQUASHFS_XATTR=y+CONFIG_SQUASHFS_LZO=y+CONFIG_SQUASHFS_XZ=y+CONFIG_NFS_FS=y+CONFIG_NFS_V3=y+CONFIG_NFS_V3_ACL=y+CONFIG_NFS_V4=y+CONFIG_ROOT_NFS=y+CONFIG_NFS_FSCACHE=y+CONFIG_CIFS=m+CONFIG_CIFS_WEAK_PW_HASH=y+CONFIG_CIFS_XATTR=y+CONFIG_CIFS_POSIX=y+CONFIG_9P_FS=m+CONFIG_PARTITION_ADVANCED=y+CONFIG_MAC_PARTITION=y+CONFIG_EFI_PARTITION=y+CONFIG_NLS_DEFAULT="utf8"+CONFIG_NLS_CODEPAGE_437=y+CONFIG_NLS_CODEPAGE_737=m+CONFIG_NLS_CODEPAGE_775=m+CONFIG_NLS_CODEPAGE_850=m+CONFIG_NLS_CODEPAGE_852=m+CONFIG_NLS_CODEPAGE_855=m+CONFIG_NLS_CODEPAGE_857=m+CONFIG_NLS_CODEPAGE_860=m+CONFIG_NLS_CODEPAGE_861=m+CONFIG_NLS_CODEPAGE_862=m+CONFIG_NLS_CODEPAGE_863=m+CONFIG_NLS_CODEPAGE_864=m+CONFIG_NLS_CODEPAGE_865=m+CONFIG_NLS_CODEPAGE_866=m+CONFIG_NLS_CODEPAGE_869=m+CONFIG_NLS_CODEPAGE_936=m+CONFIG_NLS_CODEPAGE_950=m+CONFIG_NLS_CODEPAGE_932=m+CONFIG_NLS_CODEPAGE_949=m+CONFIG_NLS_CODEPAGE_874=m+CONFIG_NLS_ISO8859_8=m+CONFIG_NLS_CODEPAGE_1250=m+CONFIG_NLS_CODEPAGE_1251=m+CONFIG_NLS_ASCII=y+CONFIG_NLS_ISO8859_1=m+CONFIG_NLS_ISO8859_2=m+CONFIG_NLS_ISO8859_3=m+CONFIG_NLS_ISO8859_4=m+CONFIG_NLS_ISO8859_5=m+CONFIG_NLS_ISO8859_6=m+CONFIG_NLS_ISO8859_7=m+CONFIG_NLS_ISO8859_9=m+CONFIG_NLS_ISO8859_13=m+CONFIG_NLS_ISO8859_14=m+CONFIG_NLS_ISO8859_15=m+CONFIG_NLS_KOI8_R=m+CONFIG_NLS_KOI8_U=m+CONFIG_NLS_UTF8=m+# CONFIG_SCHED_DEBUG is not set+# CONFIG_DEBUG_BUGVERBOSE is not set+# CONFIG_FTRACE is not set+# CONFIG_ARM_UNWIND is not set+CONFIG_CRYPTO_AUTHENC=m+CONFIG_CRYPTO_SEQIV=m+CONFIG_CRYPTO_CBC=y+CONFIG_CRYPTO_HMAC=y+CONFIG_CRYPTO_XCBC=m+CONFIG_CRYPTO_MD5=y+CONFIG_CRYPTO_SHA1=y+CONFIG_CRYPTO_SHA256=m+CONFIG_CRYPTO_SHA512=m+CONFIG_CRYPTO_TGR192=m+CONFIG_CRYPTO_WP512=m+CONFIG_CRYPTO_CAST5=m+CONFIG_CRYPTO_DES=y+CONFIG_CRYPTO_DEFLATE=m+# CONFIG_CRYPTO_ANSI_CPRNG is not set+# CONFIG_CRYPTO_HW is not set+CONFIG_CRC_ITU_T=y+CONFIG_LIBCRC32C=y+CONFIG_I2C=y+CONFIG_I2C_BOARDINFO=y+CONFIG_I2C_COMPAT=y+CONFIG_I2C_CHARDEV=m+CONFIG_I2C_HELPER_AUTO=y+CONFIG_I2C_BCM2708=m+CONFIG_SPI=y+CONFIG_SPI_MASTER=y+CONFIG_SPI_BCM2708=mdiff -Nur linux-3.11.10.orig/arch/arm/configs/bcmrpi_defconfig linux-3.11.10/arch/arm/configs/bcmrpi_defconfig--- linux-3.11.10.orig/arch/arm/configs/bcmrpi_defconfig	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/configs/bcmrpi_defconfig	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,991 @@+# CONFIG_ARM_PATCH_PHYS_VIRT is not set+# CONFIG_LOCALVERSION_AUTO is not set+CONFIG_SYSVIPC=y+CONFIG_POSIX_MQUEUE=y+CONFIG_FHANDLE=y+CONFIG_AUDIT=y+CONFIG_NO_HZ=y+CONFIG_HIGH_RES_TIMERS=y+CONFIG_BSD_PROCESS_ACCT=y+CONFIG_BSD_PROCESS_ACCT_V3=y+CONFIG_TASKSTATS=y+CONFIG_TASK_DELAY_ACCT=y+CONFIG_TASK_XACCT=y+CONFIG_TASK_IO_ACCOUNTING=y+CONFIG_IKCONFIG=y+CONFIG_IKCONFIG_PROC=y+CONFIG_CGROUP_FREEZER=y+CONFIG_CGROUP_DEVICE=y+CONFIG_CGROUP_CPUACCT=y+CONFIG_RESOURCE_COUNTERS=y+CONFIG_BLK_CGROUP=y+CONFIG_NAMESPACES=y+CONFIG_SCHED_AUTOGROUP=y+CONFIG_EMBEDDED=y+# CONFIG_COMPAT_BRK is not set+CONFIG_PROFILING=y+CONFIG_OPROFILE=m+CONFIG_KPROBES=y+CONFIG_JUMP_LABEL=y+CONFIG_MODULES=y+CONFIG_MODULE_UNLOAD=y+CONFIG_MODVERSIONS=y+CONFIG_MODULE_SRCVERSION_ALL=y+# CONFIG_BLK_DEV_BSG is not set+CONFIG_BLK_DEV_THROTTLING=y+CONFIG_PARTITION_ADVANCED=y+CONFIG_MAC_PARTITION=y+CONFIG_CFQ_GROUP_IOSCHED=y+CONFIG_ARCH_BCM2708=y+CONFIG_AEABI=y+CONFIG_SECCOMP=y+CONFIG_CC_STACKPROTECTOR=y+CONFIG_ZBOOT_ROM_TEXT=0x0+CONFIG_ZBOOT_ROM_BSS=0x0+CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rootwait"+CONFIG_KEXEC=y+CONFIG_CPU_FREQ=y+CONFIG_CPU_FREQ_STAT=m+CONFIG_CPU_FREQ_STAT_DETAILS=y+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y+CONFIG_CPU_FREQ_GOV_USERSPACE=y+CONFIG_CPU_FREQ_GOV_ONDEMAND=y+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y+CONFIG_CPU_IDLE=y+CONFIG_VFP=y+CONFIG_BINFMT_MISC=m+CONFIG_NET=y+CONFIG_PACKET=y+CONFIG_UNIX=y+CONFIG_XFRM_USER=y+CONFIG_NET_KEY=m+CONFIG_INET=y+CONFIG_IP_MULTICAST=y+CONFIG_IP_PNP=y+CONFIG_IP_PNP_DHCP=y+CONFIG_IP_PNP_RARP=y+CONFIG_SYN_COOKIES=y+CONFIG_INET_AH=m+CONFIG_INET_ESP=m+CONFIG_INET_IPCOMP=m+CONFIG_INET_XFRM_MODE_TRANSPORT=m+CONFIG_INET_XFRM_MODE_TUNNEL=m+CONFIG_INET_XFRM_MODE_BEET=m+CONFIG_INET_LRO=m+CONFIG_INET_DIAG=m+CONFIG_IPV6_PRIVACY=y+CONFIG_INET6_AH=m+CONFIG_INET6_ESP=m+CONFIG_INET6_IPCOMP=m+CONFIG_IPV6_MULTIPLE_TABLES=y+CONFIG_NETFILTER=y+CONFIG_NF_CONNTRACK=m+CONFIG_NF_CONNTRACK_ZONES=y+CONFIG_NF_CONNTRACK_EVENTS=y+CONFIG_NF_CONNTRACK_TIMESTAMP=y+CONFIG_NF_CT_PROTO_DCCP=m+CONFIG_NF_CT_PROTO_UDPLITE=m+CONFIG_NF_CONNTRACK_AMANDA=m+CONFIG_NF_CONNTRACK_FTP=m+CONFIG_NF_CONNTRACK_H323=m+CONFIG_NF_CONNTRACK_IRC=m+CONFIG_NF_CONNTRACK_NETBIOS_NS=m+CONFIG_NF_CONNTRACK_SNMP=m+CONFIG_NF_CONNTRACK_PPTP=m+CONFIG_NF_CONNTRACK_SANE=m+CONFIG_NF_CONNTRACK_SIP=m+CONFIG_NF_CONNTRACK_TFTP=m+CONFIG_NF_CT_NETLINK=m+CONFIG_NETFILTER_TPROXY=m+CONFIG_NETFILTER_XT_SET=m+CONFIG_NETFILTER_XT_TARGET_AUDIT=m+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m+CONFIG_NETFILTER_XT_TARGET_DSCP=m+CONFIG_NETFILTER_XT_TARGET_HMARK=m+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m+CONFIG_NETFILTER_XT_TARGET_LED=m+CONFIG_NETFILTER_XT_TARGET_LOG=m+CONFIG_NETFILTER_XT_TARGET_MARK=m+CONFIG_NETFILTER_XT_TARGET_NFLOG=m+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m+CONFIG_NETFILTER_XT_TARGET_TEE=m+CONFIG_NETFILTER_XT_TARGET_TPROXY=m+CONFIG_NETFILTER_XT_TARGET_TRACE=m+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m+CONFIG_NETFILTER_XT_MATCH_BPF=m+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m+CONFIG_NETFILTER_XT_MATCH_COMMENT=m+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m+CONFIG_NETFILTER_XT_MATCH_CPU=m+CONFIG_NETFILTER_XT_MATCH_DCCP=m+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m+CONFIG_NETFILTER_XT_MATCH_DSCP=m+CONFIG_NETFILTER_XT_MATCH_ESP=m+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m+CONFIG_NETFILTER_XT_MATCH_HELPER=m+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m+CONFIG_NETFILTER_XT_MATCH_LENGTH=m+CONFIG_NETFILTER_XT_MATCH_LIMIT=m+CONFIG_NETFILTER_XT_MATCH_MAC=m+CONFIG_NETFILTER_XT_MATCH_MARK=m+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m+CONFIG_NETFILTER_XT_MATCH_NFACCT=m+CONFIG_NETFILTER_XT_MATCH_OSF=m+CONFIG_NETFILTER_XT_MATCH_OWNER=m+CONFIG_NETFILTER_XT_MATCH_POLICY=m+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m+CONFIG_NETFILTER_XT_MATCH_QUOTA=m+CONFIG_NETFILTER_XT_MATCH_RATEEST=m+CONFIG_NETFILTER_XT_MATCH_REALM=m+CONFIG_NETFILTER_XT_MATCH_RECENT=m+CONFIG_NETFILTER_XT_MATCH_SOCKET=m+CONFIG_NETFILTER_XT_MATCH_STATE=m+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m+CONFIG_NETFILTER_XT_MATCH_STRING=m+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m+CONFIG_NETFILTER_XT_MATCH_TIME=m+CONFIG_NETFILTER_XT_MATCH_U32=m+CONFIG_IP_SET=m+CONFIG_IP_SET_BITMAP_IP=m+CONFIG_IP_SET_BITMAP_IPMAC=m+CONFIG_IP_SET_BITMAP_PORT=m+CONFIG_IP_SET_HASH_IP=m+CONFIG_IP_SET_HASH_IPPORT=m+CONFIG_IP_SET_HASH_IPPORTIP=m+CONFIG_IP_SET_HASH_IPPORTNET=m+CONFIG_IP_SET_HASH_NET=m+CONFIG_IP_SET_HASH_NETPORT=m+CONFIG_IP_SET_HASH_NETIFACE=m+CONFIG_IP_SET_LIST_SET=m+CONFIG_IP_VS=m+CONFIG_IP_VS_PROTO_TCP=y+CONFIG_IP_VS_PROTO_UDP=y+CONFIG_IP_VS_PROTO_ESP=y+CONFIG_IP_VS_PROTO_AH=y+CONFIG_IP_VS_PROTO_SCTP=y+CONFIG_IP_VS_RR=m+CONFIG_IP_VS_WRR=m+CONFIG_IP_VS_LC=m+CONFIG_IP_VS_WLC=m+CONFIG_IP_VS_LBLC=m+CONFIG_IP_VS_LBLCR=m+CONFIG_IP_VS_DH=m+CONFIG_IP_VS_SH=m+CONFIG_IP_VS_SED=m+CONFIG_IP_VS_NQ=m+CONFIG_IP_VS_FTP=m+CONFIG_IP_VS_PE_SIP=m+CONFIG_NF_CONNTRACK_IPV4=m+CONFIG_IP_NF_IPTABLES=m+CONFIG_IP_NF_MATCH_AH=m+CONFIG_IP_NF_MATCH_ECN=m+CONFIG_IP_NF_MATCH_TTL=m+CONFIG_IP_NF_FILTER=m+CONFIG_IP_NF_TARGET_REJECT=m+CONFIG_IP_NF_TARGET_ULOG=m+CONFIG_NF_NAT_IPV4=m+CONFIG_IP_NF_TARGET_MASQUERADE=m+CONFIG_IP_NF_TARGET_NETMAP=m+CONFIG_IP_NF_TARGET_REDIRECT=m+CONFIG_IP_NF_MANGLE=m+CONFIG_IP_NF_TARGET_ECN=m+CONFIG_IP_NF_TARGET_TTL=m+CONFIG_IP_NF_RAW=m+CONFIG_IP_NF_ARPTABLES=m+CONFIG_IP_NF_ARPFILTER=m+CONFIG_IP_NF_ARP_MANGLE=m+CONFIG_NF_CONNTRACK_IPV6=m+CONFIG_IP6_NF_IPTABLES=m+CONFIG_IP6_NF_MATCH_AH=m+CONFIG_IP6_NF_MATCH_EUI64=m+CONFIG_IP6_NF_MATCH_FRAG=m+CONFIG_IP6_NF_MATCH_OPTS=m+CONFIG_IP6_NF_MATCH_HL=m+CONFIG_IP6_NF_MATCH_IPV6HEADER=m+CONFIG_IP6_NF_MATCH_MH=m+CONFIG_IP6_NF_MATCH_RT=m+CONFIG_IP6_NF_TARGET_HL=m+CONFIG_IP6_NF_FILTER=m+CONFIG_IP6_NF_TARGET_REJECT=m+CONFIG_IP6_NF_MANGLE=m+CONFIG_IP6_NF_RAW=m+CONFIG_NF_NAT_IPV6=m+CONFIG_BRIDGE_NF_EBTABLES=m+CONFIG_BRIDGE_EBT_BROUTE=m+CONFIG_BRIDGE_EBT_T_FILTER=m+CONFIG_BRIDGE_EBT_T_NAT=m+CONFIG_BRIDGE_EBT_802_3=m+CONFIG_BRIDGE_EBT_AMONG=m+CONFIG_BRIDGE_EBT_ARP=m+CONFIG_BRIDGE_EBT_IP=m+CONFIG_BRIDGE_EBT_IP6=m+CONFIG_BRIDGE_EBT_LIMIT=m+CONFIG_BRIDGE_EBT_MARK=m+CONFIG_BRIDGE_EBT_PKTTYPE=m+CONFIG_BRIDGE_EBT_STP=m+CONFIG_BRIDGE_EBT_VLAN=m+CONFIG_BRIDGE_EBT_ARPREPLY=m+CONFIG_BRIDGE_EBT_DNAT=m+CONFIG_BRIDGE_EBT_MARK_T=m+CONFIG_BRIDGE_EBT_REDIRECT=m+CONFIG_BRIDGE_EBT_SNAT=m+CONFIG_BRIDGE_EBT_LOG=m+CONFIG_BRIDGE_EBT_ULOG=m+CONFIG_BRIDGE_EBT_NFLOG=m+CONFIG_SCTP_COOKIE_HMAC_SHA1=y+CONFIG_L2TP=m+CONFIG_BRIDGE=m+CONFIG_VLAN_8021Q=m+CONFIG_VLAN_8021Q_GVRP=y+CONFIG_ATALK=m+CONFIG_NET_SCHED=y+CONFIG_NET_SCH_CBQ=m+CONFIG_NET_SCH_HTB=m+CONFIG_NET_SCH_HFSC=m+CONFIG_NET_SCH_PRIO=m+CONFIG_NET_SCH_MULTIQ=m+CONFIG_NET_SCH_RED=m+CONFIG_NET_SCH_SFB=m+CONFIG_NET_SCH_SFQ=m+CONFIG_NET_SCH_TEQL=m+CONFIG_NET_SCH_TBF=m+CONFIG_NET_SCH_GRED=m+CONFIG_NET_SCH_DSMARK=m+CONFIG_NET_SCH_NETEM=m+CONFIG_NET_SCH_DRR=m+CONFIG_NET_SCH_MQPRIO=m+CONFIG_NET_SCH_CHOKE=m+CONFIG_NET_SCH_QFQ=m+CONFIG_NET_SCH_CODEL=m+CONFIG_NET_SCH_FQ_CODEL=m+CONFIG_NET_SCH_INGRESS=m+CONFIG_NET_SCH_PLUG=m+CONFIG_NET_CLS_BASIC=m+CONFIG_NET_CLS_TCINDEX=m+CONFIG_NET_CLS_ROUTE4=m+CONFIG_NET_CLS_FW=m+CONFIG_NET_CLS_U32=m+CONFIG_CLS_U32_MARK=y+CONFIG_NET_CLS_RSVP=m+CONFIG_NET_CLS_RSVP6=m+CONFIG_NET_CLS_FLOW=m+CONFIG_NET_CLS_CGROUP=m+CONFIG_NET_EMATCH=y+CONFIG_NET_EMATCH_CMP=m+CONFIG_NET_EMATCH_NBYTE=m+CONFIG_NET_EMATCH_U32=m+CONFIG_NET_EMATCH_META=m+CONFIG_NET_EMATCH_TEXT=m+CONFIG_NET_EMATCH_IPSET=m+CONFIG_NET_CLS_ACT=y+CONFIG_NET_ACT_POLICE=m+CONFIG_NET_ACT_GACT=m+CONFIG_GACT_PROB=y+CONFIG_NET_ACT_MIRRED=m+CONFIG_NET_ACT_IPT=m+CONFIG_NET_ACT_NAT=m+CONFIG_NET_ACT_PEDIT=m+CONFIG_NET_ACT_SIMP=m+CONFIG_NET_ACT_SKBEDIT=m+CONFIG_NET_ACT_CSUM=m+CONFIG_BATMAN_ADV=m+CONFIG_OPENVSWITCH=m+CONFIG_NET_PKTGEN=m+CONFIG_HAMRADIO=y+CONFIG_AX25=m+CONFIG_NETROM=m+CONFIG_ROSE=m+CONFIG_MKISS=m+CONFIG_6PACK=m+CONFIG_BPQETHER=m+CONFIG_BAYCOM_SER_FDX=m+CONFIG_BAYCOM_SER_HDX=m+CONFIG_YAM=m+CONFIG_IRDA=m+CONFIG_IRLAN=m+CONFIG_IRNET=m+CONFIG_IRCOMM=m+CONFIG_IRDA_ULTRA=y+CONFIG_IRDA_CACHE_LAST_LSAP=y+CONFIG_IRDA_FAST_RR=y+CONFIG_IRTTY_SIR=m+CONFIG_KINGSUN_DONGLE=m+CONFIG_KSDAZZLE_DONGLE=m+CONFIG_KS959_DONGLE=m+CONFIG_USB_IRDA=m+CONFIG_SIGMATEL_FIR=m+CONFIG_MCS_FIR=m+CONFIG_BT=m+CONFIG_BT_RFCOMM=m+CONFIG_BT_RFCOMM_TTY=y+CONFIG_BT_BNEP=m+CONFIG_BT_BNEP_MC_FILTER=y+CONFIG_BT_BNEP_PROTO_FILTER=y+CONFIG_BT_HIDP=m+CONFIG_BT_HCIBTUSB=m+CONFIG_BT_HCIBCM203X=m+CONFIG_BT_HCIBPA10X=m+CONFIG_BT_HCIBFUSB=m+CONFIG_BT_HCIVHCI=m+CONFIG_BT_MRVL=m+CONFIG_BT_MRVL_SDIO=m+CONFIG_BT_ATH3K=m+CONFIG_BT_WILINK=m+CONFIG_CFG80211=m+CONFIG_CFG80211_WEXT=y+CONFIG_MAC80211=m+CONFIG_MAC80211_RC_PID=y+CONFIG_MAC80211_MESH=y+CONFIG_WIMAX=m+CONFIG_RFKILL=m+CONFIG_RFKILL_INPUT=y+CONFIG_NET_9P=m+CONFIG_NFC=m+CONFIG_NFC_PN533=m+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"+CONFIG_DEVTMPFS=y+CONFIG_DEVTMPFS_MOUNT=y+CONFIG_CMA=y+CONFIG_BLK_DEV_LOOP=y+CONFIG_BLK_DEV_CRYPTOLOOP=m+CONFIG_BLK_DEV_DRBD=m+CONFIG_BLK_DEV_NBD=m+CONFIG_BLK_DEV_RAM=y+CONFIG_CDROM_PKTCDVD=m+CONFIG_SCSI=y+# CONFIG_SCSI_PROC_FS is not set+CONFIG_BLK_DEV_SD=m+CONFIG_BLK_DEV_SR=m+CONFIG_SCSI_MULTI_LUN=y+# CONFIG_SCSI_LOWLEVEL is not set+CONFIG_MD=y+CONFIG_NETDEVICES=y+CONFIG_DUMMY=m+CONFIG_NETCONSOLE=m+CONFIG_TUN=m+CONFIG_MDIO_BITBANG=m+CONFIG_PPP=m+CONFIG_PPP_BSDCOMP=m+CONFIG_PPP_DEFLATE=m+CONFIG_PPP_ASYNC=m+CONFIG_PPP_SYNC_TTY=m+CONFIG_SLIP=m+CONFIG_SLIP_COMPRESSED=y+CONFIG_USB_CATC=m+CONFIG_USB_KAWETH=m+CONFIG_USB_PEGASUS=m+CONFIG_USB_RTL8150=m+CONFIG_USB_RTL8152=m+CONFIG_USB_USBNET=y+CONFIG_USB_NET_AX8817X=m+CONFIG_USB_NET_CDCETHER=m+CONFIG_USB_NET_CDC_EEM=m+CONFIG_USB_NET_CDC_MBIM=m+CONFIG_USB_NET_DM9601=m+CONFIG_USB_NET_SMSC75XX=m+CONFIG_USB_NET_SMSC95XX=y+CONFIG_USB_NET_GL620A=m+CONFIG_USB_NET_NET1080=m+CONFIG_USB_NET_PLUSB=m+CONFIG_USB_NET_MCS7830=m+CONFIG_USB_NET_CDC_SUBSET=m+CONFIG_USB_ALI_M5632=y+CONFIG_USB_AN2720=y+CONFIG_USB_EPSON2888=y+CONFIG_USB_KC2190=y+CONFIG_USB_NET_ZAURUS=m+CONFIG_USB_NET_CX82310_ETH=m+CONFIG_USB_NET_KALMIA=m+CONFIG_USB_NET_QMI_WWAN=m+CONFIG_USB_NET_INT51X1=m+CONFIG_USB_IPHETH=m+CONFIG_USB_SIERRA_NET=m+CONFIG_USB_VL600=m+CONFIG_LIBERTAS_THINFIRM=m+CONFIG_LIBERTAS_THINFIRM_USB=m+CONFIG_AT76C50X_USB=m+CONFIG_USB_ZD1201=m+CONFIG_USB_NET_RNDIS_WLAN=m+CONFIG_RTL8187=m+CONFIG_MAC80211_HWSIM=m+CONFIG_ATH_CARDS=m+CONFIG_ATH9K=m+CONFIG_ATH9K_HTC=m+CONFIG_CARL9170=m+CONFIG_ATH6KL=m+CONFIG_ATH6KL_USB=m+CONFIG_AR5523=m+CONFIG_ATH10K=m+CONFIG_B43=m+# CONFIG_B43_PHY_N is not set+CONFIG_B43LEGACY=m+CONFIG_HOSTAP=m+CONFIG_LIBERTAS=m+CONFIG_LIBERTAS_USB=m+CONFIG_LIBERTAS_SDIO=m+CONFIG_P54_COMMON=m+CONFIG_P54_USB=m+CONFIG_RT2X00=m+CONFIG_RT2500USB=m+CONFIG_RT73USB=m+CONFIG_RT2800USB=m+CONFIG_RT2800USB_RT53XX=y+CONFIG_RT2800USB_UNKNOWN=y+CONFIG_RTL8192CU=m+CONFIG_ZD1211RW=m+CONFIG_MWIFIEX=m+CONFIG_MWIFIEX_SDIO=m+CONFIG_WIMAX_I2400M_USB=m+CONFIG_INPUT_POLLDEV=m+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set+CONFIG_INPUT_JOYDEV=m+CONFIG_INPUT_EVDEV=m+# CONFIG_INPUT_KEYBOARD is not set+# CONFIG_INPUT_MOUSE is not set+CONFIG_INPUT_JOYSTICK=y+CONFIG_JOYSTICK_IFORCE=m+CONFIG_JOYSTICK_IFORCE_USB=y+CONFIG_JOYSTICK_XPAD=m+CONFIG_JOYSTICK_XPAD_FF=y+CONFIG_INPUT_MISC=y+CONFIG_INPUT_AD714X=m+CONFIG_INPUT_ATI_REMOTE2=m+CONFIG_INPUT_KEYSPAN_REMOTE=m+CONFIG_INPUT_POWERMATE=m+CONFIG_INPUT_YEALINK=m+CONFIG_INPUT_CM109=m+CONFIG_INPUT_UINPUT=m+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m+CONFIG_INPUT_ADXL34X=m+CONFIG_INPUT_CMA3000=m+# CONFIG_SERIO is not set+CONFIG_VT_HW_CONSOLE_BINDING=y+# CONFIG_LEGACY_PTYS is not set+# CONFIG_DEVKMEM is not set+CONFIG_SERIAL_AMBA_PL011=y+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y+# CONFIG_HW_RANDOM is not set+CONFIG_RAW_DRIVER=y+CONFIG_BRCM_CHAR_DRIVERS=y+CONFIG_BCM_VC_CMA=y+CONFIG_I2C=y+CONFIG_I2C_CHARDEV=m+CONFIG_I2C_BCM2708=m+CONFIG_SPI=y+CONFIG_SPI_BCM2708=m+CONFIG_SPI_SPIDEV=m+CONFIG_GPIO_SYSFS=y+# CONFIG_HWMON is not set+CONFIG_THERMAL=y+CONFIG_THERMAL_BCM2835=y+CONFIG_WATCHDOG=y+CONFIG_BCM2708_WDT=m+CONFIG_MEDIA_SUPPORT=m+CONFIG_MEDIA_CAMERA_SUPPORT=y+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y+CONFIG_MEDIA_RADIO_SUPPORT=y+CONFIG_MEDIA_RC_SUPPORT=y+CONFIG_MEDIA_CONTROLLER=y+CONFIG_LIRC=m+CONFIG_RC_DEVICES=y+CONFIG_RC_ATI_REMOTE=m+CONFIG_IR_IMON=m+CONFIG_IR_MCEUSB=m+CONFIG_IR_REDRAT3=m+CONFIG_IR_STREAMZAP=m+CONFIG_IR_IGUANA=m+CONFIG_IR_TTUSBIR=m+CONFIG_RC_LOOPBACK=m+CONFIG_IR_GPIO_CIR=m+CONFIG_MEDIA_USB_SUPPORT=y+CONFIG_USB_VIDEO_CLASS=m+CONFIG_USB_M5602=m+CONFIG_USB_STV06XX=m+CONFIG_USB_GL860=m+CONFIG_USB_GSPCA_BENQ=m+CONFIG_USB_GSPCA_CONEX=m+CONFIG_USB_GSPCA_CPIA1=m+CONFIG_USB_GSPCA_ETOMS=m+CONFIG_USB_GSPCA_FINEPIX=m+CONFIG_USB_GSPCA_JEILINJ=m+CONFIG_USB_GSPCA_JL2005BCD=m+CONFIG_USB_GSPCA_KINECT=m+CONFIG_USB_GSPCA_KONICA=m+CONFIG_USB_GSPCA_MARS=m+CONFIG_USB_GSPCA_MR97310A=m+CONFIG_USB_GSPCA_NW80X=m+CONFIG_USB_GSPCA_OV519=m+CONFIG_USB_GSPCA_OV534=m+CONFIG_USB_GSPCA_OV534_9=m+CONFIG_USB_GSPCA_PAC207=m+CONFIG_USB_GSPCA_PAC7302=m+CONFIG_USB_GSPCA_PAC7311=m+CONFIG_USB_GSPCA_SE401=m+CONFIG_USB_GSPCA_SN9C2028=m+CONFIG_USB_GSPCA_SN9C20X=m+CONFIG_USB_GSPCA_SONIXB=m+CONFIG_USB_GSPCA_SONIXJ=m+CONFIG_USB_GSPCA_SPCA500=m+CONFIG_USB_GSPCA_SPCA501=m+CONFIG_USB_GSPCA_SPCA505=m+CONFIG_USB_GSPCA_SPCA506=m+CONFIG_USB_GSPCA_SPCA508=m+CONFIG_USB_GSPCA_SPCA561=m+CONFIG_USB_GSPCA_SPCA1528=m+CONFIG_USB_GSPCA_SQ905=m+CONFIG_USB_GSPCA_SQ905C=m+CONFIG_USB_GSPCA_SQ930X=m+CONFIG_USB_GSPCA_STK014=m+CONFIG_USB_GSPCA_STV0680=m+CONFIG_USB_GSPCA_SUNPLUS=m+CONFIG_USB_GSPCA_T613=m+CONFIG_USB_GSPCA_TOPRO=m+CONFIG_USB_GSPCA_TV8532=m+CONFIG_USB_GSPCA_VC032X=m+CONFIG_USB_GSPCA_VICAM=m+CONFIG_USB_GSPCA_XIRLINK_CIT=m+CONFIG_USB_GSPCA_ZC3XX=m+CONFIG_USB_PWC=m+CONFIG_VIDEO_CPIA2=m+CONFIG_USB_ZR364XX=m+CONFIG_USB_STKWEBCAM=m+CONFIG_USB_S2255=m+CONFIG_USB_SN9C102=m+CONFIG_VIDEO_USBTV=m+CONFIG_VIDEO_PVRUSB2=m+CONFIG_VIDEO_HDPVR=m+CONFIG_VIDEO_TLG2300=m+CONFIG_VIDEO_USBVISION=m+CONFIG_VIDEO_STK1160=m+CONFIG_VIDEO_STK1160_AC97=y+CONFIG_VIDEO_AU0828=m+CONFIG_VIDEO_CX231XX=m+CONFIG_VIDEO_CX231XX_ALSA=m+CONFIG_VIDEO_CX231XX_DVB=m+CONFIG_VIDEO_TM6000=m+CONFIG_VIDEO_TM6000_ALSA=m+CONFIG_VIDEO_TM6000_DVB=m+CONFIG_DVB_USB=m+CONFIG_DVB_USB_A800=m+CONFIG_DVB_USB_DIBUSB_MB=m+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y+CONFIG_DVB_USB_DIBUSB_MC=m+CONFIG_DVB_USB_DIB0700=m+CONFIG_DVB_USB_UMT_010=m+CONFIG_DVB_USB_CXUSB=m+CONFIG_DVB_USB_M920X=m+CONFIG_DVB_USB_DIGITV=m+CONFIG_DVB_USB_VP7045=m+CONFIG_DVB_USB_VP702X=m+CONFIG_DVB_USB_GP8PSK=m+CONFIG_DVB_USB_NOVA_T_USB2=m+CONFIG_DVB_USB_TTUSB2=m+CONFIG_DVB_USB_DTT200U=m+CONFIG_DVB_USB_OPERA1=m+CONFIG_DVB_USB_AF9005=m+CONFIG_DVB_USB_AF9005_REMOTE=m+CONFIG_DVB_USB_PCTV452E=m+CONFIG_DVB_USB_DW2102=m+CONFIG_DVB_USB_CINERGY_T2=m+CONFIG_DVB_USB_DTV5100=m+CONFIG_DVB_USB_FRIIO=m+CONFIG_DVB_USB_AZ6027=m+CONFIG_DVB_USB_TECHNISAT_USB2=m+CONFIG_DVB_USB_V2=m+CONFIG_DVB_USB_AF9015=m+CONFIG_DVB_USB_AF9035=m+CONFIG_DVB_USB_ANYSEE=m+CONFIG_DVB_USB_AU6610=m+CONFIG_DVB_USB_AZ6007=m+CONFIG_DVB_USB_CE6230=m+CONFIG_DVB_USB_EC168=m+CONFIG_DVB_USB_GL861=m+CONFIG_DVB_USB_IT913X=m+CONFIG_DVB_USB_LME2510=m+CONFIG_DVB_USB_MXL111SF=m+CONFIG_DVB_USB_RTL28XXU=m+CONFIG_SMS_USB_DRV=m+CONFIG_DVB_B2C2_FLEXCOP_USB=m+CONFIG_VIDEO_EM28XX=m+CONFIG_VIDEO_EM28XX_ALSA=m+CONFIG_VIDEO_EM28XX_DVB=m+CONFIG_RADIO_SI470X=y+CONFIG_USB_SI470X=m+CONFIG_USB_MR800=m+CONFIG_USB_DSBR=m+CONFIG_RADIO_SHARK=m+CONFIG_RADIO_SHARK2=m+CONFIG_RADIO_SI4713=m+CONFIG_USB_KEENE=m+CONFIG_USB_MA901=m+CONFIG_RADIO_SAA7706H=m+CONFIG_RADIO_TEF6862=m+CONFIG_RADIO_WL128X=m+CONFIG_FB=y+CONFIG_FB_BCM2708=y+CONFIG_FRAMEBUFFER_CONSOLE=y+CONFIG_LOGO=y+# CONFIG_LOGO_LINUX_MONO is not set+# CONFIG_LOGO_LINUX_VGA16 is not set+CONFIG_SOUND=y+CONFIG_SND=m+CONFIG_SND_SEQUENCER=m+CONFIG_SND_SEQ_DUMMY=m+CONFIG_SND_MIXER_OSS=m+CONFIG_SND_PCM_OSS=m+CONFIG_SND_SEQUENCER_OSS=y+CONFIG_SND_HRTIMER=m+CONFIG_SND_DUMMY=m+CONFIG_SND_ALOOP=m+CONFIG_SND_VIRMIDI=m+CONFIG_SND_MTPAV=m+CONFIG_SND_SERIAL_U16550=m+CONFIG_SND_MPU401=m+CONFIG_SND_BCM2835=m+CONFIG_SND_USB_AUDIO=m+CONFIG_SND_USB_UA101=m+CONFIG_SND_USB_CAIAQ=m+CONFIG_SND_USB_6FIRE=m+CONFIG_SND_USB_HIFACE=m+CONFIG_SOUND_PRIME=m+CONFIG_HIDRAW=y+CONFIG_HID_A4TECH=m+CONFIG_HID_ACRUX=m+CONFIG_HID_APPLE=m+CONFIG_HID_BELKIN=m+CONFIG_HID_CHERRY=m+CONFIG_HID_CHICONY=m+CONFIG_HID_CYPRESS=m+CONFIG_HID_DRAGONRISE=m+CONFIG_HID_EMS_FF=m+CONFIG_HID_ELECOM=m+CONFIG_HID_ELO=m+CONFIG_HID_EZKEY=m+CONFIG_HID_HOLTEK=m+CONFIG_HID_KEYTOUCH=m+CONFIG_HID_KYE=m+CONFIG_HID_UCLOGIC=m+CONFIG_HID_WALTOP=m+CONFIG_HID_GYRATION=m+CONFIG_HID_TWINHAN=m+CONFIG_HID_KENSINGTON=m+CONFIG_HID_LCPOWER=m+CONFIG_HID_LOGITECH=m+CONFIG_HID_MAGICMOUSE=m+CONFIG_HID_MICROSOFT=m+CONFIG_HID_MONTEREY=m+CONFIG_HID_MULTITOUCH=m+CONFIG_HID_NTRIG=m+CONFIG_HID_ORTEK=m+CONFIG_HID_PANTHERLORD=m+CONFIG_HID_PETALYNX=m+CONFIG_HID_PICOLCD=m+CONFIG_HID_ROCCAT=m+CONFIG_HID_SAMSUNG=m+CONFIG_HID_SONY=m+CONFIG_HID_SPEEDLINK=m+CONFIG_HID_SUNPLUS=m+CONFIG_HID_GREENASIA=m+CONFIG_HID_SMARTJOYPLUS=m+CONFIG_HID_TOPSEED=m+CONFIG_HID_THINGM=m+CONFIG_HID_THRUSTMASTER=m+CONFIG_HID_WACOM=m+CONFIG_HID_WIIMOTE=m+CONFIG_HID_ZEROPLUS=m+CONFIG_HID_ZYDACRON=m+CONFIG_HID_PID=y+CONFIG_USB_HIDDEV=y+CONFIG_USB=y+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y+CONFIG_USB_MON=m+CONFIG_USB_DWCOTG=y+CONFIG_USB_PRINTER=m+CONFIG_USB_STORAGE=y+CONFIG_USB_STORAGE_REALTEK=m+CONFIG_USB_STORAGE_DATAFAB=m+CONFIG_USB_STORAGE_FREECOM=m+CONFIG_USB_STORAGE_ISD200=m+CONFIG_USB_STORAGE_USBAT=m+CONFIG_USB_STORAGE_SDDR09=m+CONFIG_USB_STORAGE_SDDR55=m+CONFIG_USB_STORAGE_JUMPSHOT=m+CONFIG_USB_STORAGE_ALAUDA=m+CONFIG_USB_STORAGE_ONETOUCH=m+CONFIG_USB_STORAGE_KARMA=m+CONFIG_USB_STORAGE_CYPRESS_ATACB=m+CONFIG_USB_STORAGE_ENE_UB6250=m+CONFIG_USB_MDC800=m+CONFIG_USB_MICROTEK=m+CONFIG_USB_SERIAL=m+CONFIG_USB_SERIAL_GENERIC=y+CONFIG_USB_SERIAL_AIRCABLE=m+CONFIG_USB_SERIAL_ARK3116=m+CONFIG_USB_SERIAL_BELKIN=m+CONFIG_USB_SERIAL_CH341=m+CONFIG_USB_SERIAL_WHITEHEAT=m+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m+CONFIG_USB_SERIAL_CP210X=m+CONFIG_USB_SERIAL_CYPRESS_M8=m+CONFIG_USB_SERIAL_EMPEG=m+CONFIG_USB_SERIAL_FTDI_SIO=m+CONFIG_USB_SERIAL_FUNSOFT=m+CONFIG_USB_SERIAL_VISOR=m+CONFIG_USB_SERIAL_IPAQ=m+CONFIG_USB_SERIAL_IR=m+CONFIG_USB_SERIAL_EDGEPORT=m+CONFIG_USB_SERIAL_EDGEPORT_TI=m+CONFIG_USB_SERIAL_F81232=m+CONFIG_USB_SERIAL_GARMIN=m+CONFIG_USB_SERIAL_IPW=m+CONFIG_USB_SERIAL_IUU=m+CONFIG_USB_SERIAL_KEYSPAN_PDA=m+CONFIG_USB_SERIAL_KEYSPAN=m+CONFIG_USB_SERIAL_KLSI=m+CONFIG_USB_SERIAL_KOBIL_SCT=m+CONFIG_USB_SERIAL_MCT_U232=m+CONFIG_USB_SERIAL_METRO=m+CONFIG_USB_SERIAL_MOS7720=m+CONFIG_USB_SERIAL_MOS7840=m+CONFIG_USB_SERIAL_MOTOROLA=m+CONFIG_USB_SERIAL_NAVMAN=m+CONFIG_USB_SERIAL_PL2303=m+CONFIG_USB_SERIAL_OTI6858=m+CONFIG_USB_SERIAL_QCAUX=m+CONFIG_USB_SERIAL_QUALCOMM=m+CONFIG_USB_SERIAL_SPCP8X5=m+CONFIG_USB_SERIAL_HP4X=m+CONFIG_USB_SERIAL_SAFE=m+CONFIG_USB_SERIAL_SIEMENS_MPI=m+CONFIG_USB_SERIAL_SIERRAWIRELESS=m+CONFIG_USB_SERIAL_SYMBOL=m+CONFIG_USB_SERIAL_TI=m+CONFIG_USB_SERIAL_CYBERJACK=m+CONFIG_USB_SERIAL_XIRCOM=m+CONFIG_USB_SERIAL_OPTION=m+CONFIG_USB_SERIAL_OMNINET=m+CONFIG_USB_SERIAL_OPTICON=m+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m+CONFIG_USB_SERIAL_XSENS_MT=m+CONFIG_USB_SERIAL_ZIO=m+CONFIG_USB_SERIAL_WISHBONE=m+CONFIG_USB_SERIAL_ZTE=m+CONFIG_USB_SERIAL_SSU100=m+CONFIG_USB_SERIAL_QT2=m+CONFIG_USB_SERIAL_DEBUG=m+CONFIG_USB_EMI62=m+CONFIG_USB_EMI26=m+CONFIG_USB_ADUTUX=m+CONFIG_USB_SEVSEG=m+CONFIG_USB_RIO500=m+CONFIG_USB_LEGOTOWER=m+CONFIG_USB_LCD=m+CONFIG_USB_LED=m+CONFIG_USB_CYPRESS_CY7C63=m+CONFIG_USB_CYTHERM=m+CONFIG_USB_IDMOUSE=m+CONFIG_USB_FTDI_ELAN=m+CONFIG_USB_APPLEDISPLAY=m+CONFIG_USB_LD=m+CONFIG_USB_TRANCEVIBRATOR=m+CONFIG_USB_IOWARRIOR=m+CONFIG_USB_TEST=m+CONFIG_USB_ISIGHTFW=m+CONFIG_USB_YUREX=m+CONFIG_MMC=y+CONFIG_MMC_BLOCK_MINORS=32+CONFIG_MMC_SDHCI=y+CONFIG_MMC_SDHCI_PLTFM=y+CONFIG_MMC_SDHCI_BCM2708=y+CONFIG_MMC_SDHCI_BCM2708_DMA=y+CONFIG_LEDS_GPIO=m+CONFIG_LEDS_TRIGGER_TIMER=y+CONFIG_LEDS_TRIGGER_ONESHOT=y+CONFIG_LEDS_TRIGGER_HEARTBEAT=y+CONFIG_LEDS_TRIGGER_BACKLIGHT=y+CONFIG_LEDS_TRIGGER_CPU=y+CONFIG_LEDS_TRIGGER_GPIO=y+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y+CONFIG_LEDS_TRIGGER_TRANSIENT=m+CONFIG_LEDS_TRIGGER_CAMERA=m+CONFIG_RTC_CLASS=y+CONFIG_RTC_DRV_DS1307=m+CONFIG_RTC_DRV_DS1374=m+CONFIG_RTC_DRV_DS1672=m+CONFIG_RTC_DRV_DS3232=m+CONFIG_RTC_DRV_MAX6900=m+CONFIG_RTC_DRV_RS5C372=m+CONFIG_RTC_DRV_ISL1208=m+CONFIG_RTC_DRV_ISL12022=m+CONFIG_RTC_DRV_X1205=m+CONFIG_RTC_DRV_PCF2127=m+CONFIG_RTC_DRV_PCF8523=m+CONFIG_RTC_DRV_PCF8563=m+CONFIG_RTC_DRV_PCF8583=m+CONFIG_RTC_DRV_M41T80=m+CONFIG_RTC_DRV_BQ32K=m+CONFIG_RTC_DRV_S35390A=m+CONFIG_RTC_DRV_FM3130=m+CONFIG_RTC_DRV_RX8581=m+CONFIG_RTC_DRV_RX8025=m+CONFIG_RTC_DRV_EM3027=m+CONFIG_RTC_DRV_RV3029C2=m+CONFIG_RTC_DRV_M41T93=m+CONFIG_RTC_DRV_M41T94=m+CONFIG_RTC_DRV_DS1305=m+CONFIG_RTC_DRV_DS1390=m+CONFIG_RTC_DRV_MAX6902=m+CONFIG_RTC_DRV_R9701=m+CONFIG_RTC_DRV_RS5C348=m+CONFIG_RTC_DRV_DS3234=m+CONFIG_RTC_DRV_PCF2123=m+CONFIG_RTC_DRV_RX4581=m+CONFIG_UIO=m+CONFIG_UIO_PDRV=m+CONFIG_UIO_PDRV_GENIRQ=m+# CONFIG_IOMMU_SUPPORT is not set+CONFIG_EXT4_FS=y+CONFIG_EXT4_FS_POSIX_ACL=y+CONFIG_EXT4_FS_SECURITY=y+CONFIG_REISERFS_FS=m+CONFIG_REISERFS_FS_XATTR=y+CONFIG_REISERFS_FS_POSIX_ACL=y+CONFIG_REISERFS_FS_SECURITY=y+CONFIG_JFS_FS=m+CONFIG_JFS_POSIX_ACL=y+CONFIG_JFS_SECURITY=y+CONFIG_JFS_STATISTICS=y+CONFIG_XFS_FS=m+CONFIG_XFS_QUOTA=y+CONFIG_XFS_POSIX_ACL=y+CONFIG_XFS_RT=y+CONFIG_GFS2_FS=m+CONFIG_OCFS2_FS=m+CONFIG_BTRFS_FS=m+CONFIG_BTRFS_FS_POSIX_ACL=y+CONFIG_NILFS2_FS=m+CONFIG_FANOTIFY=y+CONFIG_QFMT_V1=m+CONFIG_QFMT_V2=m+CONFIG_AUTOFS4_FS=y+CONFIG_FUSE_FS=m+CONFIG_CUSE=m+CONFIG_FSCACHE=y+CONFIG_FSCACHE_STATS=y+CONFIG_FSCACHE_HISTOGRAM=y+CONFIG_CACHEFILES=y+CONFIG_ISO9660_FS=m+CONFIG_JOLIET=y+CONFIG_ZISOFS=y+CONFIG_UDF_FS=m+CONFIG_MSDOS_FS=y+CONFIG_VFAT_FS=y+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"+CONFIG_NTFS_FS=m+CONFIG_TMPFS=y+CONFIG_TMPFS_POSIX_ACL=y+CONFIG_CONFIGFS_FS=y+CONFIG_SQUASHFS=m+CONFIG_SQUASHFS_XATTR=y+CONFIG_SQUASHFS_LZO=y+CONFIG_SQUASHFS_XZ=y+CONFIG_F2FS_FS=y+CONFIG_NFS_FS=y+CONFIG_NFS_V3_ACL=y+CONFIG_NFS_V4=y+CONFIG_ROOT_NFS=y+CONFIG_NFS_FSCACHE=y+CONFIG_NFSD=m+CONFIG_NFSD_V3_ACL=y+CONFIG_NFSD_V4=y+CONFIG_CIFS=m+CONFIG_CIFS_WEAK_PW_HASH=y+CONFIG_CIFS_XATTR=y+CONFIG_CIFS_POSIX=y+CONFIG_9P_FS=m+CONFIG_9P_FS_POSIX_ACL=y+CONFIG_9P_FS_SECURITY=y+CONFIG_NLS_DEFAULT="utf8"+CONFIG_NLS_CODEPAGE_437=y+CONFIG_NLS_CODEPAGE_737=m+CONFIG_NLS_CODEPAGE_775=m+CONFIG_NLS_CODEPAGE_850=m+CONFIG_NLS_CODEPAGE_852=m+CONFIG_NLS_CODEPAGE_855=m+CONFIG_NLS_CODEPAGE_857=m+CONFIG_NLS_CODEPAGE_860=m+CONFIG_NLS_CODEPAGE_861=m+CONFIG_NLS_CODEPAGE_862=m+CONFIG_NLS_CODEPAGE_863=m+CONFIG_NLS_CODEPAGE_864=m+CONFIG_NLS_CODEPAGE_865=m+CONFIG_NLS_CODEPAGE_866=m+CONFIG_NLS_CODEPAGE_869=m+CONFIG_NLS_CODEPAGE_936=m+CONFIG_NLS_CODEPAGE_950=m+CONFIG_NLS_CODEPAGE_932=m+CONFIG_NLS_CODEPAGE_949=m+CONFIG_NLS_CODEPAGE_874=m+CONFIG_NLS_ISO8859_8=m+CONFIG_NLS_CODEPAGE_1250=m+CONFIG_NLS_CODEPAGE_1251=m+CONFIG_NLS_ASCII=y+CONFIG_NLS_ISO8859_1=m+CONFIG_NLS_ISO8859_2=m+CONFIG_NLS_ISO8859_3=m+CONFIG_NLS_ISO8859_4=m+CONFIG_NLS_ISO8859_5=m+CONFIG_NLS_ISO8859_6=m+CONFIG_NLS_ISO8859_7=m+CONFIG_NLS_ISO8859_9=m+CONFIG_NLS_ISO8859_13=m+CONFIG_NLS_ISO8859_14=m+CONFIG_NLS_ISO8859_15=m+CONFIG_NLS_KOI8_R=m+CONFIG_NLS_KOI8_U=m+CONFIG_NLS_UTF8=m+CONFIG_DLM=m+CONFIG_PRINTK_TIME=y+CONFIG_BOOT_PRINTK_DELAY=y+CONFIG_DEBUG_INFO=y+CONFIG_DEBUG_STACK_USAGE=y+CONFIG_DEBUG_MEMORY_INIT=y+CONFIG_DETECT_HUNG_TASK=y+CONFIG_TIMER_STATS=y+CONFIG_LATENCYTOP=y+CONFIG_IRQSOFF_TRACER=y+CONFIG_SCHED_TRACER=y+CONFIG_STACK_TRACER=y+CONFIG_BLK_DEV_IO_TRACE=y+CONFIG_FUNCTION_PROFILER=y+CONFIG_KGDB=y+CONFIG_KGDB_KDB=y+CONFIG_KDB_KEYBOARD=y+CONFIG_STRICT_DEVMEM=y+CONFIG_CRYPTO_SEQIV=m+CONFIG_CRYPTO_CBC=y+CONFIG_CRYPTO_HMAC=y+CONFIG_CRYPTO_XCBC=m+CONFIG_CRYPTO_MD5=y+CONFIG_CRYPTO_SHA1=y+CONFIG_CRYPTO_SHA512=m+CONFIG_CRYPTO_TGR192=m+CONFIG_CRYPTO_WP512=m+CONFIG_CRYPTO_CAST5=m+CONFIG_CRYPTO_DES=y+# CONFIG_CRYPTO_ANSI_CPRNG is not set+# CONFIG_CRYPTO_HW is not set+CONFIG_CRC_ITU_T=y+CONFIG_LIBCRC32C=ydiff -Nur linux-3.11.10.orig/arch/arm/configs/bcmrpi_emergency_defconfig linux-3.11.10/arch/arm/configs/bcmrpi_emergency_defconfig--- linux-3.11.10.orig/arch/arm/configs/bcmrpi_emergency_defconfig	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/configs/bcmrpi_emergency_defconfig	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,532 @@+CONFIG_EXPERIMENTAL=y+# CONFIG_LOCALVERSION_AUTO is not set+CONFIG_SYSVIPC=y+CONFIG_POSIX_MQUEUE=y+CONFIG_BSD_PROCESS_ACCT=y+CONFIG_BSD_PROCESS_ACCT_V3=y+CONFIG_FHANDLE=y+CONFIG_AUDIT=y+CONFIG_IKCONFIG=y+CONFIG_IKCONFIG_PROC=y+CONFIG_BLK_DEV_INITRD=y+CONFIG_INITRAMFS_SOURCE="../target_fs"+CONFIG_CGROUP_FREEZER=y+CONFIG_CGROUP_DEVICE=y+CONFIG_CGROUP_CPUACCT=y+CONFIG_RESOURCE_COUNTERS=y+CONFIG_BLK_CGROUP=y+CONFIG_NAMESPACES=y+CONFIG_SCHED_AUTOGROUP=y+CONFIG_EMBEDDED=y+# CONFIG_COMPAT_BRK is not set+CONFIG_SLAB=y+CONFIG_PROFILING=y+CONFIG_OPROFILE=m+CONFIG_KPROBES=y+CONFIG_MODULES=y+CONFIG_MODULE_UNLOAD=y+CONFIG_MODVERSIONS=y+CONFIG_MODULE_SRCVERSION_ALL=y+# CONFIG_BLK_DEV_BSG is not set+CONFIG_BLK_DEV_THROTTLING=y+CONFIG_CFQ_GROUP_IOSCHED=y+CONFIG_ARCH_BCM2708=y+CONFIG_NO_HZ=y+CONFIG_HIGH_RES_TIMERS=y+CONFIG_AEABI=y+CONFIG_SECCOMP=y+CONFIG_CC_STACKPROTECTOR=y+CONFIG_ZBOOT_ROM_TEXT=0x0+CONFIG_ZBOOT_ROM_BSS=0x0+CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rootwait"+CONFIG_KEXEC=y+CONFIG_CPU_IDLE=y+CONFIG_VFP=y+CONFIG_BINFMT_MISC=m+CONFIG_NET=y+CONFIG_PACKET=y+CONFIG_UNIX=y+CONFIG_XFRM_USER=y+CONFIG_NET_KEY=m+CONFIG_INET=y+CONFIG_IP_MULTICAST=y+CONFIG_IP_PNP=y+CONFIG_IP_PNP_DHCP=y+CONFIG_IP_PNP_RARP=y+CONFIG_SYN_COOKIES=y+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set+# CONFIG_INET_XFRM_MODE_TUNNEL is not set+# CONFIG_INET_XFRM_MODE_BEET is not set+# CONFIG_INET_LRO is not set+# CONFIG_INET_DIAG is not set+# CONFIG_IPV6 is not set+CONFIG_NET_PKTGEN=m+CONFIG_IRDA=m+CONFIG_IRLAN=m+CONFIG_IRCOMM=m+CONFIG_IRDA_ULTRA=y+CONFIG_IRDA_CACHE_LAST_LSAP=y+CONFIG_IRDA_FAST_RR=y+CONFIG_IRTTY_SIR=m+CONFIG_KINGSUN_DONGLE=m+CONFIG_KSDAZZLE_DONGLE=m+CONFIG_KS959_DONGLE=m+CONFIG_USB_IRDA=m+CONFIG_SIGMATEL_FIR=m+CONFIG_MCS_FIR=m+CONFIG_BT=m+CONFIG_BT_L2CAP=y+CONFIG_BT_SCO=y+CONFIG_BT_RFCOMM=m+CONFIG_BT_RFCOMM_TTY=y+CONFIG_BT_BNEP=m+CONFIG_BT_BNEP_MC_FILTER=y+CONFIG_BT_BNEP_PROTO_FILTER=y+CONFIG_BT_HIDP=m+CONFIG_BT_HCIBTUSB=m+CONFIG_BT_HCIBCM203X=m+CONFIG_BT_HCIBPA10X=m+CONFIG_BT_HCIBFUSB=m+CONFIG_BT_HCIVHCI=m+CONFIG_BT_MRVL=m+CONFIG_BT_MRVL_SDIO=m+CONFIG_BT_ATH3K=m+CONFIG_CFG80211=m+CONFIG_MAC80211=m+CONFIG_MAC80211_RC_PID=y+CONFIG_MAC80211_MESH=y+CONFIG_WIMAX=m+CONFIG_NET_9P=m+CONFIG_NFC=m+CONFIG_NFC_PN533=m+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"+CONFIG_BLK_DEV_LOOP=y+CONFIG_BLK_DEV_CRYPTOLOOP=m+CONFIG_BLK_DEV_NBD=m+CONFIG_BLK_DEV_RAM=y+CONFIG_CDROM_PKTCDVD=m+CONFIG_MISC_DEVICES=y+CONFIG_SCSI=y+# CONFIG_SCSI_PROC_FS is not set+CONFIG_BLK_DEV_SD=y+CONFIG_BLK_DEV_SR=m+CONFIG_SCSI_MULTI_LUN=y+# CONFIG_SCSI_LOWLEVEL is not set+CONFIG_MD=y+CONFIG_NETDEVICES=y+CONFIG_TUN=m+CONFIG_PHYLIB=m+CONFIG_MDIO_BITBANG=m+CONFIG_NET_ETHERNET=y+# CONFIG_NETDEV_1000 is not set+# CONFIG_NETDEV_10000 is not set+CONFIG_LIBERTAS_THINFIRM=m+CONFIG_LIBERTAS_THINFIRM_USB=m+CONFIG_AT76C50X_USB=m+CONFIG_USB_ZD1201=m+CONFIG_USB_NET_RNDIS_WLAN=m+CONFIG_RTL8187=m+CONFIG_MAC80211_HWSIM=m+CONFIG_ATH_COMMON=m+CONFIG_ATH9K=m+CONFIG_ATH9K_HTC=m+CONFIG_CARL9170=m+CONFIG_B43=m+CONFIG_B43LEGACY=m+CONFIG_HOSTAP=m+CONFIG_IWM=m+CONFIG_LIBERTAS=m+CONFIG_LIBERTAS_USB=m+CONFIG_LIBERTAS_SDIO=m+CONFIG_P54_COMMON=m+CONFIG_P54_USB=m+CONFIG_RT2X00=m+CONFIG_RT2500USB=m+CONFIG_RT73USB=m+CONFIG_RT2800USB=m+CONFIG_RT2800USB_RT53XX=y+CONFIG_RTL8192CU=m+CONFIG_WL1251=m+CONFIG_WL12XX_MENU=m+CONFIG_ZD1211RW=m+CONFIG_MWIFIEX=m+CONFIG_MWIFIEX_SDIO=m+CONFIG_WIMAX_I2400M_USB=m+CONFIG_USB_CATC=m+CONFIG_USB_KAWETH=m+CONFIG_USB_PEGASUS=m+CONFIG_USB_RTL8150=m+CONFIG_USB_USBNET=y+CONFIG_USB_NET_AX8817X=m+CONFIG_USB_NET_CDCETHER=m+CONFIG_USB_NET_CDC_EEM=m+CONFIG_USB_NET_DM9601=m+CONFIG_USB_NET_SMSC75XX=m+CONFIG_USB_NET_SMSC95XX=y+CONFIG_USB_NET_GL620A=m+CONFIG_USB_NET_NET1080=m+CONFIG_USB_NET_PLUSB=m+CONFIG_USB_NET_MCS7830=m+CONFIG_USB_NET_CDC_SUBSET=m+CONFIG_USB_ALI_M5632=y+CONFIG_USB_AN2720=y+CONFIG_USB_KC2190=y+# CONFIG_USB_NET_ZAURUS is not set+CONFIG_USB_NET_CX82310_ETH=m+CONFIG_USB_NET_KALMIA=m+CONFIG_USB_NET_INT51X1=m+CONFIG_USB_IPHETH=m+CONFIG_USB_SIERRA_NET=m+CONFIG_USB_VL600=m+CONFIG_PPP=m+CONFIG_PPP_ASYNC=m+CONFIG_PPP_SYNC_TTY=m+CONFIG_PPP_DEFLATE=m+CONFIG_PPP_BSDCOMP=m+CONFIG_SLIP=m+CONFIG_SLIP_COMPRESSED=y+CONFIG_NETCONSOLE=m+CONFIG_INPUT_POLLDEV=m+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set+CONFIG_INPUT_JOYDEV=m+CONFIG_INPUT_EVDEV=m+# CONFIG_INPUT_KEYBOARD is not set+# CONFIG_INPUT_MOUSE is not set+CONFIG_INPUT_MISC=y+CONFIG_INPUT_AD714X=m+CONFIG_INPUT_ATI_REMOTE=m+CONFIG_INPUT_ATI_REMOTE2=m+CONFIG_INPUT_KEYSPAN_REMOTE=m+CONFIG_INPUT_POWERMATE=m+CONFIG_INPUT_YEALINK=m+CONFIG_INPUT_CM109=m+CONFIG_INPUT_UINPUT=m+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m+CONFIG_INPUT_ADXL34X=m+CONFIG_INPUT_CMA3000=m+CONFIG_SERIO=m+CONFIG_SERIO_RAW=m+CONFIG_GAMEPORT=m+CONFIG_GAMEPORT_NS558=m+CONFIG_GAMEPORT_L4=m+CONFIG_VT_HW_CONSOLE_BINDING=y+# CONFIG_LEGACY_PTYS is not set+# CONFIG_DEVKMEM is not set+CONFIG_SERIAL_AMBA_PL011=y+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y+# CONFIG_HW_RANDOM is not set+CONFIG_RAW_DRIVER=y+CONFIG_GPIO_SYSFS=y+# CONFIG_HWMON is not set+CONFIG_WATCHDOG=y+CONFIG_BCM2708_WDT=m+# CONFIG_MFD_SUPPORT is not set+CONFIG_FB=y+CONFIG_FB_BCM2708=y+CONFIG_FRAMEBUFFER_CONSOLE=y+CONFIG_LOGO=y+# CONFIG_LOGO_LINUX_MONO is not set+# CONFIG_LOGO_LINUX_VGA16 is not set+CONFIG_SOUND=y+CONFIG_SND=m+CONFIG_SND_SEQUENCER=m+CONFIG_SND_SEQ_DUMMY=m+CONFIG_SND_MIXER_OSS=m+CONFIG_SND_PCM_OSS=m+CONFIG_SND_SEQUENCER_OSS=y+CONFIG_SND_HRTIMER=m+CONFIG_SND_DUMMY=m+CONFIG_SND_ALOOP=m+CONFIG_SND_VIRMIDI=m+CONFIG_SND_MTPAV=m+CONFIG_SND_SERIAL_U16550=m+CONFIG_SND_MPU401=m+CONFIG_SND_BCM2835=m+CONFIG_SND_USB_AUDIO=m+CONFIG_SND_USB_UA101=m+CONFIG_SND_USB_CAIAQ=m+CONFIG_SND_USB_6FIRE=m+CONFIG_SOUND_PRIME=m+CONFIG_HID_PID=y+CONFIG_USB_HIDDEV=y+CONFIG_HID_A4TECH=m+CONFIG_HID_ACRUX=m+CONFIG_HID_APPLE=m+CONFIG_HID_BELKIN=m+CONFIG_HID_CHERRY=m+CONFIG_HID_CHICONY=m+CONFIG_HID_CYPRESS=m+CONFIG_HID_DRAGONRISE=m+CONFIG_HID_EMS_FF=m+CONFIG_HID_ELECOM=m+CONFIG_HID_EZKEY=m+CONFIG_HID_HOLTEK=m+CONFIG_HID_KEYTOUCH=m+CONFIG_HID_KYE=m+CONFIG_HID_UCLOGIC=m+CONFIG_HID_WALTOP=m+CONFIG_HID_GYRATION=m+CONFIG_HID_TWINHAN=m+CONFIG_HID_KENSINGTON=m+CONFIG_HID_LCPOWER=m+CONFIG_HID_LOGITECH=m+CONFIG_HID_MAGICMOUSE=m+CONFIG_HID_MICROSOFT=m+CONFIG_HID_MONTEREY=m+CONFIG_HID_MULTITOUCH=m+CONFIG_HID_NTRIG=m+CONFIG_HID_ORTEK=m+CONFIG_HID_PANTHERLORD=m+CONFIG_HID_PETALYNX=m+CONFIG_HID_PICOLCD=m+CONFIG_HID_QUANTA=m+CONFIG_HID_ROCCAT=m+CONFIG_HID_SAMSUNG=m+CONFIG_HID_SONY=m+CONFIG_HID_SPEEDLINK=m+CONFIG_HID_SUNPLUS=m+CONFIG_HID_GREENASIA=m+CONFIG_HID_SMARTJOYPLUS=m+CONFIG_HID_TOPSEED=m+CONFIG_HID_THRUSTMASTER=m+CONFIG_HID_WACOM=m+CONFIG_HID_WIIMOTE=m+CONFIG_HID_ZEROPLUS=m+CONFIG_HID_ZYDACRON=m+CONFIG_USB=y+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y+CONFIG_USB_MON=m+CONFIG_USB_DWCOTG=y+CONFIG_USB_STORAGE=y+CONFIG_USB_STORAGE_REALTEK=m+CONFIG_USB_STORAGE_DATAFAB=m+CONFIG_USB_STORAGE_FREECOM=m+CONFIG_USB_STORAGE_ISD200=m+CONFIG_USB_STORAGE_USBAT=m+CONFIG_USB_STORAGE_SDDR09=m+CONFIG_USB_STORAGE_SDDR55=m+CONFIG_USB_STORAGE_JUMPSHOT=m+CONFIG_USB_STORAGE_ALAUDA=m+CONFIG_USB_STORAGE_ONETOUCH=m+CONFIG_USB_STORAGE_KARMA=m+CONFIG_USB_STORAGE_CYPRESS_ATACB=m+CONFIG_USB_STORAGE_ENE_UB6250=m+CONFIG_USB_UAS=y+CONFIG_USB_LIBUSUAL=y+CONFIG_USB_MDC800=m+CONFIG_USB_MICROTEK=m+CONFIG_USB_SERIAL=m+CONFIG_USB_SERIAL_GENERIC=y+CONFIG_USB_SERIAL_AIRCABLE=m+CONFIG_USB_SERIAL_ARK3116=m+CONFIG_USB_SERIAL_BELKIN=m+CONFIG_USB_SERIAL_CH341=m+CONFIG_USB_SERIAL_WHITEHEAT=m+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m+CONFIG_USB_SERIAL_CP210X=m+CONFIG_USB_SERIAL_CYPRESS_M8=m+CONFIG_USB_SERIAL_EMPEG=m+CONFIG_USB_SERIAL_FTDI_SIO=m+CONFIG_USB_SERIAL_FUNSOFT=m+CONFIG_USB_SERIAL_VISOR=m+CONFIG_USB_SERIAL_IPAQ=m+CONFIG_USB_SERIAL_IR=m+CONFIG_USB_SERIAL_EDGEPORT=m+CONFIG_USB_SERIAL_EDGEPORT_TI=m+CONFIG_USB_SERIAL_GARMIN=m+CONFIG_USB_SERIAL_IPW=m+CONFIG_USB_SERIAL_IUU=m+CONFIG_USB_SERIAL_KEYSPAN_PDA=m+CONFIG_USB_SERIAL_KEYSPAN=m+CONFIG_USB_SERIAL_KLSI=m+CONFIG_USB_SERIAL_KOBIL_SCT=m+CONFIG_USB_SERIAL_MCT_U232=m+CONFIG_USB_SERIAL_MOS7720=m+CONFIG_USB_SERIAL_MOS7840=m+CONFIG_USB_SERIAL_MOTOROLA=m+CONFIG_USB_SERIAL_NAVMAN=m+CONFIG_USB_SERIAL_PL2303=m+CONFIG_USB_SERIAL_OTI6858=m+CONFIG_USB_SERIAL_QCAUX=m+CONFIG_USB_SERIAL_QUALCOMM=m+CONFIG_USB_SERIAL_SPCP8X5=m+CONFIG_USB_SERIAL_HP4X=m+CONFIG_USB_SERIAL_SAFE=m+CONFIG_USB_SERIAL_SIEMENS_MPI=m+CONFIG_USB_SERIAL_SIERRAWIRELESS=m+CONFIG_USB_SERIAL_SYMBOL=m+CONFIG_USB_SERIAL_TI=m+CONFIG_USB_SERIAL_CYBERJACK=m+CONFIG_USB_SERIAL_XIRCOM=m+CONFIG_USB_SERIAL_OPTION=m+CONFIG_USB_SERIAL_OMNINET=m+CONFIG_USB_SERIAL_OPTICON=m+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m+CONFIG_USB_SERIAL_ZIO=m+CONFIG_USB_SERIAL_SSU100=m+CONFIG_USB_SERIAL_DEBUG=m+CONFIG_USB_EMI62=m+CONFIG_USB_EMI26=m+CONFIG_USB_ADUTUX=m+CONFIG_USB_SEVSEG=m+CONFIG_USB_RIO500=m+CONFIG_USB_LEGOTOWER=m+CONFIG_USB_LCD=m+CONFIG_USB_LED=m+CONFIG_USB_CYPRESS_CY7C63=m+CONFIG_USB_CYTHERM=m+CONFIG_USB_IDMOUSE=m+CONFIG_USB_FTDI_ELAN=m+CONFIG_USB_APPLEDISPLAY=m+CONFIG_USB_LD=m+CONFIG_USB_TRANCEVIBRATOR=m+CONFIG_USB_IOWARRIOR=m+CONFIG_USB_TEST=m+CONFIG_USB_ISIGHTFW=m+CONFIG_USB_YUREX=m+CONFIG_MMC=y+CONFIG_MMC_SDHCI=y+CONFIG_MMC_SDHCI_PLTFM=y+CONFIG_MMC_SDHCI_BCM2708=y+CONFIG_MMC_SDHCI_BCM2708_DMA=y+CONFIG_LEDS_GPIO=y+CONFIG_LEDS_TRIGGER_TIMER=m+CONFIG_LEDS_TRIGGER_HEARTBEAT=m+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m+CONFIG_UIO=m+CONFIG_UIO_PDRV=m+CONFIG_UIO_PDRV_GENIRQ=m+# CONFIG_IOMMU_SUPPORT is not set+CONFIG_EXT4_FS=y+CONFIG_EXT4_FS_POSIX_ACL=y+CONFIG_EXT4_FS_SECURITY=y+CONFIG_REISERFS_FS=m+CONFIG_REISERFS_FS_XATTR=y+CONFIG_REISERFS_FS_POSIX_ACL=y+CONFIG_REISERFS_FS_SECURITY=y+CONFIG_JFS_FS=m+CONFIG_JFS_POSIX_ACL=y+CONFIG_JFS_SECURITY=y+CONFIG_JFS_STATISTICS=y+CONFIG_XFS_FS=m+CONFIG_XFS_QUOTA=y+CONFIG_XFS_POSIX_ACL=y+CONFIG_XFS_RT=y+CONFIG_GFS2_FS=m+CONFIG_OCFS2_FS=m+CONFIG_BTRFS_FS=m+CONFIG_BTRFS_FS_POSIX_ACL=y+CONFIG_NILFS2_FS=m+CONFIG_FANOTIFY=y+CONFIG_AUTOFS4_FS=y+CONFIG_FUSE_FS=m+CONFIG_CUSE=m+CONFIG_FSCACHE=y+CONFIG_FSCACHE_STATS=y+CONFIG_FSCACHE_HISTOGRAM=y+CONFIG_CACHEFILES=y+CONFIG_ISO9660_FS=m+CONFIG_JOLIET=y+CONFIG_ZISOFS=y+CONFIG_UDF_FS=m+CONFIG_MSDOS_FS=y+CONFIG_VFAT_FS=y+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"+CONFIG_NTFS_FS=m+CONFIG_TMPFS=y+CONFIG_TMPFS_POSIX_ACL=y+CONFIG_CONFIGFS_FS=y+CONFIG_SQUASHFS=m+CONFIG_SQUASHFS_XATTR=y+CONFIG_SQUASHFS_LZO=y+CONFIG_SQUASHFS_XZ=y+CONFIG_NFS_FS=y+CONFIG_NFS_V3=y+CONFIG_NFS_V3_ACL=y+CONFIG_NFS_V4=y+CONFIG_ROOT_NFS=y+CONFIG_NFS_FSCACHE=y+CONFIG_CIFS=m+CONFIG_CIFS_WEAK_PW_HASH=y+CONFIG_CIFS_XATTR=y+CONFIG_CIFS_POSIX=y+CONFIG_9P_FS=m+CONFIG_9P_FS_POSIX_ACL=y+CONFIG_PARTITION_ADVANCED=y+CONFIG_MAC_PARTITION=y+CONFIG_EFI_PARTITION=y+CONFIG_NLS_DEFAULT="utf8"+CONFIG_NLS_CODEPAGE_437=y+CONFIG_NLS_CODEPAGE_737=m+CONFIG_NLS_CODEPAGE_775=m+CONFIG_NLS_CODEPAGE_850=m+CONFIG_NLS_CODEPAGE_852=m+CONFIG_NLS_CODEPAGE_855=m+CONFIG_NLS_CODEPAGE_857=m+CONFIG_NLS_CODEPAGE_860=m+CONFIG_NLS_CODEPAGE_861=m+CONFIG_NLS_CODEPAGE_862=m+CONFIG_NLS_CODEPAGE_863=m+CONFIG_NLS_CODEPAGE_864=m+CONFIG_NLS_CODEPAGE_865=m+CONFIG_NLS_CODEPAGE_866=m+CONFIG_NLS_CODEPAGE_869=m+CONFIG_NLS_CODEPAGE_936=m+CONFIG_NLS_CODEPAGE_950=m+CONFIG_NLS_CODEPAGE_932=m+CONFIG_NLS_CODEPAGE_949=m+CONFIG_NLS_CODEPAGE_874=m+CONFIG_NLS_ISO8859_8=m+CONFIG_NLS_CODEPAGE_1250=m+CONFIG_NLS_CODEPAGE_1251=m+CONFIG_NLS_ASCII=y+CONFIG_NLS_ISO8859_1=m+CONFIG_NLS_ISO8859_2=m+CONFIG_NLS_ISO8859_3=m+CONFIG_NLS_ISO8859_4=m+CONFIG_NLS_ISO8859_5=m+CONFIG_NLS_ISO8859_6=m+CONFIG_NLS_ISO8859_7=m+CONFIG_NLS_ISO8859_9=m+CONFIG_NLS_ISO8859_13=m+CONFIG_NLS_ISO8859_14=m+CONFIG_NLS_ISO8859_15=m+CONFIG_NLS_KOI8_R=m+CONFIG_NLS_KOI8_U=m+CONFIG_NLS_UTF8=m+CONFIG_PRINTK_TIME=y+CONFIG_DETECT_HUNG_TASK=y+CONFIG_TIMER_STATS=y+CONFIG_DEBUG_STACK_USAGE=y+CONFIG_DEBUG_INFO=y+CONFIG_DEBUG_MEMORY_INIT=y+CONFIG_BOOT_PRINTK_DELAY=y+CONFIG_LATENCYTOP=y+CONFIG_SYSCTL_SYSCALL_CHECK=y+CONFIG_IRQSOFF_TRACER=y+CONFIG_SCHED_TRACER=y+CONFIG_STACK_TRACER=y+CONFIG_BLK_DEV_IO_TRACE=y+CONFIG_FUNCTION_PROFILER=y+CONFIG_KGDB=y+CONFIG_KGDB_KDB=y+CONFIG_KDB_KEYBOARD=y+CONFIG_STRICT_DEVMEM=y+CONFIG_CRYPTO_AUTHENC=m+CONFIG_CRYPTO_SEQIV=m+CONFIG_CRYPTO_CBC=y+CONFIG_CRYPTO_HMAC=y+CONFIG_CRYPTO_XCBC=m+CONFIG_CRYPTO_MD5=y+CONFIG_CRYPTO_SHA1=y+CONFIG_CRYPTO_SHA256=m+CONFIG_CRYPTO_SHA512=m+CONFIG_CRYPTO_TGR192=m+CONFIG_CRYPTO_WP512=m+CONFIG_CRYPTO_CAST5=m+CONFIG_CRYPTO_DES=y+CONFIG_CRYPTO_DEFLATE=m+# CONFIG_CRYPTO_ANSI_CPRNG is not set+# CONFIG_CRYPTO_HW is not set+CONFIG_CRC_ITU_T=y+CONFIG_LIBCRC32C=ydiff -Nur linux-3.11.10.orig/arch/arm/configs/bcmrpi_quick_defconfig linux-3.11.10/arch/arm/configs/bcmrpi_quick_defconfig--- linux-3.11.10.orig/arch/arm/configs/bcmrpi_quick_defconfig	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/configs/bcmrpi_quick_defconfig	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,197 @@+# CONFIG_ARM_PATCH_PHYS_VIRT is not set+CONFIG_LOCALVERSION="-quick"+# CONFIG_LOCALVERSION_AUTO is not set+# CONFIG_SWAP is not set+CONFIG_SYSVIPC=y+CONFIG_POSIX_MQUEUE=y+CONFIG_NO_HZ=y+CONFIG_HIGH_RES_TIMERS=y+CONFIG_IKCONFIG=y+CONFIG_IKCONFIG_PROC=y+CONFIG_KALLSYMS_ALL=y+CONFIG_EMBEDDED=y+CONFIG_PERF_EVENTS=y+# CONFIG_COMPAT_BRK is not set+CONFIG_SLAB=y+CONFIG_MODULES=y+CONFIG_MODULE_UNLOAD=y+CONFIG_MODVERSIONS=y+CONFIG_MODULE_SRCVERSION_ALL=y+# CONFIG_BLK_DEV_BSG is not set+CONFIG_ARCH_BCM2708=y+CONFIG_PREEMPT=y+CONFIG_AEABI=y+CONFIG_UACCESS_WITH_MEMCPY=y+CONFIG_ZBOOT_ROM_TEXT=0x0+CONFIG_ZBOOT_ROM_BSS=0x0+CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait"+CONFIG_CPU_FREQ=y+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y+CONFIG_CPU_FREQ_GOV_USERSPACE=y+CONFIG_CPU_FREQ_GOV_ONDEMAND=y+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y+CONFIG_CPU_IDLE=y+CONFIG_VFP=y+CONFIG_BINFMT_MISC=y+CONFIG_NET=y+CONFIG_PACKET=y+CONFIG_UNIX=y+CONFIG_INET=y+CONFIG_IP_MULTICAST=y+CONFIG_IP_PNP=y+CONFIG_IP_PNP_DHCP=y+CONFIG_IP_PNP_RARP=y+CONFIG_SYN_COOKIES=y+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set+# CONFIG_INET_XFRM_MODE_TUNNEL is not set+# CONFIG_INET_XFRM_MODE_BEET is not set+# CONFIG_INET_LRO is not set+# CONFIG_INET_DIAG is not set+# CONFIG_IPV6 is not set+# CONFIG_WIRELESS is not set+CONFIG_DEVTMPFS=y+CONFIG_DEVTMPFS_MOUNT=y+CONFIG_BLK_DEV_LOOP=y+CONFIG_BLK_DEV_RAM=y+CONFIG_SCSI=y+# CONFIG_SCSI_PROC_FS is not set+# CONFIG_SCSI_LOWLEVEL is not set+CONFIG_NETDEVICES=y+# CONFIG_NET_VENDOR_BROADCOM is not set+# CONFIG_NET_VENDOR_CIRRUS is not set+# CONFIG_NET_VENDOR_FARADAY is not set+# CONFIG_NET_VENDOR_INTEL is not set+# CONFIG_NET_VENDOR_MARVELL is not set+# CONFIG_NET_VENDOR_MICREL is not set+# CONFIG_NET_VENDOR_NATSEMI is not set+# CONFIG_NET_VENDOR_SEEQ is not set+# CONFIG_NET_VENDOR_STMICRO is not set+# CONFIG_NET_VENDOR_WIZNET is not set+CONFIG_USB_USBNET=y+# CONFIG_USB_NET_AX8817X is not set+# CONFIG_USB_NET_CDCETHER is not set+# CONFIG_USB_NET_CDC_NCM is not set+CONFIG_USB_NET_SMSC95XX=y+# CONFIG_USB_NET_NET1080 is not set+# CONFIG_USB_NET_CDC_SUBSET is not set+# CONFIG_USB_NET_ZAURUS is not set+# CONFIG_WLAN is not set+# CONFIG_INPUT_MOUSEDEV is not set+CONFIG_INPUT_EVDEV=y+# CONFIG_INPUT_KEYBOARD is not set+# CONFIG_INPUT_MOUSE is not set+# CONFIG_SERIO is not set+CONFIG_VT_HW_CONSOLE_BINDING=y+# CONFIG_LEGACY_PTYS is not set+# CONFIG_DEVKMEM is not set+CONFIG_SERIAL_AMBA_PL011=y+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y+CONFIG_TTY_PRINTK=y+CONFIG_HW_RANDOM=y+CONFIG_HW_RANDOM_BCM2708=y+CONFIG_RAW_DRIVER=y+CONFIG_THERMAL=y+CONFIG_THERMAL_BCM2835=y+CONFIG_WATCHDOG=y+CONFIG_BCM2708_WDT=y+CONFIG_REGULATOR=y+CONFIG_REGULATOR_DEBUG=y+CONFIG_REGULATOR_FIXED_VOLTAGE=y+CONFIG_REGULATOR_VIRTUAL_CONSUMER=y+CONFIG_REGULATOR_USERSPACE_CONSUMER=y+CONFIG_FB=y+CONFIG_FB_BCM2708=y+CONFIG_FRAMEBUFFER_CONSOLE=y+CONFIG_LOGO=y+# CONFIG_LOGO_LINUX_MONO is not set+# CONFIG_LOGO_LINUX_VGA16 is not set+CONFIG_SOUND=y+CONFIG_SND=y+CONFIG_SND_BCM2835=y+# CONFIG_SND_USB is not set+CONFIG_USB=y+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y+CONFIG_USB_DWCOTG=y+CONFIG_MMC=y+CONFIG_MMC_SDHCI=y+CONFIG_MMC_SDHCI_PLTFM=y+CONFIG_MMC_SDHCI_BCM2708=y+CONFIG_MMC_SDHCI_BCM2708_DMA=y+CONFIG_NEW_LEDS=y+CONFIG_LEDS_CLASS=y+CONFIG_LEDS_TRIGGERS=y+# CONFIG_IOMMU_SUPPORT is not set+CONFIG_EXT4_FS=y+CONFIG_EXT4_FS_POSIX_ACL=y+CONFIG_EXT4_FS_SECURITY=y+CONFIG_AUTOFS4_FS=y+CONFIG_FSCACHE=y+CONFIG_CACHEFILES=y+CONFIG_MSDOS_FS=y+CONFIG_VFAT_FS=y+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"+CONFIG_TMPFS=y+CONFIG_TMPFS_POSIX_ACL=y+CONFIG_CONFIGFS_FS=y+# CONFIG_MISC_FILESYSTEMS is not set+CONFIG_NFS_FS=y+CONFIG_NFS_V3_ACL=y+CONFIG_NFS_V4=y+CONFIG_ROOT_NFS=y+CONFIG_NFS_FSCACHE=y+CONFIG_NLS_DEFAULT="utf8"+CONFIG_NLS_CODEPAGE_437=y+CONFIG_NLS_CODEPAGE_737=y+CONFIG_NLS_CODEPAGE_775=y+CONFIG_NLS_CODEPAGE_850=y+CONFIG_NLS_CODEPAGE_852=y+CONFIG_NLS_CODEPAGE_855=y+CONFIG_NLS_CODEPAGE_857=y+CONFIG_NLS_CODEPAGE_860=y+CONFIG_NLS_CODEPAGE_861=y+CONFIG_NLS_CODEPAGE_862=y+CONFIG_NLS_CODEPAGE_863=y+CONFIG_NLS_CODEPAGE_864=y+CONFIG_NLS_CODEPAGE_865=y+CONFIG_NLS_CODEPAGE_866=y+CONFIG_NLS_CODEPAGE_869=y+CONFIG_NLS_CODEPAGE_936=y+CONFIG_NLS_CODEPAGE_950=y+CONFIG_NLS_CODEPAGE_932=y+CONFIG_NLS_CODEPAGE_949=y+CONFIG_NLS_CODEPAGE_874=y+CONFIG_NLS_ISO8859_8=y+CONFIG_NLS_CODEPAGE_1250=y+CONFIG_NLS_CODEPAGE_1251=y+CONFIG_NLS_ASCII=y+CONFIG_NLS_ISO8859_1=y+CONFIG_NLS_ISO8859_2=y+CONFIG_NLS_ISO8859_3=y+CONFIG_NLS_ISO8859_4=y+CONFIG_NLS_ISO8859_5=y+CONFIG_NLS_ISO8859_6=y+CONFIG_NLS_ISO8859_7=y+CONFIG_NLS_ISO8859_9=y+CONFIG_NLS_ISO8859_13=y+CONFIG_NLS_ISO8859_14=y+CONFIG_NLS_ISO8859_15=y+CONFIG_NLS_UTF8=y+CONFIG_PRINTK_TIME=y+CONFIG_DEBUG_FS=y+CONFIG_DETECT_HUNG_TASK=y+# CONFIG_DEBUG_PREEMPT is not set+# CONFIG_DEBUG_BUGVERBOSE is not set+# CONFIG_FTRACE is not set+CONFIG_KGDB=y+CONFIG_KGDB_KDB=y+# CONFIG_ARM_UNWIND is not set+CONFIG_CRYPTO_CBC=y+CONFIG_CRYPTO_HMAC=y+CONFIG_CRYPTO_MD5=y+CONFIG_CRYPTO_SHA1=y+CONFIG_CRYPTO_DES=y+# CONFIG_CRYPTO_ANSI_CPRNG is not set+# CONFIG_CRYPTO_HW is not set+CONFIG_CRC_ITU_T=y+CONFIG_LIBCRC32C=ydiff -Nur linux-3.11.10.orig/arch/arm/include/asm/fiq.h linux-3.11.10/arch/arm/include/asm/fiq.h--- linux-3.11.10.orig/arch/arm/include/asm/fiq.h	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/arch/arm/include/asm/fiq.h	2014-02-07 19:57:28.000000000 +0100@@ -42,6 +42,7 @@ /* helpers defined in fiqasm.S: */ extern void __set_fiq_regs(unsigned long const *regs); extern void __get_fiq_regs(unsigned long *regs);+extern void __FIQ_Branch(unsigned long *regs);  static inline void set_fiq_regs(struct pt_regs const *regs) {diff -Nur linux-3.11.10.orig/arch/arm/Kconfig linux-3.11.10/arch/arm/Kconfig--- linux-3.11.10.orig/arch/arm/Kconfig	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/arch/arm/Kconfig	2014-02-07 19:57:28.000000000 +0100@@ -366,6 +366,23 @@ 	  This enables support for systems based on Atmel 	  AT91RM9200 and AT91SAM9* processors. +config ARCH_BCM2708+	bool "Broadcom BCM2708 family"+	select CPU_V6+	select ARM_AMBA+	select HAVE_CLK+	select HAVE_SCHED_CLOCK+	select NEED_MACH_MEMORY_H+	select CLKDEV_LOOKUP+	select ARCH_HAS_CPUFREQ+	select GENERIC_CLOCKEVENTS+	select ARM_ERRATA_411920+	select MACH_BCM2708+	select VC4+	select FIQ+	help+	  This enables support for Broadcom BCM2708 boards.+ config ARCH_CLPS711X 	bool "Cirrus Logic CLPS711x/EP721x/EP731x-based" 	select ARCH_REQUIRE_GPIOLIB@@ -1041,6 +1058,7 @@ source "arch/arm/mach-vt8500/Kconfig"  source "arch/arm/mach-w90x900/Kconfig"+source "arch/arm/mach-bcm2708/Kconfig"  source "arch/arm/mach-zynq/Kconfig" diff -Nur linux-3.11.10.orig/arch/arm/Kconfig.debug linux-3.11.10/arch/arm/Kconfig.debug--- linux-3.11.10.orig/arch/arm/Kconfig.debug	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/arch/arm/Kconfig.debug	2014-02-07 19:57:28.000000000 +0100@@ -610,6 +610,14 @@ 		  For more details about semihosting, please see 		  chapter 8 of DUI0203I_rvct_developer_guide.pdf from ARM Ltd. +	config DEBUG_BCM2708_UART0+		bool "Broadcom BCM2708 UART0 (PL011)"+		depends on MACH_BCM2708+		help+		  Say Y here if you want the debug print routines to direct+		  their output to UART 0. The port must have been initialised+		  by the boot-loader before use.+ endchoice  config DEBUG_EXYNOS_UARTdiff -Nur linux-3.11.10.orig/arch/arm/kernel/fiqasm.S linux-3.11.10/arch/arm/kernel/fiqasm.S--- linux-3.11.10.orig/arch/arm/kernel/fiqasm.S	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/arch/arm/kernel/fiqasm.S	2014-02-07 19:57:28.000000000 +0100@@ -25,6 +25,9 @@ ENTRY(__set_fiq_regs) 	mov	r2, #PSR_I_BIT | PSR_F_BIT | FIQ_MODE 	mrs	r1, cpsr+@@@@@@@@@@@@@@@ hack: enable the fiq here to keep usb driver happy+	and	r1, #~PSR_F_BIT+@@@@@@@@@@@@@@@ endhack: (need to find better place for this to happen) 	msr	cpsr_c, r2	@ select FIQ mode 	mov	r0, r0		@ avoid hazard prior to ARMv4 	ldmia	r0!, {r8 - r12}@@ -47,3 +50,7 @@ 	mov	r0, r0		@ avoid hazard prior to ARMv4 	mov	pc, lr ENDPROC(__get_fiq_regs)++ENTRY(__FIQ_Branch)+	mov pc, r8+ENDPROC(__FIQ_Branch)diff -Nur linux-3.11.10.orig/arch/arm/kernel/fiq.c linux-3.11.10/arch/arm/kernel/fiq.c--- linux-3.11.10.orig/arch/arm/kernel/fiq.c	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/arch/arm/kernel/fiq.c	2014-02-07 19:57:28.000000000 +0100@@ -142,6 +142,7 @@ EXPORT_SYMBOL(set_fiq_handler); EXPORT_SYMBOL(__set_fiq_regs);	/* defined in fiqasm.S */ EXPORT_SYMBOL(__get_fiq_regs);	/* defined in fiqasm.S */+EXPORT_SYMBOL(__FIQ_Branch);	/* defined in fiqasm.S */ EXPORT_SYMBOL(claim_fiq); EXPORT_SYMBOL(release_fiq); EXPORT_SYMBOL(enable_fiq);diff -Nur linux-3.11.10.orig/arch/arm/kernel/process.c linux-3.11.10/arch/arm/kernel/process.c--- linux-3.11.10.orig/arch/arm/kernel/process.c	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/arch/arm/kernel/process.c	2014-02-07 19:57:28.000000000 +0100@@ -176,6 +176,16 @@ 		default_idle(); } +char bcm2708_reboot_mode = 'h';++int __init reboot_setup(char *str)+{+	bcm2708_reboot_mode = str[0];+	return 1;+}++__setup("reboot=", reboot_setup);+ /*  * Called by kexec, immediately prior to machine_kexec().  *diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/armctrl.c linux-3.11.10/arch/arm/mach-bcm2708/armctrl.c--- linux-3.11.10.orig/arch/arm/mach-bcm2708/armctrl.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/armctrl.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,219 @@+/*+ *  linux/arch/arm/mach-bcm2708/armctrl.c+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */+#include <linux/init.h>+#include <linux/list.h>+#include <linux/io.h>+#include <linux/version.h>+#include <linux/syscore_ops.h>+#include <linux/interrupt.h>++#include <asm/mach/irq.h>+#include <mach/hardware.h>+#include "armctrl.h"++/* For support of kernels >= 3.0 assume only one VIC for now*/+static unsigned int remap_irqs[(INTERRUPT_ARASANSDIO + 1) - INTERRUPT_JPEG] = {+	INTERRUPT_VC_JPEG,+	INTERRUPT_VC_USB,+	INTERRUPT_VC_3D,+	INTERRUPT_VC_DMA2,+	INTERRUPT_VC_DMA3,+	INTERRUPT_VC_I2C,+	INTERRUPT_VC_SPI,+	INTERRUPT_VC_I2SPCM,+	INTERRUPT_VC_SDIO,+	INTERRUPT_VC_UART,+	INTERRUPT_VC_ARASANSDIO+};++static void armctrl_mask_irq(struct irq_data *d)+{+	static const unsigned int disables[4] = {+		ARM_IRQ_DIBL1,+		ARM_IRQ_DIBL2,+		ARM_IRQ_DIBL3,+		0+	};++	if (d->irq >= FIQ_START) {+		writel(0, __io_address(ARM_IRQ_FAST));+	} else {+		unsigned int data = (unsigned int)irq_get_chip_data(d->irq);+		writel(1 << (data & 0x1f), __io_address(disables[(data >> 5) & 0x3]));+	}+}++static void armctrl_unmask_irq(struct irq_data *d)+{+	static const unsigned int enables[4] = {+		ARM_IRQ_ENBL1,+		ARM_IRQ_ENBL2,+		ARM_IRQ_ENBL3,+		0+	};++	if (d->irq >= FIQ_START) {+		unsigned int data =+		    (unsigned int)irq_get_chip_data(d->irq) - FIQ_START;+		writel(0x80 | data, __io_address(ARM_IRQ_FAST));+	} else {+		unsigned int data = (unsigned int)irq_get_chip_data(d->irq);+		writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3]));+	}+}++#if defined(CONFIG_PM)++/* for kernels 3.xx use the new syscore_ops apis but for older kernels use the sys dev class */++/* Static defines+ * struct armctrl_device - VIC PM device (< 3.xx)+ * @sysdev: The system device which is registered. (< 3.xx)+ * @irq: The IRQ number for the base of the VIC.+ * @base: The register base for the VIC.+ * @resume_sources: A bitmask of interrupts for resume.+ * @resume_irqs: The IRQs enabled for resume.+ * @int_select: Save for VIC_INT_SELECT.+ * @int_enable: Save for VIC_INT_ENABLE.+ * @soft_int: Save for VIC_INT_SOFT.+ * @protect: Save for VIC_PROTECT.+ */+struct armctrl_info {+	void __iomem *base;+	int irq;+	u32 resume_sources;+	u32 resume_irqs;+	u32 int_select;+	u32 int_enable;+	u32 soft_int;+	u32 protect;+} armctrl;++static int armctrl_suspend(void)+{+	return 0;+}++static void armctrl_resume(void)+{+	return;+}++/**+ * armctrl_pm_register - Register a VIC for later power management control+ * @base: The base address of the VIC.+ * @irq: The base IRQ for the VIC.+ * @resume_sources: bitmask of interrupts allowed for resume sources.+ *+ * For older kernels (< 3.xx) do -+ * Register the VIC with the system device tree so that it can be notified+ * of suspend and resume requests and ensure that the correct actions are+ * taken to re-instate the settings on resume.+ */+static void __init armctrl_pm_register(void __iomem * base, unsigned int irq,+				       u32 resume_sources)+{+	armctrl.base = base;+	armctrl.resume_sources = resume_sources;+	armctrl.irq = irq;+}++static int armctrl_set_wake(struct irq_data *d, unsigned int on)+{+	unsigned int off = d->irq & 31;+	u32 bit = 1 << off;++	if (!(bit & armctrl.resume_sources))+		return -EINVAL;++	if (on)+		armctrl.resume_irqs |= bit;+	else+		armctrl.resume_irqs &= ~bit;++	return 0;+}++#else+static inline void armctrl_pm_register(void __iomem * base, unsigned int irq,+				       u32 arg1)+{+}++#define armctrl_suspend NULL+#define armctrl_resume NULL+#define armctrl_set_wake NULL+#endif /* CONFIG_PM */++static struct syscore_ops armctrl_syscore_ops = {+	.suspend = armctrl_suspend,+	.resume = armctrl_resume,+};++/**+ * armctrl_syscore_init - initicall to register VIC pm functions+ *+ * This is called via late_initcall() to register+ * the resources for the VICs due to the early+ * nature of the VIC's registration.+*/+static int __init armctrl_syscore_init(void)+{+	register_syscore_ops(&armctrl_syscore_ops);+	return 0;+}++late_initcall(armctrl_syscore_init);++static struct irq_chip armctrl_chip = {+	.name = "ARMCTRL",+	.irq_ack = armctrl_mask_irq,+	.irq_mask = armctrl_mask_irq,+	.irq_unmask = armctrl_unmask_irq,+	.irq_set_wake = armctrl_set_wake,+};++/**+ * armctrl_init - initialise a vectored interrupt controller+ * @base: iomem base address+ * @irq_start: starting interrupt number, must be muliple of 32+ * @armctrl_sources: bitmask of interrupt sources to allow+ * @resume_sources: bitmask of interrupt sources to allow for resume+ */+int __init armctrl_init(void __iomem * base, unsigned int irq_start,+			u32 armctrl_sources, u32 resume_sources)+{+	unsigned int irq;++	for (irq = 0; irq < NR_IRQS; irq++) {+		unsigned int data = irq;+		if (irq >= INTERRUPT_JPEG && irq <= INTERRUPT_ARASANSDIO)+			data = remap_irqs[irq - INTERRUPT_JPEG];++		irq_set_chip(irq, &armctrl_chip);+		irq_set_chip_data(irq, (void *)data);+		irq_set_handler(irq, handle_level_irq);+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_DISABLED);+	}++	armctrl_pm_register(base, irq_start, resume_sources);+	init_FIQ(FIQ_START);+	return 0;+}diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/armctrl.h linux-3.11.10/arch/arm/mach-bcm2708/armctrl.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/armctrl.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/armctrl.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,27 @@+/*+ *  linux/arch/arm/mach-bcm2708/armctrl.h+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */++#ifndef __BCM2708_ARMCTRL_H+#define __BCM2708_ARMCTRL_H++extern int __init armctrl_init(void __iomem * base, unsigned int irq_start,+			       u32 armctrl_sources, u32 resume_sources);++#endifdiff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/bcm2708.c linux-3.11.10/arch/arm/mach-bcm2708/bcm2708.c--- linux-3.11.10.orig/arch/arm/mach-bcm2708/bcm2708.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/bcm2708.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,917 @@+/*+ *  linux/arch/arm/mach-bcm2708/bcm2708.c+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */++#include <linux/init.h>+#include <linux/device.h>+#include <linux/dma-mapping.h>+#include <linux/serial_8250.h>+#include <linux/platform_device.h>+#include <linux/syscore_ops.h>+#include <linux/interrupt.h>+#include <linux/amba/bus.h>+#include <linux/amba/clcd.h>+#include <linux/clockchips.h>+#include <linux/cnt32_to_63.h>+#include <linux/io.h>+#include <linux/module.h>+#include <linux/spi/spi.h>+#include <linux/w1-gpio.h>++#include <linux/version.h>+#include <linux/clkdev.h>+#include <asm/system.h>+#include <mach/hardware.h>+#include <asm/irq.h>+#include <linux/leds.h>+#include <asm/mach-types.h>+#include <asm/sched_clock.h>++#include <asm/mach/arch.h>+#include <asm/mach/flash.h>+#include <asm/mach/irq.h>+#include <asm/mach/time.h>+#include <asm/mach/map.h>++#include <mach/timex.h>+#include <mach/dma.h>+#include <mach/vcio.h>+#include <mach/system.h>++#include <linux/delay.h>++#include "bcm2708.h"+#include "armctrl.h"+#include "clock.h"++#ifdef CONFIG_BCM_VC_CMA+#include <linux/broadcom/vc_cma.h>+#endif+++/* Effectively we have an IOMMU (ARM<->VideoCore map) that is set up to+ * give us IO access only to 64Mbytes of physical memory (26 bits).  We could+ * represent this window by setting our dmamasks to 26 bits but, in fact+ * we're not going to use addresses outside this range (they're not in real+ * memory) so we don't bother.+ *+ * In the future we might include code to use this IOMMU to remap other+ * physical addresses onto VideoCore memory then the use of 32-bits would be+ * more legitimate.+ */+#define DMA_MASK_BITS_COMMON 32++// use GPIO 4 for the one-wire GPIO pin, if enabled+#define W1_GPIO 4++/* command line parameters */+static unsigned boardrev, serial;+static unsigned uart_clock;+static unsigned reboot_part = 0;++static void __init bcm2708_init_led(void);++void __init bcm2708_init_irq(void)+{+	armctrl_init(__io_address(ARMCTRL_IC_BASE), 0, 0, 0);+}++static struct map_desc bcm2708_io_desc[] __initdata = {+	{+	 .virtual = IO_ADDRESS(ARMCTRL_BASE),+	 .pfn = __phys_to_pfn(ARMCTRL_BASE),+	 .length = SZ_4K,+	 .type = MT_DEVICE},+	{+	 .virtual = IO_ADDRESS(UART0_BASE),+	 .pfn = __phys_to_pfn(UART0_BASE),+	 .length = SZ_4K,+	 .type = MT_DEVICE},+	{+	 .virtual = IO_ADDRESS(UART1_BASE),+	 .pfn = __phys_to_pfn(UART1_BASE),+	 .length = SZ_4K,+	 .type = MT_DEVICE},+	{+	 .virtual = IO_ADDRESS(DMA_BASE),+	 .pfn = __phys_to_pfn(DMA_BASE),+	 .length = SZ_4K,+	 .type = MT_DEVICE},+	{+	 .virtual = IO_ADDRESS(MCORE_BASE),+	 .pfn = __phys_to_pfn(MCORE_BASE),+	 .length = SZ_4K,+	 .type = MT_DEVICE},+	{+	 .virtual = IO_ADDRESS(ST_BASE),+	 .pfn = __phys_to_pfn(ST_BASE),+	 .length = SZ_4K,+	 .type = MT_DEVICE},+	{+	 .virtual = IO_ADDRESS(USB_BASE),+	 .pfn = __phys_to_pfn(USB_BASE),+	 .length = SZ_128K,+	 .type = MT_DEVICE},+	{+	 .virtual = IO_ADDRESS(PM_BASE),+	 .pfn = __phys_to_pfn(PM_BASE),+	 .length = SZ_4K,+	 .type = MT_DEVICE},+	{+	 .virtual = IO_ADDRESS(GPIO_BASE),+	 .pfn = __phys_to_pfn(GPIO_BASE),+	 .length = SZ_4K,+	 .type = MT_DEVICE}+};++void __init bcm2708_map_io(void)+{+	iotable_init(bcm2708_io_desc, ARRAY_SIZE(bcm2708_io_desc));+}++/* The STC is a free running counter that increments at the rate of 1MHz */+#define STC_FREQ_HZ 1000000++static inline uint32_t timer_read(void)+{+	/* STC: a free running counter that increments at the rate of 1MHz */+	return readl(__io_address(ST_BASE + 0x04));+}++static unsigned long bcm2708_read_current_timer(void)+{+	return timer_read();+}++static u32 notrace bcm2708_read_sched_clock(void)+{+	return timer_read();+}++static cycle_t clksrc_read(struct clocksource *cs)+{+	return timer_read();+}++static struct clocksource clocksource_stc = {+	.name = "stc",+	.rating = 300,+	.read = clksrc_read,+	.mask = CLOCKSOURCE_MASK(32),+	.flags = CLOCK_SOURCE_IS_CONTINUOUS,+};++unsigned long frc_clock_ticks32(void)+{+	return timer_read();+}++static void __init bcm2708_clocksource_init(void)+{+	if (clocksource_register_hz(&clocksource_stc, STC_FREQ_HZ)) {+		printk(KERN_ERR "timer: failed to initialize clock "+		       "source %s\n", clocksource_stc.name);+	}+}+++/*+ * These are fixed clocks.+ */+static struct clk ref24_clk = {+	.rate = UART0_CLOCK,	/* The UART is clocked at 3MHz via APB_CLK */+};++static struct clk osc_clk = {+#ifdef CONFIG_ARCH_BCM2708_CHIPIT+	.rate = 27000000,+#else+	.rate = 500000000,	/* ARM clock is set from the VideoCore booter */+#endif+};++/* warning - the USB needs a clock > 34MHz */++static struct clk sdhost_clk = {+#ifdef CONFIG_ARCH_BCM2708_CHIPIT+	.rate = 4000000,	/* 4MHz */+#else+	.rate = 250000000,	/* 250MHz */+#endif+};++static struct clk_lookup lookups[] = {+	{			/* UART0 */+	 .dev_id = "dev:f1",+	 .clk = &ref24_clk,+	 },+	{			/* USB */+	 .dev_id = "bcm2708_usb",+	 .clk = &osc_clk,+	 }, {	/* SPI */+		 .dev_id = "bcm2708_spi.0",+		 .clk = &sdhost_clk,+	 }, {	/* BSC0 */+		 .dev_id = "bcm2708_i2c.0",+		 .clk = &sdhost_clk,+	 }, {	/* BSC1 */+		 .dev_id = "bcm2708_i2c.1",+		 .clk = &sdhost_clk,+	 }+};++#define UART0_IRQ	{ IRQ_UART, 0 /*NO_IRQ*/ }+#define UART0_DMA	{ 15, 14 }++AMBA_DEVICE(uart0, "dev:f1", UART0, NULL);++static struct amba_device *amba_devs[] __initdata = {+	&uart0_device,+};++static struct resource bcm2708_dmaman_resources[] = {+	{+	 .start = DMA_BASE,+	 .end = DMA_BASE + SZ_4K - 1,+	 .flags = IORESOURCE_MEM,+	 }+};++static struct platform_device bcm2708_dmaman_device = {+	.name = BCM_DMAMAN_DRIVER_NAME,+	.id = 0,		/* first bcm2708_dma */+	.resource = bcm2708_dmaman_resources,+	.num_resources = ARRAY_SIZE(bcm2708_dmaman_resources),+};++#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE)+static struct w1_gpio_platform_data w1_gpio_pdata = {+	.pin = W1_GPIO,+	.is_open_drain = 0,+};++static struct platform_device w1_device = {+	.name = "w1-gpio",+	.id = -1,+	.dev.platform_data = &w1_gpio_pdata,+};+#endif++static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);++static struct platform_device bcm2708_fb_device = {+	.name = "bcm2708_fb",+	.id = -1,		/* only one bcm2708_fb */+	.resource = NULL,+	.num_resources = 0,+	.dev = {+		.dma_mask = &fb_dmamask,+		.coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),+		},+};++static struct plat_serial8250_port bcm2708_uart1_platform_data[] = {+	{+	 .mapbase = UART1_BASE + 0x40,+	 .irq = IRQ_AUX,+	 .uartclk = 125000000,+	 .regshift = 2,+	 .iotype = UPIO_MEM,+	 .flags = UPF_FIXED_TYPE | UPF_IOREMAP | UPF_SKIP_TEST,+	 .type = PORT_8250,+	 },+	{},+};++static struct platform_device bcm2708_uart1_device = {+	.name = "serial8250",+	.id = PLAT8250_DEV_PLATFORM,+	.dev = {+		.platform_data = bcm2708_uart1_platform_data,+		},+};++static struct resource bcm2708_usb_resources[] = {+	[0] = {+	       .start = USB_BASE,+	       .end = USB_BASE + SZ_128K - 1,+	       .flags = IORESOURCE_MEM,+	       },+	[1] = {+		.start = MPHI_BASE,+		.end = MPHI_BASE + SZ_4K - 1,+		.flags = IORESOURCE_MEM,+	      },+	[2] = {+	       .start = IRQ_HOSTPORT,+	       .end = IRQ_HOSTPORT,+	       .flags = IORESOURCE_IRQ,+	       },+};++bool fiq_fix_enable = true;++static struct resource bcm2708_usb_resources_no_fiq_fix[] = {+	[0] = {+		.start = USB_BASE,+		.end = USB_BASE + SZ_128K - 1,+		.flags = IORESOURCE_MEM,+		},+	[1] = {+		.start = IRQ_USB,+		.end = IRQ_USB,+		.flags = IORESOURCE_IRQ,+		},+};++static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);++static struct platform_device bcm2708_usb_device = {+	.name = "bcm2708_usb",+	.id = -1,		/* only one bcm2708_usb */+	.resource = bcm2708_usb_resources,+	.num_resources = ARRAY_SIZE(bcm2708_usb_resources),+	.dev = {+		.dma_mask = &usb_dmamask,+		.coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),+		},+};++static struct resource bcm2708_vcio_resources[] = {+	[0] = {			/* mailbox/semaphore/doorbell access */+	       .start = MCORE_BASE,+	       .end = MCORE_BASE + SZ_4K - 1,+	       .flags = IORESOURCE_MEM,+	       },+};++static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);++static struct platform_device bcm2708_vcio_device = {+	.name = BCM_VCIO_DRIVER_NAME,+	.id = -1,		/* only one VideoCore I/O area */+	.resource = bcm2708_vcio_resources,+	.num_resources = ARRAY_SIZE(bcm2708_vcio_resources),+	.dev = {+		.dma_mask = &vcio_dmamask,+		.coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),+		},+};++#ifdef CONFIG_BCM2708_GPIO+#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio"++static struct resource bcm2708_gpio_resources[] = {+	[0] = {			/* general purpose I/O */+	       .start = GPIO_BASE,+	       .end = GPIO_BASE + SZ_4K - 1,+	       .flags = IORESOURCE_MEM,+	       },+};++static u64 gpio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);++static struct platform_device bcm2708_gpio_device = {+	.name = BCM_GPIO_DRIVER_NAME,+	.id = -1,		/* only one VideoCore I/O area */+	.resource = bcm2708_gpio_resources,+	.num_resources = ARRAY_SIZE(bcm2708_gpio_resources),+	.dev = {+		.dma_mask = &gpio_dmamask,+		.coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),+		},+};+#endif++static struct resource bcm2708_systemtimer_resources[] = {+	[0] = {			/* system timer access */+	       .start = ST_BASE,+	       .end = ST_BASE + SZ_4K - 1,+	       .flags = IORESOURCE_MEM,+	       },+	{+	 .start = IRQ_TIMER3,+	 .end = IRQ_TIMER3,+	 .flags = IORESOURCE_IRQ,+	 }++};++static u64 systemtimer_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);++static struct platform_device bcm2708_systemtimer_device = {+	.name = "bcm2708_systemtimer",+	.id = -1,		/* only one VideoCore I/O area */+	.resource = bcm2708_systemtimer_resources,+	.num_resources = ARRAY_SIZE(bcm2708_systemtimer_resources),+	.dev = {+		.dma_mask = &systemtimer_dmamask,+		.coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),+		},+};++#ifdef CONFIG_MMC_SDHCI_BCM2708	/* Arasan emmc SD */+static struct resource bcm2708_emmc_resources[] = {+	[0] = {+	       .start = EMMC_BASE,+	       .end = EMMC_BASE + SZ_256 - 1,	/* we only need this area */+	       /* the memory map actually makes SZ_4K available  */+	       .flags = IORESOURCE_MEM,+	       },+	[1] = {+	       .start = IRQ_ARASANSDIO,+	       .end = IRQ_ARASANSDIO,+	       .flags = IORESOURCE_IRQ,+	       },+};++static u64 bcm2708_emmc_dmamask = 0xffffffffUL;++struct platform_device bcm2708_emmc_device = {+	.name = "bcm2708_sdhci",+	.id = 0,+	.num_resources = ARRAY_SIZE(bcm2708_emmc_resources),+	.resource = bcm2708_emmc_resources,+	.dev = {+		.dma_mask = &bcm2708_emmc_dmamask,+		.coherent_dma_mask = 0xffffffffUL},+};+#endif /* CONFIG_MMC_SDHCI_BCM2708 */++static struct resource bcm2708_powerman_resources[] = {+	[0] = {+	       .start = PM_BASE,+	       .end = PM_BASE + SZ_256 - 1,+	       .flags = IORESOURCE_MEM,+	       },+};++static u64 powerman_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);++struct platform_device bcm2708_powerman_device = {+	.name = "bcm2708_powerman",+	.id = 0,+	.num_resources = ARRAY_SIZE(bcm2708_powerman_resources),+	.resource = bcm2708_powerman_resources,+	.dev = {+		.dma_mask = &powerman_dmamask,+		.coherent_dma_mask = 0xffffffffUL},+};+++static struct platform_device bcm2708_alsa_devices[] = {+	[0] = {+	       .name = "bcm2835_AUD0",+	       .id = 0,		/* first audio device */+	       .resource = 0,+	       .num_resources = 0,+	       },+	[1] = {+	       .name = "bcm2835_AUD1",+	       .id = 1,		/* second audio device */+	       .resource = 0,+	       .num_resources = 0,+	       },+	[2] = {+	       .name = "bcm2835_AUD2",+	       .id = 2,		/* third audio device */+	       .resource = 0,+	       .num_resources = 0,+	       },+	[3] = {+	       .name = "bcm2835_AUD3",+	       .id = 3,		/* forth audio device */+	       .resource = 0,+	       .num_resources = 0,+	       },+	[4] = {+	       .name = "bcm2835_AUD4",+	       .id = 4,		/* fifth audio device */+	       .resource = 0,+	       .num_resources = 0,+	       },+	[5] = {+	       .name = "bcm2835_AUD5",+	       .id = 5,		/* sixth audio device */+	       .resource = 0,+	       .num_resources = 0,+	       },+	[6] = {+	       .name = "bcm2835_AUD6",+	       .id = 6,		/* seventh audio device */+	       .resource = 0,+	       .num_resources = 0,+	       },+	[7] = {+	       .name = "bcm2835_AUD7",+	       .id = 7,		/* eighth audio device */+	       .resource = 0,+	       .num_resources = 0,+	       },+};++static struct resource bcm2708_spi_resources[] = {+	{+		.start = SPI0_BASE,+		.end = SPI0_BASE + SZ_256 - 1,+		.flags = IORESOURCE_MEM,+	}, {+		.start = IRQ_SPI,+		.end = IRQ_SPI,+		.flags = IORESOURCE_IRQ,+	}+};+++static struct platform_device bcm2708_spi_device = {+	.name = "bcm2708_spi",+	.id = 0,+	.num_resources = ARRAY_SIZE(bcm2708_spi_resources),+	.resource = bcm2708_spi_resources,+};++#ifdef CONFIG_BCM2708_SPIDEV+static struct spi_board_info bcm2708_spi_devices[] = {+#ifdef CONFIG_SPI_SPIDEV+	{+		.modalias = "spidev",+		.max_speed_hz = 500000,+		.bus_num = 0,+		.chip_select = 0,+		.mode = SPI_MODE_0,+	}, {+		.modalias = "spidev",+		.max_speed_hz = 500000,+		.bus_num = 0,+		.chip_select = 1,+		.mode = SPI_MODE_0,+	}+#endif+};+#endif++static struct resource bcm2708_bsc0_resources[] = {+	{+		.start = BSC0_BASE,+		.end = BSC0_BASE + SZ_256 - 1,+		.flags = IORESOURCE_MEM,+	}, {+		.start = INTERRUPT_I2C,+		.end = INTERRUPT_I2C,+		.flags = IORESOURCE_IRQ,+	}+};++static struct platform_device bcm2708_bsc0_device = {+	.name = "bcm2708_i2c",+	.id = 0,+	.num_resources = ARRAY_SIZE(bcm2708_bsc0_resources),+	.resource = bcm2708_bsc0_resources,+};+++static struct resource bcm2708_bsc1_resources[] = {+	{+		.start = BSC1_BASE,+		.end = BSC1_BASE + SZ_256 - 1,+		.flags = IORESOURCE_MEM,+	}, {+		.start = INTERRUPT_I2C,+		.end = INTERRUPT_I2C,+		.flags = IORESOURCE_IRQ,+	}+};++static struct platform_device bcm2708_bsc1_device = {+	.name = "bcm2708_i2c",+	.id = 1,+	.num_resources = ARRAY_SIZE(bcm2708_bsc1_resources),+	.resource = bcm2708_bsc1_resources,+};++static struct platform_device bcm2835_hwmon_device = {+	.name = "bcm2835_hwmon",+};++static struct platform_device bcm2835_thermal_device = {+	.name = "bcm2835_thermal",+};++int __init bcm_register_device(struct platform_device *pdev)+{+	int ret;++	ret = platform_device_register(pdev);+	if (ret)+		pr_debug("Unable to register platform device '%s': %d\n",+			 pdev->name, ret);++	return ret;+}++int calc_rsts(int partition)+{+	return PM_PASSWORD |+		((partition & (1 << 0))  << 0) |+		((partition & (1 << 1))  << 1) |+		((partition & (1 << 2))  << 2) |+		((partition & (1 << 3))  << 3) |+		((partition & (1 << 4))  << 4) |+		((partition & (1 << 5))  << 5);+}++static void bcm2708_restart(enum reboot_mode mode, const char *cmd)+{+	extern char bcm2708_reboot_mode;+	uint32_t pm_rstc, pm_wdog;+	uint32_t timeout = 10;+	uint32_t pm_rsts = 0;++	if(bcm2708_reboot_mode == 'q')+	{+		// NOOBS < 1.3 booting with reboot=q+		pm_rsts = readl(__io_address(PM_RSTS));+		pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRQ_SET;+	}+	else if(bcm2708_reboot_mode == 'p')+	{+		// NOOBS < 1.3 halting+		pm_rsts = readl(__io_address(PM_RSTS));+		pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRH_SET;+	}+	else+	{+		pm_rsts = calc_rsts(reboot_part);+	}++	writel(pm_rsts, __io_address(PM_RSTS));++	/* Setup watchdog for reset */+	pm_rstc = readl(__io_address(PM_RSTC));++	pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); // watchdog timer = timer clock / 16; need password (31:16) + value (11:0)+	pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET;++	writel(pm_wdog, __io_address(PM_WDOG));+	writel(pm_rstc, __io_address(PM_RSTC));+}++/* We can't really power off, but if we do the normal reset scheme, and indicate to bootcode.bin not to reboot, then most of the chip will be powered off */+static void bcm2708_power_off(void)+{+	extern char bcm2708_reboot_mode;+	if(bcm2708_reboot_mode == 'q')+	{+		// NOOBS < v1.3+		bcm2708_restart('p', "");+	}+	else+	{+		/* partition 63 is special code for HALT the bootloader knows not to boot*/+		reboot_part = 63;+		/* continue with normal reset mechanism */+		bcm2708_restart(0, "");+	}+}++void __init bcm2708_init(void)+{+	int i;++#if defined(CONFIG_BCM_VC_CMA)+	vc_cma_early_init();+#endif+	printk("bcm2708.uart_clock = %d\n", uart_clock);+	pm_power_off = bcm2708_power_off;++	if (uart_clock)+		lookups[0].clk->rate = uart_clock;++	for (i = 0; i < ARRAY_SIZE(lookups); i++)+		clkdev_add(&lookups[i]);++	bcm_register_device(&bcm2708_dmaman_device);+	bcm_register_device(&bcm2708_vcio_device);+#ifdef CONFIG_BCM2708_GPIO+	bcm_register_device(&bcm2708_gpio_device);+#endif+#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE)+	platform_device_register(&w1_device);+#endif+	bcm_register_device(&bcm2708_systemtimer_device);+	bcm_register_device(&bcm2708_fb_device);+	if (!fiq_fix_enable)+	{+		bcm2708_usb_device.resource = bcm2708_usb_resources_no_fiq_fix;+		bcm2708_usb_device.num_resources = ARRAY_SIZE(bcm2708_usb_resources_no_fiq_fix);+	}+	bcm_register_device(&bcm2708_usb_device);+	bcm_register_device(&bcm2708_uart1_device);+	bcm_register_device(&bcm2708_powerman_device);++#ifdef CONFIG_MMC_SDHCI_BCM2708+	bcm_register_device(&bcm2708_emmc_device);+#endif+	bcm2708_init_led();+	for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++)+		bcm_register_device(&bcm2708_alsa_devices[i]);++	bcm_register_device(&bcm2708_spi_device);+	bcm_register_device(&bcm2708_bsc0_device);+	bcm_register_device(&bcm2708_bsc1_device);++	bcm_register_device(&bcm2835_hwmon_device);+	bcm_register_device(&bcm2835_thermal_device);++	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {+		struct amba_device *d = amba_devs[i];+		amba_device_register(d, &iomem_resource);+	}+	system_rev = boardrev;+	system_serial_low = serial;++#ifdef CONFIG_BCM2708_SPIDEV+	spi_register_board_info(bcm2708_spi_devices,+			ARRAY_SIZE(bcm2708_spi_devices));+#endif+}++static void timer_set_mode(enum clock_event_mode mode,+			   struct clock_event_device *clk)+{+	switch (mode) {+	case CLOCK_EVT_MODE_ONESHOT: /* Leave the timer disabled, .set_next_event will enable it */+	case CLOCK_EVT_MODE_SHUTDOWN:+		break;+	case CLOCK_EVT_MODE_PERIODIC:++	case CLOCK_EVT_MODE_UNUSED:+	case CLOCK_EVT_MODE_RESUME:++	default:+		printk(KERN_ERR "timer_set_mode: unhandled mode:%d\n",+		       (int)mode);+		break;+	}++}++static int timer_set_next_event(unsigned long cycles,+				struct clock_event_device *unused)+{+	unsigned long stc;++	stc = readl(__io_address(ST_BASE + 0x04));+	writel(stc + cycles, __io_address(ST_BASE + 0x18));	/* stc3 */+	return 0;+}++static struct clock_event_device timer0_clockevent = {+	.name = "timer0",+	.shift = 32,+	.features = CLOCK_EVT_FEAT_ONESHOT,+	.set_mode = timer_set_mode,+	.set_next_event = timer_set_next_event,+};++/*+ * IRQ handler for the timer+ */+static irqreturn_t bcm2708_timer_interrupt(int irq, void *dev_id)+{+	struct clock_event_device *evt = &timer0_clockevent;++	writel(1 << 3, __io_address(ST_BASE + 0x00));	/* stcs clear timer int */++	evt->event_handler(evt);++	return IRQ_HANDLED;+}++static struct irqaction bcm2708_timer_irq = {+	.name = "BCM2708 Timer Tick",+	.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,+	.handler = bcm2708_timer_interrupt,+};++/*+ * Set up timer interrupt, and return the current time in seconds.+ */++static struct delay_timer bcm2708_delay_timer = {+	.read_current_timer = bcm2708_read_current_timer,+	.freq = STC_FREQ_HZ,+};++static void __init bcm2708_timer_init(void)+{+	/* init high res timer */+	bcm2708_clocksource_init();++	/*+	 * Initialise to a known state (all timers off)+	 */+	writel(0, __io_address(ARM_T_CONTROL));+	/*+	 * Make irqs happen for the system timer+	 */+	setup_irq(IRQ_TIMER3, &bcm2708_timer_irq);++	setup_sched_clock(bcm2708_read_sched_clock, 32, STC_FREQ_HZ);++	timer0_clockevent.mult =+	    div_sc(STC_FREQ_HZ, NSEC_PER_SEC, timer0_clockevent.shift);+	timer0_clockevent.max_delta_ns =+	    clockevent_delta2ns(0xffffffff, &timer0_clockevent);+	timer0_clockevent.min_delta_ns =+	    clockevent_delta2ns(0xf, &timer0_clockevent);++	timer0_clockevent.cpumask = cpumask_of(0);+	clockevents_register_device(&timer0_clockevent);++	register_current_timer_delay(&bcm2708_delay_timer);+}++#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)+#include <linux/leds.h>++static struct gpio_led bcm2708_leds[] = {+	[0] = {+	       .gpio = 16,+	       .name = "led0",+	       .default_trigger = "mmc0",+	       .active_low = 1,+	       },+};++static struct gpio_led_platform_data bcm2708_led_pdata = {+	.num_leds = ARRAY_SIZE(bcm2708_leds),+	.leds = bcm2708_leds,+};++static struct platform_device bcm2708_led_device = {+	.name = "leds-gpio",+	.id = -1,+	.dev = {+		.platform_data = &bcm2708_led_pdata,+		},+};++static void __init bcm2708_init_led(void)+{+	platform_device_register(&bcm2708_led_device);+}+#else+static inline void bcm2708_init_led(void)+{+}+#endif++void __init bcm2708_init_early(void)+{+	/*+	 * Some devices allocate their coherent buffers from atomic+	 * context. Increase size of atomic coherent pool to make sure such+	 * the allocations won't fail.+	 */+	init_dma_coherent_pool_size(SZ_4M);+}++static void __init board_reserve(void)+{+#if defined(CONFIG_BCM_VC_CMA)+	vc_cma_reserve();+#endif+}++MACHINE_START(BCM2708, "BCM2708")+    /* Maintainer: Broadcom Europe Ltd. */+	.map_io = bcm2708_map_io,+	.init_irq = bcm2708_init_irq,+	.init_time = bcm2708_timer_init,+	.init_machine = bcm2708_init,+	.init_early = bcm2708_init_early,+	.reserve = board_reserve,+	.restart	= bcm2708_restart,+MACHINE_END++module_param(boardrev, uint, 0644);+module_param(serial, uint, 0644);+module_param(uart_clock, uint, 0644);+module_param(reboot_part, uint, 0644);diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-3.11.10/arch/arm/mach-bcm2708/bcm2708_gpio.c--- linux-3.11.10.orig/arch/arm/mach-bcm2708/bcm2708_gpio.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/bcm2708_gpio.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,339 @@+/*+ *  linux/arch/arm/mach-bcm2708/bcm2708_gpio.c+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License version 2 as+ * published by the Free Software Foundation.+ *+ */++#include <linux/spinlock.h>+#include <linux/module.h>+#include <linux/list.h>+#include <linux/io.h>+#include <linux/irq.h>+#include <linux/interrupt.h>+#include <linux/slab.h>+#include <mach/gpio.h>+#include <linux/gpio.h>+#include <linux/platform_device.h>+#include <mach/platform.h>++#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio"+#define DRIVER_NAME BCM_GPIO_DRIVER_NAME+#define BCM_GPIO_USE_IRQ 1++#define GPIOFSEL(x)  (0x00+(x)*4)+#define GPIOSET(x)   (0x1c+(x)*4)+#define GPIOCLR(x)   (0x28+(x)*4)+#define GPIOLEV(x)   (0x34+(x)*4)+#define GPIOEDS(x)   (0x40+(x)*4)+#define GPIOREN(x)   (0x4c+(x)*4)+#define GPIOFEN(x)   (0x58+(x)*4)+#define GPIOHEN(x)   (0x64+(x)*4)+#define GPIOLEN(x)   (0x70+(x)*4)+#define GPIOAREN(x)  (0x7c+(x)*4)+#define GPIOAFEN(x)  (0x88+(x)*4)+#define GPIOUD(x)    (0x94+(x)*4)+#define GPIOUDCLK(x) (0x98+(x)*4)++enum { GPIO_FSEL_INPUT, GPIO_FSEL_OUTPUT,+	GPIO_FSEL_ALT5, GPIO_FSEL_ALT_4,+	GPIO_FSEL_ALT0, GPIO_FSEL_ALT1,+	GPIO_FSEL_ALT2, GPIO_FSEL_ALT3,+};++	/* Each of the two spinlocks protects a different set of hardware+	 * regiters and data structurs. This decouples the code of the IRQ from+	 * the GPIO code. This also makes the case of a GPIO routine call from+	 * the IRQ code simpler.+	 */+static DEFINE_SPINLOCK(lock);	/* GPIO registers */++struct bcm2708_gpio {+	struct list_head list;+	void __iomem *base;+	struct gpio_chip gc;+	unsigned long rising;+	unsigned long falling;+};++static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset,+				int function)+{+	struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc);+	unsigned long flags;+	unsigned gpiodir;+	unsigned gpio_bank = offset / 10;+	unsigned gpio_field_offset = (offset - 10 * gpio_bank) * 3;++//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set_function %p (%d,%d)\n", gc, offset, function);+	if (offset >= ARCH_NR_GPIOS)+		return -EINVAL;++	spin_lock_irqsave(&lock, flags);++	gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank));+	gpiodir &= ~(7 << gpio_field_offset);+	gpiodir |= function << gpio_field_offset;+	writel(gpiodir, gpio->base + GPIOFSEL(gpio_bank));+	spin_unlock_irqrestore(&lock, flags);+	gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank));++	return 0;+}++static int bcm2708_gpio_dir_in(struct gpio_chip *gc, unsigned offset)+{+	return bcm2708_set_function(gc, offset, GPIO_FSEL_INPUT);+}++static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value);+static int bcm2708_gpio_dir_out(struct gpio_chip *gc, unsigned offset,+				int value)+{+	int ret;+	ret = bcm2708_set_function(gc, offset, GPIO_FSEL_OUTPUT);+	if (ret >= 0)+		bcm2708_gpio_set(gc, offset, value);+	return ret;+}++static int bcm2708_gpio_get(struct gpio_chip *gc, unsigned offset)+{+	struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc);+	unsigned gpio_bank = offset / 32;+	unsigned gpio_field_offset = (offset - 32 * gpio_bank);+	unsigned lev;++	if (offset >= ARCH_NR_GPIOS)+		return 0;+	lev = readl(gpio->base + GPIOLEV(gpio_bank));+//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_get %p (%d)=%d\n", gc, offset, 0x1 & (lev>>gpio_field_offset));+	return 0x1 & (lev >> gpio_field_offset);+}++static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value)+{+	struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc);+	unsigned gpio_bank = offset / 32;+	unsigned gpio_field_offset = (offset - 32 * gpio_bank);+//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set %p (%d=%d)\n", gc, offset, value);+	if (offset >= ARCH_NR_GPIOS)+		return;+	if (value)+		writel(1 << gpio_field_offset, gpio->base + GPIOSET(gpio_bank));+	else+		writel(1 << gpio_field_offset, gpio->base + GPIOCLR(gpio_bank));+}++/*************************************************************************************************************************+ * bcm2708 GPIO IRQ+ */++#if BCM_GPIO_USE_IRQ++static int bcm2708_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)+{+	return gpio_to_irq(gpio);+}++static int bcm2708_gpio_irq_set_type(struct irq_data *d, unsigned type)+{+	unsigned irq = d->irq;+	struct bcm2708_gpio *gpio = irq_get_chip_data(irq);++	if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))+		return -EINVAL;++	if (type & IRQ_TYPE_EDGE_RISING) {+		gpio->rising |= (1 << irq_to_gpio(irq));+	} else {+		gpio->rising &= ~(1 << irq_to_gpio(irq));+	}++	if (type & IRQ_TYPE_EDGE_FALLING) {+		gpio->falling |= (1 << irq_to_gpio(irq));+	} else {+		gpio->falling &= ~(1 << irq_to_gpio(irq));+	}+	return 0;+}++static void bcm2708_gpio_irq_mask(struct irq_data *d)+{+	unsigned irq = d->irq;+	struct bcm2708_gpio *gpio = irq_get_chip_data(irq);+	unsigned gn = irq_to_gpio(irq);+	unsigned gb = gn / 32;+	unsigned long rising = readl(gpio->base + GPIOREN(gb));+	unsigned long falling = readl(gpio->base + GPIOFEN(gb));++	gn = gn % 32;++	writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));+	writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb));+}++static void bcm2708_gpio_irq_unmask(struct irq_data *d)+{+	unsigned irq = d->irq;+	struct bcm2708_gpio *gpio = irq_get_chip_data(irq);+	unsigned gn = irq_to_gpio(irq);+	unsigned gb = gn / 32;+	unsigned long rising = readl(gpio->base + GPIOREN(gb));+	unsigned long falling = readl(gpio->base + GPIOFEN(gb));++	gn = gn % 32;++	writel(1 << gn, gpio->base + GPIOEDS(gb));++	if (gpio->rising & (1 << gn)) {+		writel(rising | (1 << gn), gpio->base + GPIOREN(gb));+	} else {+		writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));+	}++	if (gpio->falling & (1 << gn)) {+		writel(falling | (1 << gn), gpio->base + GPIOFEN(gb));+	} else {+		writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb));+	}+}++static struct irq_chip bcm2708_irqchip = {+	.name = "GPIO",+	.irq_enable = bcm2708_gpio_irq_unmask,+	.irq_disable = bcm2708_gpio_irq_mask,+	.irq_unmask = bcm2708_gpio_irq_unmask,+	.irq_mask = bcm2708_gpio_irq_mask,+	.irq_set_type = bcm2708_gpio_irq_set_type,+};++static irqreturn_t bcm2708_gpio_interrupt(int irq, void *dev_id)+{+	unsigned long edsr;+	unsigned bank;+	int i;+	unsigned gpio;+	for (bank = 0; bank <= 1; bank++) {+		edsr = readl(__io_address(GPIO_BASE) + GPIOEDS(bank));+		for_each_set_bit(i, &edsr, 32) {+			gpio = i + bank * 32;+			generic_handle_irq(gpio_to_irq(gpio));+		}+		writel(0xffffffff, __io_address(GPIO_BASE) + GPIOEDS(bank));+	}+	return IRQ_HANDLED;+}++static struct irqaction bcm2708_gpio_irq = {+	.name = "BCM2708 GPIO catchall handler",+	.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,+	.handler = bcm2708_gpio_interrupt,+};++static void bcm2708_gpio_irq_init(struct bcm2708_gpio *ucb)+{+	unsigned irq;++	ucb->gc.to_irq = bcm2708_gpio_to_irq;++	for (irq = GPIO_IRQ_START; irq < (GPIO_IRQ_START + GPIO_IRQS); irq++) {+		irq_set_chip_data(irq, ucb);+		irq_set_chip(irq, &bcm2708_irqchip);+		set_irq_flags(irq, IRQF_VALID);+	}+	setup_irq(IRQ_GPIO3, &bcm2708_gpio_irq);+}++#else++static void bcm2708_gpio_irq_init(struct bcm2708_gpio *ucb)+{+}++#endif /* #if BCM_GPIO_USE_IRQ ***************************************************************************************************************** */++static int bcm2708_gpio_probe(struct platform_device *dev)+{+	struct bcm2708_gpio *ucb;+	struct resource *res;+	int err = 0;++	printk(KERN_INFO DRIVER_NAME ": bcm2708_gpio_probe %p\n", dev);++	ucb = kzalloc(sizeof(*ucb), GFP_KERNEL);+	if (NULL == ucb) {+		printk(KERN_ERR DRIVER_NAME ": failed to allocate "+		       "mailbox memory\n");+		err = -ENOMEM;+		goto err;+	}++	res = platform_get_resource(dev, IORESOURCE_MEM, 0);++	platform_set_drvdata(dev, ucb);+	ucb->base = __io_address(GPIO_BASE);++	ucb->gc.label = "bcm2708_gpio";+	ucb->gc.base = 0;+	ucb->gc.ngpio = ARCH_NR_GPIOS;+	ucb->gc.owner = THIS_MODULE;++	ucb->gc.direction_input = bcm2708_gpio_dir_in;+	ucb->gc.direction_output = bcm2708_gpio_dir_out;+	ucb->gc.get = bcm2708_gpio_get;+	ucb->gc.set = bcm2708_gpio_set;+	ucb->gc.can_sleep = 0;++	bcm2708_gpio_irq_init(ucb);++	err = gpiochip_add(&ucb->gc);+	if (err)+		goto err;++err:+	return err;++}++static int bcm2708_gpio_remove(struct platform_device *dev)+{+	int err = 0;+	struct bcm2708_gpio *ucb = platform_get_drvdata(dev);++	printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_remove %p\n", dev);++	err = gpiochip_remove(&ucb->gc);++	platform_set_drvdata(dev, NULL);+	kfree(ucb);++	return err;+}++static struct platform_driver bcm2708_gpio_driver = {+	.probe = bcm2708_gpio_probe,+	.remove = bcm2708_gpio_remove,+	.driver = {+		   .name = "bcm2708_gpio"},+};++static int __init bcm2708_gpio_init(void)+{+	return platform_driver_register(&bcm2708_gpio_driver);+}++static void __exit bcm2708_gpio_exit(void)+{+	platform_driver_unregister(&bcm2708_gpio_driver);+}++module_init(bcm2708_gpio_init);+module_exit(bcm2708_gpio_exit);++MODULE_DESCRIPTION("Broadcom BCM2708 GPIO driver");+MODULE_LICENSE("GPL");diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/bcm2708.h linux-3.11.10/arch/arm/mach-bcm2708/bcm2708.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/bcm2708.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/bcm2708.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,51 @@+/*+ * linux/arch/arm/mach-bcm2708/bcm2708.h+ *+ * BCM2708 machine support header+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */++#ifndef __BCM2708_BCM2708_H+#define __BCM2708_BCM2708_H++#include <linux/amba/bus.h>++extern void __init bcm2708_init(void);+extern void __init bcm2708_init_irq(void);+extern void __init bcm2708_map_io(void);+extern struct sys_timer bcm2708_timer;+extern unsigned int mmc_status(struct device *dev);++#define AMBA_DEVICE(name, busid, base, plat)			\+static struct amba_device name##_device = {			\+	.dev		= {					\+		.coherent_dma_mask = ~0,			\+		.init_name = busid,				\+		.platform_data = plat,				\+	},							\+	.res		= {					\+		.start	= base##_BASE,		\+		.end	= (base##_BASE) + SZ_4K - 1,\+		.flags	= IORESOURCE_MEM,			\+	},							\+	.dma_mask	= ~0,					\+	.irq		= base##_IRQ,				\+	/* .dma		= base##_DMA,*/				\+}++#endifdiff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/clock.c linux-3.11.10/arch/arm/mach-bcm2708/clock.c--- linux-3.11.10.orig/arch/arm/mach-bcm2708/clock.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/clock.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,61 @@+/*+ *  linux/arch/arm/mach-bcm2708/clock.c+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */+#include <linux/module.h>+#include <linux/kernel.h>+#include <linux/device.h>+#include <linux/list.h>+#include <linux/errno.h>+#include <linux/err.h>+#include <linux/string.h>+#include <linux/clk.h>+#include <linux/mutex.h>++#include <asm/clkdev.h>++#include "clock.h"++int clk_enable(struct clk *clk)+{+	return 0;+}+EXPORT_SYMBOL(clk_enable);++void clk_disable(struct clk *clk)+{+}+EXPORT_SYMBOL(clk_disable);++unsigned long clk_get_rate(struct clk *clk)+{+	return clk->rate;+}+EXPORT_SYMBOL(clk_get_rate);++long clk_round_rate(struct clk *clk, unsigned long rate)+{+	return clk->rate;+}+EXPORT_SYMBOL(clk_round_rate);++int clk_set_rate(struct clk *clk, unsigned long rate)+{+	return -EIO;+}+EXPORT_SYMBOL(clk_set_rate);diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/clock.h linux-3.11.10/arch/arm/mach-bcm2708/clock.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/clock.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/clock.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,24 @@+/*+ *  linux/arch/arm/mach-bcm2708/clock.h+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */+struct module;++struct clk {+	unsigned long		rate;+};diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/dma.c linux-3.11.10/arch/arm/mach-bcm2708/dma.c--- linux-3.11.10.orig/arch/arm/mach-bcm2708/dma.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/dma.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,399 @@+/*+ *  linux/arch/arm/mach-bcm2708/dma.c+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License version 2 as+ * published by the Free Software Foundation.+ */++#include <linux/slab.h>+#include <linux/device.h>+#include <linux/platform_device.h>+#include <linux/module.h>+#include <linux/scatterlist.h>++#include <mach/dma.h>+#include <mach/irqs.h>++/*****************************************************************************\+ *									     *+ * Configuration							     *+ *									     *+\*****************************************************************************/++#define CACHE_LINE_MASK 31+#define DRIVER_NAME BCM_DMAMAN_DRIVER_NAME+#define DEFAULT_DMACHAN_BITMAP 0x10  /* channel 4 only */++/* valid only for channels 0 - 14, 15 has its own base address */+#define BCM2708_DMA_CHAN(n)	((n)<<8) /* base address */+#define BCM2708_DMA_CHANIO(dma_base, n) \+   ((void __iomem *)((char *)(dma_base)+BCM2708_DMA_CHAN(n)))+++/*****************************************************************************\+ *									     *+ * DMA Auxilliary Functions						     *+ *									     *+\*****************************************************************************/++/* A DMA buffer on an arbitrary boundary may separate a cache line into a+   section inside the DMA buffer and another section outside it.+   Even if we flush DMA buffers from the cache there is always the chance that+   during a DMA someone will access the part of a cache line that is outside+   the DMA buffer - which will then bring in unwelcome data.+   Without being able to dictate our own buffer pools we must insist that+   DMA buffers consist of a whole number of cache lines.+*/++extern int+bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len)+{+	int i;++	for (i = 0; i < sg_len; i++) {+		if (sg_ptr[i].offset & CACHE_LINE_MASK ||+		    sg_ptr[i].length & CACHE_LINE_MASK)+			return 0;+	}++	return 1;+}+EXPORT_SYMBOL_GPL(bcm_sg_suitable_for_dma);++extern void+bcm_dma_start(void __iomem *dma_chan_base, dma_addr_t control_block)+{+	dsb();	/* ARM data synchronization (push) operation */++	writel(control_block,	     dma_chan_base + BCM2708_DMA_ADDR);+	writel(BCM2708_DMA_ACTIVE,   dma_chan_base + BCM2708_DMA_CS);+}++extern void bcm_dma_wait_idle(void __iomem *dma_chan_base)+{+  dsb();++  /* ugly busy wait only option for now */+  while (readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE)+    cpu_relax();+}++EXPORT_SYMBOL_GPL(bcm_dma_start);++/* Complete an ongoing DMA (assuming its results are to be ignored)+   Does nothing if there is no DMA in progress.+   This routine waits for the current AXI transfer to complete before+   terminating the current DMA.	 If the current transfer is hung on a DREQ used+   by an uncooperative peripheral the AXI transfer may never complete.	In this+   case the routine times out and return a non-zero error code.+   Use of this routine doesn't guarantee that the ongoing or aborted DMA+   does not produce an interrupt.+*/+extern int+bcm_dma_abort(void __iomem *dma_chan_base)+{+	unsigned long int cs;+	int rc = 0;++	cs = readl(dma_chan_base + BCM2708_DMA_CS);++	if (BCM2708_DMA_ACTIVE & cs) {+		long int timeout = 10000;++		/* write 0 to the active bit - pause the DMA */+		writel(0, dma_chan_base + BCM2708_DMA_CS);++		/* wait for any current AXI transfer to complete */+		while (0 != (cs & BCM2708_DMA_ISPAUSED) && --timeout >= 0)+			cs = readl(dma_chan_base + BCM2708_DMA_CS);++		if (0 != (cs & BCM2708_DMA_ISPAUSED)) {+			/* we'll un-pause when we set of our next DMA */+			rc = -ETIMEDOUT;++		} else if (BCM2708_DMA_ACTIVE & cs) {+			/* terminate the control block chain */+			writel(0, dma_chan_base + BCM2708_DMA_NEXTCB);++			/* abort the whole DMA */+			writel(BCM2708_DMA_ABORT | BCM2708_DMA_ACTIVE,+			       dma_chan_base + BCM2708_DMA_CS);+		}+	}++	return rc;+}+EXPORT_SYMBOL_GPL(bcm_dma_abort);+++/***************************************************************************** \+ *									     *+ * DMA Manager Device Methods						     *+ *									     *+\*****************************************************************************/++struct vc_dmaman {+	void __iomem *dma_base;+	u32 chan_available; /* bitmap of available channels */+	u32 has_feature[BCM_DMA_FEATURE_COUNT]; /* bitmap of feature presence */+};++static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base,+			   u32 chans_available)+{+	dmaman->dma_base = dma_base;+	dmaman->chan_available = chans_available;+	dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c;  /* chans 2 & 3 */+	dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01;  /* chan 0 */+}++static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman,+				unsigned preferred_feature_set)+{+	u32 chans;+	int feature;++	chans = dmaman->chan_available;+	for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++)+		/* select the subset of available channels with the desired+		   feature so long as some of the candidate channels have that+		   feature */+		if ((preferred_feature_set & (1 << feature)) &&+		    (chans & dmaman->has_feature[feature]))+			chans &= dmaman->has_feature[feature];++	if (chans) {+		int chan = 0;+		/* return the ordinal of the first channel in the bitmap */+		while (chans != 0 && (chans & 1) == 0) {+			chans >>= 1;+			chan++;+		}+		/* claim the channel */+		dmaman->chan_available &= ~(1 << chan);+		return chan;+	} else+		return -ENOMEM;+}++static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan)+{+	if (chan < 0)+		return -EINVAL;+	else if ((1 << chan) & dmaman->chan_available)+		return -EIDRM;+	else {+		dmaman->chan_available |= (1 << chan);+		return 0;+	}+}++/*****************************************************************************\+ *									     *+ * DMA IRQs								     *+ *									     *+\*****************************************************************************/++static unsigned char bcm_dma_irqs[] = {+	IRQ_DMA0,+	IRQ_DMA1,+	IRQ_DMA2,+	IRQ_DMA3,+	IRQ_DMA4,+	IRQ_DMA5,+	IRQ_DMA6,+	IRQ_DMA7,+	IRQ_DMA8,+	IRQ_DMA9,+	IRQ_DMA10,+	IRQ_DMA11,+	IRQ_DMA12+};+++/***************************************************************************** \+ *									     *+ * DMA Manager Monitor							     *+ *									     *+\*****************************************************************************/++static struct device *dmaman_dev;	/* we assume there's only one! */++extern int bcm_dma_chan_alloc(unsigned preferred_feature_set,+			      void __iomem **out_dma_base, int *out_dma_irq)+{+	if (!dmaman_dev)+		return -ENODEV;+	else {+		struct vc_dmaman *dmaman  = dev_get_drvdata(dmaman_dev);+		int rc;++		device_lock(dmaman_dev);+		rc = vc_dmaman_chan_alloc(dmaman, preferred_feature_set);+		if (rc >= 0) {+			*out_dma_base = BCM2708_DMA_CHANIO(dmaman->dma_base,+							   rc);+			*out_dma_irq = bcm_dma_irqs[rc];+		}+		device_unlock(dmaman_dev);++		return rc;+	}+}+EXPORT_SYMBOL_GPL(bcm_dma_chan_alloc);++extern int bcm_dma_chan_free(int channel)+{+	if (dmaman_dev) {+		struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev);+		int rc;++		device_lock(dmaman_dev);+		rc = vc_dmaman_chan_free(dmaman, channel);+		device_unlock(dmaman_dev);++		return rc;+	} else+		return -ENODEV;+}+EXPORT_SYMBOL_GPL(bcm_dma_chan_free);++static int dev_dmaman_register(const char *dev_name, struct device *dev)+{+	int rc = dmaman_dev ? -EINVAL : 0;+	dmaman_dev = dev;+	return rc;+}++static void dev_dmaman_deregister(const char *dev_name, struct device *dev)+{+	dmaman_dev = NULL;+}++/*****************************************************************************\+ *									     *+ * DMA Device								     *+ *									     *+\*****************************************************************************/++static int dmachans = -1; /* module parameter */++static int bcm_dmaman_probe(struct platform_device *pdev)+{+	int ret = 0;+	struct vc_dmaman *dmaman;+	struct resource *dma_res = NULL;+	void __iomem *dma_base = NULL;+	int have_dma_region = 0;++	dmaman = kzalloc(sizeof(*dmaman), GFP_KERNEL);+	if (NULL == dmaman) {+		printk(KERN_ERR DRIVER_NAME ": failed to allocate "+		       "DMA management memory\n");+		ret = -ENOMEM;+	} else {++		dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);+		if (dma_res == NULL) {+			printk(KERN_ERR DRIVER_NAME ": failed to obtain memory "+			       "resource\n");+			ret = -ENODEV;+		} else if (!request_mem_region(dma_res->start,+					       resource_size(dma_res),+					       DRIVER_NAME)) {+			dev_err(&pdev->dev, "cannot obtain DMA region\n");+			ret = -EBUSY;+		} else {+			have_dma_region = 1;+			dma_base = ioremap(dma_res->start,+					   resource_size(dma_res));+			if (!dma_base) {+				dev_err(&pdev->dev, "cannot map DMA region\n");+				ret = -ENOMEM;+			} else {+				/* use module parameter if one was provided */+				if (dmachans > 0)+					vc_dmaman_init(dmaman, dma_base,+						       dmachans);+				else+					vc_dmaman_init(dmaman, dma_base,+						       DEFAULT_DMACHAN_BITMAP);++				platform_set_drvdata(pdev, dmaman);+				dev_dmaman_register(DRIVER_NAME, &pdev->dev);++				printk(KERN_INFO DRIVER_NAME ": DMA manager "+				       "at %p\n", dma_base);+			}+		}+	}+	if (ret != 0) {+		if (dma_base)+			iounmap(dma_base);+		if (dma_res && have_dma_region)+			release_mem_region(dma_res->start,+					   resource_size(dma_res));+		if (dmaman)+			kfree(dmaman);+	}+	return ret;+}++static int bcm_dmaman_remove(struct platform_device *pdev)+{+	struct vc_dmaman *dmaman = platform_get_drvdata(pdev);++	platform_set_drvdata(pdev, NULL);+	dev_dmaman_deregister(DRIVER_NAME, &pdev->dev);+	kfree(dmaman);++	return 0;+}++static struct platform_driver bcm_dmaman_driver = {+	.probe = bcm_dmaman_probe,+	.remove = bcm_dmaman_remove,++	.driver = {+		   .name = DRIVER_NAME,+		   .owner = THIS_MODULE,+		   },+};++/*****************************************************************************\+ *									     *+ * Driver init/exit							     *+ *									     *+\*****************************************************************************/++static int __init bcm_dmaman_drv_init(void)+{+	int ret;++	ret = platform_driver_register(&bcm_dmaman_driver);+	if (ret != 0) {+		printk(KERN_ERR DRIVER_NAME ": failed to register "+		       "on platform\n");+	}++	return ret;+}++static void __exit bcm_dmaman_drv_exit(void)+{+	platform_driver_unregister(&bcm_dmaman_driver);+}++module_init(bcm_dmaman_drv_init);+module_exit(bcm_dmaman_drv_exit);++module_param(dmachans, int, 0644);++MODULE_AUTHOR("Gray Girling <grayg@broadcom.com>");+MODULE_DESCRIPTION("DMA channel manager driver");+MODULE_LICENSE("GPL");++MODULE_PARM_DESC(dmachans, "Bitmap of DMA channels available to the ARM");diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/dmaer.c linux-3.11.10/arch/arm/mach-bcm2708/dmaer.c--- linux-3.11.10.orig/arch/arm/mach-bcm2708/dmaer.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/dmaer.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,886 @@+#include <linux/init.h>+#include <linux/sched.h>+#include <linux/module.h>+#include <linux/types.h>+#include <linux/kdev_t.h>+#include <linux/fs.h>+#include <linux/cdev.h>+#include <linux/mm.h>+#include <linux/slab.h>+#include <linux/pagemap.h>+#include <linux/device.h>+#include <linux/jiffies.h>+#include <linux/timex.h>+#include <linux/dma-mapping.h>++#include <asm/uaccess.h>+#include <asm/atomic.h>+#include <asm/cacheflush.h>+#include <asm/io.h>++#include <mach/dma.h>+#include <mach/vc_support.h>++#ifdef ECLIPSE_IGNORE++#define __user+#define __init+#define __exit+#define __iomem+#define KERN_DEBUG+#define KERN_ERR+#define KERN_WARNING+#define KERN_INFO+#define _IOWR(a, b, c) b+#define _IOW(a, b, c) b+#define _IO(a, b) b++#endif++//#define inline++#define PRINTK(args...) printk(args)+//#define PRINTK_VERBOSE(args...) printk(args)+//#define PRINTK(args...)+#define PRINTK_VERBOSE(args...)++/***** TYPES ****/+#define PAGES_PER_LIST 500+struct PageList+{+	struct page *m_pPages[PAGES_PER_LIST];+	unsigned int m_used;+	struct PageList *m_pNext;+};++struct VmaPageList+{+	//each vma has a linked list of pages associated with it+	struct PageList *m_pPageHead;+	struct PageList *m_pPageTail;+	unsigned int m_refCount;+};++struct DmaControlBlock+{+	unsigned int m_transferInfo;+	void __user *m_pSourceAddr;+	void __user *m_pDestAddr;+	unsigned int m_xferLen;+	unsigned int m_tdStride;+	struct DmaControlBlock *m_pNext;+	unsigned int m_blank1, m_blank2;+};++/***** DEFINES ******/+//magic number defining the module+#define DMA_MAGIC		0xdd++//do user virtual to physical translation of the CB chain+#define DMA_PREPARE		_IOWR(DMA_MAGIC, 0, struct DmaControlBlock *)++//kick the pre-prepared CB chain+#define DMA_KICK		_IOW(DMA_MAGIC, 1, struct DmaControlBlock *)++//prepare it, kick it, wait for it+#define DMA_PREPARE_KICK_WAIT	_IOWR(DMA_MAGIC, 2, struct DmaControlBlock *)++//prepare it, kick it, don't wait for it+#define DMA_PREPARE_KICK	_IOWR(DMA_MAGIC, 3, struct DmaControlBlock *)++//not currently implemented+#define DMA_WAIT_ONE		_IO(DMA_MAGIC, 4, struct DmaControlBlock *)++//wait on all kicked CB chains+#define DMA_WAIT_ALL		_IO(DMA_MAGIC, 5)++//in order to discover the largest AXI burst that should be programmed into the transfer params+#define DMA_MAX_BURST		_IO(DMA_MAGIC, 6)++//set the address range through which the user address is assumed to already by a physical address+#define DMA_SET_MIN_PHYS	_IOW(DMA_MAGIC, 7, unsigned long)+#define DMA_SET_MAX_PHYS	_IOW(DMA_MAGIC, 8, unsigned long)+#define DMA_SET_PHYS_OFFSET	_IOW(DMA_MAGIC, 9, unsigned long)++//used to define the size for the CMA-based allocation *in pages*, can only be done once once the file is opened+#define DMA_CMA_SET_SIZE	_IOW(DMA_MAGIC, 10, unsigned long)++//used to get the version of the module, to test for a capability+#define DMA_GET_VERSION		_IO(DMA_MAGIC, 99)++#define VERSION_NUMBER 1++#define VIRT_TO_BUS_CACHE_SIZE 8++/***** FILE OPS *****/+static int Open(struct inode *pInode, struct file *pFile);+static int Release(struct inode *pInode, struct file *pFile);+static long Ioctl(struct file *pFile, unsigned int cmd, unsigned long arg);+static ssize_t Read(struct file *pFile, char __user *pUser, size_t count, loff_t *offp);+static int Mmap(struct file *pFile, struct vm_area_struct *pVma);++/***** VMA OPS ****/+static void VmaOpen4k(struct vm_area_struct *pVma);+static void VmaClose4k(struct vm_area_struct *pVma);+static int VmaFault4k(struct vm_area_struct *pVma, struct vm_fault *pVmf);++/**** DMA PROTOTYPES */+static struct DmaControlBlock __user *DmaPrepare(struct DmaControlBlock __user *pUserCB, int *pError);+static int DmaKick(struct DmaControlBlock __user *pUserCB);+static void DmaWaitAll(void);++/**** GENERIC ****/+static int __init dmaer_init(void);+static void __exit dmaer_exit(void);++/*** OPS ***/+static struct vm_operations_struct g_vmOps4k = {+	.open = VmaOpen4k,+	.close = VmaClose4k,+	.fault = VmaFault4k,+};++static struct file_operations g_fOps = {+	.owner = THIS_MODULE,+	.llseek = 0,+	.read = Read,+	.write = 0,+	.unlocked_ioctl = Ioctl,+	.open = Open,+	.release = Release,+	.mmap = Mmap,+};++/***** GLOBALS ******/+static dev_t g_majorMinor;++//tracking usage of the two files+static atomic_t g_oneLock4k = ATOMIC_INIT(1);++//device operations+static struct cdev g_cDev;+static int g_trackedPages = 0;++//dma control+static unsigned int *g_pDmaChanBase;+static int g_dmaIrq;+static int g_dmaChan;++//cma allocation+static int g_cmaHandle;++//user virtual to bus address translation acceleration+static unsigned long g_virtAddr[VIRT_TO_BUS_CACHE_SIZE];+static unsigned long g_busAddr[VIRT_TO_BUS_CACHE_SIZE];+static unsigned long g_cbVirtAddr;+static unsigned long g_cbBusAddr;+static int g_cacheInsertAt;+static int g_cacheHit, g_cacheMiss;++//off by default+static void __user *g_pMinPhys;+static void __user *g_pMaxPhys;+static unsigned long g_physOffset;++/****** CACHE OPERATIONS ********/+static inline void FlushAddrCache(void)+{+	int count = 0;+	for (count = 0; count < VIRT_TO_BUS_CACHE_SIZE; count++)+		g_virtAddr[count] = 0xffffffff;			//never going to match as we always chop the bottom bits anyway++	g_cbVirtAddr = 0xffffffff;++	g_cacheInsertAt = 0;+}++//translate from a user virtual address to a bus address by mapping the page+//NB this won't lock a page in memory, so to avoid potential paging issues using kernel logical addresses+static inline void __iomem *UserVirtualToBus(void __user *pUser)+{+	int mapped;+	struct page *pPage;+	void *phys;++	//map it (requiring that the pointer points to something that does not hang off the page boundary)+	mapped = get_user_pages(current, current->mm,+		(unsigned long)pUser, 1,+		1, 0,+		&pPage,+		0);++	if (mapped <= 0)		//error+		return 0;++	PRINTK_VERBOSE(KERN_DEBUG "user virtual %p arm phys %p bus %p\n",+			pUser, page_address(pPage), (void __iomem *)__virt_to_bus(page_address(pPage)));++	//get the arm physical address+	phys = page_address(pPage) + offset_in_page(pUser);+	page_cache_release(pPage);++	//and now the bus address+	return (void __iomem *)__virt_to_bus(phys);+}++static inline void __iomem *UserVirtualToBusViaCbCache(void __user *pUser)+{+	unsigned long virtual_page = (unsigned long)pUser & ~4095;+	unsigned long page_offset = (unsigned long)pUser & 4095;+	unsigned long bus_addr;++	if (g_cbVirtAddr == virtual_page)+	{+		bus_addr = g_cbBusAddr + page_offset;+		g_cacheHit++;+		return (void __iomem *)bus_addr;+	}+	else+	{+		bus_addr = (unsigned long)UserVirtualToBus(pUser);++		if (!bus_addr)+			return 0;++		g_cbVirtAddr = virtual_page;+		g_cbBusAddr = bus_addr & ~4095;+		g_cacheMiss++;++		return (void __iomem *)bus_addr;+	}+}++//do the same as above, by query our virt->bus cache+static inline void __iomem *UserVirtualToBusViaCache(void __user *pUser)+{+	int count;+	//get the page and its offset+	unsigned long virtual_page = (unsigned long)pUser & ~4095;+	unsigned long page_offset = (unsigned long)pUser & 4095;+	unsigned long bus_addr;++	if (pUser >= g_pMinPhys && pUser < g_pMaxPhys)+	{+		PRINTK_VERBOSE(KERN_DEBUG "user->phys passthrough on %p\n", pUser);+		return (void __iomem *)((unsigned long)pUser + g_physOffset);+	}++	//check the cache for our entry+	for (count = 0; count < VIRT_TO_BUS_CACHE_SIZE; count++)+		if (g_virtAddr[count] == virtual_page)+		{+			bus_addr = g_busAddr[count] + page_offset;+			g_cacheHit++;+			return (void __iomem *)bus_addr;+		}++	//not found, look up manually and then insert its page address+	bus_addr = (unsigned long)UserVirtualToBus(pUser);++	if (!bus_addr)+		return 0;++	g_virtAddr[g_cacheInsertAt] = virtual_page;+	g_busAddr[g_cacheInsertAt] = bus_addr & ~4095;++	//round robin+	g_cacheInsertAt++;+	if (g_cacheInsertAt == VIRT_TO_BUS_CACHE_SIZE)+		g_cacheInsertAt = 0;++	g_cacheMiss++;++	return (void __iomem *)bus_addr;+}++/***** FILE OPERATIONS ****/+static int Open(struct inode *pInode, struct file *pFile)+{+	PRINTK(KERN_DEBUG "file opening: %d/%d\n", imajor(pInode), iminor(pInode));++	//check which device we are+	if (iminor(pInode) == 0)		//4k+	{+		//only one at a time+		if (!atomic_dec_and_test(&g_oneLock4k))+		{+			atomic_inc(&g_oneLock4k);+			return -EBUSY;+		}+	}+	else+		return -EINVAL;++	//todo there will be trouble if two different processes open the files++	//reset after any file is opened+	g_pMinPhys = (void __user *)-1;+	g_pMaxPhys = (void __user *)0;+	g_physOffset = 0;+	g_cmaHandle = 0;++	return 0;+}++static int Release(struct inode *pInode, struct file *pFile)+{+	PRINTK(KERN_DEBUG "file closing, %d pages tracked\n", g_trackedPages);+	if (g_trackedPages)+		PRINTK(KERN_ERR "we\'re leaking memory!\n");++	//wait for any dmas to finish+	DmaWaitAll();++	//free this memory on the application closing the file or it crashing (implicitly closing the file)+	if (g_cmaHandle)+	{+		PRINTK(KERN_DEBUG "unlocking vc memory\n");+		if (UnlockVcMemory(g_cmaHandle))+			PRINTK(KERN_ERR "uh-oh, unable to unlock vc memory!\n");+		PRINTK(KERN_DEBUG "releasing vc memory\n");+		if (ReleaseVcMemory(g_cmaHandle))+			PRINTK(KERN_ERR "uh-oh, unable to release vc memory!\n");+	}++	if (iminor(pInode) == 0)+		atomic_inc(&g_oneLock4k);+	else+		return -EINVAL;++	return 0;+}++static struct DmaControlBlock __user *DmaPrepare(struct DmaControlBlock __user *pUserCB, int *pError)+{+	struct DmaControlBlock kernCB;+	struct DmaControlBlock __user *pUNext;+	void __iomem *pSourceBus, __iomem *pDestBus;++	//get the control block into kernel memory so we can work on it+	if (copy_from_user(&kernCB, pUserCB, sizeof(struct DmaControlBlock)) != 0)+	{+		PRINTK(KERN_ERR "copy_from_user failed for user cb %p\n", pUserCB);+		*pError = 1;+		return 0;+	}++	if (kernCB.m_pSourceAddr == 0 || kernCB.m_pDestAddr == 0)+	{+		PRINTK(KERN_ERR "faulty source (%p) dest (%p) addresses for user cb %p\n",+			kernCB.m_pSourceAddr, kernCB.m_pDestAddr, pUserCB);+		*pError = 1;+		return 0;+	}++	pSourceBus = UserVirtualToBusViaCache(kernCB.m_pSourceAddr);+	pDestBus = UserVirtualToBusViaCache(kernCB.m_pDestAddr);++	if (!pSourceBus || !pDestBus)+	{+		PRINTK(KERN_ERR "virtual to bus translation failure for source/dest %p/%p->%p/%p\n",+				kernCB.m_pSourceAddr, kernCB.m_pDestAddr,+				pSourceBus, pDestBus);+		*pError = 1;+		return 0;+	}++	//update the user structure with the new bus addresses+	kernCB.m_pSourceAddr = pSourceBus;+	kernCB.m_pDestAddr = pDestBus;++	PRINTK_VERBOSE(KERN_DEBUG "final source %p dest %p\n", kernCB.m_pSourceAddr, kernCB.m_pDestAddr);++	//sort out the bus address for the next block+	pUNext = kernCB.m_pNext;++	if (kernCB.m_pNext)+	{+		void __iomem *pNextBus;+		pNextBus = UserVirtualToBusViaCbCache(kernCB.m_pNext);++		if (!pNextBus)+		{+			PRINTK(KERN_ERR "virtual to bus translation failure for m_pNext\n");+			*pError = 1;+			return 0;+		}++		//update the pointer with the bus address+		kernCB.m_pNext = pNextBus;+	}++	//write it back to user space+	if (copy_to_user(pUserCB, &kernCB, sizeof(struct DmaControlBlock)) != 0)+	{+		PRINTK(KERN_ERR "copy_to_user failed for cb %p\n", pUserCB);+		*pError = 1;+		return 0;+	}++	__cpuc_flush_dcache_area(pUserCB, 32);++	*pError = 0;+	return pUNext;+}++static int DmaKick(struct DmaControlBlock __user *pUserCB)+{+	void __iomem *pBusCB;++	pBusCB = UserVirtualToBusViaCbCache(pUserCB);+	if (!pBusCB)+	{+		PRINTK(KERN_ERR "virtual to bus translation failure for cb\n");+		return 1;+	}++	//flush_cache_all();++	bcm_dma_start(g_pDmaChanBase, (dma_addr_t)pBusCB);++	return 0;+}++static void DmaWaitAll(void)+{+	int counter = 0;+	volatile int inner_count;+	volatile unsigned int cs;+	unsigned long time_before, time_after;++	time_before = jiffies;+	//bcm_dma_wait_idle(g_pDmaChanBase);+	dsb();++	cs = readl(g_pDmaChanBase);++	while ((cs & 1) == 1)+	{+		cs = readl(g_pDmaChanBase);+		counter++;++		for (inner_count = 0; inner_count < 32; inner_count++);++		asm volatile ("MCR p15,0,r0,c7,c0,4 \n");+		//cpu_do_idle();+		if (counter >= 1000000)+		{+			PRINTK(KERN_WARNING "DMA failed to finish in a timely fashion\n");+			break;+		}+	}+	time_after = jiffies;+	PRINTK_VERBOSE(KERN_DEBUG "done, counter %d, cs %08x", counter, cs);+	PRINTK_VERBOSE(KERN_DEBUG "took %ld jiffies, %d HZ\n", time_after - time_before, HZ);+}++static long Ioctl(struct file *pFile, unsigned int cmd, unsigned long arg)+{+	int error = 0;+	PRINTK_VERBOSE(KERN_DEBUG "ioctl cmd %x arg %lx\n", cmd, arg);++	switch (cmd)+	{+	case DMA_PREPARE:+	case DMA_PREPARE_KICK:+	case DMA_PREPARE_KICK_WAIT:+		{+			struct DmaControlBlock __user *pUCB = (struct DmaControlBlock *)arg;+			int steps = 0;+			unsigned long start_time = jiffies;+			(void)start_time;++			//flush our address cache+			FlushAddrCache();++			PRINTK_VERBOSE(KERN_DEBUG "dma prepare\n");++			//do virtual to bus translation for each entry+			do+			{+				pUCB = DmaPrepare(pUCB, &error);+			} while (error == 0 && ++steps && pUCB);+			PRINTK_VERBOSE(KERN_DEBUG "prepare done in %d steps, %ld\n", steps, jiffies - start_time);++			//carry straight on if we want to kick too+			if (cmd == DMA_PREPARE || error)+			{+				PRINTK_VERBOSE(KERN_DEBUG "falling out\n");+				return error ? -EINVAL : 0;+			}+		}+	case DMA_KICK:+		PRINTK_VERBOSE(KERN_DEBUG "dma begin\n");++		if (cmd == DMA_KICK)+			FlushAddrCache();++		DmaKick((struct DmaControlBlock __user *)arg);++		if (cmd != DMA_PREPARE_KICK_WAIT)+			break;+/*	case DMA_WAIT_ONE:+		//PRINTK(KERN_DEBUG "dma wait one\n");+		break;*/+	case DMA_WAIT_ALL:+		//PRINTK(KERN_DEBUG "dma wait all\n");+		DmaWaitAll();+		break;+	case DMA_MAX_BURST:+		if (g_dmaChan == 0)+			return 10;+		else+			return 5;+	case DMA_SET_MIN_PHYS:+		g_pMinPhys = (void __user *)arg;+		PRINTK(KERN_DEBUG "min/max user/phys bypass set to %p %p\n", g_pMinPhys, g_pMaxPhys);+		break;+	case DMA_SET_MAX_PHYS:+		g_pMaxPhys = (void __user *)arg;+		PRINTK(KERN_DEBUG "min/max user/phys bypass set to %p %p\n", g_pMinPhys, g_pMaxPhys);+		break;+	case DMA_SET_PHYS_OFFSET:+		g_physOffset = arg;+		PRINTK(KERN_DEBUG "user/phys bypass offset set to %ld\n", g_physOffset);+		break;+	case DMA_CMA_SET_SIZE:+	{+		unsigned int pBusAddr;++		if (g_cmaHandle)+		{+			PRINTK(KERN_ERR "memory has already been allocated (handle %d)\n", g_cmaHandle);+			return -EINVAL;+		}++		PRINTK(KERN_INFO "allocating %ld bytes of VC memory\n", arg * 4096);++		//get the memory+		if (AllocateVcMemory(&g_cmaHandle, arg * 4096, 4096, MEM_FLAG_L1_NONALLOCATING | MEM_FLAG_NO_INIT | MEM_FLAG_HINT_PERMALOCK))+		{+			PRINTK(KERN_ERR "failed to allocate %ld bytes of VC memory\n", arg * 4096);+			g_cmaHandle = 0;+			return -EINVAL;+		}++		//get an address for it+		PRINTK(KERN_INFO "trying to map VC memory\n");++		if (LockVcMemory(&pBusAddr, g_cmaHandle))+		{+			PRINTK(KERN_ERR "failed to map CMA handle %d, releasing memory\n", g_cmaHandle);+			ReleaseVcMemory(g_cmaHandle);+			g_cmaHandle = 0;+		}++		PRINTK(KERN_INFO "bus address for CMA memory is %x\n", pBusAddr);+		return pBusAddr;+	}+	case DMA_GET_VERSION:+		PRINTK(KERN_DEBUG "returning version number, %d\n", VERSION_NUMBER);+		return VERSION_NUMBER;+	default:+		PRINTK(KERN_DEBUG "unknown ioctl: %d\n", cmd);+		return -EINVAL;+	}++	return 0;+}++static ssize_t Read(struct file *pFile, char __user *pUser, size_t count, loff_t *offp)+{+	return -EIO;+}++static int Mmap(struct file *pFile, struct vm_area_struct *pVma)+{+	struct PageList *pPages;+	struct VmaPageList *pVmaList;++	PRINTK_VERBOSE(KERN_DEBUG "MMAP vma %p, length %ld (%s %d)\n",+		pVma, pVma->vm_end - pVma->vm_start,+		current->comm, current->pid);+	PRINTK_VERBOSE(KERN_DEBUG "MMAP %p %d (tracked %d)\n", pVma, current->pid, g_trackedPages);++	//make a new page list+	pPages = (struct PageList *)kmalloc(sizeof(struct PageList), GFP_KERNEL);+	if (!pPages)+	{+		PRINTK(KERN_ERR "couldn\'t allocate a new page list (%s %d)\n",+			current->comm, current->pid);+		return -ENOMEM;+	}++	//clear the page list+	pPages->m_used = 0;+	pPages->m_pNext = 0;++	//insert our vma and new page list somewhere+	if (!pVma->vm_private_data)+	{+		struct VmaPageList *pList;++		PRINTK_VERBOSE(KERN_DEBUG "new vma list, making new one (%s %d)\n",+			current->comm, current->pid);++		//make a new vma list+		pList = (struct VmaPageList *)kmalloc(sizeof(struct VmaPageList), GFP_KERNEL);+		if (!pList)+		{+			PRINTK(KERN_ERR "couldn\'t allocate vma page list (%s %d)\n",+				current->comm, current->pid);+			kfree(pPages);+			return -ENOMEM;+		}++		//clear this list+		pVma->vm_private_data = (void *)pList;+		pList->m_refCount = 0;+	}++	pVmaList = (struct VmaPageList *)pVma->vm_private_data;++	//add it to the vma list+	pVmaList->m_pPageHead = pPages;+	pVmaList->m_pPageTail = pPages;++	pVma->vm_ops = &g_vmOps4k;+	pVma->vm_flags |= VM_IO;++	VmaOpen4k(pVma);++	return 0;+}++/****** VMA OPERATIONS ******/++static void VmaOpen4k(struct vm_area_struct *pVma)+{+	struct VmaPageList *pVmaList;++	PRINTK_VERBOSE(KERN_DEBUG "vma open %p private %p (%s %d), %d live pages\n", pVma, pVma->vm_private_data, current->comm, current->pid, g_trackedPages);+	PRINTK_VERBOSE(KERN_DEBUG "OPEN %p %d %ld pages (tracked pages %d)\n",+		pVma, current->pid, (pVma->vm_end - pVma->vm_start) >> 12,+		g_trackedPages);++	pVmaList = (struct VmaPageList *)pVma->vm_private_data;++	if (pVmaList)+	{+		pVmaList->m_refCount++;+		PRINTK_VERBOSE(KERN_DEBUG "ref count is now %d\n", pVmaList->m_refCount);+	}+	else+	{+		PRINTK_VERBOSE(KERN_DEBUG "err, open but no vma page list\n");+	}+}++static void VmaClose4k(struct vm_area_struct *pVma)+{+	struct VmaPageList *pVmaList;+	int freed = 0;++	PRINTK_VERBOSE(KERN_DEBUG "vma close %p private %p (%s %d)\n", pVma, pVma->vm_private_data, current->comm, current->pid);++	//wait for any dmas to finish+	DmaWaitAll();++	//find our vma in the list+	pVmaList = (struct VmaPageList *)pVma->vm_private_data;++	//may be a fork+	if (pVmaList)+	{+		struct PageList *pPages;++		pVmaList->m_refCount--;++		if (pVmaList->m_refCount == 0)+		{+			PRINTK_VERBOSE(KERN_DEBUG "found vma, freeing pages (%s %d)\n",+				current->comm, current->pid);++			pPages = pVmaList->m_pPageHead;++			if (!pPages)+			{+				PRINTK(KERN_ERR "no page list (%s %d)!\n",+					current->comm, current->pid);+				return;+			}++			while (pPages)+			{+				struct PageList *next;+				int count;++				PRINTK_VERBOSE(KERN_DEBUG "page list (%s %d)\n",+					current->comm, current->pid);++				next = pPages->m_pNext;+				for (count = 0; count < pPages->m_used; count++)+				{+					PRINTK_VERBOSE(KERN_DEBUG "freeing page %p (%s %d)\n",+						pPages->m_pPages[count],+						current->comm, current->pid);+					__free_pages(pPages->m_pPages[count], 0);+					g_trackedPages--;+					freed++;+				}++				PRINTK_VERBOSE(KERN_DEBUG "freeing page list (%s %d)\n",+					current->comm, current->pid);+				kfree(pPages);+				pPages = next;+			}++			//remove our vma from the list+			kfree(pVmaList);+			pVma->vm_private_data = 0;+		}+		else+		{+			PRINTK_VERBOSE(KERN_DEBUG "ref count is %d, not closing\n", pVmaList->m_refCount);+		}+	}+	else+	{+		PRINTK_VERBOSE(KERN_ERR "uh-oh, vma %p not found (%s %d)!\n", pVma, current->comm, current->pid);+		PRINTK_VERBOSE(KERN_ERR "CLOSE ERR\n");+	}++	PRINTK_VERBOSE(KERN_DEBUG "CLOSE %p %d %d pages (tracked pages %d)",+		pVma, current->pid, freed, g_trackedPages);++	PRINTK_VERBOSE(KERN_DEBUG "%d pages open\n", g_trackedPages);+}++static int VmaFault4k(struct vm_area_struct *pVma, struct vm_fault *pVmf)+{+	PRINTK_VERBOSE(KERN_DEBUG "vma fault for vma %p private %p at offset %ld (%s %d)\n", pVma, pVma->vm_private_data, pVmf->pgoff,+		current->comm, current->pid);+	PRINTK_VERBOSE(KERN_DEBUG "FAULT\n");+	pVmf->page = alloc_page(GFP_KERNEL);++	if (pVmf->page)+	{+		PRINTK_VERBOSE(KERN_DEBUG "alloc page virtual %p\n", page_address(pVmf->page));+	}++	if (!pVmf->page)+	{+		PRINTK(KERN_ERR "vma fault oom (%s %d)\n", current->comm, current->pid);+		return VM_FAULT_OOM;+	}+	else+	{+		struct VmaPageList *pVmaList;++		get_page(pVmf->page);+		g_trackedPages++;++		//find our vma in the list+		pVmaList = (struct VmaPageList *)pVma->vm_private_data;++		if (pVmaList)+		{+			PRINTK_VERBOSE(KERN_DEBUG "vma found (%s %d)\n", current->comm, current->pid);++			if (pVmaList->m_pPageTail->m_used == PAGES_PER_LIST)+			{+				PRINTK_VERBOSE(KERN_DEBUG "making new page list (%s %d)\n", current->comm, current->pid);+				//making a new page list+				pVmaList->m_pPageTail->m_pNext = (struct PageList *)kmalloc(sizeof(struct PageList), GFP_KERNEL);+				if (!pVmaList->m_pPageTail->m_pNext)+					return -ENOMEM;++				//update the tail pointer+				pVmaList->m_pPageTail = pVmaList->m_pPageTail->m_pNext;+				pVmaList->m_pPageTail->m_used = 0;+				pVmaList->m_pPageTail->m_pNext = 0;+			}++			PRINTK_VERBOSE(KERN_DEBUG "adding page to list (%s %d)\n", current->comm, current->pid);++			pVmaList->m_pPageTail->m_pPages[pVmaList->m_pPageTail->m_used] = pVmf->page;+			pVmaList->m_pPageTail->m_used++;+		}+		else+			PRINTK(KERN_ERR "returned page for vma we don\'t know %p (%s %d)\n", pVma, current->comm, current->pid);++		return 0;+	}+}++/****** GENERIC FUNCTIONS ******/+static int __init dmaer_init(void)+{+	int result = alloc_chrdev_region(&g_majorMinor, 0, 1, "dmaer");+	if (result < 0)+	{+		PRINTK(KERN_ERR "unable to get major device number\n");+		return result;+	}+	else+		PRINTK(KERN_DEBUG "major device number %d\n", MAJOR(g_majorMinor));++	PRINTK(KERN_DEBUG "vma list size %d, page list size %d, page size %ld\n",+		sizeof(struct VmaPageList), sizeof(struct PageList), PAGE_SIZE);++	//get a dma channel to work with+	result = bcm_dma_chan_alloc(BCM_DMA_FEATURE_FAST, (void **)&g_pDmaChanBase, &g_dmaIrq);++	//uncomment to force to channel 0+	//result = 0;+	//g_pDmaChanBase = 0xce808000;++	if (result < 0)+	{+		PRINTK(KERN_ERR "failed to allocate dma channel\n");+		cdev_del(&g_cDev);+		unregister_chrdev_region(g_majorMinor, 1);+	}++	//reset the channel+	PRINTK(KERN_DEBUG "allocated dma channel %d (%p), initial state %08x\n", result, g_pDmaChanBase, *g_pDmaChanBase);+	*g_pDmaChanBase = 1 << 31;+	PRINTK(KERN_DEBUG "post-reset %08x\n", *g_pDmaChanBase);++	g_dmaChan = result;++	//clear the cache stats+	g_cacheHit = 0;+	g_cacheMiss = 0;++	//register our device - after this we are go go go+	cdev_init(&g_cDev, &g_fOps);+	g_cDev.owner = THIS_MODULE;+	g_cDev.ops = &g_fOps;++	result = cdev_add(&g_cDev, g_majorMinor, 1);+	if (result < 0)+	{+		PRINTK(KERN_ERR "failed to add character device\n");+		unregister_chrdev_region(g_majorMinor, 1);+		bcm_dma_chan_free(g_dmaChan);+		return result;+	}++	return 0;+}++static void __exit dmaer_exit(void)+{+	PRINTK(KERN_INFO "closing dmaer device, cache stats: %d hits %d misses\n", g_cacheHit, g_cacheMiss);+	//unregister the device+	cdev_del(&g_cDev);+	unregister_chrdev_region(g_majorMinor, 1);+	//free the dma channel+	bcm_dma_chan_free(g_dmaChan);+}++MODULE_LICENSE("Dual BSD/GPL");+MODULE_AUTHOR("Simon Hall");+module_init(dmaer_init);+module_exit(dmaer_exit);diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/arm_control.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/arm_control.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/arm_control.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/arm_control.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,419 @@+/*+ *  linux/arch/arm/mach-bcm2708/arm_control.h+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */++#ifndef __BCM2708_ARM_CONTROL_H+#define __BCM2708_ARM_CONTROL_H++/*+ * Definitions and addresses for the ARM CONTROL logic+ * This file is manually generated.+ */++#define ARM_BASE  0x7E00B000++/* Basic configuration */+#define ARM_CONTROL0  HW_REGISTER_RW(ARM_BASE+0x000)+#define ARM_C0_SIZ128M   0x00000000+#define ARM_C0_SIZ256M   0x00000001+#define ARM_C0_SIZ512M   0x00000002+#define ARM_C0_SIZ1G     0x00000003+#define ARM_C0_BRESP0    0x00000000+#define ARM_C0_BRESP1    0x00000004+#define ARM_C0_BRESP2    0x00000008+#define ARM_C0_BOOTHI    0x00000010+#define ARM_C0_UNUSED05  0x00000020 /* free */+#define ARM_C0_FULLPERI  0x00000040+#define ARM_C0_UNUSED78  0x00000180 /* free */+#define ARM_C0_JTAGMASK  0x00000E00+#define ARM_C0_JTAGOFF   0x00000000+#define ARM_C0_JTAGBASH  0x00000800 /* Debug on GPIO off */+#define ARM_C0_JTAGGPIO  0x00000C00 /* Debug on GPIO on */+#define ARM_C0_APROTMSK  0x0000F000+#define ARM_C0_DBG0SYNC  0x00010000 /* VPU0 halt sync */+#define ARM_C0_DBG1SYNC  0x00020000 /* VPU1 halt sync */+#define ARM_C0_SWDBGREQ  0x00040000 /* HW debug request */+#define ARM_C0_PASSHALT  0x00080000 /* ARM halt passed to debugger */+#define ARM_C0_PRIO_PER  0x00F00000 /* per priority mask */+#define ARM_C0_PRIO_L2   0x0F000000+#define ARM_C0_PRIO_UC   0xF0000000++#define ARM_C0_APROTPASS  0x0000A000 /* Translate 1:1 */+#define ARM_C0_APROTUSER  0x00000000 /* Only user mode */+#define ARM_C0_APROTSYST  0x0000F000 /* Only system mode */+++#define ARM_CONTROL1  HW_REGISTER_RW(ARM_BASE+0x440)+#define ARM_C1_TIMER     0x00000001 /* re-route timer IRQ  to VC */+#define ARM_C1_MAIL      0x00000002 /* re-route Mail IRQ   to VC */+#define ARM_C1_BELL0     0x00000004 /* re-route Doorbell 0 to VC */+#define ARM_C1_BELL1     0x00000008 /* re-route Doorbell 1 to VC */+#define ARM_C1_PERSON    0x00000100 /* peripherals on */+#define ARM_C1_REQSTOP   0x00000200 /* ASYNC bridge request stop */++#define ARM_STATUS    HW_REGISTER_RW(ARM_BASE+0x444)+#define ARM_S_ACKSTOP    0x80000000 /* Bridge stopped */+#define ARM_S_READPEND   0x000003FF /* pending reads counter */+#define ARM_S_WRITPEND   0x000FFC00 /* pending writes counter */++#define ARM_ERRHALT   HW_REGISTER_RW(ARM_BASE+0x448)+#define ARM_EH_PERIBURST  0x00000001 /* Burst write seen on peri bus */+#define ARM_EH_ILLADDRS1  0x00000002 /* Address bits 25-27 error */+#define ARM_EH_ILLADDRS2  0x00000004 /* Address bits 31-28 error */+#define ARM_EH_VPU0HALT   0x00000008 /* VPU0 halted & in debug mode */+#define ARM_EH_VPU1HALT   0x00000010 /* VPU1 halted & in debug mode */+#define ARM_EH_ARMHALT    0x00000020 /* ARM in halted debug mode */++#define ARM_ID_SECURE HW_REGISTER_RW(ARM_BASE+0x00C)+#define ARM_ID        HW_REGISTER_RW(ARM_BASE+0x44C)+#define ARM_IDVAL        0x364D5241++/* Translation memory */+#define ARM_TRANSLATE HW_REGISTER_RW(ARM_BASE+0x100)+/* 32 locations: 0x100.. 0x17F */+/* 32 spare means we CAN go to 64 pages.... */+++/* Interrupts */+#define ARM_IRQ_PEND0 HW_REGISTER_RW(ARM_BASE+0x200)        /* Top IRQ bits */+#define ARM_I0_TIMER    0x00000001 /* timer IRQ */+#define ARM_I0_MAIL     0x00000002 /* Mail IRQ */+#define ARM_I0_BELL0    0x00000004 /* Doorbell 0 */+#define ARM_I0_BELL1    0x00000008 /* Doorbell 1 */+#define ARM_I0_BANK1    0x00000100 /* Bank1 IRQ */+#define ARM_I0_BANK2    0x00000200 /* Bank2 IRQ */++#define ARM_IRQ_PEND1 HW_REGISTER_RW(ARM_BASE+0x204) /* All bank1 IRQ bits */+/* todo: all I1_interrupt sources */+#define ARM_IRQ_PEND2 HW_REGISTER_RW(ARM_BASE+0x208) /* All bank2 IRQ bits */+/* todo: all I2_interrupt sources */++#define ARM_IRQ_FAST  HW_REGISTER_RW(ARM_BASE+0x20C) /* FIQ control */+#define ARM_IF_INDEX    0x0000007F     /* FIQ select */+#define ARM_IF_ENABLE   0x00000080     /* FIQ enable */+#define ARM_IF_VCMASK   0x0000003F     /* FIQ = (index from VC source) */+#define ARM_IF_TIMER    0x00000040     /* FIQ = ARM timer */+#define ARM_IF_MAIL     0x00000041     /* FIQ = ARM Mail */+#define ARM_IF_BELL0    0x00000042     /* FIQ = ARM Doorbell 0 */+#define ARM_IF_BELL1    0x00000043     /* FIQ = ARM Doorbell 1 */+#define ARM_IF_VP0HALT  0x00000044     /* FIQ = VPU0 Halt seen */+#define ARM_IF_VP1HALT  0x00000045     /* FIQ = VPU1 Halt seen */+#define ARM_IF_ILLEGAL  0x00000046     /* FIQ = Illegal access seen */++#define ARM_IRQ_ENBL1 HW_REGISTER_RW(ARM_BASE+0x210) /* Bank1 enable bits */+#define ARM_IRQ_ENBL2 HW_REGISTER_RW(ARM_BASE+0x214) /* Bank2 enable bits */+#define ARM_IRQ_ENBL3 HW_REGISTER_RW(ARM_BASE+0x218) /* ARM irqs enable bits */+#define ARM_IRQ_DIBL1 HW_REGISTER_RW(ARM_BASE+0x21C) /* Bank1 disable bits */+#define ARM_IRQ_DIBL2 HW_REGISTER_RW(ARM_BASE+0x220) /* Bank2 disable bits */+#define ARM_IRQ_DIBL3 HW_REGISTER_RW(ARM_BASE+0x224) /* ARM irqs disable bits */+#define ARM_IE_TIMER    0x00000001     /* Timer IRQ */+#define ARM_IE_MAIL     0x00000002     /* Mail IRQ */+#define ARM_IE_BELL0    0x00000004     /* Doorbell 0 */+#define ARM_IE_BELL1    0x00000008     /* Doorbell 1 */+#define ARM_IE_VP0HALT  0x00000010     /* VPU0 Halt */+#define ARM_IE_VP1HALT  0x00000020     /* VPU1 Halt */+#define ARM_IE_ILLEGAL  0x00000040     /* Illegal access seen */++/* Timer */+/* For reg. fields see sp804 spec. */+#define ARM_T_LOAD    HW_REGISTER_RW(ARM_BASE+0x400)+#define ARM_T_VALUE   HW_REGISTER_RW(ARM_BASE+0x404)+#define ARM_T_CONTROL HW_REGISTER_RW(ARM_BASE+0x408)+#define ARM_T_IRQCNTL HW_REGISTER_RW(ARM_BASE+0x40C)+#define ARM_T_RAWIRQ  HW_REGISTER_RW(ARM_BASE+0x410)+#define ARM_T_MSKIRQ  HW_REGISTER_RW(ARM_BASE+0x414)+#define ARM_T_RELOAD  HW_REGISTER_RW(ARM_BASE+0x418)+#define ARM_T_PREDIV  HW_REGISTER_RW(ARM_BASE+0x41c)+#define ARM_T_FREECNT HW_REGISTER_RW(ARM_BASE+0x420)++#define TIMER_CTRL_ONESHOT  (1 << 0)+#define TIMER_CTRL_32BIT    (1 << 1)+#define TIMER_CTRL_DIV1     (0 << 2)+#define TIMER_CTRL_DIV16    (1 << 2)+#define TIMER_CTRL_DIV256   (2 << 2)+#define TIMER_CTRL_IE       (1 << 5)+#define TIMER_CTRL_PERIODIC (1 << 6)+#define TIMER_CTRL_ENABLE   (1 << 7)+#define TIMER_CTRL_DBGHALT  (1 << 8)+#define TIMER_CTRL_ENAFREE  (1 << 9)+#define TIMER_CTRL_FREEDIV_SHIFT 16)+#define TIMER_CTRL_FREEDIV_MASK  0xff++/* Semaphores, Doorbells, Mailboxes */+#define ARM_SBM_OWN0  (ARM_BASE+0x800)+#define ARM_SBM_OWN1  (ARM_BASE+0x900)+#define ARM_SBM_OWN2  (ARM_BASE+0xA00)+#define ARM_SBM_OWN3  (ARM_BASE+0xB00)++/* MAILBOXES+ * Register flags are common across all+ * owner registers. See end of this section+ *+ * Semaphores, Doorbells, Mailboxes Owner 0+ *+ */++#define ARM_0_SEMS       HW_REGISTER_RW(ARM_SBM_OWN0+0x00)+#define ARM_0_SEM0       HW_REGISTER_RW(ARM_SBM_OWN0+0x00)+#define ARM_0_SEM1       HW_REGISTER_RW(ARM_SBM_OWN0+0x04)+#define ARM_0_SEM2       HW_REGISTER_RW(ARM_SBM_OWN0+0x08)+#define ARM_0_SEM3       HW_REGISTER_RW(ARM_SBM_OWN0+0x0C)+#define ARM_0_SEM4       HW_REGISTER_RW(ARM_SBM_OWN0+0x10)+#define ARM_0_SEM5       HW_REGISTER_RW(ARM_SBM_OWN0+0x14)+#define ARM_0_SEM6       HW_REGISTER_RW(ARM_SBM_OWN0+0x18)+#define ARM_0_SEM7       HW_REGISTER_RW(ARM_SBM_OWN0+0x1C)+#define ARM_0_BELL0      HW_REGISTER_RW(ARM_SBM_OWN0+0x40)+#define ARM_0_BELL1      HW_REGISTER_RW(ARM_SBM_OWN0+0x44)+#define ARM_0_BELL2      HW_REGISTER_RW(ARM_SBM_OWN0+0x48)+#define ARM_0_BELL3      HW_REGISTER_RW(ARM_SBM_OWN0+0x4C)+/* MAILBOX 0 access in Owner 0 area */+/* Some addresses should ONLY be used by owner 0 */+#define ARM_0_MAIL0_WRT  HW_REGISTER_RW(ARM_SBM_OWN0+0x80)  /* .. 0x8C (4 locations) */+#define ARM_0_MAIL0_RD   HW_REGISTER_RW(ARM_SBM_OWN0+0x80)  /* .. 0x8C (4 locations) Normal read */+#define ARM_0_MAIL0_POL  HW_REGISTER_RW(ARM_SBM_OWN0+0x90)  /* none-pop read */+#define ARM_0_MAIL0_SND  HW_REGISTER_RW(ARM_SBM_OWN0+0x94)  /* Sender read (only LS 2 bits) */+#define ARM_0_MAIL0_STA  HW_REGISTER_RW(ARM_SBM_OWN0+0x98)  /* Status read */+#define ARM_0_MAIL0_CNF  HW_REGISTER_RW(ARM_SBM_OWN0+0x9C)  /* Config read/write */+/* MAILBOX 1 access in Owner 0 area */+/* Owner 0 should only WRITE to this mailbox */+#define ARM_0_MAIL1_WRT  HW_REGISTER_RW(ARM_SBM_OWN0+0xA0)   /* .. 0xAC (4 locations) */+/*#define ARM_0_MAIL1_RD   HW_REGISTER_RW(ARM_SBM_OWN0+0xA0) */ /* DO NOT USE THIS !!!!! */+/*#define ARM_0_MAIL1_POL  HW_REGISTER_RW(ARM_SBM_OWN0+0xB0) */ /* DO NOT USE THIS !!!!! */+/*#define ARM_0_MAIL1_SND  HW_REGISTER_RW(ARM_SBM_OWN0+0xB4) */ /* DO NOT USE THIS !!!!! */+#define ARM_0_MAIL1_STA  HW_REGISTER_RW(ARM_SBM_OWN0+0xB8)   /* Status read */+/*#define ARM_0_MAIL1_CNF  HW_REGISTER_RW(ARM_SBM_OWN0+0xBC) */ /* DO NOT USE THIS !!!!! */+/* General SEM, BELL, MAIL config/status */+#define ARM_0_SEMCLRDBG   HW_REGISTER_RW(ARM_SBM_OWN0+0xE0)  /* semaphore clear/debug register */+#define ARM_0_BELLCLRDBG  HW_REGISTER_RW(ARM_SBM_OWN0+0xE4)  /* Doorbells clear/debug register */+#define ARM_0_ALL_IRQS    HW_REGISTER_RW(ARM_SBM_OWN0+0xF8)  /* ALL interrupts */+#define ARM_0_MY_IRQS     HW_REGISTER_RW(ARM_SBM_OWN0+0xFC)  /* IRQS pending for owner 0 */++/* Semaphores, Doorbells, Mailboxes Owner 1 */+#define ARM_1_SEMS       HW_REGISTER_RW(ARM_SBM_OWN1+0x00)+#define ARM_1_SEM0       HW_REGISTER_RW(ARM_SBM_OWN1+0x00)+#define ARM_1_SEM1       HW_REGISTER_RW(ARM_SBM_OWN1+0x04)+#define ARM_1_SEM2       HW_REGISTER_RW(ARM_SBM_OWN1+0x08)+#define ARM_1_SEM3       HW_REGISTER_RW(ARM_SBM_OWN1+0x0C)+#define ARM_1_SEM4       HW_REGISTER_RW(ARM_SBM_OWN1+0x10)+#define ARM_1_SEM5       HW_REGISTER_RW(ARM_SBM_OWN1+0x14)+#define ARM_1_SEM6       HW_REGISTER_RW(ARM_SBM_OWN1+0x18)+#define ARM_1_SEM7       HW_REGISTER_RW(ARM_SBM_OWN1+0x1C)+#define ARM_1_BELL0      HW_REGISTER_RW(ARM_SBM_OWN1+0x40)+#define ARM_1_BELL1      HW_REGISTER_RW(ARM_SBM_OWN1+0x44)+#define ARM_1_BELL2      HW_REGISTER_RW(ARM_SBM_OWN1+0x48)+#define ARM_1_BELL3      HW_REGISTER_RW(ARM_SBM_OWN1+0x4C)+/* MAILBOX 0 access in Owner 0 area */+/* Owner 1 should only WRITE to this mailbox */+#define ARM_1_MAIL0_WRT  HW_REGISTER_RW(ARM_SBM_OWN1+0x80)  /* .. 0x8C (4 locations) */+/*#define ARM_1_MAIL0_RD  HW_REGISTER_RW(ARM_SBM_OWN1+0x80) */ /* DO NOT USE THIS !!!!! */+/*#define ARM_1_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN1+0x90) */ /* DO NOT USE THIS !!!!! */+/*#define ARM_1_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN1+0x94) */ /* DO NOT USE THIS !!!!! */+#define ARM_1_MAIL0_STA  HW_REGISTER_RW(ARM_SBM_OWN1+0x98)  /* Status read */+/*#define ARM_1_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN1+0x9C) */ /* DO NOT USE THIS !!!!! */+/* MAILBOX 1 access in Owner 0 area */+#define ARM_1_MAIL1_WRT  HW_REGISTER_RW(ARM_SBM_OWN1+0xA0)  /* .. 0xAC (4 locations) */+#define ARM_1_MAIL1_RD   HW_REGISTER_RW(ARM_SBM_OWN1+0xA0)  /* .. 0xAC (4 locations) Normal read */+#define ARM_1_MAIL1_POL  HW_REGISTER_RW(ARM_SBM_OWN1+0xB0)  /* none-pop read */+#define ARM_1_MAIL1_SND  HW_REGISTER_RW(ARM_SBM_OWN1+0xB4)  /* Sender read (only LS 2 bits) */+#define ARM_1_MAIL1_STA  HW_REGISTER_RW(ARM_SBM_OWN1+0xB8)  /* Status read */+#define ARM_1_MAIL1_CNF  HW_REGISTER_RW(ARM_SBM_OWN1+0xBC)+/* General SEM, BELL, MAIL config/status */+#define ARM_1_SEMCLRDBG   HW_REGISTER_RW(ARM_SBM_OWN1+0xE0)  /* semaphore clear/debug register */+#define ARM_1_BELLCLRDBG  HW_REGISTER_RW(ARM_SBM_OWN1+0xE4)  /* Doorbells clear/debug register */+#define ARM_1_MY_IRQS     HW_REGISTER_RW(ARM_SBM_OWN1+0xFC)  /* IRQS pending for owner 1 */+#define ARM_1_ALL_IRQS    HW_REGISTER_RW(ARM_SBM_OWN1+0xF8)  /* ALL interrupts */++/* Semaphores, Doorbells, Mailboxes Owner 2 */+#define ARM_2_SEMS       HW_REGISTER_RW(ARM_SBM_OWN2+0x00)+#define ARM_2_SEM0       HW_REGISTER_RW(ARM_SBM_OWN2+0x00)+#define ARM_2_SEM1       HW_REGISTER_RW(ARM_SBM_OWN2+0x04)+#define ARM_2_SEM2       HW_REGISTER_RW(ARM_SBM_OWN2+0x08)+#define ARM_2_SEM3       HW_REGISTER_RW(ARM_SBM_OWN2+0x0C)+#define ARM_2_SEM4       HW_REGISTER_RW(ARM_SBM_OWN2+0x10)+#define ARM_2_SEM5       HW_REGISTER_RW(ARM_SBM_OWN2+0x14)+#define ARM_2_SEM6       HW_REGISTER_RW(ARM_SBM_OWN2+0x18)+#define ARM_2_SEM7       HW_REGISTER_RW(ARM_SBM_OWN2+0x1C)+#define ARM_2_BELL0      HW_REGISTER_RW(ARM_SBM_OWN2+0x40)+#define ARM_2_BELL1      HW_REGISTER_RW(ARM_SBM_OWN2+0x44)+#define ARM_2_BELL2      HW_REGISTER_RW(ARM_SBM_OWN2+0x48)+#define ARM_2_BELL3      HW_REGISTER_RW(ARM_SBM_OWN2+0x4C)+/* MAILBOX 0 access in Owner 2 area */+/* Owner 2 should only WRITE to this mailbox */+#define ARM_2_MAIL0_WRT  HW_REGISTER_RW(ARM_SBM_OWN2+0x80)   /* .. 0x8C (4 locations) */+/*#define ARM_2_MAIL0_RD  HW_REGISTER_RW(ARM_SBM_OWN2+0x80)  */ /* DO NOT USE THIS !!!!! */+/*#define ARM_2_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN2+0x90)  */ /* DO NOT USE THIS !!!!! */+/*#define ARM_2_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN2+0x94)  */ /* DO NOT USE THIS !!!!! */+#define ARM_2_MAIL0_STA  HW_REGISTER_RW(ARM_SBM_OWN2+0x98)   /* Status read */+/*#define ARM_2_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN2+0x9C)  */ /* DO NOT USE THIS !!!!! */+/* MAILBOX 1 access in Owner 2 area */+/* Owner 2 should only WRITE to this mailbox */+#define ARM_2_MAIL1_WRT  HW_REGISTER_RW(ARM_SBM_OWN2+0xA0)   /* .. 0xAC (4 locations) */+/*#define ARM_2_MAIL1_RD   HW_REGISTER_RW(ARM_SBM_OWN2+0xA0) */ /* DO NOT USE THIS !!!!! */+/*#define ARM_2_MAIL1_POL  HW_REGISTER_RW(ARM_SBM_OWN2+0xB0) */ /* DO NOT USE THIS !!!!! */+/*#define ARM_2_MAIL1_SND  HW_REGISTER_RW(ARM_SBM_OWN2+0xB4) */ /* DO NOT USE THIS !!!!! */+#define ARM_2_MAIL1_STA  HW_REGISTER_RW(ARM_SBM_OWN2+0xB8)   /* Status read */+/*#define ARM_2_MAIL1_CNF  HW_REGISTER_RW(ARM_SBM_OWN2+0xBC) */ /* DO NOT USE THIS !!!!! */+/* General SEM, BELL, MAIL config/status */+#define ARM_2_SEMCLRDBG   HW_REGISTER_RW(ARM_SBM_OWN2+0xE0)  /* semaphore clear/debug register */+#define ARM_2_BELLCLRDBG  HW_REGISTER_RW(ARM_SBM_OWN2+0xE4)  /* Doorbells clear/debug register */+#define ARM_2_MY_IRQS     HW_REGISTER_RW(ARM_SBM_OWN2+0xFC)  /* IRQS pending for owner 2 */+#define ARM_2_ALL_IRQS    HW_REGISTER_RW(ARM_SBM_OWN2+0xF8)  /* ALL interrupts */++/* Semaphores, Doorbells, Mailboxes Owner 3 */+#define ARM_3_SEMS       HW_REGISTER_RW(ARM_SBM_OWN3+0x00)+#define ARM_3_SEM0       HW_REGISTER_RW(ARM_SBM_OWN3+0x00)+#define ARM_3_SEM1       HW_REGISTER_RW(ARM_SBM_OWN3+0x04)+#define ARM_3_SEM2       HW_REGISTER_RW(ARM_SBM_OWN3+0x08)+#define ARM_3_SEM3       HW_REGISTER_RW(ARM_SBM_OWN3+0x0C)+#define ARM_3_SEM4       HW_REGISTER_RW(ARM_SBM_OWN3+0x10)+#define ARM_3_SEM5       HW_REGISTER_RW(ARM_SBM_OWN3+0x14)+#define ARM_3_SEM6       HW_REGISTER_RW(ARM_SBM_OWN3+0x18)+#define ARM_3_SEM7       HW_REGISTER_RW(ARM_SBM_OWN3+0x1C)+#define ARM_3_BELL0      HW_REGISTER_RW(ARM_SBM_OWN3+0x40)+#define ARM_3_BELL1      HW_REGISTER_RW(ARM_SBM_OWN3+0x44)+#define ARM_3_BELL2      HW_REGISTER_RW(ARM_SBM_OWN3+0x48)+#define ARM_3_BELL3      HW_REGISTER_RW(ARM_SBM_OWN3+0x4C)+/* MAILBOX 0 access in Owner 3 area */+/* Owner 3 should only WRITE to this mailbox */+#define ARM_3_MAIL0_WRT  HW_REGISTER_RW(ARM_SBM_OWN3+0x80)   /* .. 0x8C (4 locations) */+/*#define ARM_3_MAIL0_RD  HW_REGISTER_RW(ARM_SBM_OWN3+0x80)  */ /* DO NOT USE THIS !!!!! */+/*#define ARM_3_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN3+0x90)  */ /* DO NOT USE THIS !!!!! */+/*#define ARM_3_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN3+0x94)  */ /* DO NOT USE THIS !!!!! */+#define ARM_3_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN3+0x98)    /* Status read */+/*#define ARM_3_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN3+0x9C)  */ /* DO NOT USE THIS !!!!! */+/* MAILBOX 1 access in Owner 3 area */+/* Owner 3 should only WRITE to this mailbox */+#define ARM_3_MAIL1_WRT  HW_REGISTER_RW(ARM_SBM_OWN3+0xA0)   /* .. 0xAC (4 locations) */+/*#define ARM_3_MAIL1_RD   HW_REGISTER_RW(ARM_SBM_OWN3+0xA0) */ /* DO NOT USE THIS !!!!! */+/*#define ARM_3_MAIL1_POL  HW_REGISTER_RW(ARM_SBM_OWN3+0xB0) */ /* DO NOT USE THIS !!!!! */+/*#define ARM_3_MAIL1_SND  HW_REGISTER_RW(ARM_SBM_OWN3+0xB4) */ /* DO NOT USE THIS !!!!! */+#define ARM_3_MAIL1_STA  HW_REGISTER_RW(ARM_SBM_OWN3+0xB8)   /* Status read */+/*#define ARM_3_MAIL1_CNF  HW_REGISTER_RW(ARM_SBM_OWN3+0xBC) */ /* DO NOT USE THIS !!!!! */+/* General SEM, BELL, MAIL config/status */+#define ARM_3_SEMCLRDBG   HW_REGISTER_RW(ARM_SBM_OWN3+0xE0)  /* semaphore clear/debug register */+#define ARM_3_BELLCLRDBG  HW_REGISTER_RW(ARM_SBM_OWN3+0xE4)  /* Doorbells clear/debug register */+#define ARM_3_MY_IRQS     HW_REGISTER_RW(ARM_SBM_OWN3+0xFC)  /* IRQS pending for owner 3 */+#define ARM_3_ALL_IRQS    HW_REGISTER_RW(ARM_SBM_OWN3+0xF8)  /* ALL interrupts */++++/*  Mailbox flags. Valid for all owners */++/* Mailbox status register (...0x98) */+#define ARM_MS_FULL       0x80000000+#define ARM_MS_EMPTY      0x40000000+#define ARM_MS_LEVEL      0x400000FF /* Max. value depdnds on mailbox depth parameter */++/* MAILBOX config/status register (...0x9C) */+/* ANY write to this register clears the error bits! */+#define ARM_MC_IHAVEDATAIRQEN    0x00000001 /* mailbox irq enable:  has data */+#define ARM_MC_IHAVESPACEIRQEN   0x00000002 /* mailbox irq enable:  has space */+#define ARM_MC_OPPISEMPTYIRQEN   0x00000004 /* mailbox irq enable: Opp. is empty */+#define ARM_MC_MAIL_CLEAR        0x00000008 /* mailbox clear write 1, then  0 */+#define ARM_MC_IHAVEDATAIRQPEND  0x00000010 /* mailbox irq pending:  has space */+#define ARM_MC_IHAVESPACEIRQPEND 0x00000020 /* mailbox irq pending: Opp. is empty */+#define ARM_MC_OPPISEMPTYIRQPEND 0x00000040 /* mailbox irq pending */+/* Bit 7 is unused */+#define ARM_MC_ERRNOOWN   0x00000100 /* error : none owner read from mailbox */+#define ARM_MC_ERROVERFLW 0x00000200 /* error : write to fill mailbox */+#define ARM_MC_ERRUNDRFLW 0x00000400 /* error : read from empty mailbox */++/* Semaphore clear/debug register (...0xE0) */+#define ARM_SD_OWN0      0x00000003  /* Owner of sem 0 */+#define ARM_SD_OWN1      0x0000000C  /* Owner of sem 1 */+#define ARM_SD_OWN2      0x00000030  /* Owner of sem 2 */+#define ARM_SD_OWN3      0x000000C0  /* Owner of sem 3 */+#define ARM_SD_OWN4      0x00000300  /* Owner of sem 4 */+#define ARM_SD_OWN5      0x00000C00  /* Owner of sem 5 */+#define ARM_SD_OWN6      0x00003000  /* Owner of sem 6 */+#define ARM_SD_OWN7      0x0000C000  /* Owner of sem 7 */+#define ARM_SD_SEM0      0x00010000  /* Status of sem 0 */+#define ARM_SD_SEM1      0x00020000  /* Status of sem 1 */+#define ARM_SD_SEM2      0x00040000  /* Status of sem 2 */+#define ARM_SD_SEM3      0x00080000  /* Status of sem 3 */+#define ARM_SD_SEM4      0x00100000  /* Status of sem 4 */+#define ARM_SD_SEM5      0x00200000  /* Status of sem 5 */+#define ARM_SD_SEM6      0x00400000  /* Status of sem 6 */+#define ARM_SD_SEM7      0x00800000  /* Status of sem 7 */++/* Doorbells clear/debug register (...0xE4) */+#define ARM_BD_OWN0      0x00000003  /* Owner of doorbell 0 */+#define ARM_BD_OWN1      0x0000000C  /* Owner of doorbell 1 */+#define ARM_BD_OWN2      0x00000030  /* Owner of doorbell 2 */+#define ARM_BD_OWN3      0x000000C0  /* Owner of doorbell 3 */+#define ARM_BD_BELL0     0x00000100  /* Status of doorbell 0 */+#define ARM_BD_BELL1     0x00000200  /* Status of doorbell 1 */+#define ARM_BD_BELL2     0x00000400  /* Status of doorbell 2 */+#define ARM_BD_BELL3     0x00000800  /* Status of doorbell 3 */++/* MY IRQS register (...0xF8) */+#define ARM_MYIRQ_BELL   0x00000001  /* This owner has a doorbell IRQ */+#define ARM_MYIRQ_MAIL   0x00000002  /* This owner has a mailbox  IRQ */++/* ALL IRQS register (...0xF8) */+#define ARM_AIS_BELL0 0x00000001  /* Doorbell 0 IRQ pending */+#define ARM_AIS_BELL1 0x00000002  /* Doorbell 1 IRQ pending */+#define ARM_AIS_BELL2 0x00000004  /* Doorbell 2 IRQ pending */+#define ARM_AIS_BELL3 0x00000008  /* Doorbell 3 IRQ pending */+#define ARM_AIS0_HAVEDATA 0x00000010  /* MAIL 0 has data IRQ pending */+#define ARM_AIS0_HAVESPAC 0x00000020  /* MAIL 0 has space IRQ pending */+#define ARM_AIS0_OPPEMPTY 0x00000040  /* MAIL 0 opposite is empty IRQ */+#define ARM_AIS1_HAVEDATA 0x00000080  /* MAIL 1 has data IRQ pending */+#define ARM_AIS1_HAVESPAC 0x00000100  /* MAIL 1 has space IRQ pending */+#define ARM_AIS1_OPPEMPTY 0x00000200  /* MAIL 1 opposite is empty IRQ */+/* Note   that bell-0, bell-1 and MAIL0 IRQ go only to the ARM */+/* Whilst that bell-2, bell-3 and MAIL1 IRQ go only to the VC */+/* */+/* ARM JTAG BASH */+/* */+#define AJB_BASE 0x7e2000c0++#define AJBCONF HW_REGISTER_RW(AJB_BASE+0x00)+#define   AJB_BITS0    0x000000+#define   AJB_BITS4    0x000004+#define   AJB_BITS8    0x000008+#define   AJB_BITS12   0x00000C+#define   AJB_BITS16   0x000010+#define   AJB_BITS20   0x000014+#define   AJB_BITS24   0x000018+#define   AJB_BITS28   0x00001C+#define   AJB_BITS32   0x000020+#define   AJB_BITS34   0x000022+#define   AJB_OUT_MS   0x000040+#define   AJB_OUT_LS   0x000000+#define   AJB_INV_CLK  0x000080+#define   AJB_D0_RISE  0x000100+#define   AJB_D0_FALL  0x000000+#define   AJB_D1_RISE  0x000200+#define   AJB_D1_FALL  0x000000+#define   AJB_IN_RISE  0x000400+#define   AJB_IN_FALL  0x000000+#define   AJB_ENABLE   0x000800+#define   AJB_HOLD0    0x000000+#define   AJB_HOLD1    0x001000+#define   AJB_HOLD2    0x002000+#define   AJB_HOLD3    0x003000+#define   AJB_RESETN   0x004000+#define   AJB_CLKSHFT  16+#define   AJB_BUSY     0x80000000+#define AJBTMS HW_REGISTER_RW(AJB_BASE+0x04)+#define AJBTDI HW_REGISTER_RW(AJB_BASE+0x08)+#define AJBTDO HW_REGISTER_RW(AJB_BASE+0x0c)++#endifdiff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/arm_power.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/arm_power.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/arm_power.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/arm_power.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,60 @@+/*+ *  linux/arch/arm/mach-bcm2708/include/mach/arm_power.h+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */++#ifndef _ARM_POWER_H+#define _ARM_POWER_H++/* Use meaningful names on each side */+#ifdef __VIDEOCORE__+#define PREFIX(x) ARM_##x+#else+#define PREFIX(x) BCM_##x+#endif++enum {+	PREFIX(POWER_SDCARD_BIT),+	PREFIX(POWER_UART_BIT),+	PREFIX(POWER_MINIUART_BIT),+	PREFIX(POWER_USB_BIT),+	PREFIX(POWER_I2C0_BIT),+	PREFIX(POWER_I2C1_BIT),+	PREFIX(POWER_I2C2_BIT),+	PREFIX(POWER_SPI_BIT),+	PREFIX(POWER_CCP2TX_BIT),++	PREFIX(POWER_MAX)+};++enum {+	PREFIX(POWER_SDCARD) = (1 << PREFIX(POWER_SDCARD_BIT)),+	PREFIX(POWER_UART) = (1 << PREFIX(POWER_UART_BIT)),+	PREFIX(POWER_MINIUART) = (1 << PREFIX(POWER_MINIUART_BIT)),+	PREFIX(POWER_USB) = (1 << PREFIX(POWER_USB_BIT)),+	PREFIX(POWER_I2C0) = (1 << PREFIX(POWER_I2C0_BIT)),+	PREFIX(POWER_I2C1_MASK) = (1 << PREFIX(POWER_I2C1_BIT)),+	PREFIX(POWER_I2C2_MASK) = (1 << PREFIX(POWER_I2C2_BIT)),+	PREFIX(POWER_SPI_MASK) = (1 << PREFIX(POWER_SPI_BIT)),+	PREFIX(POWER_CCP2TX_MASK) = (1 << PREFIX(POWER_CCP2TX_BIT)),++	PREFIX(POWER_MASK) = (1 << PREFIX(POWER_MAX)) - 1,+	PREFIX(POWER_NONE) = 0+};++#endifdiff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/clkdev.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/clkdev.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/clkdev.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/clkdev.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,7 @@+#ifndef __ASM_MACH_CLKDEV_H+#define __ASM_MACH_CLKDEV_H++#define __clk_get(clk) ({ 1; })+#define __clk_put(clk) do { } while (0)++#endifdiff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/debug-macro.S linux-3.11.10/arch/arm/mach-bcm2708/include/mach/debug-macro.S--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/debug-macro.S	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/debug-macro.S	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,22 @@+/* arch/arm/mach-bcm2708/include/mach/debug-macro.S+ *+ * Debugging macro include header+ *+ *  Copyright (C) 2010 Broadcom+ *  Copyright (C) 1994-1999 Russell King+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License version 2 as+ * published by the Free Software Foundation.+ *+*/++#include <mach/platform.h>++		.macro	addruart, rp, rv, tmp+		ldr	\rp, =UART0_BASE+		ldr	\rv, =IO_ADDRESS(UART0_BASE)+		.endm++#include <asm/hardware/debug-pl01x.S>diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/dma.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/dma.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/dma.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/dma.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,86 @@+/*+ *  linux/arch/arm/mach-bcm2708/include/mach/dma.h+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License version 2 as+ * published by the Free Software Foundation.+ */+++#ifndef _MACH_BCM2708_DMA_H+#define _MACH_BCM2708_DMA_H++#define BCM_DMAMAN_DRIVER_NAME "bcm2708_dma"++/* DMA CS Control and Status bits */+#define BCM2708_DMA_ACTIVE	(1 << 0)+#define BCM2708_DMA_INT		(1 << 2)+#define BCM2708_DMA_ISPAUSED	(1 << 4)  /* Pause requested or not active */+#define BCM2708_DMA_ISHELD	(1 << 5)  /* Is held by DREQ flow control */+#define BCM2708_DMA_ERR		(1 << 8)+#define BCM2708_DMA_ABORT	(1 << 30) /* stop current CB, go to next, WO */+#define BCM2708_DMA_RESET	(1 << 31) /* WO, self clearing */++/* DMA control block "info" field bits */+#define BCM2708_DMA_INT_EN	(1 << 0)+#define BCM2708_DMA_TDMODE	(1 << 1)+#define BCM2708_DMA_WAIT_RESP	(1 << 3)+#define BCM2708_DMA_D_INC	(1 << 4)+#define BCM2708_DMA_D_WIDTH	(1 << 5)+#define BCM2708_DMA_D_DREQ	(1 << 6)+#define BCM2708_DMA_S_INC	(1 << 8)+#define BCM2708_DMA_S_WIDTH	(1 << 9)+#define BCM2708_DMA_S_DREQ	(1 << 10)++#define	BCM2708_DMA_BURST(x)	(((x)&0xf) << 12)+#define	BCM2708_DMA_PER_MAP(x)	((x) << 16)+#define	BCM2708_DMA_WAITS(x)	(((x)&0x1f) << 21)++#define BCM2708_DMA_DREQ_EMMC	11+#define BCM2708_DMA_DREQ_SDHOST	13++#define BCM2708_DMA_CS		0x00 /* Control and Status */+#define BCM2708_DMA_ADDR	0x04+/* the current control block appears in the following registers - read only */+#define BCM2708_DMA_INFO	0x08+#define BCM2708_DMA_NEXTCB	0x1C+#define BCM2708_DMA_DEBUG	0x20++#define BCM2708_DMA4_CS		(BCM2708_DMA_CHAN(4)+BCM2708_DMA_CS)+#define BCM2708_DMA4_ADDR	(BCM2708_DMA_CHAN(4)+BCM2708_DMA_ADDR)++#define BCM2708_DMA_TDMODE_LEN(w, h) ((h) << 16 | (w))++struct bcm2708_dma_cb {+	unsigned long info;+	unsigned long src;+	unsigned long dst;+	unsigned long length;+	unsigned long stride;+	unsigned long next;+	unsigned long pad[2];+};++extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len);+extern void bcm_dma_start(void __iomem *dma_chan_base,+			  dma_addr_t control_block);+extern void bcm_dma_wait_idle(void __iomem *dma_chan_base);+extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base);++/* When listing features we can ask for when allocating DMA channels give+   those with higher priority smaller ordinal numbers */+#define BCM_DMA_FEATURE_FAST_ORD 0+#define BCM_DMA_FEATURE_BULK_ORD 1+#define BCM_DMA_FEATURE_FAST	 (1<<BCM_DMA_FEATURE_FAST_ORD)+#define BCM_DMA_FEATURE_BULK	 (1<<BCM_DMA_FEATURE_BULK_ORD)+#define BCM_DMA_FEATURE_COUNT	 2++/* return channel no or -ve error */+extern int bcm_dma_chan_alloc(unsigned preferred_feature_set,+			      void __iomem **out_dma_base, int *out_dma_irq);+extern int bcm_dma_chan_free(int channel);+++#endif /* _MACH_BCM2708_DMA_H */diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/entry-macro.S linux-3.11.10/arch/arm/mach-bcm2708/include/mach/entry-macro.S--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/entry-macro.S	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/entry-macro.S	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,69 @@+/*+ * arch/arm/mach-bcm2708/include/mach/entry-macro.S+ *+ * Low-level IRQ helper macros for BCM2708 platforms+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */+#include <mach/hardware.h>++		.macro	disable_fiq+		.endm++		.macro  get_irqnr_preamble, base, tmp+		ldr	\base, =IO_ADDRESS(ARMCTRL_IC_BASE)+		.endm++		.macro  arch_ret_to_user, tmp1, tmp2+		.endm++		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp+		/* get masked status */+		ldr	\irqstat, [\base, #(ARM_IRQ_PEND0 - ARMCTRL_IC_BASE)]+		mov	\irqnr, #(ARM_IRQ0_BASE + 31)+		and	\tmp, \irqstat, #0x300		 @ save bits 8 and 9+		/* clear bits 8 and 9, and test */+		bics	\irqstat, \irqstat, #0x300+		bne	1010f++		tst	\tmp, #0x100+		ldrne	\irqstat, [\base, #(ARM_IRQ_PEND1 - ARMCTRL_IC_BASE)]+		movne \irqnr, #(ARM_IRQ1_BASE + 31)+		@ Mask out the interrupts also present in PEND0 - see SW-5809+		bicne \irqstat, #((1<<7) | (1<<9) | (1<<10))+		bicne \irqstat, #((1<<18) | (1<<19))+		bne	1010f++		tst	\tmp, #0x200+		ldrne \irqstat, [\base, #(ARM_IRQ_PEND2 - ARMCTRL_IC_BASE)]+		movne \irqnr, #(ARM_IRQ2_BASE + 31)+		@ Mask out the interrupts also present in PEND0 - see SW-5809+		bicne \irqstat, #((1<<21) | (1<<22) | (1<<23) | (1<<24) | (1<<25))+		bicne \irqstat, #((1<<30))+		beq 1020f++1010:+		@ For non-zero x, LSB(x) = 31 - CLZ(x^(x-1))+		@ N.B. CLZ is an ARM5 instruction.+		sub	\tmp, \irqstat, #1+		eor	\irqstat, \irqstat, \tmp+		clz	\tmp, \irqstat+		sub	\irqnr, \tmp++1020:	@ EQ will be set if no irqs pending++		.endmdiff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/frc.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/frc.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/frc.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/frc.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,38 @@+/*+ *  arch/arm/mach-bcm2708/include/mach/timex.h+ *+ *  BCM2708 free running counter (timer)+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */++#ifndef _MACH_FRC_H+#define _MACH_FRC_H++#define FRC_TICK_RATE		(1000000)++/*! Free running counter incrementing at the CLOCK_TICK_RATE+    (slightly faster than frc_clock_ticks63()+ */+extern unsigned long frc_clock_ticks32(void);++/*! Free running counter incrementing at the CLOCK_TICK_RATE+ *  Note - top bit should be ignored (see cnt32_to_63)+ */+extern unsigned long long frc_clock_ticks63(void);++#endifdiff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/gpio.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/gpio.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/gpio.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/gpio.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,17 @@+/*+ * arch/arm/mach-bcm2708/include/mach/gpio.h+ *+ * This file is licensed under the terms of the GNU General Public+ * License version 2.  This program is licensed "as is" without any+ * warranty of any kind, whether express or implied.+ */++#ifndef __ASM_ARCH_GPIO_H+#define __ASM_ARCH_GPIO_H++#define ARCH_NR_GPIOS 54 // number of gpio lines++#define gpio_to_irq(x)	((x) + GPIO_IRQ_START)+#define irq_to_gpio(x)	((x) - GPIO_IRQ_START)++#endifdiff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/hardware.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/hardware.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/hardware.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/hardware.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,28 @@+/*+ *  arch/arm/mach-bcm2708/include/mach/hardware.h+ *+ *  This file contains the hardware definitions of the BCM2708 devices.+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */+#ifndef __ASM_ARCH_HARDWARE_H+#define __ASM_ARCH_HARDWARE_H++#include <asm/sizes.h>+#include <mach/platform.h>++#endifdiff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/io.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/io.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/io.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/io.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,27 @@+/*+ *  arch/arm/mach-bcm2708/include/mach/io.h+ *+ *  Copyright (C) 2003 ARM Limited+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */+#ifndef __ASM_ARM_ARCH_IO_H+#define __ASM_ARM_ARCH_IO_H++#define IO_SPACE_LIMIT 0xffffffff++#define __io(a)		__typesafe_io(a)++#endifdiff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/irqs.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/irqs.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/irqs.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/irqs.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,199 @@+/*+ *  arch/arm/mach-bcm2708/include/mach/irqs.h+ *+ *  Copyright (C) 2010 Broadcom+ *  Copyright (C) 2003 ARM Limited+ *  Copyright (C) 2000 Deep Blue Solutions Ltd.+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */++#ifndef _BCM2708_IRQS_H_+#define _BCM2708_IRQS_H_++#include <mach/platform.h>++/*+ *  IRQ interrupts definitions are the same as the INT definitions+ *  held within platform.h+ */+#define IRQ_ARMCTRL_START     0+#define IRQ_TIMER0            (IRQ_ARMCTRL_START + INTERRUPT_TIMER0)+#define IRQ_TIMER1            (IRQ_ARMCTRL_START + INTERRUPT_TIMER1)+#define IRQ_TIMER2            (IRQ_ARMCTRL_START + INTERRUPT_TIMER2)+#define IRQ_TIMER3            (IRQ_ARMCTRL_START + INTERRUPT_TIMER3)+#define IRQ_CODEC0            (IRQ_ARMCTRL_START + INTERRUPT_CODEC0)+#define IRQ_CODEC1            (IRQ_ARMCTRL_START + INTERRUPT_CODEC1)+#define IRQ_CODEC2            (IRQ_ARMCTRL_START + INTERRUPT_CODEC2)+#define IRQ_JPEG              (IRQ_ARMCTRL_START + INTERRUPT_JPEG)+#define IRQ_ISP               (IRQ_ARMCTRL_START + INTERRUPT_ISP)+#define IRQ_USB               (IRQ_ARMCTRL_START + INTERRUPT_USB)+#define IRQ_3D                (IRQ_ARMCTRL_START + INTERRUPT_3D)+#define IRQ_TRANSPOSER        (IRQ_ARMCTRL_START + INTERRUPT_TRANSPOSER)+#define IRQ_MULTICORESYNC0    (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC0)+#define IRQ_MULTICORESYNC1    (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC1)+#define IRQ_MULTICORESYNC2    (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC2)+#define IRQ_MULTICORESYNC3    (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC3)+#define IRQ_DMA0              (IRQ_ARMCTRL_START + INTERRUPT_DMA0)+#define IRQ_DMA1              (IRQ_ARMCTRL_START + INTERRUPT_DMA1)+#define IRQ_DMA2              (IRQ_ARMCTRL_START + INTERRUPT_DMA2)+#define IRQ_DMA3              (IRQ_ARMCTRL_START + INTERRUPT_DMA3)+#define IRQ_DMA4              (IRQ_ARMCTRL_START + INTERRUPT_DMA4)+#define IRQ_DMA5              (IRQ_ARMCTRL_START + INTERRUPT_DMA5)+#define IRQ_DMA6              (IRQ_ARMCTRL_START + INTERRUPT_DMA6)+#define IRQ_DMA7              (IRQ_ARMCTRL_START + INTERRUPT_DMA7)+#define IRQ_DMA8              (IRQ_ARMCTRL_START + INTERRUPT_DMA8)+#define IRQ_DMA9              (IRQ_ARMCTRL_START + INTERRUPT_DMA9)+#define IRQ_DMA10             (IRQ_ARMCTRL_START + INTERRUPT_DMA10)+#define IRQ_DMA11             (IRQ_ARMCTRL_START + INTERRUPT_DMA11)+#define IRQ_DMA12             (IRQ_ARMCTRL_START + INTERRUPT_DMA12)+#define IRQ_AUX               (IRQ_ARMCTRL_START + INTERRUPT_AUX)+#define IRQ_ARM               (IRQ_ARMCTRL_START + INTERRUPT_ARM)+#define IRQ_VPUDMA            (IRQ_ARMCTRL_START + INTERRUPT_VPUDMA)+#define IRQ_HOSTPORT          (IRQ_ARMCTRL_START + INTERRUPT_HOSTPORT)+#define IRQ_VIDEOSCALER       (IRQ_ARMCTRL_START + INTERRUPT_VIDEOSCALER)+#define IRQ_CCP2TX            (IRQ_ARMCTRL_START + INTERRUPT_CCP2TX)+#define IRQ_SDC               (IRQ_ARMCTRL_START + INTERRUPT_SDC)+#define IRQ_DSI0              (IRQ_ARMCTRL_START + INTERRUPT_DSI0)+#define IRQ_AVE               (IRQ_ARMCTRL_START + INTERRUPT_AVE)+#define IRQ_CAM0              (IRQ_ARMCTRL_START + INTERRUPT_CAM0)+#define IRQ_CAM1              (IRQ_ARMCTRL_START + INTERRUPT_CAM1)+#define IRQ_HDMI0             (IRQ_ARMCTRL_START + INTERRUPT_HDMI0)+#define IRQ_HDMI1             (IRQ_ARMCTRL_START + INTERRUPT_HDMI1)+#define IRQ_PIXELVALVE1       (IRQ_ARMCTRL_START + INTERRUPT_PIXELVALVE1)+#define IRQ_I2CSPISLV         (IRQ_ARMCTRL_START + INTERRUPT_I2CSPISLV)+#define IRQ_DSI1              (IRQ_ARMCTRL_START + INTERRUPT_DSI1)+#define IRQ_PWA0              (IRQ_ARMCTRL_START + INTERRUPT_PWA0)+#define IRQ_PWA1              (IRQ_ARMCTRL_START + INTERRUPT_PWA1)+#define IRQ_CPR               (IRQ_ARMCTRL_START + INTERRUPT_CPR)+#define IRQ_SMI               (IRQ_ARMCTRL_START + INTERRUPT_SMI)+#define IRQ_GPIO0             (IRQ_ARMCTRL_START + INTERRUPT_GPIO0)+#define IRQ_GPIO1             (IRQ_ARMCTRL_START + INTERRUPT_GPIO1)+#define IRQ_GPIO2             (IRQ_ARMCTRL_START + INTERRUPT_GPIO2)+#define IRQ_GPIO3             (IRQ_ARMCTRL_START + INTERRUPT_GPIO3)+#define IRQ_I2C               (IRQ_ARMCTRL_START + INTERRUPT_I2C)+#define IRQ_SPI               (IRQ_ARMCTRL_START + INTERRUPT_SPI)+#define IRQ_I2SPCM            (IRQ_ARMCTRL_START + INTERRUPT_I2SPCM)+#define IRQ_SDIO              (IRQ_ARMCTRL_START + INTERRUPT_SDIO)+#define IRQ_UART              (IRQ_ARMCTRL_START + INTERRUPT_UART)+#define IRQ_SLIMBUS           (IRQ_ARMCTRL_START + INTERRUPT_SLIMBUS)+#define IRQ_VEC               (IRQ_ARMCTRL_START + INTERRUPT_VEC)+#define IRQ_CPG               (IRQ_ARMCTRL_START + INTERRUPT_CPG)+#define IRQ_RNG               (IRQ_ARMCTRL_START + INTERRUPT_RNG)+#define IRQ_ARASANSDIO        (IRQ_ARMCTRL_START + INTERRUPT_ARASANSDIO)+#define IRQ_AVSPMON           (IRQ_ARMCTRL_START + INTERRUPT_AVSPMON)++#define IRQ_ARM_TIMER         (IRQ_ARMCTRL_START + INTERRUPT_ARM_TIMER)+#define IRQ_ARM_MAILBOX       (IRQ_ARMCTRL_START + INTERRUPT_ARM_MAILBOX)+#define IRQ_ARM_DOORBELL_0    (IRQ_ARMCTRL_START + INTERRUPT_ARM_DOORBELL_0)+#define IRQ_ARM_DOORBELL_1    (IRQ_ARMCTRL_START + INTERRUPT_ARM_DOORBELL_1)+#define IRQ_VPU0_HALTED       (IRQ_ARMCTRL_START + INTERRUPT_VPU0_HALTED)+#define IRQ_VPU1_HALTED       (IRQ_ARMCTRL_START + INTERRUPT_VPU1_HALTED)+#define IRQ_ILLEGAL_TYPE0     (IRQ_ARMCTRL_START + INTERRUPT_ILLEGAL_TYPE0)+#define IRQ_ILLEGAL_TYPE1     (IRQ_ARMCTRL_START + INTERRUPT_ILLEGAL_TYPE1)+#define IRQ_PENDING1          (IRQ_ARMCTRL_START + INTERRUPT_PENDING1)+#define IRQ_PENDING2          (IRQ_ARMCTRL_START + INTERRUPT_PENDING2)++#define FIQ_START             HARD_IRQS++/*+ *  FIQ interrupts definitions are the same as the INT definitions.+ */+#define FIQ_TIMER0            (FIQ_START+INTERRUPT_TIMER0)+#define FIQ_TIMER1            (FIQ_START+INTERRUPT_TIMER1)+#define FIQ_TIMER2            (FIQ_START+INTERRUPT_TIMER2)+#define FIQ_TIMER3            (FIQ_START+INTERRUPT_TIMER3)+#define FIQ_CODEC0            (FIQ_START+INTERRUPT_CODEC0)+#define FIQ_CODEC1            (FIQ_START+INTERRUPT_CODEC1)+#define FIQ_CODEC2            (FIQ_START+INTERRUPT_CODEC2)+#define FIQ_JPEG              (FIQ_START+INTERRUPT_JPEG)+#define FIQ_ISP               (FIQ_START+INTERRUPT_ISP)+#define FIQ_USB               (FIQ_START+INTERRUPT_USB)+#define FIQ_3D                (FIQ_START+INTERRUPT_3D)+#define FIQ_TRANSPOSER        (FIQ_START+INTERRUPT_TRANSPOSER)+#define FIQ_MULTICORESYNC0    (FIQ_START+INTERRUPT_MULTICORESYNC0)+#define FIQ_MULTICORESYNC1    (FIQ_START+INTERRUPT_MULTICORESYNC1)+#define FIQ_MULTICORESYNC2    (FIQ_START+INTERRUPT_MULTICORESYNC2)+#define FIQ_MULTICORESYNC3    (FIQ_START+INTERRUPT_MULTICORESYNC3)+#define FIQ_DMA0              (FIQ_START+INTERRUPT_DMA0)+#define FIQ_DMA1              (FIQ_START+INTERRUPT_DMA1)+#define FIQ_DMA2              (FIQ_START+INTERRUPT_DMA2)+#define FIQ_DMA3              (FIQ_START+INTERRUPT_DMA3)+#define FIQ_DMA4              (FIQ_START+INTERRUPT_DMA4)+#define FIQ_DMA5              (FIQ_START+INTERRUPT_DMA5)+#define FIQ_DMA6              (FIQ_START+INTERRUPT_DMA6)+#define FIQ_DMA7              (FIQ_START+INTERRUPT_DMA7)+#define FIQ_DMA8              (FIQ_START+INTERRUPT_DMA8)+#define FIQ_DMA9              (FIQ_START+INTERRUPT_DMA9)+#define FIQ_DMA10             (FIQ_START+INTERRUPT_DMA10)+#define FIQ_DMA11             (FIQ_START+INTERRUPT_DMA11)+#define FIQ_DMA12             (FIQ_START+INTERRUPT_DMA12)+#define FIQ_AUX               (FIQ_START+INTERRUPT_AUX)+#define FIQ_ARM               (FIQ_START+INTERRUPT_ARM)+#define FIQ_VPUDMA            (FIQ_START+INTERRUPT_VPUDMA)+#define FIQ_HOSTPORT          (FIQ_START+INTERRUPT_HOSTPORT)+#define FIQ_VIDEOSCALER       (FIQ_START+INTERRUPT_VIDEOSCALER)+#define FIQ_CCP2TX            (FIQ_START+INTERRUPT_CCP2TX)+#define FIQ_SDC               (FIQ_START+INTERRUPT_SDC)+#define FIQ_DSI0              (FIQ_START+INTERRUPT_DSI0)+#define FIQ_AVE               (FIQ_START+INTERRUPT_AVE)+#define FIQ_CAM0              (FIQ_START+INTERRUPT_CAM0)+#define FIQ_CAM1              (FIQ_START+INTERRUPT_CAM1)+#define FIQ_HDMI0             (FIQ_START+INTERRUPT_HDMI0)+#define FIQ_HDMI1             (FIQ_START+INTERRUPT_HDMI1)+#define FIQ_PIXELVALVE1       (FIQ_START+INTERRUPT_PIXELVALVE1)+#define FIQ_I2CSPISLV         (FIQ_START+INTERRUPT_I2CSPISLV)+#define FIQ_DSI1              (FIQ_START+INTERRUPT_DSI1)+#define FIQ_PWA0              (FIQ_START+INTERRUPT_PWA0)+#define FIQ_PWA1              (FIQ_START+INTERRUPT_PWA1)+#define FIQ_CPR               (FIQ_START+INTERRUPT_CPR)+#define FIQ_SMI               (FIQ_START+INTERRUPT_SMI)+#define FIQ_GPIO0             (FIQ_START+INTERRUPT_GPIO0)+#define FIQ_GPIO1             (FIQ_START+INTERRUPT_GPIO1)+#define FIQ_GPIO2             (FIQ_START+INTERRUPT_GPIO2)+#define FIQ_GPIO3             (FIQ_START+INTERRUPT_GPIO3)+#define FIQ_I2C               (FIQ_START+INTERRUPT_I2C)+#define FIQ_SPI               (FIQ_START+INTERRUPT_SPI)+#define FIQ_I2SPCM            (FIQ_START+INTERRUPT_I2SPCM)+#define FIQ_SDIO              (FIQ_START+INTERRUPT_SDIO)+#define FIQ_UART              (FIQ_START+INTERRUPT_UART)+#define FIQ_SLIMBUS           (FIQ_START+INTERRUPT_SLIMBUS)+#define FIQ_VEC               (FIQ_START+INTERRUPT_VEC)+#define FIQ_CPG               (FIQ_START+INTERRUPT_CPG)+#define FIQ_RNG               (FIQ_START+INTERRUPT_RNG)+#define FIQ_ARASANSDIO        (FIQ_START+INTERRUPT_ARASANSDIO)+#define FIQ_AVSPMON           (FIQ_START+INTERRUPT_AVSPMON)++#define FIQ_ARM_TIMER         (FIQ_START+INTERRUPT_ARM_TIMER)+#define FIQ_ARM_MAILBOX       (FIQ_START+INTERRUPT_ARM_MAILBOX)+#define FIQ_ARM_DOORBELL_0    (FIQ_START+INTERRUPT_ARM_DOORBELL_0)+#define FIQ_ARM_DOORBELL_1    (FIQ_START+INTERRUPT_ARM_DOORBELL_1)+#define FIQ_VPU0_HALTED       (FIQ_START+INTERRUPT_VPU0_HALTED)+#define FIQ_VPU1_HALTED       (FIQ_START+INTERRUPT_VPU1_HALTED)+#define FIQ_ILLEGAL_TYPE0     (FIQ_START+INTERRUPT_ILLEGAL_TYPE0)+#define FIQ_ILLEGAL_TYPE1     (FIQ_START+INTERRUPT_ILLEGAL_TYPE1)+#define FIQ_PENDING1          (FIQ_START+INTERRUPT_PENDING1)+#define FIQ_PENDING2          (FIQ_START+INTERRUPT_PENDING2)++#define GPIO_IRQ_START	      (HARD_IRQS + FIQ_IRQS)++#define HARD_IRQS	      (64 + 21)+#define FIQ_IRQS              (64 + 21)+#define GPIO_IRQS	      (32*5)++#define NR_IRQS		      HARD_IRQS+FIQ_IRQS+GPIO_IRQS+++#endif /* _BCM2708_IRQS_H_ */diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/memory.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/memory.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/memory.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/memory.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,57 @@+/*+ *  arch/arm/mach-bcm2708/include/mach/memory.h+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */+#ifndef __ASM_ARCH_MEMORY_H+#define __ASM_ARCH_MEMORY_H++/* Memory overview:++   [ARMcore] <--virtual addr-->+   [ARMmmu] <--physical addr-->+   [GERTmap] <--bus add-->+   [VCperiph]++*/++/*+ * Physical DRAM offset.+ */+#define PLAT_PHYS_OFFSET	UL(0x00000000)+#define VC_ARMMEM_OFFSET	UL(0x00000000)   /* offset in VC of ARM memory */++#ifdef CONFIG_BCM2708_NOL2CACHE+ #define _REAL_BUS_OFFSET UL(0xC0000000)   /* don't use L1 or L2 caches */+#else+ #define _REAL_BUS_OFFSET UL(0x40000000)   /* use L2 cache */+#endif++/* We're using the memory at 64M in the VideoCore for Linux - this adjustment+ * will provide the offset into this area as well as setting the bits that+ * stop the L1 and L2 cache from being used+ *+ * WARNING: this only works because the ARM is given memory at a fixed location+ *          (ARMMEM_OFFSET)+ */+#define BUS_OFFSET          (VC_ARMMEM_OFFSET + _REAL_BUS_OFFSET)+#define __virt_to_bus(x)    ((x) + (BUS_OFFSET - PAGE_OFFSET))+#define __bus_to_virt(x)    ((x) - (BUS_OFFSET - PAGE_OFFSET))+#define __pfn_to_bus(x)     (__pfn_to_phys(x) + (BUS_OFFSET - PLAT_PHYS_OFFSET))+#define __bus_to_pfn(x)     __phys_to_pfn((x) - (BUS_OFFSET - PLAT_PHYS_OFFSET))++#endifdiff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/platform.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/platform.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/platform.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/platform.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,226 @@+/*+ * arch/arm/mach-bcm2708/include/mach/platform.h+ *+ * Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */++#ifndef _BCM2708_PLATFORM_H+#define _BCM2708_PLATFORM_H+++/* macros to get at IO space when running virtually */+#define IO_ADDRESS(x)	(((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)++#define __io_address(n)     IOMEM(IO_ADDRESS(n))+++/*+ *  SDRAM+ */+#define BCM2708_SDRAM_BASE           0x00000000++/*+ *  Logic expansion modules+ *+ */+++/* ------------------------------------------------------------------------+ *  BCM2708 ARMCTRL Registers+ * ------------------------------------------------------------------------+ */++#define HW_REGISTER_RW(addr) (addr)+#define HW_REGISTER_RO(addr) (addr)++#include "arm_control.h"+#undef ARM_BASE++/*+ * Definitions and addresses for the ARM CONTROL logic+ * This file is manually generated.+ */++#define BCM2708_PERI_BASE        0x20000000+#define IC0_BASE                 (BCM2708_PERI_BASE + 0x2000)+#define ST_BASE                  (BCM2708_PERI_BASE + 0x3000)   /* System Timer */+#define MPHI_BASE		 (BCM2708_PERI_BASE + 0x6000)	/* Message -based Parallel Host Interface */+#define DMA_BASE		 (BCM2708_PERI_BASE + 0x7000)	/* DMA controller */+#define ARM_BASE                 (BCM2708_PERI_BASE + 0xB000)	 /* BCM2708 ARM control block */+#define PM_BASE			 (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */+#define RNG_BASE                 (BCM2708_PERI_BASE + 0x104000) /* Hardware RNG */+#define GPIO_BASE                (BCM2708_PERI_BASE + 0x200000) /* GPIO */+#define UART0_BASE               (BCM2708_PERI_BASE + 0x201000)	/* Uart 0 */+#define MMCI0_BASE               (BCM2708_PERI_BASE + 0x202000) /* MMC interface */+#define SPI0_BASE		 (BCM2708_PERI_BASE + 0x204000) /* SPI0 */+#define BSC0_BASE		 (BCM2708_PERI_BASE + 0x205000) /* BSC0 I2C/TWI */+#define UART1_BASE               (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */+#define EMMC_BASE                (BCM2708_PERI_BASE + 0x300000) /* eMMC interface */+#define SMI_BASE		 (BCM2708_PERI_BASE + 0x600000) /* SMI */+#define BSC1_BASE		 (BCM2708_PERI_BASE + 0x804000) /* BSC1 I2C/TWI */+#define USB_BASE                 (BCM2708_PERI_BASE + 0x980000) /* DTC_OTG USB controller */+#define MCORE_BASE               (BCM2708_PERI_BASE + 0x0000)   /* Fake frame buffer device (actually the multicore sync block*/++#define ARMCTRL_BASE             (ARM_BASE + 0x000)+#define ARMCTRL_IC_BASE          (ARM_BASE + 0x200)           /* ARM interrupt controller */+#define ARMCTRL_TIMER0_1_BASE    (ARM_BASE + 0x400)           /* Timer 0 and 1 */+#define ARMCTRL_0_SBM_BASE       (ARM_BASE + 0x800)           /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */+++/*+ * Interrupt assignments+ */++#define ARM_IRQ1_BASE                  0+#define INTERRUPT_TIMER0               (ARM_IRQ1_BASE + 0)+#define INTERRUPT_TIMER1               (ARM_IRQ1_BASE + 1)+#define INTERRUPT_TIMER2               (ARM_IRQ1_BASE + 2)+#define INTERRUPT_TIMER3               (ARM_IRQ1_BASE + 3)+#define INTERRUPT_CODEC0               (ARM_IRQ1_BASE + 4)+#define INTERRUPT_CODEC1               (ARM_IRQ1_BASE + 5)+#define INTERRUPT_CODEC2               (ARM_IRQ1_BASE + 6)+#define INTERRUPT_VC_JPEG              (ARM_IRQ1_BASE + 7)+#define INTERRUPT_ISP                  (ARM_IRQ1_BASE + 8)+#define INTERRUPT_VC_USB               (ARM_IRQ1_BASE + 9)+#define INTERRUPT_VC_3D                (ARM_IRQ1_BASE + 10)+#define INTERRUPT_TRANSPOSER           (ARM_IRQ1_BASE + 11)+#define INTERRUPT_MULTICORESYNC0       (ARM_IRQ1_BASE + 12)+#define INTERRUPT_MULTICORESYNC1       (ARM_IRQ1_BASE + 13)+#define INTERRUPT_MULTICORESYNC2       (ARM_IRQ1_BASE + 14)+#define INTERRUPT_MULTICORESYNC3       (ARM_IRQ1_BASE + 15)+#define INTERRUPT_DMA0                 (ARM_IRQ1_BASE + 16)+#define INTERRUPT_DMA1                 (ARM_IRQ1_BASE + 17)+#define INTERRUPT_VC_DMA2              (ARM_IRQ1_BASE + 18)+#define INTERRUPT_VC_DMA3              (ARM_IRQ1_BASE + 19)+#define INTERRUPT_DMA4                 (ARM_IRQ1_BASE + 20)+#define INTERRUPT_DMA5                 (ARM_IRQ1_BASE + 21)+#define INTERRUPT_DMA6                 (ARM_IRQ1_BASE + 22)+#define INTERRUPT_DMA7                 (ARM_IRQ1_BASE + 23)+#define INTERRUPT_DMA8                 (ARM_IRQ1_BASE + 24)+#define INTERRUPT_DMA9                 (ARM_IRQ1_BASE + 25)+#define INTERRUPT_DMA10                (ARM_IRQ1_BASE + 26)+#define INTERRUPT_DMA11                (ARM_IRQ1_BASE + 27)+#define INTERRUPT_DMA12                (ARM_IRQ1_BASE + 28)+#define INTERRUPT_AUX                (ARM_IRQ1_BASE + 29)+#define INTERRUPT_ARM                  (ARM_IRQ1_BASE + 30)+#define INTERRUPT_VPUDMA               (ARM_IRQ1_BASE + 31)++#define ARM_IRQ2_BASE                  32+#define INTERRUPT_HOSTPORT             (ARM_IRQ2_BASE + 0)+#define INTERRUPT_VIDEOSCALER          (ARM_IRQ2_BASE + 1)+#define INTERRUPT_CCP2TX               (ARM_IRQ2_BASE + 2)+#define INTERRUPT_SDC                  (ARM_IRQ2_BASE + 3)+#define INTERRUPT_DSI0                 (ARM_IRQ2_BASE + 4)+#define INTERRUPT_AVE                  (ARM_IRQ2_BASE + 5)+#define INTERRUPT_CAM0                 (ARM_IRQ2_BASE + 6)+#define INTERRUPT_CAM1                 (ARM_IRQ2_BASE + 7)+#define INTERRUPT_HDMI0                (ARM_IRQ2_BASE + 8)+#define INTERRUPT_HDMI1                (ARM_IRQ2_BASE + 9)+#define INTERRUPT_PIXELVALVE1          (ARM_IRQ2_BASE + 10)+#define INTERRUPT_I2CSPISLV            (ARM_IRQ2_BASE + 11)+#define INTERRUPT_DSI1                 (ARM_IRQ2_BASE + 12)+#define INTERRUPT_PWA0                 (ARM_IRQ2_BASE + 13)+#define INTERRUPT_PWA1                 (ARM_IRQ2_BASE + 14)+#define INTERRUPT_CPR                  (ARM_IRQ2_BASE + 15)+#define INTERRUPT_SMI                  (ARM_IRQ2_BASE + 16)+#define INTERRUPT_GPIO0                (ARM_IRQ2_BASE + 17)+#define INTERRUPT_GPIO1                (ARM_IRQ2_BASE + 18)+#define INTERRUPT_GPIO2                (ARM_IRQ2_BASE + 19)+#define INTERRUPT_GPIO3                (ARM_IRQ2_BASE + 20)+#define INTERRUPT_VC_I2C               (ARM_IRQ2_BASE + 21)+#define INTERRUPT_VC_SPI               (ARM_IRQ2_BASE + 22)+#define INTERRUPT_VC_I2SPCM            (ARM_IRQ2_BASE + 23)+#define INTERRUPT_VC_SDIO              (ARM_IRQ2_BASE + 24)+#define INTERRUPT_VC_UART              (ARM_IRQ2_BASE + 25)+#define INTERRUPT_SLIMBUS              (ARM_IRQ2_BASE + 26)+#define INTERRUPT_VEC                  (ARM_IRQ2_BASE + 27)+#define INTERRUPT_CPG                  (ARM_IRQ2_BASE + 28)+#define INTERRUPT_RNG                  (ARM_IRQ2_BASE + 29)+#define INTERRUPT_VC_ARASANSDIO        (ARM_IRQ2_BASE + 30)+#define INTERRUPT_AVSPMON              (ARM_IRQ2_BASE + 31)++#define ARM_IRQ0_BASE                  64+#define INTERRUPT_ARM_TIMER            (ARM_IRQ0_BASE + 0)+#define INTERRUPT_ARM_MAILBOX          (ARM_IRQ0_BASE + 1)+#define INTERRUPT_ARM_DOORBELL_0       (ARM_IRQ0_BASE + 2)+#define INTERRUPT_ARM_DOORBELL_1       (ARM_IRQ0_BASE + 3)+#define INTERRUPT_VPU0_HALTED          (ARM_IRQ0_BASE + 4)+#define INTERRUPT_VPU1_HALTED          (ARM_IRQ0_BASE + 5)+#define INTERRUPT_ILLEGAL_TYPE0        (ARM_IRQ0_BASE + 6)+#define INTERRUPT_ILLEGAL_TYPE1        (ARM_IRQ0_BASE + 7)+#define INTERRUPT_PENDING1             (ARM_IRQ0_BASE + 8)+#define INTERRUPT_PENDING2             (ARM_IRQ0_BASE + 9)+#define INTERRUPT_JPEG                 (ARM_IRQ0_BASE + 10)+#define INTERRUPT_USB                  (ARM_IRQ0_BASE + 11)+#define INTERRUPT_3D                   (ARM_IRQ0_BASE + 12)+#define INTERRUPT_DMA2                 (ARM_IRQ0_BASE + 13)+#define INTERRUPT_DMA3                 (ARM_IRQ0_BASE + 14)+#define INTERRUPT_I2C                  (ARM_IRQ0_BASE + 15)+#define INTERRUPT_SPI                  (ARM_IRQ0_BASE + 16)+#define INTERRUPT_I2SPCM               (ARM_IRQ0_BASE + 17)+#define INTERRUPT_SDIO                 (ARM_IRQ0_BASE + 18)+#define INTERRUPT_UART                 (ARM_IRQ0_BASE + 19)+#define INTERRUPT_ARASANSDIO           (ARM_IRQ0_BASE + 20)++#define MAXIRQNUM                      (32 + 32 + 20)+#define MAXFIQNUM                      (32 + 32 + 20)++#define MAX_TIMER                       2+#define MAX_PERIOD                      699050+#define TICKS_PER_uSEC                  1++/*+ *  These are useconds NOT ticks.+ *+ */+#define mSEC_1                          1000+#define mSEC_5                          (mSEC_1 * 5)+#define mSEC_10                         (mSEC_1 * 10)+#define mSEC_25                         (mSEC_1 * 25)+#define SEC_1                           (mSEC_1 * 1000)++/*+ * Watchdog+ */+#define PM_RSTC			       (PM_BASE+0x1c)+#define PM_RSTS			       (PM_BASE+0x20)+#define PM_WDOG			       (PM_BASE+0x24)++#define PM_WDOG_RESET                                         0000000000+#define PM_PASSWORD		       0x5a000000+#define PM_WDOG_TIME_SET	       0x000fffff+#define PM_RSTC_WRCFG_CLR              0xffffffcf+#define PM_RSTC_WRCFG_SET              0x00000030+#define PM_RSTC_WRCFG_FULL_RESET       0x00000020+#define PM_RSTC_RESET                  0x00000102++#define PM_RSTS_HADPOR_SET                                 0x00001000+#define PM_RSTS_HADSRH_SET                                 0x00000400+#define PM_RSTS_HADSRF_SET                                 0x00000200+#define PM_RSTS_HADSRQ_SET                                 0x00000100+#define PM_RSTS_HADWRH_SET                                 0x00000040+#define PM_RSTS_HADWRF_SET                                 0x00000020+#define PM_RSTS_HADWRQ_SET                                 0x00000010+#define PM_RSTS_HADDRH_SET                                 0x00000004+#define PM_RSTS_HADDRF_SET                                 0x00000002+#define PM_RSTS_HADDRQ_SET                                 0x00000001++#define UART0_CLOCK      3000000++#endif++/* END */diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/power.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/power.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/power.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/power.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,26 @@+/*+ *  linux/arch/arm/mach-bcm2708/power.h+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License version 2 as+ * published by the Free Software Foundation.+ *+ * This device provides a shared mechanism for controlling the power to+ * VideoCore subsystems.+ */++#ifndef _MACH_BCM2708_POWER_H+#define _MACH_BCM2708_POWER_H++#include <linux/types.h>+#include <mach/arm_power.h>++typedef unsigned int BCM_POWER_HANDLE_T;++extern int bcm_power_open(BCM_POWER_HANDLE_T *handle);+extern int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request);+extern int bcm_power_close(BCM_POWER_HANDLE_T handle);++#endifdiff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/system.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/system.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/system.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/system.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,38 @@+/*+ *  arch/arm/mach-bcm2708/include/mach/system.h+ *+ *  Copyright (C) 2010 Broadcom+ *  Copyright (C) 2003 ARM Limited+ *  Copyright (C) 2000 Deep Blue Solutions Ltd+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */+#ifndef __ASM_ARCH_SYSTEM_H+#define __ASM_ARCH_SYSTEM_H++#include <linux/io.h>+#include <mach/hardware.h>+#include <mach/platform.h>++static inline void arch_idle(void)+{+	/*+	 * This should do all the clock switching+	 * and wait for interrupt tricks+	 */+	cpu_do_idle();+}++#endifdiff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/timex.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/timex.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/timex.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/timex.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,23 @@+/*+ *  arch/arm/mach-bcm2708/include/mach/timex.h+ *+ *  BCM2708 sysem clock frequency+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */++#define CLOCK_TICK_RATE		(1000000)diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/uncompress.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/uncompress.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/uncompress.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/uncompress.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,84 @@+/*+ *  arch/arm/mach-bcn2708/include/mach/uncompress.h+ *+ *  Copyright (C) 2010 Broadcom+ *  Copyright (C) 2003 ARM Limited+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */++#include <linux/io.h>+#include <linux/amba/serial.h>+#include <mach/hardware.h>++#define UART_BAUD 115200++#define BCM2708_UART_DR   __io(UART0_BASE + UART01x_DR)+#define BCM2708_UART_FR   __io(UART0_BASE + UART01x_FR)+#define BCM2708_UART_IBRD __io(UART0_BASE + UART011_IBRD)+#define BCM2708_UART_FBRD __io(UART0_BASE + UART011_FBRD)+#define BCM2708_UART_LCRH __io(UART0_BASE + UART011_LCRH)+#define BCM2708_UART_CR   __io(UART0_BASE + UART011_CR)++/*+ * This does not append a newline+ */+static inline void putc(int c)+{+	while (__raw_readl(BCM2708_UART_FR) & UART01x_FR_TXFF)+		barrier();++	__raw_writel(c, BCM2708_UART_DR);+}++static inline void flush(void)+{+	int fr;++	do {+		fr = __raw_readl(BCM2708_UART_FR);+		barrier();+	} while ((fr & (UART011_FR_TXFE | UART01x_FR_BUSY)) != UART011_FR_TXFE);+}++static inline void arch_decomp_setup(void)+{+	int temp, div, rem, frac;++	temp = 16 * UART_BAUD;+	div = UART0_CLOCK / temp;+	rem = UART0_CLOCK % temp;+	temp = (8 * rem) / UART_BAUD;+	frac = (temp >> 1) + (temp & 1);++	/* Make sure the UART is disabled before we start */+	__raw_writel(0, BCM2708_UART_CR);++	/* Set the baud rate */+	__raw_writel(div, BCM2708_UART_IBRD);+	__raw_writel(frac, BCM2708_UART_FBRD);++	/* Set the UART to 8n1, FIFO enabled */+	__raw_writel(UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN, BCM2708_UART_LCRH);++	/* Enable the UART */+	__raw_writel(UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE,+			BCM2708_UART_CR);+}++/*+ * nothing to do+ */+#define arch_decomp_wdog()diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/vcio.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/vcio.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/vcio.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/vcio.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,141 @@+/*+ *  arch/arm/mach-bcm2708/include/mach/vcio.h+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */+#ifndef _MACH_BCM2708_VCIO_H+#define _MACH_BCM2708_VCIO_H++/* Routines to handle I/O via the VideoCore "ARM control" registers+ * (semaphores, doorbells, mailboxes)+ */++#define BCM_VCIO_DRIVER_NAME "bcm2708_vcio"++/* Constants shared with the ARM identifying separate mailbox channels */+#define MBOX_CHAN_POWER    0 /* for use by the power management interface */+#define MBOX_CHAN_FB       1 /* for use by the frame buffer */+#define MBOX_CHAN_VCHIQ    3 /* for use by the VCHIQ interface */+#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */+#define MBOX_CHAN_COUNT    9++/* Mailbox property tags */+enum {+	VCMSG_PROPERTY_END               = 0x00000000,+	VCMSG_GET_FIRMWARE_REVISION      = 0x00000001,+	VCMSG_GET_BOARD_MODEL            = 0x00010001,+	VCMSG_GET_BOARD_REVISION	 = 0x00020002,+	VCMSG_GET_BOARD_MAC_ADDRESS	 = 0x00020003,+	VCMSG_GET_BOARD_SERIAL		 = 0x00020004,+	VCMSG_GET_ARM_MEMORY		 = 0x00020005,+	VCMSG_GET_VC_MEMORY		 = 0x00020006,+	VCMSG_GET_CLOCKS		 = 0x00020007,+	VCMSG_GET_COMMAND_LINE           = 0x00050001,+	VCMSG_GET_DMA_CHANNELS           = 0x00060001,+	VCMSG_GET_POWER_STATE            = 0x00020001,+	VCMSG_GET_TIMING		 = 0x00020002,+	VCMSG_SET_POWER_STATE            = 0x00028001,+	VCMSG_GET_CLOCK_STATE            = 0x00030001,+	VCMSG_SET_CLOCK_STATE            = 0x00038001,+	VCMSG_GET_CLOCK_RATE             = 0x00030002,+	VCMSG_SET_CLOCK_RATE             = 0x00038002,+	VCMSG_GET_VOLTAGE                = 0x00030003,+	VCMSG_SET_VOLTAGE                = 0x00038003,+	VCMSG_GET_MAX_CLOCK              = 0x00030004,+	VCMSG_GET_MAX_VOLTAGE            = 0x00030005,+	VCMSG_GET_TEMPERATURE            = 0x00030006,+	VCMSG_GET_MIN_CLOCK              = 0x00030007,+	VCMSG_GET_MIN_VOLTAGE            = 0x00030008,+	VCMSG_GET_TURBO                  = 0x00030009,+	VCMSG_SET_TURBO                  = 0x00038009,+	VCMSG_SET_ALLOCATE_BUFFER        = 0x00040001,+	VCMSG_SET_RELEASE_BUFFER         = 0x00048001,+	VCMSG_SET_BLANK_SCREEN           = 0x00040002,+	VCMSG_TST_BLANK_SCREEN           = 0x00044002,+	VCMSG_GET_PHYSICAL_WIDTH_HEIGHT  = 0x00040003,+	VCMSG_TST_PHYSICAL_WIDTH_HEIGHT  = 0x00044003,+	VCMSG_SET_PHYSICAL_WIDTH_HEIGHT  = 0x00048003,+	VCMSG_GET_VIRTUAL_WIDTH_HEIGHT   = 0x00040004,+	VCMSG_TST_VIRTUAL_WIDTH_HEIGHT   = 0x00044004,+	VCMSG_SET_VIRTUAL_WIDTH_HEIGHT   = 0x00048004,+	VCMSG_GET_DEPTH                  = 0x00040005,+	VCMSG_TST_DEPTH                  = 0x00044005,+	VCMSG_SET_DEPTH                  = 0x00048005,+	VCMSG_GET_PIXEL_ORDER            = 0x00040006,+	VCMSG_TST_PIXEL_ORDER            = 0x00044006,+	VCMSG_SET_PIXEL_ORDER            = 0x00048006,+	VCMSG_GET_ALPHA_MODE             = 0x00040007,+	VCMSG_TST_ALPHA_MODE             = 0x00044007,+	VCMSG_SET_ALPHA_MODE             = 0x00048007,+	VCMSG_GET_PITCH                  = 0x00040008,+	VCMSG_TST_PITCH                  = 0x00044008,+	VCMSG_SET_PITCH                  = 0x00048008,+	VCMSG_GET_VIRTUAL_OFFSET         = 0x00040009,+	VCMSG_TST_VIRTUAL_OFFSET         = 0x00044009,+	VCMSG_SET_VIRTUAL_OFFSET         = 0x00048009,+	VCMSG_GET_OVERSCAN               = 0x0004000a,+	VCMSG_TST_OVERSCAN               = 0x0004400a,+	VCMSG_SET_OVERSCAN               = 0x0004800a,+	VCMSG_GET_PALETTE                = 0x0004000b,+	VCMSG_TST_PALETTE                = 0x0004400b,+	VCMSG_SET_PALETTE                = 0x0004800b,+	VCMSG_GET_LAYER                  = 0x0004000c,+	VCMSG_TST_LAYER                  = 0x0004400c,+	VCMSG_SET_LAYER                  = 0x0004800c,+	VCMSG_GET_TRANSFORM              = 0x0004000d,+	VCMSG_TST_TRANSFORM              = 0x0004400d,+	VCMSG_SET_TRANSFORM              = 0x0004800d,+};++extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28);+extern int /*rc*/ bcm_mailbox_write(unsigned chan, uint32_t data28);+extern int /*rc*/ bcm_mailbox_property(void *data, int size);++#include <linux/ioctl.h>++/*+ * The major device number. We can't rely on dynamic+ * registration any more, because ioctls need to know+ * it.+ */+#define MAJOR_NUM 100++/*+ * Set the message of the device driver+ */+#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *)+/*+ * _IOWR means that we're creating an ioctl command+ * number for passing information from a user process+ * to the kernel module and from the kernel module to user process+ *+ * The first arguments, MAJOR_NUM, is the major device+ * number we're using.+ *+ * The second argument is the number of the command+ * (there could be several with different meanings).+ *+ * The third argument is the type we want to get from+ * the process to the kernel.+ */++/*+ * The name of the device file+ */+#define DEVICE_FILE_NAME "char_dev"++#endifdiff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/vc_mem.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/vc_mem.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/vc_mem.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/vc_mem.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,35 @@+/*****************************************************************************+* Copyright 2010 - 2011 Broadcom Corporation.  All rights reserved.+*+* Unless you and Broadcom execute a separate written software license+* agreement governing use of this software, this software is licensed to you+* under the terms of the GNU General Public License version 2, available at+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").+*+* Notwithstanding the above, under no circumstances may you combine this+* software in any way with any other Broadcom software provided under a+* license other than the GPL, without Broadcom's express prior written+* consent.+*****************************************************************************/++#if !defined( VC_MEM_H )+#define VC_MEM_H++#include <linux/ioctl.h>++#define VC_MEM_IOC_MAGIC  'v'++#define VC_MEM_IOC_MEM_PHYS_ADDR    _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long )+#define VC_MEM_IOC_MEM_SIZE         _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int )+#define VC_MEM_IOC_MEM_BASE         _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int )+#define VC_MEM_IOC_MEM_LOAD         _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int )++#if defined( __KERNEL__ )+#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF++extern unsigned long mm_vc_mem_phys_addr;+extern unsigned int  mm_vc_mem_size;+extern int vc_mem_get_current_size( void );+#endif++#endif  /* VC_MEM_H */diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/vc_support.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/vc_support.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/vc_support.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/vc_support.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,69 @@+#ifndef _VC_SUPPORT_H_+#define _VC_SUPPORT_H_++/*+ * vc_support.h+ *+ *  Created on: 25 Nov 2012+ *      Author: Simon+ */++enum {+/*+      If a MEM_HANDLE_T is discardable, the memory manager may resize it to size+      0 at any time when it is not locked or retained.+   */+   MEM_FLAG_DISCARDABLE = 1 << 0,++   /*+      If a MEM_HANDLE_T is allocating (or normal), its block of memory will be+      accessed in an allocating fashion through the cache.+   */+   MEM_FLAG_NORMAL = 0 << 2,+   MEM_FLAG_ALLOCATING = MEM_FLAG_NORMAL,++   /*+      If a MEM_HANDLE_T is direct, its block of memory will be accessed+      directly, bypassing the cache.+   */+   MEM_FLAG_DIRECT = 1 << 2,++   /*+      If a MEM_HANDLE_T is coherent, its block of memory will be accessed in a+      non-allocating fashion through the cache.+   */+   MEM_FLAG_COHERENT = 2 << 2,++   /*+      If a MEM_HANDLE_T is L1-nonallocating, its block of memory will be accessed by+      the VPU in a fashion which is allocating in L2, but only coherent in L1.+   */+   MEM_FLAG_L1_NONALLOCATING = (MEM_FLAG_DIRECT | MEM_FLAG_COHERENT),++   /*+      If a MEM_HANDLE_T is zero'd, its contents are set to 0 rather than+      MEM_HANDLE_INVALID on allocation and resize up.+   */+   MEM_FLAG_ZERO = 1 << 4,++   /*+      If a MEM_HANDLE_T is uninitialised, it will not be reset to a defined value+      (either zero, or all 1's) on allocation.+    */+   MEM_FLAG_NO_INIT = 1 << 5,++   /*+      Hints.+   */+   MEM_FLAG_HINT_PERMALOCK = 1 << 6, /* Likely to be locked for long periods of time. */+};++unsigned int AllocateVcMemory(unsigned int *pHandle, unsigned int size, unsigned int alignment, unsigned int flags);+unsigned int ReleaseVcMemory(unsigned int handle);+unsigned int LockVcMemory(unsigned int *pBusAddress, unsigned int handle);+unsigned int UnlockVcMemory(unsigned int handle);++unsigned int ExecuteVcCode(unsigned int code,+		unsigned int r0, unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int r5);++#endifdiff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/vmalloc.h linux-3.11.10/arch/arm/mach-bcm2708/include/mach/vmalloc.h--- linux-3.11.10.orig/arch/arm/mach-bcm2708/include/mach/vmalloc.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/include/mach/vmalloc.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,20 @@+/*+ *  arch/arm/mach-bcm2708/include/mach/vmalloc.h+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */+#define VMALLOC_END		(0xe8000000)diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/Kconfig linux-3.11.10/arch/arm/mach-bcm2708/Kconfig--- linux-3.11.10.orig/arch/arm/mach-bcm2708/Kconfig	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/Kconfig	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,48 @@+menu "Broadcom BCM2708 Implementations"+	depends on ARCH_BCM2708++config MACH_BCM2708+	bool "Broadcom BCM2708 Development Platform"+	select NEED_MACH_MEMORY_H+	select NEED_MACH_IO_H+	select CPU_V6+	help+	  Include support for the Broadcom(R) BCM2708 platform.++config BCM2708_GPIO+	bool "BCM2708 gpio support"+	depends on MACH_BCM2708+	select ARCH_REQUIRE_GPIOLIB+        default y+	help+	  Include support for the Broadcom(R) BCM2708 gpio.++config BCM2708_VCMEM+	bool "Videocore Memory"+	depends on MACH_BCM2708+        default y+        help+          Helper for videocore memory access and total size allocation.++config BCM2708_NOL2CACHE+	bool "Videocore L2 cache disable"+	depends on MACH_BCM2708+        default n+        help+          Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt.++config BCM2708_DMAER+	tristate "BCM2708 DMA helper"+	depends on MACH_BCM2708+        default n+        help+          Enable DMA helper for accelerating X composition++config BCM2708_SPIDEV+	bool "Bind spidev to SPI0 master"+	depends on MACH_BCM2708+	depends on SPI+        default y+		help+			Binds spidev driver to the SPI0 master+endmenudiff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/Makefile linux-3.11.10/arch/arm/mach-bcm2708/Makefile--- linux-3.11.10.orig/arch/arm/mach-bcm2708/Makefile	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/Makefile	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,10 @@+#+# Makefile for the linux kernel.+#++obj-$(CONFIG_MACH_BCM2708) 	+= clock.o bcm2708.o armctrl.o vcio.o power.o dma.o+obj-$(CONFIG_BCM2708_GPIO)	+= bcm2708_gpio.o+obj-$(CONFIG_BCM2708_VCMEM)	+= vc_mem.o++obj-$(CONFIG_BCM2708_DMAER)	+= dmaer_master.o+dmaer_master-objs		:= dmaer.o vc_support.odiff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/Makefile.boot linux-3.11.10/arch/arm/mach-bcm2708/Makefile.boot--- linux-3.11.10.orig/arch/arm/mach-bcm2708/Makefile.boot	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/Makefile.boot	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,3 @@+   zreladdr-y	:= 0x00008000+params_phys-y	:= 0x00000100+initrd_phys-y	:= 0x00800000diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/power.c linux-3.11.10/arch/arm/mach-bcm2708/power.c--- linux-3.11.10.orig/arch/arm/mach-bcm2708/power.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/power.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,194 @@+/*+ *	 linux/arch/arm/mach-bcm2708/power.c+ *+ *	 Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License version 2 as+ * published by the Free Software Foundation.+ *+ * This device provides a shared mechanism for controlling the power to+ * VideoCore subsystems.+ */++#include <linux/module.h>+#include <linux/semaphore.h>+#include <linux/bug.h>+#include <mach/power.h>+#include <mach/vcio.h>+#include <mach/arm_power.h>++#define DRIVER_NAME "bcm2708_power"++#define BCM_POWER_MAXCLIENTS 4+#define BCM_POWER_NOCLIENT (1<<31)++/* Some drivers expect there devices to be permanently powered */+#define BCM_POWER_ALWAYS_ON (BCM_POWER_USB)++#if 1+#define DPRINTK printk+#else+#define DPRINTK if (0) printk+#endif++struct state_struct {+	uint32_t global_request;+	uint32_t client_request[BCM_POWER_MAXCLIENTS];+	struct semaphore client_mutex;+	struct semaphore mutex;+} g_state;++int bcm_power_open(BCM_POWER_HANDLE_T *handle)+{+	BCM_POWER_HANDLE_T i;+	int ret = -EBUSY;++	down(&g_state.client_mutex);++	for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) {+		if (g_state.client_request[i] == BCM_POWER_NOCLIENT) {+			g_state.client_request[i] = BCM_POWER_NONE;+			*handle = i;+			ret = 0;+			break;+		}+	}++	up(&g_state.client_mutex);++	DPRINTK("bcm_power_open() -> %d\n", *handle);++	return ret;+}+EXPORT_SYMBOL_GPL(bcm_power_open);++int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request)+{+	int rc = 0;++	DPRINTK("bcm_power_request(%d, %x)\n", handle, request);++	if ((handle < BCM_POWER_MAXCLIENTS) &&+	    (g_state.client_request[handle] != BCM_POWER_NOCLIENT)) {+		if (down_interruptible(&g_state.mutex) != 0) {+			DPRINTK("bcm_power_request -> interrupted\n");+			return -EINTR;+		}++		if (request != g_state.client_request[handle]) {+			uint32_t others_request = 0;+			uint32_t global_request;+			BCM_POWER_HANDLE_T i;++			for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) {+				if (i != handle)+					others_request |=+					    g_state.client_request[i];+			}+			others_request &= ~BCM_POWER_NOCLIENT;++			global_request = request | others_request;+			if (global_request != g_state.global_request) {+				uint32_t actual;++				/* Send a request to VideoCore */+				bcm_mailbox_write(MBOX_CHAN_POWER,+						  global_request << 4);++				/* Wait for a response during power-up */+				if (global_request & ~g_state.global_request) {+					rc = bcm_mailbox_read(MBOX_CHAN_POWER,+							      &actual);+					DPRINTK+					    ("bcm_mailbox_read -> %08x, %d\n",+					     actual, rc);+					actual >>= 4;+				} else {+					rc = 0;+					actual = global_request;+				}++				if (rc == 0) {+					if (actual != global_request) {+						printk(KERN_ERR+						     "%s: prev global %x, new global %x, actual %x, request %x, others_request %x\n",+						     __func__,+						     g_state.global_request,+						     global_request, actual, request, others_request);+						/* A failure */+						BUG_ON((others_request & actual)+						       != others_request);+						request &= actual;+						rc = -EIO;+					}++					g_state.global_request = actual;+					g_state.client_request[handle] =+					    request;+				}+			}+		}+		up(&g_state.mutex);+	} else {+		rc = -EINVAL;+	}+	DPRINTK("bcm_power_request -> %d\n", rc);+	return rc;+}+EXPORT_SYMBOL_GPL(bcm_power_request);++int bcm_power_close(BCM_POWER_HANDLE_T handle)+{+	int rc;++	DPRINTK("bcm_power_close(%d)\n", handle);++	rc = bcm_power_request(handle, BCM_POWER_NONE);+	if (rc == 0)+		g_state.client_request[handle] = BCM_POWER_NOCLIENT;++	return rc;+}+EXPORT_SYMBOL_GPL(bcm_power_close);++static int __init bcm_power_init(void)+{+#if defined(BCM_POWER_ALWAYS_ON)+	BCM_POWER_HANDLE_T always_on_handle;+#endif+	int rc = 0;+	int i;++	printk(KERN_INFO "bcm_power: Broadcom power driver\n");+	bcm_mailbox_write(MBOX_CHAN_POWER, 0);++	for (i = 0; i < BCM_POWER_MAXCLIENTS; i++)+		g_state.client_request[i] = BCM_POWER_NOCLIENT;++	sema_init(&g_state.client_mutex, 1);+	sema_init(&g_state.mutex, 1);++	g_state.global_request = 0;++#if defined(BCM_POWER_ALWAYS_ON)+	if (BCM_POWER_ALWAYS_ON) {+		bcm_power_open(&always_on_handle);+		bcm_power_request(always_on_handle, BCM_POWER_ALWAYS_ON);+	}+#endif++	return rc;+}++static void __exit bcm_power_exit(void)+{+	bcm_mailbox_write(MBOX_CHAN_POWER, 0);+}++arch_initcall(bcm_power_init);	/* Initialize early */+module_exit(bcm_power_exit);++MODULE_AUTHOR("Phil Elwell");+MODULE_DESCRIPTION("Interface to BCM2708 power management");+MODULE_LICENSE("GPL");diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/vcio.c linux-3.11.10/arch/arm/mach-bcm2708/vcio.c--- linux-3.11.10.orig/arch/arm/mach-bcm2708/vcio.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/vcio.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,474 @@+/*+ *  linux/arch/arm/mach-bcm2708/vcio.c+ *+ *  Copyright (C) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License version 2 as+ * published by the Free Software Foundation.+ *+ * This device provides a shared mechanism for writing to the mailboxes,+ * semaphores, doorbells etc. that are shared between the ARM and the+ * VideoCore processor+ */++#if defined(CONFIG_SERIAL_BCM_MBOX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)+#define SUPPORT_SYSRQ+#endif++#include <linux/module.h>+#include <linux/console.h>+#include <linux/serial_core.h>+#include <linux/serial.h>+#include <linux/errno.h>+#include <linux/device.h>+#include <linux/init.h>+#include <linux/mm.h>+#include <linux/dma-mapping.h>+#include <linux/platform_device.h>+#include <linux/sysrq.h>+#include <linux/delay.h>+#include <linux/slab.h>+#include <linux/interrupt.h>+#include <linux/irq.h>++#include <linux/io.h>++#include <mach/vcio.h>+#include <mach/platform.h>++#include <asm/uaccess.h>+++#define DRIVER_NAME BCM_VCIO_DRIVER_NAME++/* ----------------------------------------------------------------------+ *	Mailbox+ * -------------------------------------------------------------------- */++/* offsets from a mail box base address */+#define MAIL_WRT	0x00	/* write - and next 4 words */+#define MAIL_RD		0x00	/* read - and next 4 words */+#define MAIL_POL	0x10	/* read without popping the fifo */+#define MAIL_SND	0x14	/* sender ID (bottom two bits) */+#define MAIL_STA	0x18	/* status */+#define MAIL_CNF	0x1C	/* configuration */++#define MBOX_MSG(chan, data28)		(((data28) & ~0xf) | ((chan) & 0xf))+#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf))+#define MBOX_CHAN(msg)			((msg) & 0xf)+#define MBOX_DATA28(msg)		((msg) & ~0xf)+#define MBOX_DATA28_LSB(msg)		(((uint32_t)msg) >> 4)++#define MBOX_MAGIC 0xd0d0c0de++struct vc_mailbox {+	struct device *dev;	/* parent device */+	void __iomem *status;+	void __iomem *config;+	void __iomem *read;+	void __iomem *write;+	uint32_t msg[MBOX_CHAN_COUNT];+	struct semaphore sema[MBOX_CHAN_COUNT];+	uint32_t magic;+};++static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev,+		      uint32_t addr_mbox)+{+	int i;++	mbox_out->dev = dev;+	mbox_out->status = __io_address(addr_mbox + MAIL_STA);+	mbox_out->config = __io_address(addr_mbox + MAIL_CNF);+	mbox_out->read = __io_address(addr_mbox + MAIL_RD);+	/* Write to the other mailbox */+	mbox_out->write =+	    __io_address((addr_mbox ^ ARM_0_MAIL0_WRT ^ ARM_0_MAIL1_WRT) ++			 MAIL_WRT);++	for (i = 0; i < MBOX_CHAN_COUNT; i++) {+		mbox_out->msg[i] = 0;+		sema_init(&mbox_out->sema[i], 0);+	}++	/* Enable the interrupt on data reception */+	writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->config);++	mbox_out->magic = MBOX_MAGIC;+}++static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28)+{+	int rc;++	if (mbox->magic != MBOX_MAGIC)+		rc = -EINVAL;+	else {+		/* wait for the mailbox FIFO to have some space in it */+		while (0 != (readl(mbox->status) & ARM_MS_FULL))+			cpu_relax();++		writel(MBOX_MSG(chan, data28), mbox->write);+		rc = 0;+	}+	return rc;+}++static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28)+{+	int rc;++	if (mbox->magic != MBOX_MAGIC)+		rc = -EINVAL;+	else {+		down(&mbox->sema[chan]);+		*data28 = MBOX_DATA28(mbox->msg[chan]);+		mbox->msg[chan] = 0;+		rc = 0;+	}+	return rc;+}++static irqreturn_t mbox_irq(int irq, void *dev_id)+{+	/* wait for the mailbox FIFO to have some data in it */+	struct vc_mailbox *mbox = (struct vc_mailbox *) dev_id;+	int status = readl(mbox->status);+	int ret = IRQ_NONE;++	while (!(status & ARM_MS_EMPTY)) {+		uint32_t msg = readl(mbox->read);+		int chan = MBOX_CHAN(msg);+		if (chan < MBOX_CHAN_COUNT) {+			if (mbox->msg[chan]) {+				/* Overflow */+				printk(KERN_ERR DRIVER_NAME+				       ": mbox chan %d overflow - drop %08x\n",+				       chan, msg);+			} else {+				mbox->msg[chan] = (msg | 0xf);+				up(&mbox->sema[chan]);+			}+		} else {+			printk(KERN_ERR DRIVER_NAME+			       ": invalid channel selector (msg %08x)\n", msg);+		}+		ret = IRQ_HANDLED;+		status = readl(mbox->status);+	}+	return ret;+}++static struct irqaction mbox_irqaction = {+	.name = "ARM Mailbox IRQ",+	.flags = IRQF_DISABLED | IRQF_IRQPOLL,+	.handler = mbox_irq,+};++/* ----------------------------------------------------------------------+ *	Mailbox Methods+ * -------------------------------------------------------------------- */++static struct device *mbox_dev;	/* we assume there's only one! */++static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28)+{+	int rc;++	struct vc_mailbox *mailbox = dev_get_drvdata(dev);+	device_lock(dev);+	rc = mbox_write(mailbox, chan, data28);+	device_unlock(dev);++	return rc;+}++static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28)+{+	int rc;++	struct vc_mailbox *mailbox = dev_get_drvdata(dev);+	device_lock(dev);+	rc = mbox_read(mailbox, chan, data28);+	device_unlock(dev);++	return rc;+}++extern int bcm_mailbox_write(unsigned chan, uint32_t data28)+{+	if (mbox_dev)+		return dev_mbox_write(mbox_dev, chan, data28);+	else+		return -ENODEV;+}+EXPORT_SYMBOL_GPL(bcm_mailbox_write);++extern int bcm_mailbox_read(unsigned chan, uint32_t *data28)+{+	if (mbox_dev)+		return dev_mbox_read(mbox_dev, chan, data28);+	else+		return -ENODEV;+}+EXPORT_SYMBOL_GPL(bcm_mailbox_read);++static void dev_mbox_register(const char *dev_name, struct device *dev)+{+	mbox_dev = dev;+}++static int mbox_copy_from_user(void *dst, const void *src, int size)+{+	if ( (uint32_t)src < TASK_SIZE)+	{+		return copy_from_user(dst, src, size);+	}+	else+	{+		memcpy( dst, src, size );+		return 0;+	}+}++static int mbox_copy_to_user(void *dst, const void *src, int size)+{+	if ( (uint32_t)dst < TASK_SIZE)+	{+		return copy_to_user(dst, src, size);+	}+	else+	{+		memcpy( dst, src, size );+		return 0;+	}+}++static DEFINE_MUTEX(mailbox_lock);+extern int bcm_mailbox_property(void *data, int size)+{+	uint32_t success;+	dma_addr_t mem_bus;				/* the memory address accessed from videocore */+	void *mem_kern;					/* the memory address accessed from driver */+	int s = 0;++        mutex_lock(&mailbox_lock);+	/* allocate some memory for the messages communicating with GPU */+	mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, GFP_ATOMIC);+	if (mem_kern) {+		/* create the message */+		mbox_copy_from_user(mem_kern, data, size);++		/* send the message */+		wmb();+		s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus);+		if (s == 0) {+			s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success);+		}+		if (s == 0) {+			/* copy the response */+			rmb();+			mbox_copy_to_user(data, mem_kern, size);+		}+		dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus);+	} else {+		s = -ENOMEM;+	}+	if (s != 0)+		printk(KERN_ERR DRIVER_NAME ": %s failed (%d)\n", __func__, s);++        mutex_unlock(&mailbox_lock);+	return s;+}+EXPORT_SYMBOL_GPL(bcm_mailbox_property);++/* ----------------------------------------------------------------------+ *	Platform Device for Mailbox+ * -------------------------------------------------------------------- */++/*+ * Is the device open right now? Used to prevent+ * concurent access into the same device+ */+static int Device_Open = 0;++/*+ * This is called whenever a process attempts to open the device file+ */+static int device_open(struct inode *inode, struct file *file)+{+	/*+	 * We don't want to talk to two processes at the same time+	 */+	if (Device_Open)+		return -EBUSY;++	Device_Open++;+	/*+	 * Initialize the message+	 */+	try_module_get(THIS_MODULE);+	return 0;+}++static int device_release(struct inode *inode, struct file *file)+{+	/*+	 * We're now ready for our next caller+	 */+	Device_Open--;++	module_put(THIS_MODULE);+	return 0;+}++/*+ * This function is called whenever a process tries to do an ioctl on our+ * device file. We get two extra parameters (additional to the inode and file+ * structures, which all device functions get): the number of the ioctl called+ * and the parameter given to the ioctl function.+ *+ * If the ioctl is write or read/write (meaning output is returned to the+ * calling process), the ioctl call returns the output of this function.+ *+ */+static long device_ioctl(struct file *file,	/* see include/linux/fs.h */+		 unsigned int ioctl_num,	/* number and param for ioctl */+		 unsigned long ioctl_param)+{+	unsigned size;+	/*+	 * Switch according to the ioctl called+	 */+	switch (ioctl_num) {+	case IOCTL_MBOX_PROPERTY:+		/*+		 * Receive a pointer to a message (in user space) and set that+		 * to be the device's message.  Get the parameter given to+		 * ioctl by the process.+		 */+		mbox_copy_from_user(&size, (void *)ioctl_param, sizeof size);+		return bcm_mailbox_property((void *)ioctl_param, size);+		break;+	default:+		printk(KERN_ERR DRIVER_NAME "unknown ioctl: %d\n", ioctl_num);+		return -EINVAL;+	}++	return 0;+}++/* Module Declarations */++/*+ * This structure will hold the functions to be called+ * when a process does something to the device we+ * created. Since a pointer to this structure is kept in+ * the devices table, it can't be local to+ * init_module. NULL is for unimplemented functios.+ */+struct file_operations fops = {+	.unlocked_ioctl = device_ioctl,+	.open = device_open,+	.release = device_release,	/* a.k.a. close */+};++static int bcm_vcio_probe(struct platform_device *pdev)+{+	int ret = 0;+	struct vc_mailbox *mailbox;++	mailbox = kzalloc(sizeof(*mailbox), GFP_KERNEL);+	if (NULL == mailbox) {+		printk(KERN_ERR DRIVER_NAME ": failed to allocate "+		       "mailbox memory\n");+		ret = -ENOMEM;+	} else {+		struct resource *res;++		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);+		if (res == NULL) {+			printk(KERN_ERR DRIVER_NAME ": failed to obtain memory "+			       "resource\n");+			ret = -ENODEV;+			kfree(mailbox);+		} else {+			/* should be based on the registers from res really */+			mbox_init(mailbox, &pdev->dev, ARM_0_MAIL0_RD);++			platform_set_drvdata(pdev, mailbox);+			dev_mbox_register(DRIVER_NAME, &pdev->dev);++			mbox_irqaction.dev_id = mailbox;+			setup_irq(IRQ_ARM_MAILBOX, &mbox_irqaction);+			printk(KERN_INFO DRIVER_NAME ": mailbox at %p\n",+			       __io_address(ARM_0_MAIL0_RD));+		}+	}++	if (ret == 0) {+		/*+		 * Register the character device+		 */+		ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops);++		/*+		 * Negative values signify an error+		 */+		if (ret < 0) {+			printk(KERN_ERR DRIVER_NAME+			       "Failed registering the character device %d\n", ret);+			return ret;+		}+	}+	return ret;+}++static int bcm_vcio_remove(struct platform_device *pdev)+{+	struct vc_mailbox *mailbox = platform_get_drvdata(pdev);++	platform_set_drvdata(pdev, NULL);+	kfree(mailbox);++	return 0;+}++static struct platform_driver bcm_mbox_driver = {+	.probe = bcm_vcio_probe,+	.remove = bcm_vcio_remove,++	.driver = {+		   .name = DRIVER_NAME,+		   .owner = THIS_MODULE,+		   },+};++static int __init bcm_mbox_init(void)+{+	int ret;++	printk(KERN_INFO "mailbox: Broadcom VideoCore Mailbox driver\n");++	ret = platform_driver_register(&bcm_mbox_driver);+	if (ret != 0) {+		printk(KERN_ERR DRIVER_NAME ": failed to register "+		       "on platform\n");+	}++	return ret;+}++static void __exit bcm_mbox_exit(void)+{+	platform_driver_unregister(&bcm_mbox_driver);+}++arch_initcall(bcm_mbox_init);	/* Initialize early */+module_exit(bcm_mbox_exit);++MODULE_AUTHOR("Gray Girling");+MODULE_DESCRIPTION("ARM I/O to VideoCore processor");+MODULE_LICENSE("GPL");+MODULE_ALIAS("platform:bcm-mbox");diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/vc_mem.c linux-3.11.10/arch/arm/mach-bcm2708/vc_mem.c--- linux-3.11.10.orig/arch/arm/mach-bcm2708/vc_mem.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/vc_mem.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,462 @@+/*****************************************************************************+* Copyright 2010 - 2011 Broadcom Corporation.  All rights reserved.+*+* Unless you and Broadcom execute a separate written software license+* agreement governing use of this software, this software is licensed to you+* under the terms of the GNU General Public License version 2, available at+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").+*+* Notwithstanding the above, under no circumstances may you combine this+* software in any way with any other Broadcom software provided under a+* license other than the GPL, without Broadcom's express prior written+* consent.+*****************************************************************************/++#include <linux/kernel.h>+#include <linux/module.h>+#include <linux/fs.h>+#include <linux/device.h>+#include <linux/cdev.h>+#include <linux/mm.h>+#include <linux/slab.h>+#include <linux/proc_fs.h>+#include <asm/uaccess.h>+#include <linux/dma-mapping.h>++#ifdef CONFIG_ARCH_KONA+#include <chal/chal_ipc.h>+#elif CONFIG_ARCH_BCM2708+#else+#include <csp/chal_ipc.h>+#endif++#include "mach/vc_mem.h"+#include <mach/vcio.h>++#define DRIVER_NAME  "vc-mem"++// Uncomment to enable debug logging+// #define ENABLE_DBG++#if defined(ENABLE_DBG)+#define LOG_DBG( fmt, ... )  printk( KERN_INFO fmt "\n", ##__VA_ARGS__ )+#else+#define LOG_DBG( fmt, ... )+#endif+#define LOG_ERR( fmt, ... )  printk( KERN_ERR fmt "\n", ##__VA_ARGS__ )++// Device (/dev) related variables+static dev_t vc_mem_devnum = 0;+static struct class *vc_mem_class = NULL;+static struct cdev vc_mem_cdev;+static int vc_mem_inited = 0;++// Proc entry+static struct proc_dir_entry *vc_mem_proc_entry;++/*+ * Videocore memory addresses and size+ *+ * Drivers that wish to know the videocore memory addresses and sizes should+ * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in+ * headers. This allows the other drivers to not be tied down to a a certain+ * address/size at compile time.+ *+ * In the future, the goal is to have the videocore memory virtual address and+ * size be calculated at boot time rather than at compile time. The decision of+ * where the videocore memory resides and its size would be in the hands of the+ * bootloader (and/or kernel). When that happens, the values of these variables+ * would be calculated and assigned in the init function.+ */+// in the 2835 VC in mapped above ARM, but ARM has full access to VC space+unsigned long mm_vc_mem_phys_addr = 0x00000000;+unsigned int mm_vc_mem_size = 0;+unsigned int mm_vc_mem_base = 0;++EXPORT_SYMBOL(mm_vc_mem_phys_addr);+EXPORT_SYMBOL(mm_vc_mem_size);+EXPORT_SYMBOL(mm_vc_mem_base);++static uint phys_addr = 0;+static uint mem_size = 0;+static uint mem_base = 0;+++/****************************************************************************+*+*   vc_mem_open+*+***************************************************************************/++static int+vc_mem_open(struct inode *inode, struct file *file)+{+	(void) inode;+	(void) file;++	LOG_DBG("%s: called file = 0x%p", __func__, file);++	return 0;+}++/****************************************************************************+*+*   vc_mem_release+*+***************************************************************************/++static int+vc_mem_release(struct inode *inode, struct file *file)+{+	(void) inode;+	(void) file;++	LOG_DBG("%s: called file = 0x%p", __func__, file);++	return 0;+}++/****************************************************************************+*+*   vc_mem_get_size+*+***************************************************************************/++static void+vc_mem_get_size(void)+{+}++/****************************************************************************+*+*   vc_mem_get_base+*+***************************************************************************/++static void+vc_mem_get_base(void)+{+}++/****************************************************************************+*+*   vc_mem_get_current_size+*+***************************************************************************/++int+vc_mem_get_current_size(void)+{+	return mm_vc_mem_size;+}++EXPORT_SYMBOL_GPL(vc_mem_get_current_size);++/****************************************************************************+*+*   vc_mem_ioctl+*+***************************************************************************/++static long+vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)+{+	int rc = 0;++	(void) cmd;+	(void) arg;++	LOG_DBG("%s: called file = 0x%p", __func__, file);++	switch (cmd) {+	case VC_MEM_IOC_MEM_PHYS_ADDR:+		{+			LOG_DBG("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p",+				__func__, (void *) mm_vc_mem_phys_addr);++			if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr,+					 sizeof (mm_vc_mem_phys_addr)) != 0) {+				rc = -EFAULT;+			}+			break;+		}+	case VC_MEM_IOC_MEM_SIZE:+		{+			// Get the videocore memory size first+			vc_mem_get_size();++			LOG_DBG("%s: VC_MEM_IOC_MEM_SIZE=%u", __func__,+				mm_vc_mem_size);++			if (copy_to_user((void *) arg, &mm_vc_mem_size,+					 sizeof (mm_vc_mem_size)) != 0) {+				rc = -EFAULT;+			}+			break;+		}+	case VC_MEM_IOC_MEM_BASE:+		{+			// Get the videocore memory base+			vc_mem_get_base();++			LOG_DBG("%s: VC_MEM_IOC_MEM_BASE=%u", __func__,+				mm_vc_mem_base);++			if (copy_to_user((void *) arg, &mm_vc_mem_base,+					 sizeof (mm_vc_mem_base)) != 0) {+				rc = -EFAULT;+			}+			break;+		}+	case VC_MEM_IOC_MEM_LOAD:+		{+			// Get the videocore memory base+			vc_mem_get_base();++			LOG_DBG("%s: VC_MEM_IOC_MEM_LOAD=%u", __func__,+				mm_vc_mem_base);++			if (copy_to_user((void *) arg, &mm_vc_mem_base,+					 sizeof (mm_vc_mem_base)) != 0) {+				rc = -EFAULT;+			}+			break;+		}+	default:+		{+			return -ENOTTY;+		}+	}+	LOG_DBG("%s: file = 0x%p returning %d", __func__, file, rc);++	return rc;+}++/****************************************************************************+*+*   vc_mem_mmap+*+***************************************************************************/++static int+vc_mem_mmap(struct file *filp, struct vm_area_struct *vma)+{+	int rc = 0;+	unsigned long length = vma->vm_end - vma->vm_start;+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;++	LOG_DBG("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx",+		__func__, (long) vma->vm_start, (long) vma->vm_end,+		(long) vma->vm_pgoff);++	if (offset + length > mm_vc_mem_size) {+		LOG_ERR("%s: length %ld is too big", __func__, length);+		return -EINVAL;+	}+	// Do not cache the memory map+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);++	rc = remap_pfn_range(vma, vma->vm_start,+			     (mm_vc_mem_phys_addr >> PAGE_SHIFT) ++			     vma->vm_pgoff, length, vma->vm_page_prot);+	if (rc != 0) {+		LOG_ERR("%s: remap_pfn_range failed (rc=%d)", __func__, rc);+	}++	return rc;+}++/****************************************************************************+*+*   File Operations for the driver.+*+***************************************************************************/++static const struct file_operations vc_mem_fops = {+	.owner = THIS_MODULE,+	.open = vc_mem_open,+	.release = vc_mem_release,+	.unlocked_ioctl = vc_mem_ioctl,+	.mmap = vc_mem_mmap,+};++/****************************************************************************+*+*   vc_mem_proc_read+*+***************************************************************************/++static int+vc_mem_proc_read(char *buf, char **start, off_t offset, int count, int *eof,+		 void *data)+{+	char *p = buf;++	(void) start;+	(void) count;+	(void) data;++	if (offset > 0) {+		*eof = 1;+		return 0;+	}+	// Get the videocore memory size first+	vc_mem_get_size();++	p += sprintf(p, "Videocore memory:\n");+	if (mm_vc_mem_phys_addr != 0)+		p += sprintf(p, "   Physical address: 0x%p\n",+			     (void *) mm_vc_mem_phys_addr);+	else+		p += sprintf(p, "   Physical address: 0x00000000\n");+	p += sprintf(p, "   Length (bytes):   %u\n", mm_vc_mem_size);++	*eof = 1;+	return p - buf;+}++/****************************************************************************+*+*   vc_mem_proc_write+*+***************************************************************************/++static int+vc_mem_proc_write(struct file *file, const char __user * buffer,+		  unsigned long count, void *data)+{+	int rc = -EFAULT;+	char input_str[10];++	memset(input_str, 0, sizeof (input_str));++	if (count > sizeof (input_str)) {+		LOG_ERR("%s: input string length too long", __func__);+		goto out;+	}++	if (copy_from_user(input_str, buffer, count - 1)) {+		LOG_ERR("%s: failed to get input string", __func__);+		goto out;+	}++	if (strncmp(input_str, "connect", strlen("connect")) == 0) {+		// Get the videocore memory size from the videocore+		vc_mem_get_size();+	}++      out:+	return rc;+}++/****************************************************************************+*+*   vc_mem_init+*+***************************************************************************/++static int __init+vc_mem_init(void)+{+	int rc = -EFAULT;+	struct device *dev;++	LOG_DBG("%s: called", __func__);++	mm_vc_mem_phys_addr = phys_addr;+	mm_vc_mem_size = mem_size;+	mm_vc_mem_base = mem_base;++	vc_mem_get_size();++	printk("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n",+		mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024));++	if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) {+		LOG_ERR("%s: alloc_chrdev_region failed (rc=%d)", __func__, rc);+		goto out_err;+	}++	cdev_init(&vc_mem_cdev, &vc_mem_fops);+	if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) {+		LOG_ERR("%s: cdev_add failed (rc=%d)", __func__, rc);+		goto out_unregister;+	}++	vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME);+	if (IS_ERR(vc_mem_class)) {+		rc = PTR_ERR(vc_mem_class);+		LOG_ERR("%s: class_create failed (rc=%d)", __func__, rc);+		goto out_cdev_del;+	}++	dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL,+			    DRIVER_NAME);+	if (IS_ERR(dev)) {+		rc = PTR_ERR(dev);+		LOG_ERR("%s: device_create failed (rc=%d)", __func__, rc);+		goto out_class_destroy;+	}++#if 0+	vc_mem_proc_entry = create_proc_entry(DRIVER_NAME, 0444, NULL);+	if (vc_mem_proc_entry == NULL) {+		rc = -EFAULT;+		LOG_ERR("%s: create_proc_entry failed", __func__);+		goto out_device_destroy;+	}+	vc_mem_proc_entry->read_proc = vc_mem_proc_read;+	vc_mem_proc_entry->write_proc = vc_mem_proc_write;+#endif++	vc_mem_inited = 1;+	return 0;++      out_device_destroy:+	device_destroy(vc_mem_class, vc_mem_devnum);++      out_class_destroy:+	class_destroy(vc_mem_class);+	vc_mem_class = NULL;++      out_cdev_del:+	cdev_del(&vc_mem_cdev);++      out_unregister:+	unregister_chrdev_region(vc_mem_devnum, 1);++      out_err:+	return -1;+}++/****************************************************************************+*+*   vc_mem_exit+*+***************************************************************************/++static void __exit+vc_mem_exit(void)+{+	LOG_DBG("%s: called", __func__);++	if (vc_mem_inited) {+#if 0+		remove_proc_entry(vc_mem_proc_entry->name, NULL);+#endif+		device_destroy(vc_mem_class, vc_mem_devnum);+		class_destroy(vc_mem_class);+		cdev_del(&vc_mem_cdev);+		unregister_chrdev_region(vc_mem_devnum, 1);+	}+}++module_init(vc_mem_init);+module_exit(vc_mem_exit);+MODULE_LICENSE("GPL");+MODULE_AUTHOR("Broadcom Corporation");++module_param(phys_addr, uint, 0644);+module_param(mem_size, uint, 0644);+module_param(mem_base, uint, 0644);+diff -Nur linux-3.11.10.orig/arch/arm/mach-bcm2708/vc_support.c linux-3.11.10/arch/arm/mach-bcm2708/vc_support.c--- linux-3.11.10.orig/arch/arm/mach-bcm2708/vc_support.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/arch/arm/mach-bcm2708/vc_support.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,318 @@+/*+ * vc_support.c+ *+ *  Created on: 25 Nov 2012+ *      Author: Simon+ */++#include <linux/module.h>+#include <mach/vcio.h>++#ifdef ECLIPSE_IGNORE++#define __user+#define __init+#define __exit+#define __iomem+#define KERN_DEBUG+#define KERN_ERR+#define KERN_WARNING+#define KERN_INFO+#define _IOWR(a, b, c) b+#define _IOW(a, b, c) b+#define _IO(a, b) b++#endif++/****** VC MAILBOX FUNCTIONALITY ******/+unsigned int AllocateVcMemory(unsigned int *pHandle, unsigned int size, unsigned int alignment, unsigned int flags)+{+	struct vc_msg+	{+		unsigned int m_msgSize;+		unsigned int m_response;++		struct vc_tag+		{+			unsigned int m_tagId;+			unsigned int m_sendBufferSize;+			union {+				unsigned int m_sendDataSize;+				unsigned int m_recvDataSize;+			};++			struct args+			{+				union {+					unsigned int m_size;+					unsigned int m_handle;+				};+				unsigned int m_alignment;+				unsigned int m_flags;+			} m_args;+		} m_tag;++		unsigned int m_endTag;+	} msg;+	int s;++	msg.m_msgSize = sizeof(msg);+	msg.m_response = 0;+	msg.m_endTag = 0;++	//fill in the tag for the allocation command+	msg.m_tag.m_tagId = 0x3000c;+	msg.m_tag.m_sendBufferSize = 12;+	msg.m_tag.m_sendDataSize = 12;++	//fill in our args+	msg.m_tag.m_args.m_size = size;+	msg.m_tag.m_args.m_alignment = alignment;+	msg.m_tag.m_args.m_flags = flags;++	//run the command+	s = bcm_mailbox_property(&msg, sizeof(msg));++	if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004)+	{+		*pHandle = msg.m_tag.m_args.m_handle;+		return 0;+	}+	else+	{+		printk(KERN_ERR "failed to allocate vc memory: s=%d response=%08x recv data size=%08x\n",+				s, msg.m_response, msg.m_tag.m_recvDataSize);+		return 1;+	}+}++unsigned int ReleaseVcMemory(unsigned int handle)+{+	struct vc_msg+	{+		unsigned int m_msgSize;+		unsigned int m_response;++		struct vc_tag+		{+			unsigned int m_tagId;+			unsigned int m_sendBufferSize;+			union {+				unsigned int m_sendDataSize;+				unsigned int m_recvDataSize;+			};++			struct args+			{+				union {+					unsigned int m_handle;+					unsigned int m_error;+				};+			} m_args;+		} m_tag;++		unsigned int m_endTag;+	} msg;+	int s;++	msg.m_msgSize = sizeof(msg);+	msg.m_response = 0;+	msg.m_endTag = 0;++	//fill in the tag for the release command+	msg.m_tag.m_tagId = 0x3000f;+	msg.m_tag.m_sendBufferSize = 4;+	msg.m_tag.m_sendDataSize = 4;++	//pass across the handle+	msg.m_tag.m_args.m_handle = handle;++	s = bcm_mailbox_property(&msg, sizeof(msg));++	if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004 && msg.m_tag.m_args.m_error == 0)+		return 0;+	else+	{+		printk(KERN_ERR "failed to release vc memory: s=%d response=%08x recv data size=%08x error=%08x\n",+				s, msg.m_response, msg.m_tag.m_recvDataSize, msg.m_tag.m_args.m_error);+		return 1;+	}+}++unsigned int LockVcMemory(unsigned int *pBusAddress, unsigned int handle)+{+	struct vc_msg+	{+		unsigned int m_msgSize;+		unsigned int m_response;++		struct vc_tag+		{+			unsigned int m_tagId;+			unsigned int m_sendBufferSize;+			union {+				unsigned int m_sendDataSize;+				unsigned int m_recvDataSize;+			};++			struct args+			{+				union {+					unsigned int m_handle;+					unsigned int m_busAddress;+				};+			} m_args;+		} m_tag;++		unsigned int m_endTag;+	} msg;+	int s;++	msg.m_msgSize = sizeof(msg);+	msg.m_response = 0;+	msg.m_endTag = 0;++	//fill in the tag for the lock command+	msg.m_tag.m_tagId = 0x3000d;+	msg.m_tag.m_sendBufferSize = 4;+	msg.m_tag.m_sendDataSize = 4;++	//pass across the handle+	msg.m_tag.m_args.m_handle = handle;++	s = bcm_mailbox_property(&msg, sizeof(msg));++	if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004)+	{+		//pick out the bus address+		*pBusAddress = msg.m_tag.m_args.m_busAddress;+		return 0;+	}+	else+	{+		printk(KERN_ERR "failed to lock vc memory: s=%d response=%08x recv data size=%08x\n",+				s, msg.m_response, msg.m_tag.m_recvDataSize);+		return 1;+	}+}++unsigned int UnlockVcMemory(unsigned int handle)+{+	struct vc_msg+	{+		unsigned int m_msgSize;+		unsigned int m_response;++		struct vc_tag+		{+			unsigned int m_tagId;+			unsigned int m_sendBufferSize;+			union {+				unsigned int m_sendDataSize;+				unsigned int m_recvDataSize;+			};++			struct args+			{+				union {+					unsigned int m_handle;+					unsigned int m_error;+				};+			} m_args;+		} m_tag;++		unsigned int m_endTag;+	} msg;+	int s;++	msg.m_msgSize = sizeof(msg);+	msg.m_response = 0;+	msg.m_endTag = 0;++	//fill in the tag for the unlock command+	msg.m_tag.m_tagId = 0x3000e;+	msg.m_tag.m_sendBufferSize = 4;+	msg.m_tag.m_sendDataSize = 4;++	//pass across the handle+	msg.m_tag.m_args.m_handle = handle;++	s = bcm_mailbox_property(&msg, sizeof(msg));++	//check the error code too+	if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004 && msg.m_tag.m_args.m_error == 0)+		return 0;+	else+	{+		printk(KERN_ERR "failed to unlock vc memory: s=%d response=%08x recv data size=%08x error%08x\n",+				s, msg.m_response, msg.m_tag.m_recvDataSize, msg.m_tag.m_args.m_error);+		return 1;+	}+}++unsigned int ExecuteVcCode(unsigned int code,+		unsigned int r0, unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int r5)+{+	struct vc_msg+	{+		unsigned int m_msgSize;+		unsigned int m_response;++		struct vc_tag+		{+			unsigned int m_tagId;+			unsigned int m_sendBufferSize;+			union {+				unsigned int m_sendDataSize;+				unsigned int m_recvDataSize;+			};++			struct args+			{+				union {+					unsigned int m_pCode;+					unsigned int m_return;+				};+				unsigned int m_r0;+				unsigned int m_r1;+				unsigned int m_r2;+				unsigned int m_r3;+				unsigned int m_r4;+				unsigned int m_r5;+			} m_args;+		} m_tag;++		unsigned int m_endTag;+	} msg;+	int s;++	msg.m_msgSize = sizeof(msg);+	msg.m_response = 0;+	msg.m_endTag = 0;++	//fill in the tag for the unlock command+	msg.m_tag.m_tagId = 0x30010;+	msg.m_tag.m_sendBufferSize = 28;+	msg.m_tag.m_sendDataSize = 28;++	//pass across the handle+	msg.m_tag.m_args.m_pCode = code;+	msg.m_tag.m_args.m_r0 = r0;+	msg.m_tag.m_args.m_r1 = r1;+	msg.m_tag.m_args.m_r2 = r2;+	msg.m_tag.m_args.m_r3 = r3;+	msg.m_tag.m_args.m_r4 = r4;+	msg.m_tag.m_args.m_r5 = r5;++	s = bcm_mailbox_property(&msg, sizeof(msg));++	//check the error code too+	if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004)+		return msg.m_tag.m_args.m_return;+	else+	{+		printk(KERN_ERR "failed to execute: s=%d response=%08x recv data size=%08x\n",+				s, msg.m_response, msg.m_tag.m_recvDataSize);+		return 1;+	}+}diff -Nur linux-3.11.10.orig/arch/arm/Makefile linux-3.11.10/arch/arm/Makefile--- linux-3.11.10.orig/arch/arm/Makefile	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/arch/arm/Makefile	2014-02-07 19:57:28.000000000 +0100@@ -146,6 +146,7 @@ # by CONFIG_* macro name. machine-$(CONFIG_ARCH_AT91)		+= at91 machine-$(CONFIG_ARCH_BCM)		+= bcm+machine-$(CONFIG_ARCH_BCM2708)		+= bcm2708 machine-$(CONFIG_ARCH_BCM2835)		+= bcm2835 machine-$(CONFIG_ARCH_CLPS711X)		+= clps711x machine-$(CONFIG_ARCH_CNS3XXX)		+= cns3xxxdiff -Nur linux-3.11.10.orig/arch/arm/mm/Kconfig linux-3.11.10/arch/arm/mm/Kconfig--- linux-3.11.10.orig/arch/arm/mm/Kconfig	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/arch/arm/mm/Kconfig	2014-02-07 19:57:28.000000000 +0100@@ -358,7 +358,7 @@  # ARMv6 config CPU_V6-	bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX+	bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || MACH_BCM2708 	select CPU_32v6 	select CPU_ABRT_EV6 	select CPU_CACHE_V6diff -Nur linux-3.11.10.orig/arch/arm/mm/proc-v6.S linux-3.11.10/arch/arm/mm/proc-v6.S--- linux-3.11.10.orig/arch/arm/mm/proc-v6.S	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/arch/arm/mm/proc-v6.S	2014-02-07 19:57:28.000000000 +0100@@ -73,10 +73,19 @@  *  *	IRQs are already disabled.  */++/* See jira SW-5991 for details of this workaround */ ENTRY(cpu_v6_do_idle)-	mov	r1, #0-	mcr	p15, 0, r1, c7, c10, 4		@ DWB - WFI may enter a low-power mode-	mcr	p15, 0, r1, c7, c0, 4		@ wait for interrupt+	.align 5+	mov     r1, #2+1:	subs	r1, #1+	nop+	mcreq	p15, 0, r1, c7, c10, 4		@ DWB - WFI may enter a low-power mode+	mcreq	p15, 0, r1, c7, c0, 4		@ wait for interrupt+	nop+	nop+	nop+	bne 1b 	mov	pc, lr  ENTRY(cpu_v6_dcache_clean_area)diff -Nur linux-3.11.10.orig/arch/arm/tools/mach-types linux-3.11.10/arch/arm/tools/mach-types--- linux-3.11.10.orig/arch/arm/tools/mach-types	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/arch/arm/tools/mach-types	2014-02-07 19:57:28.000000000 +0100@@ -522,6 +522,7 @@ prima2_evb		MACH_PRIMA2_EVB		PRIMA2_EVB		3103 paz00			MACH_PAZ00		PAZ00			3128 acmenetusfoxg20		MACH_ACMENETUSFOXG20	ACMENETUSFOXG20		3129+bcm2708			MACH_BCM2708		BCM2708			3138 ag5evm			MACH_AG5EVM		AG5EVM			3189 ics_if_voip		MACH_ICS_IF_VOIP	ICS_IF_VOIP		3206 wlf_cragg_6410		MACH_WLF_CRAGG_6410	WLF_CRAGG_6410		3207diff -Nur linux-3.11.10.orig/drivers/char/broadcom/Kconfig linux-3.11.10/drivers/char/broadcom/Kconfig--- linux-3.11.10.orig/drivers/char/broadcom/Kconfig	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/char/broadcom/Kconfig	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,16 @@+#+# Broadcom char driver config+#++menuconfig BRCM_CHAR_DRIVERS+	bool "Broadcom Char Drivers"+	help+	  Broadcom's char drivers++config BCM_VC_CMA+	bool "Videocore CMA"+	depends on CMA && BRCM_CHAR_DRIVERS+	default n+        help+          Helper for videocore CMA access.+diff -Nur linux-3.11.10.orig/drivers/char/broadcom/Makefile linux-3.11.10/drivers/char/broadcom/Makefile--- linux-3.11.10.orig/drivers/char/broadcom/Makefile	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/char/broadcom/Makefile	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1 @@+obj-$(CONFIG_BCM_VC_CMA)	+= vc_cma/diff -Nur linux-3.11.10.orig/drivers/char/broadcom/vc_cma/Makefile linux-3.11.10/drivers/char/broadcom/vc_cma/Makefile--- linux-3.11.10.orig/drivers/char/broadcom/vc_cma/Makefile	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/char/broadcom/vc_cma/Makefile	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,14 @@+EXTRA_CFLAGS  += -Wall -Wstrict-prototypes -Wno-trigraphs+EXTRA_CFLAGS  += -Werror+EXTRA_CFLAGS  += -I"include/linux/broadcom"+EXTRA_CFLAGS  += -I"drivers/misc/vc04_services"+EXTRA_CFLAGS  += -I"drivers/misc/vc04_services/interface/vchi"+EXTRA_CFLAGS  += -I"drivers/misc/vc04_services/interface/vchiq_arm"++EXTRA_CFLAGS  += -D__KERNEL__+EXTRA_CFLAGS  += -D__linux__+EXTRA_CFLAGS  += -Werror++obj-$(CONFIG_BCM_VC_CMA) += vc-cma.o++vc-cma-objs := vc_cma.odiff -Nur linux-3.11.10.orig/drivers/char/broadcom/vc_cma/vc_cma.c linux-3.11.10/drivers/char/broadcom/vc_cma/vc_cma.c--- linux-3.11.10.orig/drivers/char/broadcom/vc_cma/vc_cma.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/char/broadcom/vc_cma/vc_cma.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,1143 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#include <linux/kernel.h>+#include <linux/module.h>+#include <linux/kthread.h>+#include <linux/fs.h>+#include <linux/device.h>+#include <linux/cdev.h>+#include <linux/mm.h>+#include <linux/proc_fs.h>+#include <linux/seq_file.h>+#include <linux/dma-mapping.h>+#include <linux/dma-contiguous.h>+#include <linux/platform_device.h>+#include <linux/uaccess.h>+#include <asm/cacheflush.h>++#include "vc_cma.h"++#include "vchiq_util.h"+#include "vchiq_connected.h"+//#include "debug_sym.h"+//#include "vc_mem.h"++#define DRIVER_NAME  "vc-cma"++#define LOG_DBG(fmt, ...) \+	if (vc_cma_debug) \+		printk(KERN_INFO fmt "\n", ##__VA_ARGS__)+#define LOG_ERR(fmt, ...) \+	printk(KERN_ERR fmt "\n", ##__VA_ARGS__)++#define VC_CMA_FOURCC VCHIQ_MAKE_FOURCC('C', 'M', 'A', ' ')+#define VC_CMA_VERSION 2++#define VC_CMA_CHUNK_ORDER 6	/* 256K */+#define VC_CMA_CHUNK_SIZE (4096 << VC_CMA_CHUNK_ORDER)+#define VC_CMA_MAX_PARAMS_PER_MSG \+	((VCHIQ_MAX_MSG_SIZE - sizeof(unsigned short))/sizeof(unsigned short))+#define VC_CMA_RESERVE_COUNT_MAX 16++#define PAGES_PER_CHUNK (VC_CMA_CHUNK_SIZE / PAGE_SIZE)++#define VCADDR_TO_PHYSADDR(vcaddr) (mm_vc_mem_phys_addr + vcaddr)++#define loud_error(...) \+	LOG_ERR("===== " __VA_ARGS__)++enum {+	VC_CMA_MSG_QUIT,+	VC_CMA_MSG_OPEN,+	VC_CMA_MSG_TICK,+	VC_CMA_MSG_ALLOC,	/* chunk count */+	VC_CMA_MSG_FREE,	/* chunk, chunk, ... */+	VC_CMA_MSG_ALLOCATED,	/* chunk, chunk, ... */+	VC_CMA_MSG_REQUEST_ALLOC,	/* chunk count */+	VC_CMA_MSG_REQUEST_FREE,	/* chunk count */+	VC_CMA_MSG_RESERVE,	/* bytes lo, bytes hi */+	VC_CMA_MSG_UPDATE_RESERVE,+	VC_CMA_MSG_MAX+};++struct cma_msg {+	unsigned short type;+	unsigned short params[VC_CMA_MAX_PARAMS_PER_MSG];+};++struct vc_cma_reserve_user {+	unsigned int pid;+	unsigned int reserve;+};++/* Device (/dev) related variables */+static dev_t vc_cma_devnum;+static struct class *vc_cma_class;+static struct cdev vc_cma_cdev;+static int vc_cma_inited;+static int vc_cma_debug;++/* Proc entry */+static struct proc_dir_entry *vc_cma_proc_entry;++phys_addr_t vc_cma_base;+struct page *vc_cma_base_page;+unsigned int vc_cma_size;+EXPORT_SYMBOL(vc_cma_size);+unsigned int vc_cma_initial;+unsigned int vc_cma_chunks;+unsigned int vc_cma_chunks_used;+unsigned int vc_cma_chunks_reserved;++static int in_loud_error;++unsigned int vc_cma_reserve_total;+unsigned int vc_cma_reserve_count;+struct vc_cma_reserve_user vc_cma_reserve_users[VC_CMA_RESERVE_COUNT_MAX];+static DEFINE_SEMAPHORE(vc_cma_reserve_mutex);+static DEFINE_SEMAPHORE(vc_cma_worker_queue_push_mutex);++static u64 vc_cma_dma_mask = DMA_BIT_MASK(32);+static struct platform_device vc_cma_device = {+	.name = "vc-cma",+	.id = 0,+	.dev = {+		.dma_mask = &vc_cma_dma_mask,+		.coherent_dma_mask = DMA_BIT_MASK(32),+		},+};++static VCHIQ_INSTANCE_T cma_instance;+static VCHIQ_SERVICE_HANDLE_T cma_service;+static VCHIU_QUEUE_T cma_msg_queue;+static struct task_struct *cma_worker;++static int vc_cma_set_reserve(unsigned int reserve, unsigned int pid);+static int vc_cma_alloc_chunks(int num_chunks, struct cma_msg *reply);+static VCHIQ_STATUS_T cma_service_callback(VCHIQ_REASON_T reason,+					   VCHIQ_HEADER_T * header,+					   VCHIQ_SERVICE_HANDLE_T service,+					   void *bulk_userdata);+static void send_vc_msg(unsigned short type,+			unsigned short param1, unsigned short param2);+static bool send_worker_msg(VCHIQ_HEADER_T * msg);++static int early_vc_cma_mem(char *p)+{+	unsigned int new_size;+	printk(KERN_NOTICE "early_vc_cma_mem(%s)", p);+	vc_cma_size = memparse(p, &p);+	vc_cma_initial = vc_cma_size;+	if (*p == '/')+		vc_cma_size = memparse(p + 1, &p);+	if (*p == '@')+		vc_cma_base = memparse(p + 1, &p);++	new_size = (vc_cma_size - ((-vc_cma_base) & (VC_CMA_CHUNK_SIZE - 1)))+	    & ~(VC_CMA_CHUNK_SIZE - 1);+	if (new_size > vc_cma_size)+		vc_cma_size = 0;+	vc_cma_initial = (vc_cma_initial + VC_CMA_CHUNK_SIZE - 1)+	    & ~(VC_CMA_CHUNK_SIZE - 1);+	if (vc_cma_initial > vc_cma_size)+		vc_cma_initial = vc_cma_size;+	vc_cma_base = (vc_cma_base + VC_CMA_CHUNK_SIZE - 1)+	    & ~(VC_CMA_CHUNK_SIZE - 1);++	printk(KERN_NOTICE " -> initial %x, size %x, base %x", vc_cma_initial,+	       vc_cma_size, (unsigned int)vc_cma_base);++	return 0;+}++early_param("vc-cma-mem", early_vc_cma_mem);++void vc_cma_early_init(void)+{+	LOG_DBG("vc_cma_early_init - vc_cma_chunks = %d", vc_cma_chunks);+	if (vc_cma_size) {+		int rc = platform_device_register(&vc_cma_device);+		LOG_DBG("platform_device_register -> %d", rc);+	}+}++void vc_cma_reserve(void)+{+	/* if vc_cma_size is set, then declare vc CMA area of the same+	 * size from the end of memory+	 */+	if (vc_cma_size) {+		if (dma_declare_contiguous(NULL /*&vc_cma_device.dev*/, vc_cma_size,+					   vc_cma_base, 0) == 0) {+		} else {+			LOG_ERR("vc_cma: dma_declare_contiguous(%x,%x) failed",+				vc_cma_size, (unsigned int)vc_cma_base);+			vc_cma_size = 0;+		}+	}+	vc_cma_chunks = vc_cma_size / VC_CMA_CHUNK_SIZE;+}++/****************************************************************************+*+*   vc_cma_open+*+***************************************************************************/++static int vc_cma_open(struct inode *inode, struct file *file)+{+	(void)inode;+	(void)file;++	return 0;+}++/****************************************************************************+*+*   vc_cma_release+*+***************************************************************************/++static int vc_cma_release(struct inode *inode, struct file *file)+{+	(void)inode;+	(void)file;++	vc_cma_set_reserve(0, current->tgid);++	return 0;+}++/****************************************************************************+*+*   vc_cma_ioctl+*+***************************************************************************/++static long vc_cma_ioctl(struct file *file, unsigned int cmd, unsigned long arg)+{+	int rc = 0;++	(void)cmd;+	(void)arg;++	switch (cmd) {+	case VC_CMA_IOC_RESERVE:+		rc = vc_cma_set_reserve((unsigned int)arg, current->tgid);+		if (rc >= 0)+			rc = 0;+		break;+	default:+		LOG_ERR("vc-cma: Unknown ioctl %x", cmd);+		return -ENOTTY;+	}++	return rc;+}++/****************************************************************************+*+*   File Operations for the driver.+*+***************************************************************************/++static const struct file_operations vc_cma_fops = {+	.owner = THIS_MODULE,+	.open = vc_cma_open,+	.release = vc_cma_release,+	.unlocked_ioctl = vc_cma_ioctl,+};++/****************************************************************************+*+*   vc_cma_proc_open+*+***************************************************************************/++static int vc_cma_show_info(struct seq_file *m, void *v)+{+	int i;++	seq_printf(m, "Videocore CMA:\n");+	seq_printf(m, "   Base       : %08x\n", (unsigned int)vc_cma_base);+	seq_printf(m, "   Length     : %08x\n", vc_cma_size);+	seq_printf(m, "   Initial    : %08x\n", vc_cma_initial);+	seq_printf(m, "   Chunk size : %08x\n", VC_CMA_CHUNK_SIZE);+	seq_printf(m, "   Chunks     : %4d (%d bytes)\n",+		   (int)vc_cma_chunks,+		   (int)(vc_cma_chunks * VC_CMA_CHUNK_SIZE));+	seq_printf(m, "   Used       : %4d (%d bytes)\n",+		   (int)vc_cma_chunks_used,+		   (int)(vc_cma_chunks_used * VC_CMA_CHUNK_SIZE));+	seq_printf(m, "   Reserved   : %4d (%d bytes)\n",+		   (unsigned int)vc_cma_chunks_reserved,+		   (int)(vc_cma_chunks_reserved * VC_CMA_CHUNK_SIZE));++	for (i = 0; i < vc_cma_reserve_count; i++) {+		struct vc_cma_reserve_user *user = &vc_cma_reserve_users[i];+		seq_printf(m, "     PID %5d: %d bytes\n", user->pid,+			   user->reserve);+	}++	seq_printf(m, "\n");++	return 0;+}++static int vc_cma_proc_open(struct inode *inode, struct file *file)+{+	return single_open(file, vc_cma_show_info, NULL);+}++/****************************************************************************+*+*   vc_cma_proc_write+*+***************************************************************************/++static int vc_cma_proc_write(struct file *file,+			     const char __user *buffer,+			     size_t size, loff_t *ppos)+{+	int rc = -EFAULT;+	char input_str[20];++	memset(input_str, 0, sizeof(input_str));++	if (size > sizeof(input_str)) {+		LOG_ERR("%s: input string length too long", __func__);+		goto out;+	}++	if (copy_from_user(input_str, buffer, size - 1)) {+		LOG_ERR("%s: failed to get input string", __func__);+		goto out;+	}+#define ALLOC_STR "alloc"+#define FREE_STR "free"+#define DEBUG_STR "debug"+#define RESERVE_STR "reserve"+	if (strncmp(input_str, ALLOC_STR, strlen(ALLOC_STR)) == 0) {+		int size;+		char *p = input_str + strlen(ALLOC_STR);++		while (*p == ' ')+			p++;+		size = memparse(p, NULL);+		LOG_ERR("/proc/vc-cma: alloc %d", size);+		if (size)+			send_vc_msg(VC_CMA_MSG_REQUEST_FREE,+				    size / VC_CMA_CHUNK_SIZE, 0);+		else+			LOG_ERR("invalid size '%s'", p);+		rc = size;+	} else if (strncmp(input_str, FREE_STR, strlen(FREE_STR)) == 0) {+		int size;+		char *p = input_str + strlen(FREE_STR);++		while (*p == ' ')+			p++;+		size = memparse(p, NULL);+		LOG_ERR("/proc/vc-cma: free %d", size);+		if (size)+			send_vc_msg(VC_CMA_MSG_REQUEST_ALLOC,+				    size / VC_CMA_CHUNK_SIZE, 0);+		else+			LOG_ERR("invalid size '%s'", p);+		rc = size;+	} else if (strncmp(input_str, DEBUG_STR, strlen(DEBUG_STR)) == 0) {+		char *p = input_str + strlen(DEBUG_STR);+		while (*p == ' ')+			p++;+		if ((strcmp(p, "on") == 0) || (strcmp(p, "1") == 0))+			vc_cma_debug = 1;+		else if ((strcmp(p, "off") == 0) || (strcmp(p, "0") == 0))+			vc_cma_debug = 0;+		LOG_ERR("/proc/vc-cma: debug %s", vc_cma_debug ? "on" : "off");+		rc = size;+	} else if (strncmp(input_str, RESERVE_STR, strlen(RESERVE_STR)) == 0) {+		int size;+		int reserved;+		char *p = input_str + strlen(RESERVE_STR);+		while (*p == ' ')+			p++;+		size = memparse(p, NULL);++		reserved = vc_cma_set_reserve(size, current->tgid);+		rc = (reserved >= 0) ? size : reserved;+	}++out:+	return rc;+}++/****************************************************************************+*+*   File Operations for /proc interface.+*+***************************************************************************/++static const struct file_operations vc_cma_proc_fops = {+	.open = vc_cma_proc_open,+	.read = seq_read,+	.write = vc_cma_proc_write,+	.llseek = seq_lseek,+	.release = single_release+};++static int vc_cma_set_reserve(unsigned int reserve, unsigned int pid)+{+	struct vc_cma_reserve_user *user = NULL;+	int delta = 0;+	int i;++	if (down_interruptible(&vc_cma_reserve_mutex))+		return -ERESTARTSYS;++	for (i = 0; i < vc_cma_reserve_count; i++) {+		if (pid == vc_cma_reserve_users[i].pid) {+			user = &vc_cma_reserve_users[i];+			delta = reserve - user->reserve;+			if (reserve)+				user->reserve = reserve;+			else {+				/* Remove this entry by copying downwards */+				while ((i + 1) < vc_cma_reserve_count) {+					user[0].pid = user[1].pid;+					user[0].reserve = user[1].reserve;+					user++;+					i++;+				}+				vc_cma_reserve_count--;+				user = NULL;+			}+			break;+		}+	}++	if (reserve && !user) {+		if (vc_cma_reserve_count == VC_CMA_RESERVE_COUNT_MAX) {+			LOG_ERR("vc-cma: Too many reservations - "+				"increase CMA_RESERVE_COUNT_MAX");+			up(&vc_cma_reserve_mutex);+			return -EBUSY;+		}+		user = &vc_cma_reserve_users[vc_cma_reserve_count];+		user->pid = pid;+		user->reserve = reserve;+		delta = reserve;+		vc_cma_reserve_count++;+	}++	vc_cma_reserve_total += delta;++	send_vc_msg(VC_CMA_MSG_RESERVE,+		    vc_cma_reserve_total & 0xffff, vc_cma_reserve_total >> 16);++	send_worker_msg((VCHIQ_HEADER_T *) VC_CMA_MSG_UPDATE_RESERVE);++	LOG_DBG("/proc/vc-cma: reserve %d (PID %d) - total %u",+		reserve, pid, vc_cma_reserve_total);++	up(&vc_cma_reserve_mutex);++	return vc_cma_reserve_total;+}++static VCHIQ_STATUS_T cma_service_callback(VCHIQ_REASON_T reason,+					   VCHIQ_HEADER_T * header,+					   VCHIQ_SERVICE_HANDLE_T service,+					   void *bulk_userdata)+{+	switch (reason) {+	case VCHIQ_MESSAGE_AVAILABLE:+		if (!send_worker_msg(header))+			return VCHIQ_RETRY;+		break;+	case VCHIQ_SERVICE_CLOSED:+		LOG_DBG("CMA service closed");+		break;+	default:+		LOG_ERR("Unexpected CMA callback reason %d", reason);+		break;+	}+	return VCHIQ_SUCCESS;+}++static void send_vc_msg(unsigned short type,+			unsigned short param1, unsigned short param2)+{+	unsigned short msg[] = { type, param1, param2 };+	VCHIQ_ELEMENT_T elem = { &msg, sizeof(msg) };+	VCHIQ_STATUS_T ret;+	vchiq_use_service(cma_service);+	ret = vchiq_queue_message(cma_service, &elem, 1);+	vchiq_release_service(cma_service);+	if (ret != VCHIQ_SUCCESS)+		LOG_ERR("vchiq_queue_message returned %x", ret);+}++static bool send_worker_msg(VCHIQ_HEADER_T * msg)+{+	if (down_interruptible(&vc_cma_worker_queue_push_mutex))+		return false;+	vchiu_queue_push(&cma_msg_queue, msg);+	up(&vc_cma_worker_queue_push_mutex);+	return true;+}++static int vc_cma_alloc_chunks(int num_chunks, struct cma_msg *reply)+{+	int i;+	for (i = 0; i < num_chunks; i++) {+		struct page *chunk;+		unsigned int chunk_num;+		uint8_t *chunk_addr;+		size_t chunk_size = PAGES_PER_CHUNK << PAGE_SHIFT;++		chunk = dma_alloc_from_contiguous(NULL /*&vc_cma_device.dev*/,+						  PAGES_PER_CHUNK,+						  VC_CMA_CHUNK_ORDER);+		if (!chunk)+			break;++		chunk_addr = page_address(chunk);+		dmac_flush_range(chunk_addr, chunk_addr + chunk_size);+		outer_inv_range(__pa(chunk_addr), __pa(chunk_addr) ++			chunk_size);++		chunk_num =+		    (page_to_phys(chunk) - vc_cma_base) / VC_CMA_CHUNK_SIZE;+		BUG_ON(((page_to_phys(chunk) - vc_cma_base) %+			VC_CMA_CHUNK_SIZE) != 0);+		if (chunk_num >= vc_cma_chunks) {+			LOG_ERR("%s: ===============================",+				__func__);+			LOG_ERR("%s: chunk phys %x, vc_cma %x-%x - "+				"bad SPARSEMEM configuration?",+				__func__, (unsigned int)page_to_phys(chunk),+				vc_cma_base, vc_cma_base + vc_cma_size - 1);+			LOG_ERR("%s: dev->cma_area = %p\n", __func__,+				vc_cma_device.dev.cma_area);+			LOG_ERR("%s: ===============================",+				__func__);+			break;+		}+		reply->params[i] = chunk_num;+		vc_cma_chunks_used++;+	}++	if (i < num_chunks) {+		LOG_ERR("%s: dma_alloc_from_contiguous failed "+			"for %x bytes (alloc %d of %d, %d free)",+			__func__, VC_CMA_CHUNK_SIZE, i,+			num_chunks, vc_cma_chunks - vc_cma_chunks_used);+		num_chunks = i;+	}++	LOG_DBG("CMA allocated %d chunks -> %d used",+		num_chunks, vc_cma_chunks_used);+	reply->type = VC_CMA_MSG_ALLOCATED;++	{+		VCHIQ_ELEMENT_T elem = {+			reply,+			offsetof(struct cma_msg, params[0]) ++			    num_chunks * sizeof(reply->params[0])+		};+		VCHIQ_STATUS_T ret;+		vchiq_use_service(cma_service);+		ret = vchiq_queue_message(cma_service, &elem, 1);+		vchiq_release_service(cma_service);+		if (ret != VCHIQ_SUCCESS)+			LOG_ERR("vchiq_queue_message return " "%x", ret);+	}++	return num_chunks;+}++static int cma_worker_proc(void *param)+{+	static struct cma_msg reply;+	(void)param;++	while (1) {+		VCHIQ_HEADER_T *msg;+		static struct cma_msg msg_copy;+		struct cma_msg *cma_msg = &msg_copy;+		int type, msg_size;++		msg = vchiu_queue_pop(&cma_msg_queue);+		if ((unsigned int)msg >= VC_CMA_MSG_MAX) {+			msg_size = msg->size;+			memcpy(&msg_copy, msg->data, msg_size);+			type = cma_msg->type;+			vchiq_release_message(cma_service, msg);+		} else {+			msg_size = 0;+			type = (int)msg;+			if (type == VC_CMA_MSG_QUIT)+				break;+			else if (type == VC_CMA_MSG_UPDATE_RESERVE) {+				msg = NULL;+				cma_msg = NULL;+			} else {+				BUG();+				continue;+			}+		}++		switch (type) {+		case VC_CMA_MSG_ALLOC:{+				int num_chunks, free_chunks;+				num_chunks = cma_msg->params[0];+				free_chunks =+				    vc_cma_chunks - vc_cma_chunks_used;+				LOG_DBG("CMA_MSG_ALLOC(%d chunks)", num_chunks);+				if (num_chunks > VC_CMA_MAX_PARAMS_PER_MSG) {+					LOG_ERR+					    ("CMA_MSG_ALLOC - chunk count (%d) "+					     "exceeds VC_CMA_MAX_PARAMS_PER_MSG (%d)",+					     num_chunks,+					     VC_CMA_MAX_PARAMS_PER_MSG);+					num_chunks = VC_CMA_MAX_PARAMS_PER_MSG;+				}++				if (num_chunks > free_chunks) {+					LOG_ERR+					    ("CMA_MSG_ALLOC - chunk count (%d) "+					     "exceeds free chunks (%d)",+					     num_chunks, free_chunks);+					num_chunks = free_chunks;+				}++				vc_cma_alloc_chunks(num_chunks, &reply);+			}+			break;++		case VC_CMA_MSG_FREE:{+				int chunk_count =+				    (msg_size -+				     offsetof(struct cma_msg,+					      params)) /+				    sizeof(cma_msg->params[0]);+				int i;+				BUG_ON(chunk_count <= 0);++				LOG_DBG("CMA_MSG_FREE(%d chunks - %x, ...)",+					chunk_count, cma_msg->params[0]);+				for (i = 0; i < chunk_count; i++) {+					int chunk_num = cma_msg->params[i];+					struct page *page = vc_cma_base_page ++					    chunk_num * PAGES_PER_CHUNK;+					if (chunk_num >= vc_cma_chunks) {+						LOG_ERR+						    ("CMA_MSG_FREE - chunk %d of %d"+						     " (value %x) exceeds maximum "+						     "(%x)", i, chunk_count,+						     chunk_num,+						     vc_cma_chunks - 1);+						break;+					}++					if (!dma_release_from_contiguous+					    (NULL /*&vc_cma_device.dev*/, page,+					     PAGES_PER_CHUNK)) {+						LOG_ERR+						    ("CMA_MSG_FREE - failed to "+						     "release chunk %d (phys %x, "+						     "page %x)", chunk_num,+						     page_to_phys(page),+						     (unsigned int)page);+					}+					vc_cma_chunks_used--;+				}+				LOG_DBG("CMA released %d chunks -> %d used",+					i, vc_cma_chunks_used);+			}+			break;++		case VC_CMA_MSG_UPDATE_RESERVE:{+				int chunks_needed =+				    ((vc_cma_reserve_total + VC_CMA_CHUNK_SIZE -+				      1)+				     / VC_CMA_CHUNK_SIZE) -+				    vc_cma_chunks_reserved;++				LOG_DBG+				    ("CMA_MSG_UPDATE_RESERVE(%d chunks needed)",+				     chunks_needed);++				/* Cap the reservations to what is available */+				if (chunks_needed > 0) {+					if (chunks_needed >+					    (vc_cma_chunks -+					     vc_cma_chunks_used))+						chunks_needed =+						    (vc_cma_chunks -+						     vc_cma_chunks_used);++					chunks_needed =+					    vc_cma_alloc_chunks(chunks_needed,+								&reply);+				}++				LOG_DBG+				    ("CMA_MSG_UPDATE_RESERVE(%d chunks allocated)",+				     chunks_needed);+				vc_cma_chunks_reserved += chunks_needed;+			}+			break;++		default:+			LOG_ERR("unexpected msg type %d", type);+			break;+		}+	}++	LOG_DBG("quitting...");+	return 0;+}++/****************************************************************************+*+*   vc_cma_connected_init+*+*   This function is called once the videocore has been connected.+*+***************************************************************************/++static void vc_cma_connected_init(void)+{+	VCHIQ_SERVICE_PARAMS_T service_params;++	LOG_DBG("vc_cma_connected_init");++	if (!vchiu_queue_init(&cma_msg_queue, 16)) {+		LOG_ERR("could not create CMA msg queue");+		goto fail_queue;+	}++	if (vchiq_initialise(&cma_instance) != VCHIQ_SUCCESS)+		goto fail_vchiq_init;++	vchiq_connect(cma_instance);++	service_params.fourcc = VC_CMA_FOURCC;+	service_params.callback = cma_service_callback;+	service_params.userdata = NULL;+	service_params.version = VC_CMA_VERSION;+	service_params.version_min = VC_CMA_VERSION;++	if (vchiq_open_service(cma_instance, &service_params,+			       &cma_service) != VCHIQ_SUCCESS) {+		LOG_ERR("failed to open service - already in use?");+		goto fail_vchiq_open;+	}++	vchiq_release_service(cma_service);++	cma_worker = kthread_create(cma_worker_proc, NULL, "cma_worker");+	if (!cma_worker) {+		LOG_ERR("could not create CMA worker thread");+		goto fail_worker;+	}+	set_user_nice(cma_worker, -20);+	wake_up_process(cma_worker);++	return;++fail_worker:+	vchiq_close_service(cma_service);+fail_vchiq_open:+	vchiq_shutdown(cma_instance);+fail_vchiq_init:+	vchiu_queue_delete(&cma_msg_queue);+fail_queue:+	return;+}++void+loud_error_header(void)+{+	if (in_loud_error)+		return;++	LOG_ERR("============================================================"+		"================");+	LOG_ERR("============================================================"+		"================");+	LOG_ERR("=====");++	in_loud_error = 1;+}++void+loud_error_footer(void)+{+	if (!in_loud_error)+		return;++	LOG_ERR("=====");+	LOG_ERR("============================================================"+		"================");+	LOG_ERR("============================================================"+		"================");++	in_loud_error = 0;+}++#if 1+static int check_cma_config(void) { return 1; }+#else+static int+read_vc_debug_var(VC_MEM_ACCESS_HANDLE_T handle,+	const char *symbol,+	void *buf, size_t bufsize)+{+	VC_MEM_ADDR_T vcMemAddr;+	size_t vcMemSize;+	uint8_t *mapAddr;+	off_t  vcMapAddr;++	if (!LookupVideoCoreSymbol(handle, symbol,+		&vcMemAddr,+		&vcMemSize)) {+		loud_error_header();+		loud_error(+			"failed to find VC symbol \"%s\".",+			symbol);+		loud_error_footer();+		return 0;+	}++	if (vcMemSize != bufsize) {+		loud_error_header();+		loud_error(+			"VC symbol \"%s\" is the wrong size.",+			symbol);+		loud_error_footer();+		return 0;+	}++	vcMapAddr = (off_t)vcMemAddr & VC_MEM_TO_ARM_ADDR_MASK;+	vcMapAddr += mm_vc_mem_phys_addr;+	mapAddr = ioremap_nocache(vcMapAddr, vcMemSize);+	if (mapAddr == 0) {+		loud_error_header();+		loud_error(+			"failed to ioremap \"%s\" @ 0x%x "+			"(phys: 0x%x, size: %u).",+			symbol,+			(unsigned int)vcMapAddr,+			(unsigned int)vcMemAddr,+			(unsigned int)vcMemSize);+		loud_error_footer();+		return 0;+	}++	memcpy(buf, mapAddr, bufsize);+	iounmap(mapAddr);++	return 1;+}+++static int+check_cma_config(void)+{+	VC_MEM_ACCESS_HANDLE_T mem_hndl;+	VC_MEM_ADDR_T mempool_start;+	VC_MEM_ADDR_T mempool_end;+	VC_MEM_ADDR_T mempool_offline_start;+	VC_MEM_ADDR_T mempool_offline_end;+	VC_MEM_ADDR_T cam_alloc_base;+	VC_MEM_ADDR_T cam_alloc_size;+	VC_MEM_ADDR_T cam_alloc_end;+	int success = 0;++	if (OpenVideoCoreMemory(&mem_hndl) != 0)+		goto out;++	/* Read the relevant VideoCore variables */+	if (!read_vc_debug_var(mem_hndl, "__MEMPOOL_START",+		&mempool_start,+		sizeof(mempool_start)))+		goto close;++	if (!read_vc_debug_var(mem_hndl, "__MEMPOOL_END",+		&mempool_end,+		sizeof(mempool_end)))+		goto close;++	if (!read_vc_debug_var(mem_hndl, "__MEMPOOL_OFFLINE_START",+		&mempool_offline_start,+		sizeof(mempool_offline_start)))+		goto close;++	if (!read_vc_debug_var(mem_hndl, "__MEMPOOL_OFFLINE_END",+		&mempool_offline_end,+		sizeof(mempool_offline_end)))+		goto close;++	if (!read_vc_debug_var(mem_hndl, "cam_alloc_base",+		&cam_alloc_base,+		sizeof(cam_alloc_base)))+		goto close;++	if (!read_vc_debug_var(mem_hndl, "cam_alloc_size",+		&cam_alloc_size,+		sizeof(cam_alloc_size)))+		goto close;++	cam_alloc_end = cam_alloc_base + cam_alloc_size;++	success = 1;++	/* Now the sanity checks */+	if (!mempool_offline_start)+		mempool_offline_start = mempool_start;+	if (!mempool_offline_end)+		mempool_offline_end = mempool_end;++	if (VCADDR_TO_PHYSADDR(mempool_offline_start) != vc_cma_base) {+		loud_error_header();+		loud_error(+			"__MEMPOOL_OFFLINE_START(%x -> %lx) doesn't match "+			"vc_cma_base(%x)",+			mempool_offline_start,+			VCADDR_TO_PHYSADDR(mempool_offline_start),+			vc_cma_base);+		success = 0;+	}++	if (VCADDR_TO_PHYSADDR(mempool_offline_end) !=+		(vc_cma_base + vc_cma_size)) {+		loud_error_header();+		loud_error(+			"__MEMPOOL_OFFLINE_END(%x -> %lx) doesn't match "+			"vc_cma_base(%x) + vc_cma_size(%x) = %x",+			mempool_offline_start,+			VCADDR_TO_PHYSADDR(mempool_offline_end),+			vc_cma_base, vc_cma_size, vc_cma_base + vc_cma_size);+		success = 0;+	}++	if (mempool_end < mempool_start) {+		loud_error_header();+		loud_error(+			"__MEMPOOL_END(%x) must not be before "+			"__MEMPOOL_START(%x)",+			mempool_end,+			mempool_start);+		success = 0;+	}++	if (mempool_offline_end < mempool_offline_start) {+		loud_error_header();+		loud_error(+			"__MEMPOOL_OFFLINE_END(%x) must not be before "+			"__MEMPOOL_OFFLINE_START(%x)",+			mempool_offline_end,+			mempool_offline_start);+		success = 0;+	}++	if (mempool_offline_start < mempool_start) {+		loud_error_header();+		loud_error(+			"__MEMPOOL_OFFLINE_START(%x) must not be before "+			"__MEMPOOL_START(%x)",+			mempool_offline_start,+			mempool_start);+		success = 0;+	}++	if (mempool_offline_end > mempool_end) {+		loud_error_header();+		loud_error(+			"__MEMPOOL_OFFLINE_END(%x) must not be after "+			"__MEMPOOL_END(%x)",+			mempool_offline_end,+			mempool_end);+		success = 0;+	}++	if ((cam_alloc_base < mempool_end) &&+		(cam_alloc_end > mempool_start)) {+		loud_error_header();+		loud_error(+			"cam_alloc pool(%x-%x) overlaps "+			"mempool(%x-%x)",+			cam_alloc_base, cam_alloc_end,+			mempool_start, mempool_end);+		success = 0;+	}++	loud_error_footer();++close:+	CloseVideoCoreMemory(mem_hndl);++out:+	return success;+}+#endif++static int vc_cma_init(void)+{+	int rc = -EFAULT;+	struct device *dev;++	if (!check_cma_config())+		goto out_release;++	printk(KERN_INFO "vc-cma: Videocore CMA driver\n");+	printk(KERN_INFO "vc-cma: vc_cma_base      = 0x%08x\n", vc_cma_base);+	printk(KERN_INFO "vc-cma: vc_cma_size      = 0x%08x (%u MiB)\n",+	       vc_cma_size, vc_cma_size / (1024 * 1024));+	printk(KERN_INFO "vc-cma: vc_cma_initial   = 0x%08x (%u MiB)\n",+	       vc_cma_initial, vc_cma_initial / (1024 * 1024));++	vc_cma_base_page = phys_to_page(vc_cma_base);++	if (vc_cma_chunks) {+		int chunks_needed = vc_cma_initial / VC_CMA_CHUNK_SIZE;++		for (vc_cma_chunks_used = 0;+		     vc_cma_chunks_used < chunks_needed; vc_cma_chunks_used++) {+			struct page *chunk;+			chunk = dma_alloc_from_contiguous(NULL /*&vc_cma_device.dev*/,+							  PAGES_PER_CHUNK,+							  VC_CMA_CHUNK_ORDER);+			if (!chunk)+				break;+			BUG_ON(((page_to_phys(chunk) - vc_cma_base) %+				VC_CMA_CHUNK_SIZE) != 0);+		}+		if (vc_cma_chunks_used != chunks_needed) {+			LOG_ERR("%s: dma_alloc_from_contiguous failed (%d "+				"bytes, allocation %d of %d)",+				__func__, VC_CMA_CHUNK_SIZE,+				vc_cma_chunks_used, chunks_needed);+			goto out_release;+		}++		vchiq_add_connected_callback(vc_cma_connected_init);+	}++	rc = alloc_chrdev_region(&vc_cma_devnum, 0, 1, DRIVER_NAME);+	if (rc < 0) {+		LOG_ERR("%s: alloc_chrdev_region failed (rc=%d)", __func__, rc);+		goto out_release;+	}++	cdev_init(&vc_cma_cdev, &vc_cma_fops);+	rc = cdev_add(&vc_cma_cdev, vc_cma_devnum, 1);+	if (rc != 0) {+		LOG_ERR("%s: cdev_add failed (rc=%d)", __func__, rc);+		goto out_unregister;+	}++	vc_cma_class = class_create(THIS_MODULE, DRIVER_NAME);+	if (IS_ERR(vc_cma_class)) {+		rc = PTR_ERR(vc_cma_class);+		LOG_ERR("%s: class_create failed (rc=%d)", __func__, rc);+		goto out_cdev_del;+	}++	dev = device_create(vc_cma_class, NULL, vc_cma_devnum, NULL,+			    DRIVER_NAME);+	if (IS_ERR(dev)) {+		rc = PTR_ERR(dev);+		LOG_ERR("%s: device_create failed (rc=%d)", __func__, rc);+		goto out_class_destroy;+	}++	vc_cma_proc_entry = proc_create(DRIVER_NAME, 0444, NULL, &vc_cma_proc_fops);+	if (vc_cma_proc_entry == NULL) {+		rc = -EFAULT;+		LOG_ERR("%s: proc_create failed", __func__);+		goto out_device_destroy;+	}++	vc_cma_inited = 1;+	return 0;++out_device_destroy:+	device_destroy(vc_cma_class, vc_cma_devnum);++out_class_destroy:+	class_destroy(vc_cma_class);+	vc_cma_class = NULL;++out_cdev_del:+	cdev_del(&vc_cma_cdev);++out_unregister:+	unregister_chrdev_region(vc_cma_devnum, 1);++out_release:+	/* It is tempting to try to clean up by calling+	   dma_release_from_contiguous for all allocated chunks, but it isn't+	   a very safe thing to do. If vc_cma_initial is non-zero it is because+	   VideoCore is already using that memory, so giving it back to Linux+	   is likely to be fatal.+	 */+	return -1;+}++/****************************************************************************+*+*   vc_cma_exit+*+***************************************************************************/++static void __exit vc_cma_exit(void)+{+	LOG_DBG("%s: called", __func__);++	if (vc_cma_inited) {+		remove_proc_entry(DRIVER_NAME, NULL);+		device_destroy(vc_cma_class, vc_cma_devnum);+		class_destroy(vc_cma_class);+		cdev_del(&vc_cma_cdev);+		unregister_chrdev_region(vc_cma_devnum, 1);+	}+}++module_init(vc_cma_init);+module_exit(vc_cma_exit);+MODULE_LICENSE("GPL");+MODULE_AUTHOR("Broadcom Corporation");diff -Nur linux-3.11.10.orig/drivers/char/hw_random/bcm2708-rng.c linux-3.11.10/drivers/char/hw_random/bcm2708-rng.c--- linux-3.11.10.orig/drivers/char/hw_random/bcm2708-rng.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/char/hw_random/bcm2708-rng.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,117 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#include <linux/kernel.h>+#include <linux/module.h>+#include <linux/init.h>+#include <linux/hw_random.h>+#include <linux/printk.h>++#include <asm/io.h>+#include <mach/hardware.h>+#include <mach/platform.h>++#define RNG_CTRL		(0x0)+#define RNG_STATUS		(0x4)+#define RNG_DATA		(0x8)+#define RNG_FF_THRESHOLD	(0xc)++/* enable rng */+#define RNG_RBGEN               0x1+/* double speed, less random mode */+#define RNG_RBG2X               0x2++/* the initial numbers generated are "less random" so will be discarded */+#define RNG_WARMUP_COUNT      0x40000++static int bcm2708_rng_data_read(struct hwrng *rng, u32 *buffer)+{+	void __iomem *rng_base = (void __iomem *)rng->priv;+	unsigned words;+	/* wait for a random number to be in fifo */+        do {+		words = __raw_readl(rng_base + RNG_STATUS)>>24;+	}+        while (words == 0);+	/* read the random number */+	*buffer = __raw_readl(rng_base + RNG_DATA);+	return 4;+}++static struct hwrng bcm2708_rng_ops = {+	.name		= "bcm2708",+	.data_read	= bcm2708_rng_data_read,+};++static int __init bcm2708_rng_init(void)+{+	void __iomem *rng_base;+	int err;++	/* map peripheral */+	rng_base = ioremap(RNG_BASE, 0x10);+	pr_info("bcm2708_rng_init=%p\n", rng_base);+	if (!rng_base) {+		pr_err("bcm2708_rng_init failed to ioremap\n");+		return -ENOMEM;+	}+	bcm2708_rng_ops.priv = (unsigned long)rng_base;+	/* register driver */+	err = hwrng_register(&bcm2708_rng_ops);+	if (err) {+		pr_err("bcm2708_rng_init hwrng_register()=%d\n", err);+		iounmap(rng_base);+	} else {+		/* set warm-up count & enable */+		__raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS);+		__raw_writel(RNG_RBGEN, rng_base + RNG_CTRL);+	}+	return err;+}++static void __exit bcm2708_rng_exit(void)+{+	void __iomem *rng_base = (void __iomem *)bcm2708_rng_ops.priv;+	pr_info("bcm2708_rng_exit\n");+	/* disable rng hardware */+	__raw_writel(0, rng_base + RNG_CTRL);+	/* unregister driver */+	hwrng_unregister(&bcm2708_rng_ops);+	iounmap(rng_base);+}++module_init(bcm2708_rng_init);+module_exit(bcm2708_rng_exit);++MODULE_DESCRIPTION("BCM2708 H/W Random Number Generator (RNG) driver");+MODULE_LICENSE("GPL and additional rights");diff -Nur linux-3.11.10.orig/drivers/char/hw_random/Kconfig linux-3.11.10/drivers/char/hw_random/Kconfig--- linux-3.11.10.orig/drivers/char/hw_random/Kconfig	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/char/hw_random/Kconfig	2014-02-07 19:57:28.000000000 +0100@@ -314,3 +314,14 @@ 	  module will be called tpm-rng.  	  If unsure, say Y.++config HW_RANDOM_BCM2708+	tristate "BCM2708 generic true random number generator support"+	depends on HW_RANDOM && ARCH_BCM2708+	---help---+	 This driver provides the kernel-side support for the BCM2708 hardware.++	 To compile this driver as a module, choose M here: the+	 module will be called bcm2708-rng.++	 If unsure, say N.diff -Nur linux-3.11.10.orig/drivers/char/hw_random/Makefile linux-3.11.10/drivers/char/hw_random/Makefile--- linux-3.11.10.orig/drivers/char/hw_random/Makefile	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/char/hw_random/Makefile	2014-02-07 19:57:28.000000000 +0100@@ -27,3 +27,4 @@ obj-$(CONFIG_HW_RANDOM_EXYNOS)	+= exynos-rng.o obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o+obj-$(CONFIG_HW_RANDOM_BCM2708) += bcm2708-rng.odiff -Nur linux-3.11.10.orig/drivers/char/Kconfig linux-3.11.10/drivers/char/Kconfig--- linux-3.11.10.orig/drivers/char/Kconfig	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/char/Kconfig	2014-02-07 19:57:28.000000000 +0100@@ -574,6 +574,8 @@  source "drivers/s390/char/Kconfig" +source "drivers/char/broadcom/Kconfig"+ config MSM_SMD_PKT 	bool "Enable device interface for some SMD packet ports" 	default ndiff -Nur linux-3.11.10.orig/drivers/char/Makefile linux-3.11.10/drivers/char/Makefile--- linux-3.11.10.orig/drivers/char/Makefile	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/char/Makefile	2014-02-07 19:57:28.000000000 +0100@@ -62,3 +62,5 @@ js-rtc-y = rtc.o  obj-$(CONFIG_TILE_SROM)		+= tile-srom.o++obj-$(CONFIG_BRCM_CHAR_DRIVERS) += broadcom/diff -Nur linux-3.11.10.orig/drivers/cpufreq/bcm2835-cpufreq.c linux-3.11.10/drivers/cpufreq/bcm2835-cpufreq.c--- linux-3.11.10.orig/drivers/cpufreq/bcm2835-cpufreq.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/cpufreq/bcm2835-cpufreq.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,238 @@+/*****************************************************************************+* Copyright 2011 Broadcom Corporation.  All rights reserved.+*+* Unless you and Broadcom execute a separate written software license+* agreement governing use of this software, this software is licensed to you+* under the terms of the GNU General Public License version 2, available at+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").+*+* Notwithstanding the above, under no circumstances may you combine this+* software in any way with any other Broadcom software provided under a+* license other than the GPL, without Broadcom's express prior written+* consent.+*****************************************************************************/++/*****************************************************************************+* FILENAME: bcm2835-cpufreq.h+* DESCRIPTION: This driver dynamically manages the CPU Frequency of the ARM+* processor. Messages are sent to Videocore either setting or requesting the+* frequency of the ARM in order to match an appropiate frequency to the current+* usage of the processor. The policy which selects the frequency to use is+* defined in the kernel .config file, but can be changed during runtime.+*****************************************************************************/++/* ---------- INCLUDES ---------- */+#include <linux/kernel.h>+#include <linux/init.h>+#include <linux/module.h>+#include <linux/cpufreq.h>+#include <mach/vcio.h>++/* ---------- DEFINES ---------- */+/*#define CPUFREQ_DEBUG_ENABLE*/		/* enable debugging */+#define MODULE_NAME "bcm2835-cpufreq"++#define VCMSG_ID_ARM_CLOCK 0x000000003		/* Clock/Voltage ID's */++/* debug printk macros */+#ifdef CPUFREQ_DEBUG_ENABLE+#define print_debug(fmt,...) pr_debug("%s:%s:%d: "fmt, MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__)+#else+#define print_debug(fmt,...)+#endif+#define print_err(fmt,...) pr_err("%s:%s:%d: "fmt, MODULE_NAME, __func__,__LINE__, ##__VA_ARGS__)+#define print_info(fmt,...) pr_info("%s: "fmt, MODULE_NAME, ##__VA_ARGS__)++/* tag part of the message */+struct vc_msg_tag {+	uint32_t tag_id;		/* the message id */+	uint32_t buffer_size;		/* size of the buffer (which in this case is always 8 bytes) */+	uint32_t data_size;		/* amount of data being sent or received */+	uint32_t dev_id;		/* the ID of the clock/voltage to get or set */+	uint32_t val;			/* the value (e.g. rate (in Hz)) to set */+};++/* message structure to be sent to videocore */+struct vc_msg {+	uint32_t msg_size;		/* simply, sizeof(struct vc_msg) */+	uint32_t request_code;		/* holds various information like the success and number of bytes returned (refer to mailboxes wiki) */+	struct vc_msg_tag tag;		/* the tag structure above to make */+	uint32_t end_tag;		/* an end identifier, should be set to NULL */+};++/* ---------- GLOBALS ---------- */+static struct cpufreq_driver bcm2835_cpufreq_driver;	/* the cpufreq driver global */++/*+ ===============================================+  clk_rate either gets or sets the clock rates.+ ===============================================+*/+static uint32_t bcm2835_cpufreq_set_clock(int cur_rate, int arm_rate)+{+	int s, actual_rate=0;+	struct vc_msg msg;++	/* wipe all previous message data */+	memset(&msg, 0, sizeof msg);++	msg.msg_size = sizeof msg;++	msg.tag.tag_id = VCMSG_SET_CLOCK_RATE;+	msg.tag.buffer_size = 8;+	msg.tag.data_size = 8;   /* we're sending the clock ID and the new rates which is a total of 2 words */+	msg.tag.dev_id = VCMSG_ID_ARM_CLOCK;+	msg.tag.val = arm_rate * 1000;++	/* send the message */+	s = bcm_mailbox_property(&msg, sizeof msg);++	/* check if it was all ok and return the rate in KHz */+	if (s == 0 && (msg.request_code & 0x80000000))+		actual_rate = msg.tag.val/1000;++	print_debug("Setting new frequency = %d -> %d (actual %d)\n", cur_rate, arm_rate, actual_rate);+	return actual_rate;+}++static uint32_t bcm2835_cpufreq_get_clock(int tag)+{+	int s;+	int arm_rate = 0;+	struct vc_msg msg;++	/* wipe all previous message data */+	memset(&msg, 0, sizeof msg);++	msg.msg_size = sizeof msg;+	msg.tag.tag_id = tag;+	msg.tag.buffer_size = 8;+	msg.tag.data_size = 4; /* we're just sending the clock ID which is one word long */+	msg.tag.dev_id = VCMSG_ID_ARM_CLOCK;++	/* send the message */+	s = bcm_mailbox_property(&msg, sizeof msg);++	/* check if it was all ok and return the rate in KHz */+	if (s == 0 && (msg.request_code & 0x80000000))+		arm_rate = msg.tag.val/1000;++	print_debug("%s frequency = %d\n",+		tag == VCMSG_GET_CLOCK_RATE ? "Current":+		tag == VCMSG_GET_MIN_CLOCK ? "Min":+		tag == VCMSG_GET_MAX_CLOCK ? "Max":+		"Unexpected", arm_rate);++	return arm_rate;+}++/*+ ====================================================+  Module Initialisation registers the cpufreq driver+ ====================================================+*/+static int __init bcm2835_cpufreq_module_init(void)+{+	print_debug("IN\n");+	return cpufreq_register_driver(&bcm2835_cpufreq_driver);+}++/*+ =============+  Module exit+ =============+*/+static void __exit bcm2835_cpufreq_module_exit(void)+{+	print_debug("IN\n");+	cpufreq_unregister_driver(&bcm2835_cpufreq_driver);+	return;+}++/*+ ==============================================================+  Initialisation function sets up the CPU policy for first use+ ==============================================================+*/+static int bcm2835_cpufreq_driver_init(struct cpufreq_policy *policy)+{+	/* measured value of how long it takes to change frequency */+	policy->cpuinfo.transition_latency = 355000; /* ns */++	/* now find out what the maximum and minimum frequencies are */+	policy->min = policy->cpuinfo.min_freq = bcm2835_cpufreq_get_clock(VCMSG_GET_MIN_CLOCK);+	policy->max = policy->cpuinfo.max_freq = bcm2835_cpufreq_get_clock(VCMSG_GET_MAX_CLOCK);+	policy->cur = bcm2835_cpufreq_get_clock(VCMSG_GET_CLOCK_RATE);++	print_info("min=%d max=%d cur=%d\n", policy->min, policy->max, policy->cur);+	return 0;+}++/*+ =================================================================================+  Target function chooses the most appropriate frequency from the table to enable+ =================================================================================+*/++static int bcm2835_cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation)+{+	unsigned int target = target_freq;+	unsigned int cur = policy->cur;+	print_debug("%s: min=%d max=%d cur=%d target=%d\n",policy->governor->name,policy->min,policy->max,policy->cur,target_freq);++	/* if we are above min and using ondemand, then just use max */+	if (strcmp("ondemand", policy->governor->name)==0 && target > policy->min)+		target = policy->max;+	/* if the frequency is the same, just quit */+	if (target == policy->cur)+		return 0;++	/* otherwise were good to set the clock frequency */+	policy->cur = bcm2835_cpufreq_set_clock(policy->cur, target);++	if (!policy->cur)+	{+		print_err("Error occurred setting a new frequency (%d)!\n", target);+		policy->cur = bcm2835_cpufreq_get_clock(VCMSG_GET_CLOCK_RATE);+		return -EINVAL;+	}+	print_debug("Freq %d->%d (min=%d max=%d target=%d request=%d)\n", cur, policy->cur, policy->min, policy->max, target_freq, target);+	return 0;+}++static unsigned int bcm2835_cpufreq_driver_get(unsigned int cpu)+{+	unsigned int actual_rate = bcm2835_cpufreq_get_clock(VCMSG_GET_CLOCK_RATE);+	print_debug("cpu=%d\n", actual_rate);+	return actual_rate;+}++/*+ =================================================================================+  Verify ensures that when a policy is changed, it is suitable for the CPU to use+ =================================================================================+*/++static int bcm2835_cpufreq_driver_verify(struct cpufreq_policy *policy)+{+	print_info("switching to governor %s\n", policy->governor->name);+	return 0;+}+++/* the CPUFreq driver */+static struct cpufreq_driver bcm2835_cpufreq_driver = {+		.name   = "BCM2835 CPUFreq",+		.owner  = THIS_MODULE,+		.init   = bcm2835_cpufreq_driver_init,+		.verify = bcm2835_cpufreq_driver_verify,+		.target = bcm2835_cpufreq_driver_target,+		.get    = bcm2835_cpufreq_driver_get+};++MODULE_AUTHOR("Dorian Peake and Dom Cobley");+MODULE_DESCRIPTION("CPU frequency driver for BCM2835 chip");+MODULE_LICENSE("GPL");++module_init(bcm2835_cpufreq_module_init);+module_exit(bcm2835_cpufreq_module_exit);diff -Nur linux-3.11.10.orig/drivers/cpufreq/Kconfig.arm linux-3.11.10/drivers/cpufreq/Kconfig.arm--- linux-3.11.10.orig/drivers/cpufreq/Kconfig.arm	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/cpufreq/Kconfig.arm	2014-02-07 19:57:28.000000000 +0100@@ -216,6 +216,14 @@ 	help 	  This adds the CPUFreq driver support for SPEAr SOCs. +config ARM_BCM2835_CPUFREQ+	bool "BCM2835 Driver"+	default y+	help+	  This adds the CPUFreq driver for BCM2835++	  If in doubt, say N.+ config ARM_TEGRA_CPUFREQ 	bool "TEGRA CPUFreq support" 	depends on ARCH_TEGRAdiff -Nur linux-3.11.10.orig/drivers/cpufreq/Makefile linux-3.11.10/drivers/cpufreq/Makefile--- linux-3.11.10.orig/drivers/cpufreq/Makefile	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/cpufreq/Makefile	2014-02-07 19:57:28.000000000 +0100@@ -76,6 +76,7 @@ obj-$(CONFIG_ARM_SA1100_CPUFREQ)	+= sa1100-cpufreq.o obj-$(CONFIG_ARM_SA1110_CPUFREQ)	+= sa1110-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ)		+= spear-cpufreq.o+obj-$(CONFIG_ARM_BCM2835_CPUFREQ)	+= bcm2835-cpufreq.o obj-$(CONFIG_ARM_TEGRA_CPUFREQ)		+= tegra-cpufreq.o  ##################################################################################diff -Nur linux-3.11.10.orig/drivers/hwmon/bcm2835-hwmon.c linux-3.11.10/drivers/hwmon/bcm2835-hwmon.c--- linux-3.11.10.orig/drivers/hwmon/bcm2835-hwmon.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/hwmon/bcm2835-hwmon.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,219 @@+/*****************************************************************************+* Copyright 2011 Broadcom Corporation.  All rights reserved.+*+* Unless you and Broadcom execute a separate written software license+* agreement governing use of this software, this software is licensed to you+* under the terms of the GNU General Public License version 2, available at+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").+*+* Notwithstanding the above, under no circumstances may you combine this+* software in any way with any other Broadcom software provided under a+* license other than the GPL, without Broadcom's express prior written+* consent.+*****************************************************************************/++#include <linux/kernel.h>+#include <linux/module.h>+#include <linux/init.h>+#include <linux/hwmon.h>+#include <linux/hwmon-sysfs.h>+#include <linux/platform_device.h>+#include <linux/sysfs.h>+#include <mach/vcio.h>+#include <linux/slab.h>+#include <linux/err.h>++#define MODULE_NAME "bcm2835_hwmon"++/*#define HWMON_DEBUG_ENABLE*/++#ifdef HWMON_DEBUG_ENABLE+#define print_debug(fmt,...) printk(KERN_INFO "%s:%s:%d: "fmt"\n", MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__)+#else+#define print_debug(fmt,...)+#endif+#define print_err(fmt,...) printk(KERN_ERR "%s:%s:%d: "fmt"\n", MODULE_NAME, __func__,__LINE__, ##__VA_ARGS__)+#define print_info(fmt,...) printk(KERN_INFO "%s: "fmt"\n", MODULE_NAME, ##__VA_ARGS__)++#define VC_TAG_GET_TEMP 0x00030006+#define VC_TAG_GET_MAX_TEMP 0x0003000A++/* --- STRUCTS --- */+struct bcm2835_hwmon_data {+	struct device *hwmon_dev;+};++/* tag part of the message */+struct vc_msg_tag {+	uint32_t tag_id;		/* the tag ID for the temperature */+	uint32_t buffer_size;	/* size of the buffer (should be 8) */+	uint32_t request_code;	/* identifies message as a request (should be 0) */+	uint32_t id;			/* extra ID field (should be 0) */+	uint32_t val;			/* returned value of the temperature */+};++/* message structure to be sent to videocore */+struct vc_msg {+	uint32_t msg_size;		/* simply, sizeof(struct vc_msg) */+	uint32_t request_code;		/* holds various information like the success and number of bytes returned (refer to mailboxes wiki) */+	struct vc_msg_tag tag;		/* the tag structure above to make */+	uint32_t end_tag;		/* an end identifier, should be set to NULL */+};++typedef enum {+	TEMP,+	MAX_TEMP,+} temp_type;++/* --- PROTOTYPES --- */+static ssize_t bcm2835_get_temp(struct device *dev, struct device_attribute *attr, char *buf);+static ssize_t bcm2835_get_name(struct device *dev, struct device_attribute *attr, char *buf);++/* --- GLOBALS --- */++static struct bcm2835_hwmon_data *bcm2835_data;+static struct platform_driver bcm2835_hwmon_driver;++static SENSOR_DEVICE_ATTR(name, S_IRUGO,bcm2835_get_name,NULL,0);+static SENSOR_DEVICE_ATTR(temp1_input,S_IRUGO,bcm2835_get_temp,NULL,TEMP);+static SENSOR_DEVICE_ATTR(temp1_max,S_IRUGO,bcm2835_get_temp,NULL,MAX_TEMP);++static struct attribute* bcm2835_attributes[] = {+	&sensor_dev_attr_name.dev_attr.attr,+	&sensor_dev_attr_temp1_input.dev_attr.attr,+	&sensor_dev_attr_temp1_max.dev_attr.attr,+	NULL,+};++static struct attribute_group bcm2835_attr_group = {+	.attrs = bcm2835_attributes,+};++/* --- FUNCTIONS --- */++static ssize_t bcm2835_get_name(struct device *dev, struct device_attribute *attr, char *buf)+{+	return sprintf(buf,"bcm2835_hwmon\n");+}++static ssize_t bcm2835_get_temp(struct device *dev, struct device_attribute *attr, char *buf)+{+	struct vc_msg msg;+	int result;+	uint temp = 0;+	int index = ((struct sensor_device_attribute*)to_sensor_dev_attr(attr))->index;++	print_debug("IN");++	/* wipe all previous message data */+	memset(&msg, 0, sizeof msg);++	/* determine the message type */+	if(index == TEMP)+		msg.tag.tag_id = VC_TAG_GET_TEMP;+	else if (index == MAX_TEMP)+		msg.tag.tag_id = VC_TAG_GET_MAX_TEMP;+	else+	{+		print_debug("Unknown temperature message!");+		return -EINVAL;+	}++	msg.msg_size = sizeof msg;+	msg.tag.buffer_size = 8;++	/* send the message */+	result = bcm_mailbox_property(&msg, sizeof msg);++	/* check if it was all ok and return the rate in milli degrees C */+	if (result == 0 && (msg.request_code & 0x80000000))+		temp = (uint)msg.tag.val;+	#ifdef HWMON_DEBUG_ENABLE+	else+		print_debug("Failed to get temperature!");+	#endif+	print_debug("Got temperature as %u",temp);+	print_debug("OUT");+	return sprintf(buf, "%u\n", temp);+}+++static int bcm2835_hwmon_probe(struct platform_device *pdev)+{+	int err;++	print_debug("IN");+	print_debug("HWMON Driver has been probed!");++	/* check that the device isn't null!*/+	if(pdev == NULL)+	{+		print_debug("Platform device is empty!");+		return -ENODEV;+	}++	/* allocate memory for neccessary data */+	bcm2835_data = kzalloc(sizeof(struct bcm2835_hwmon_data),GFP_KERNEL);+	if(!bcm2835_data)+	{+		print_debug("Unable to allocate memory for hwmon data!");+		err = -ENOMEM;+		goto kzalloc_error;+	}++	/* create the sysfs files */+	if(sysfs_create_group(&pdev->dev.kobj, &bcm2835_attr_group))+	{+		print_debug("Unable to create sysfs files!");+		err = -EFAULT;+		goto sysfs_error;+	}++	/* register the hwmon device */+	bcm2835_data->hwmon_dev = hwmon_device_register(&pdev->dev);+	if (IS_ERR(bcm2835_data->hwmon_dev))+	{+		err = PTR_ERR(bcm2835_data->hwmon_dev);+		goto hwmon_error;+	}+	print_debug("OUT");+	return 0;++	/* error goto's */+	hwmon_error:+	sysfs_remove_group(&pdev->dev.kobj, &bcm2835_attr_group);++	sysfs_error:+	kfree(bcm2835_data);++	kzalloc_error:++	return err;++}++static int bcm2835_hwmon_remove(struct platform_device *pdev)+{+	print_debug("IN");+	hwmon_device_unregister(bcm2835_data->hwmon_dev);++	sysfs_remove_group(&pdev->dev.kobj, &bcm2835_attr_group);+	print_debug("OUT");+	return 0;+}++/* Hwmon Driver */+static struct platform_driver bcm2835_hwmon_driver = {+	.probe = bcm2835_hwmon_probe,+	.remove = bcm2835_hwmon_remove,+	.driver = {+				.name = "bcm2835_hwmon",+				.owner = THIS_MODULE,+			},+};++MODULE_LICENSE("GPL");+MODULE_AUTHOR("Dorian Peake");+MODULE_DESCRIPTION("HW Monitor driver for bcm2835 chip");++module_platform_driver(bcm2835_hwmon_driver);diff -Nur linux-3.11.10.orig/drivers/hwmon/Kconfig linux-3.11.10/drivers/hwmon/Kconfig--- linux-3.11.10.orig/drivers/hwmon/Kconfig	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/hwmon/Kconfig	2014-02-07 19:57:28.000000000 +0100@@ -1543,6 +1543,16 @@         help           Support for the A/D converter on MC13783 and MC13892 PMIC. +config SENSORS_BCM2835+	depends on THERMAL_BCM2835=n+	tristate "Broadcom BCM2835 HWMON Driver"+	help+	  If you say yes here you get support for the hardware+	  monitoring features of the BCM2835 Chip++	  This driver can also be built as a module.  If so, the module+	  will be called bcm2835-hwmon.+ if ACPI  comment "ACPI drivers"diff -Nur linux-3.11.10.orig/drivers/hwmon/Makefile linux-3.11.10/drivers/hwmon/Makefile--- linux-3.11.10.orig/drivers/hwmon/Makefile	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/hwmon/Makefile	2014-02-07 19:57:28.000000000 +0100@@ -141,6 +141,7 @@ obj-$(CONFIG_SENSORS_W83L786NG)	+= w83l786ng.o obj-$(CONFIG_SENSORS_WM831X)	+= wm831x-hwmon.o obj-$(CONFIG_SENSORS_WM8350)	+= wm8350-hwmon.o+obj-$(CONFIG_SENSORS_BCM2835)	+= bcm2835-hwmon.o  obj-$(CONFIG_PMBUS)		+= pmbus/ diff -Nur linux-3.11.10.orig/drivers/i2c/busses/i2c-bcm2708.c linux-3.11.10/drivers/i2c/busses/i2c-bcm2708.c--- linux-3.11.10.orig/drivers/i2c/busses/i2c-bcm2708.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/i2c/busses/i2c-bcm2708.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,408 @@+/*+ * Driver for Broadcom BCM2708 BSC Controllers+ *+ * Copyright (C) 2012 Chris Boot & Frank Buss+ *+ * This driver is inspired by:+ * i2c-ocores.c, by Peter Korsgaard <jacmet@sunsite.dk>+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.+ */++#include <linux/kernel.h>+#include <linux/module.h>+#include <linux/spinlock.h>+#include <linux/clk.h>+#include <linux/err.h>+#include <linux/platform_device.h>+#include <linux/io.h>+#include <linux/slab.h>+#include <linux/i2c.h>+#include <linux/interrupt.h>+#include <linux/sched.h>+#include <linux/wait.h>++/* BSC register offsets */+#define BSC_C			0x00+#define BSC_S			0x04+#define BSC_DLEN		0x08+#define BSC_A			0x0c+#define BSC_FIFO		0x10+#define BSC_DIV			0x14+#define BSC_DEL			0x18+#define BSC_CLKT		0x1c++/* Bitfields in BSC_C */+#define BSC_C_I2CEN		0x00008000+#define BSC_C_INTR		0x00000400+#define BSC_C_INTT		0x00000200+#define BSC_C_INTD		0x00000100+#define BSC_C_ST		0x00000080+#define BSC_C_CLEAR_1		0x00000020+#define BSC_C_CLEAR_2		0x00000010+#define BSC_C_READ		0x00000001++/* Bitfields in BSC_S */+#define BSC_S_CLKT		0x00000200+#define BSC_S_ERR		0x00000100+#define BSC_S_RXF		0x00000080+#define BSC_S_TXE		0x00000040+#define BSC_S_RXD		0x00000020+#define BSC_S_TXD		0x00000010+#define BSC_S_RXR		0x00000008+#define BSC_S_TXW		0x00000004+#define BSC_S_DONE		0x00000002+#define BSC_S_TA		0x00000001++#define I2C_TIMEOUT_MS	150++#define DRV_NAME	"bcm2708_i2c"++static unsigned int baudrate = CONFIG_I2C_BCM2708_BAUDRATE;+module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);+MODULE_PARM_DESC(baudrate, "The I2C baudrate");+++struct bcm2708_i2c {+	struct i2c_adapter adapter;++	spinlock_t lock;+	void __iomem *base;+	int irq;+	struct clk *clk;++	struct completion done;++	struct i2c_msg *msg;+	int pos;+	int nmsgs;+	bool error;+};++/*+ * This function sets the ALT mode on the I2C pins so that we can use them with+ * the BSC hardware.+ *+ * FIXME: This is a hack. Use pinmux / pinctrl.+ */+static void bcm2708_i2c_init_pinmode(int id)+{+#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))+#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))++	int pin;+	u32 *gpio = ioremap(0x20200000, SZ_16K);++        BUG_ON(id != 0 && id != 1);+	/* BSC0 is on GPIO 0 & 1, BSC1 is on GPIO 2 & 3 */+	for (pin = id*2+0; pin <= id*2+1; pin++) {+printk("bcm2708_i2c_init_pinmode(%d,%d)\n", id, pin);+		INP_GPIO(pin);		/* set mode to GPIO input first */+		SET_GPIO_ALT(pin, 0);	/* set mode to ALT 0 */+	}++	iounmap(gpio);++#undef INP_GPIO+#undef SET_GPIO_ALT+}++static inline u32 bcm2708_rd(struct bcm2708_i2c *bi, unsigned reg)+{+	return readl(bi->base + reg);+}++static inline void bcm2708_wr(struct bcm2708_i2c *bi, unsigned reg, u32 val)+{+	writel(val, bi->base + reg);+}++static inline void bcm2708_bsc_reset(struct bcm2708_i2c *bi)+{+	bcm2708_wr(bi, BSC_C, 0);+	bcm2708_wr(bi, BSC_S, BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE);+}++static inline void bcm2708_bsc_fifo_drain(struct bcm2708_i2c *bi)+{+	while ((bcm2708_rd(bi, BSC_S) & BSC_S_RXD) && (bi->pos < bi->msg->len))+		bi->msg->buf[bi->pos++] = bcm2708_rd(bi, BSC_FIFO);+}++static inline void bcm2708_bsc_fifo_fill(struct bcm2708_i2c *bi)+{+	while ((bcm2708_rd(bi, BSC_S) & BSC_S_TXD) && (bi->pos < bi->msg->len))+		bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]);+}++static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi)+{+	unsigned long bus_hz;+	u32 cdiv;+	u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1;++	bus_hz = clk_get_rate(bi->clk);+	cdiv = bus_hz / baudrate;++	if (bi->msg->flags & I2C_M_RD)+		c |= BSC_C_INTR | BSC_C_READ;+	else+		c |= BSC_C_INTT;++	bcm2708_wr(bi, BSC_DIV, cdiv);+	bcm2708_wr(bi, BSC_A, bi->msg->addr);+	bcm2708_wr(bi, BSC_DLEN, bi->msg->len);+	bcm2708_wr(bi, BSC_C, c);+}++static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id)+{+	struct bcm2708_i2c *bi = dev_id;+	bool handled = true;+	u32 s;++	spin_lock(&bi->lock);++	/* we may see camera interrupts on the "other" I2C channel+           Just return if we've not sent anything */+        if (!bi->nmsgs || !bi->msg )+		goto early_exit;++	s = bcm2708_rd(bi, BSC_S);++	if (s & (BSC_S_CLKT | BSC_S_ERR)) {+		bcm2708_bsc_reset(bi);+		bi->error = true;++		/* wake up our bh */+		complete(&bi->done);+	} else if (s & BSC_S_DONE) {+		bi->nmsgs--;++		if (bi->msg->flags & I2C_M_RD)+			bcm2708_bsc_fifo_drain(bi);++		bcm2708_bsc_reset(bi);++		if (bi->nmsgs) {+			/* advance to next message */+			bi->msg++;+			bi->pos = 0;+			bcm2708_bsc_setup(bi);+		} else {+			/* wake up our bh */+			complete(&bi->done);+		}+	} else if (s & BSC_S_TXW) {+		bcm2708_bsc_fifo_fill(bi);+	} else if (s & BSC_S_RXR) {+		bcm2708_bsc_fifo_drain(bi);+	} else {+		handled = false;+	}++early_exit:+	spin_unlock(&bi->lock);++	return handled ? IRQ_HANDLED : IRQ_NONE;+}++static int bcm2708_i2c_master_xfer(struct i2c_adapter *adap,+	struct i2c_msg *msgs, int num)+{+	struct bcm2708_i2c *bi = adap->algo_data;+	unsigned long flags;+	int ret;++	spin_lock_irqsave(&bi->lock, flags);++	INIT_COMPLETION(bi->done);+	bi->msg = msgs;+	bi->pos = 0;+	bi->nmsgs = num;+	bi->error = false;++	spin_unlock_irqrestore(&bi->lock, flags);++	bcm2708_bsc_setup(bi);++	ret = wait_for_completion_timeout(&bi->done,+			msecs_to_jiffies(I2C_TIMEOUT_MS));+	if (ret == 0) {+		dev_err(&adap->dev, "transfer timed out\n");+		spin_lock_irqsave(&bi->lock, flags);+		bcm2708_bsc_reset(bi);+		spin_unlock_irqrestore(&bi->lock, flags);+		return -ETIMEDOUT;+	}++	return bi->error ? -EIO : num;+}++static u32 bcm2708_i2c_functionality(struct i2c_adapter *adap)+{+	return I2C_FUNC_I2C | /*I2C_FUNC_10BIT_ADDR |*/ I2C_FUNC_SMBUS_EMUL;+}++static struct i2c_algorithm bcm2708_i2c_algorithm = {+	.master_xfer = bcm2708_i2c_master_xfer,+	.functionality = bcm2708_i2c_functionality,+};++static int bcm2708_i2c_probe(struct platform_device *pdev)+{+	struct resource *regs;+	int irq, err = -ENOMEM;+	struct clk *clk;+	struct bcm2708_i2c *bi;+	struct i2c_adapter *adap;++	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);+	if (!regs) {+		dev_err(&pdev->dev, "could not get IO memory\n");+		return -ENXIO;+	}++	irq = platform_get_irq(pdev, 0);+	if (irq < 0) {+		dev_err(&pdev->dev, "could not get IRQ\n");+		return irq;+	}++	clk = clk_get(&pdev->dev, NULL);+	if (IS_ERR(clk)) {+		dev_err(&pdev->dev, "could not find clk: %ld\n", PTR_ERR(clk));+		return PTR_ERR(clk);+	}++	bcm2708_i2c_init_pinmode(pdev->id);++	bi = kzalloc(sizeof(*bi), GFP_KERNEL);+	if (!bi)+		goto out_clk_put;++	platform_set_drvdata(pdev, bi);++	adap = &bi->adapter;+	adap->class = I2C_CLASS_HWMON | I2C_CLASS_DDC;+	adap->algo = &bcm2708_i2c_algorithm;+	adap->algo_data = bi;+	adap->dev.parent = &pdev->dev;+	adap->nr = pdev->id;+	strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));++	switch (pdev->id) {+	case 0:+		adap->class = I2C_CLASS_HWMON;+		break;+	case 1:+		adap->class = I2C_CLASS_DDC;+		break;+	default:+		dev_err(&pdev->dev, "can only bind to BSC 0 or 1\n");+		err = -ENXIO;+		goto out_free_bi;+	}++	spin_lock_init(&bi->lock);+	init_completion(&bi->done);++	bi->base = ioremap(regs->start, resource_size(regs));+	if (!bi->base) {+		dev_err(&pdev->dev, "could not remap memory\n");+		goto out_free_bi;+	}++	bi->irq = irq;+	bi->clk = clk;++	err = request_irq(irq, bcm2708_i2c_interrupt, IRQF_SHARED,+			dev_name(&pdev->dev), bi);+	if (err) {+		dev_err(&pdev->dev, "could not request IRQ: %d\n", err);+		goto out_iounmap;+	}++	bcm2708_bsc_reset(bi);++	err = i2c_add_numbered_adapter(adap);+	if (err < 0) {+		dev_err(&pdev->dev, "could not add I2C adapter: %d\n", err);+		goto out_free_irq;+	}++	dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d) (baudrate %dk)\n",+		pdev->id, (unsigned long)regs->start, irq, baudrate/1000);++	return 0;++out_free_irq:+	free_irq(bi->irq, bi);+out_iounmap:+	iounmap(bi->base);+out_free_bi:+	kfree(bi);+out_clk_put:+	clk_put(clk);+	return err;+}++static int bcm2708_i2c_remove(struct platform_device *pdev)+{+	struct bcm2708_i2c *bi = platform_get_drvdata(pdev);++	platform_set_drvdata(pdev, NULL);++	i2c_del_adapter(&bi->adapter);+	free_irq(bi->irq, bi);+	iounmap(bi->base);+	clk_disable(bi->clk);+	clk_put(bi->clk);+	kfree(bi);++	return 0;+}++static struct platform_driver bcm2708_i2c_driver = {+	.driver		= {+		.name	= DRV_NAME,+		.owner	= THIS_MODULE,+	},+	.probe		= bcm2708_i2c_probe,+	.remove		= bcm2708_i2c_remove,+};++// module_platform_driver(bcm2708_i2c_driver);+++static int __init bcm2708_i2c_init(void)+{+	return platform_driver_register(&bcm2708_i2c_driver);+}++static void __exit bcm2708_i2c_exit(void)+{+	platform_driver_unregister(&bcm2708_i2c_driver);+}++module_init(bcm2708_i2c_init);+module_exit(bcm2708_i2c_exit);++++MODULE_DESCRIPTION("BSC controller driver for Broadcom BCM2708");+MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");+MODULE_LICENSE("GPL v2");+MODULE_ALIAS("platform:" DRV_NAME);diff -Nur linux-3.11.10.orig/drivers/i2c/busses/Kconfig linux-3.11.10/drivers/i2c/busses/Kconfig--- linux-3.11.10.orig/drivers/i2c/busses/Kconfig	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/i2c/busses/Kconfig	2014-02-07 19:57:28.000000000 +0100@@ -345,6 +345,25 @@ 	  This support is also available as a module.  If so, the module 	  will be called i2c-bcm2835. +config I2C_BCM2708+	tristate "BCM2708 BSC"+	depends on MACH_BCM2708+	help+	  Enabling this option will add BSC (Broadcom Serial Controller)+	  support for the BCM2708. BSC is a Broadcom proprietary bus compatible+	  with I2C/TWI/SMBus.++config I2C_BCM2708_BAUDRATE+    prompt "BCM2708 I2C baudrate"+	depends on I2C_BCM2708+    int+    default 100000+    help+      Set the I2C baudrate. This will alter the default value. A+      different baudrate can be set by using a module parameter as well. If+      no parameter is provided when loading, this is the value that will be+      used.+ config I2C_BLACKFIN_TWI 	tristate "Blackfin TWI I2C support" 	depends on BLACKFINdiff -Nur linux-3.11.10.orig/drivers/i2c/busses/Makefile linux-3.11.10/drivers/i2c/busses/Makefile--- linux-3.11.10.orig/drivers/i2c/busses/Makefile	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/i2c/busses/Makefile	2014-02-07 19:57:28.000000000 +0100@@ -32,6 +32,7 @@ obj-$(CONFIG_I2C_AT91)		+= i2c-at91.o obj-$(CONFIG_I2C_AU1550)	+= i2c-au1550.o obj-$(CONFIG_I2C_BCM2835)	+= i2c-bcm2835.o+obj-$(CONFIG_I2C_BCM2708)	+= i2c-bcm2708.o obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o obj-$(CONFIG_I2C_CBUS_GPIO)	+= i2c-cbus-gpio.o obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.odiff -Nur linux-3.11.10.orig/drivers/media/usb/dvb-usb-v2/rtl28xxu.c linux-3.11.10/drivers/media/usb/dvb-usb-v2/rtl28xxu.c--- linux-3.11.10.orig/drivers/media/usb/dvb-usb-v2/rtl28xxu.c	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/media/usb/dvb-usb-v2/rtl28xxu.c	2014-02-07 19:57:28.000000000 +0100@@ -1384,6 +1384,10 @@ 		&rtl2832u_props, "Compro VideoMate U620F", NULL) }, 	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd394, 		&rtl2832u_props, "MaxMedia HU394-T", NULL) },+	{ DVB_USB_DEVICE(USB_VID_GTEK, 0xb803 /*USB_PID_AUGUST_DVBT205*/,+		&rtl2832u_props, "August DVB-T 205", NULL) },+	{ DVB_USB_DEVICE(USB_VID_GTEK, 0xa803 /*USB_PID_AUGUST_DVBT205*/,+		&rtl2832u_props, "August DVB-T 205", NULL) }, 	{ DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a03, 		&rtl2832u_props, "Leadtek WinFast DTV Dongle mini", NULL) }, 	{ DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_CPYTO_REDI_PC50A,diff -Nur linux-3.11.10.orig/drivers/misc/Kconfig linux-3.11.10/drivers/misc/Kconfig--- linux-3.11.10.orig/drivers/misc/Kconfig	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/misc/Kconfig	2014-02-07 19:57:28.000000000 +0100@@ -537,4 +537,5 @@ source "drivers/misc/altera-stapl/Kconfig" source "drivers/misc/mei/Kconfig" source "drivers/misc/vmw_vmci/Kconfig"+source "drivers/misc/vc04_services/Kconfig" endmenudiff -Nur linux-3.11.10.orig/drivers/misc/Makefile linux-3.11.10/drivers/misc/Makefile--- linux-3.11.10.orig/drivers/misc/Makefile	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/misc/Makefile	2014-02-07 19:57:28.000000000 +0100@@ -53,3 +53,4 @@ obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/ obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o obj-$(CONFIG_SRAM)		+= sram.o+obj-$(CONFIG_BCM2708_VCHIQ)	+= vc04_services/diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchi/connections/connection.h linux-3.11.10/drivers/misc/vc04_services/interface/vchi/connections/connection.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchi/connections/connection.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchi/connections/connection.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,328 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef CONNECTION_H_+#define CONNECTION_H_++#include <linux/kernel.h>+#include <linux/types.h>+#include <linux/semaphore.h>++#include "interface/vchi/vchi_cfg_internal.h"+#include "interface/vchi/vchi_common.h"+#include "interface/vchi/message_drivers/message.h"++/******************************************************************************+ Global defs+ *****************************************************************************/++// Opaque handle for a connection / service pair+typedef struct opaque_vchi_connection_connected_service_handle_t *VCHI_CONNECTION_SERVICE_HANDLE_T;++// opaque handle to the connection state information+typedef struct opaque_vchi_connection_info_t VCHI_CONNECTION_STATE_T;++typedef struct vchi_connection_t VCHI_CONNECTION_T;+++/******************************************************************************+ API+ *****************************************************************************/++// Routine to init a connection with a particular low level driver+typedef VCHI_CONNECTION_STATE_T * (*VCHI_CONNECTION_INIT_T)( struct vchi_connection_t * connection,+                                                             const VCHI_MESSAGE_DRIVER_T * driver );++// Routine to control CRC enabling at a connection level+typedef int32_t (*VCHI_CONNECTION_CRC_CONTROL_T)( VCHI_CONNECTION_STATE_T *state_handle,+                                                  VCHI_CRC_CONTROL_T control );++// Routine to create a service+typedef int32_t (*VCHI_CONNECTION_SERVICE_CONNECT_T)( VCHI_CONNECTION_STATE_T *state_handle,+                                                      int32_t service_id,+                                                      uint32_t rx_fifo_size,+                                                      uint32_t tx_fifo_size,+                                                      int server,+                                                      VCHI_CALLBACK_T callback,+                                                      void *callback_param,+                                                      int32_t want_crc,+                                                      int32_t want_unaligned_bulk_rx,+                                                      int32_t want_unaligned_bulk_tx,+                                                      VCHI_CONNECTION_SERVICE_HANDLE_T *service_handle );++// Routine to close a service+typedef int32_t (*VCHI_CONNECTION_SERVICE_DISCONNECT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle );++// Routine to queue a message+typedef int32_t (*VCHI_CONNECTION_SERVICE_QUEUE_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,+                                                            const void *data,+                                                            uint32_t data_size,+                                                            VCHI_FLAGS_T flags,+                                                            void *msg_handle );++// scatter-gather (vector) message queueing+typedef int32_t (*VCHI_CONNECTION_SERVICE_QUEUE_MESSAGEV_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,+                                                             VCHI_MSG_VECTOR_T *vector,+                                                             uint32_t count,+                                                             VCHI_FLAGS_T flags,+                                                             void *msg_handle );++// Routine to dequeue a message+typedef int32_t (*VCHI_CONNECTION_SERVICE_DEQUEUE_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,+                                                              void *data,+                                                              uint32_t max_data_size_to_read,+                                                              uint32_t *actual_msg_size,+                                                              VCHI_FLAGS_T flags );++// Routine to peek at a message+typedef int32_t (*VCHI_CONNECTION_SERVICE_PEEK_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,+                                                           void **data,+                                                           uint32_t *msg_size,+                                                           VCHI_FLAGS_T flags );++// Routine to hold a message+typedef int32_t (*VCHI_CONNECTION_SERVICE_HOLD_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,+                                                           void **data,+                                                           uint32_t *msg_size,+                                                           VCHI_FLAGS_T flags,+                                                           void **message_handle );++// Routine to initialise a received message iterator+typedef int32_t (*VCHI_CONNECTION_SERVICE_LOOKAHEAD_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,+                                                                VCHI_MSG_ITER_T *iter,+                                                                VCHI_FLAGS_T flags );++// Routine to release a held message+typedef int32_t (*VCHI_CONNECTION_HELD_MSG_RELEASE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,+                                                       void *message_handle );++// Routine to get info on a held message+typedef int32_t (*VCHI_CONNECTION_HELD_MSG_INFO_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,+                                                    void *message_handle,+                                                    void **data,+                                                    int32_t *msg_size,+                                                    uint32_t *tx_timestamp,+                                                    uint32_t *rx_timestamp );++// Routine to check whether the iterator has a next message+typedef int32_t (*VCHI_CONNECTION_MSG_ITER_HAS_NEXT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service,+                                                       const VCHI_MSG_ITER_T *iter );++// Routine to advance the iterator+typedef int32_t (*VCHI_CONNECTION_MSG_ITER_NEXT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service,+                                                    VCHI_MSG_ITER_T *iter,+                                                    void **data,+                                                    uint32_t *msg_size );++// Routine to remove the last message returned by the iterator+typedef int32_t (*VCHI_CONNECTION_MSG_ITER_REMOVE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service,+                                                      VCHI_MSG_ITER_T *iter );++// Routine to hold the last message returned by the iterator+typedef int32_t (*VCHI_CONNECTION_MSG_ITER_HOLD_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service,+                                                    VCHI_MSG_ITER_T *iter,+                                                    void **msg_handle );++// Routine to transmit bulk data+typedef int32_t (*VCHI_CONNECTION_BULK_QUEUE_TRANSMIT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,+                                                          const void *data_src,+                                                          uint32_t data_size,+                                                          VCHI_FLAGS_T flags,+                                                          void *bulk_handle );++// Routine to receive data+typedef int32_t (*VCHI_CONNECTION_BULK_QUEUE_RECEIVE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,+                                                         void *data_dst,+                                                         uint32_t data_size,+                                                         VCHI_FLAGS_T flags,+                                                         void *bulk_handle );++// Routine to report if a server is available+typedef int32_t (*VCHI_CONNECTION_SERVER_PRESENT)( VCHI_CONNECTION_STATE_T *state, int32_t service_id, int32_t peer_flags );++// Routine to report the number of RX slots available+typedef int (*VCHI_CONNECTION_RX_SLOTS_AVAILABLE)( const VCHI_CONNECTION_STATE_T *state );++// Routine to report the RX slot size+typedef uint32_t (*VCHI_CONNECTION_RX_SLOT_SIZE)( const VCHI_CONNECTION_STATE_T *state );++// Callback to indicate that the other side has added a buffer to the rx bulk DMA FIFO+typedef void (*VCHI_CONNECTION_RX_BULK_BUFFER_ADDED)(VCHI_CONNECTION_STATE_T *state,+                                                     int32_t service,+                                                     uint32_t length,+                                                     MESSAGE_TX_CHANNEL_T channel,+                                                     uint32_t channel_params,+                                                     uint32_t data_length,+                                                     uint32_t data_offset);++// Callback to inform a service that a Xon or Xoff message has been received+typedef void (*VCHI_CONNECTION_FLOW_CONTROL)(VCHI_CONNECTION_STATE_T *state, int32_t service_id, int32_t xoff);++// Callback to inform a service that a server available reply message has been received+typedef void (*VCHI_CONNECTION_SERVER_AVAILABLE_REPLY)(VCHI_CONNECTION_STATE_T *state, int32_t service_id, uint32_t flags);++// Callback to indicate that bulk auxiliary messages have arrived+typedef void (*VCHI_CONNECTION_BULK_AUX_RECEIVED)(VCHI_CONNECTION_STATE_T *state);++// Callback to indicate that bulk auxiliary messages have arrived+typedef void (*VCHI_CONNECTION_BULK_AUX_TRANSMITTED)(VCHI_CONNECTION_STATE_T *state, void *handle);++// Callback with all the connection info you require+typedef void (*VCHI_CONNECTION_INFO)(VCHI_CONNECTION_STATE_T *state, uint32_t protocol_version, uint32_t slot_size, uint32_t num_slots, uint32_t min_bulk_size);++// Callback to inform of a disconnect+typedef void (*VCHI_CONNECTION_DISCONNECT)(VCHI_CONNECTION_STATE_T *state, uint32_t flags);++// Callback to inform of a power control request+typedef void (*VCHI_CONNECTION_POWER_CONTROL)(VCHI_CONNECTION_STATE_T *state, MESSAGE_TX_CHANNEL_T channel, int32_t enable);++// allocate memory suitably aligned for this connection+typedef void * (*VCHI_BUFFER_ALLOCATE)(VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, uint32_t * length);++// free memory allocated by buffer_allocate+typedef void   (*VCHI_BUFFER_FREE)(VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, void * address);+++/******************************************************************************+ System driver struct+ *****************************************************************************/++struct opaque_vchi_connection_api_t+{+   // Routine to init the connection+   VCHI_CONNECTION_INIT_T                      init;++   // Connection-level CRC control+   VCHI_CONNECTION_CRC_CONTROL_T               crc_control;++   // Routine to connect to or create service+   VCHI_CONNECTION_SERVICE_CONNECT_T           service_connect;++   // Routine to disconnect from a service+   VCHI_CONNECTION_SERVICE_DISCONNECT_T        service_disconnect;++   // Routine to queue a message+   VCHI_CONNECTION_SERVICE_QUEUE_MESSAGE_T     service_queue_msg;++   // scatter-gather (vector) message queue+   VCHI_CONNECTION_SERVICE_QUEUE_MESSAGEV_T    service_queue_msgv;++   // Routine to dequeue a message+   VCHI_CONNECTION_SERVICE_DEQUEUE_MESSAGE_T   service_dequeue_msg;++   // Routine to peek at a message+   VCHI_CONNECTION_SERVICE_PEEK_MESSAGE_T      service_peek_msg;++   // Routine to hold a message+   VCHI_CONNECTION_SERVICE_HOLD_MESSAGE_T      service_hold_msg;++   // Routine to initialise a received message iterator+   VCHI_CONNECTION_SERVICE_LOOKAHEAD_MESSAGE_T service_look_ahead_msg;++   // Routine to release a message+   VCHI_CONNECTION_HELD_MSG_RELEASE_T          held_msg_release;++   // Routine to get information on a held message+   VCHI_CONNECTION_HELD_MSG_INFO_T             held_msg_info;++   // Routine to check for next message on iterator+   VCHI_CONNECTION_MSG_ITER_HAS_NEXT_T         msg_iter_has_next;++   // Routine to get next message on iterator+   VCHI_CONNECTION_MSG_ITER_NEXT_T             msg_iter_next;++   // Routine to remove the last message returned by iterator+   VCHI_CONNECTION_MSG_ITER_REMOVE_T           msg_iter_remove;++   // Routine to hold the last message returned by iterator+   VCHI_CONNECTION_MSG_ITER_HOLD_T             msg_iter_hold;++   // Routine to transmit bulk data+   VCHI_CONNECTION_BULK_QUEUE_TRANSMIT_T       bulk_queue_transmit;++   // Routine to receive data+   VCHI_CONNECTION_BULK_QUEUE_RECEIVE_T        bulk_queue_receive;++   // Routine to report the available servers+   VCHI_CONNECTION_SERVER_PRESENT              server_present;++   // Routine to report the number of RX slots available+   VCHI_CONNECTION_RX_SLOTS_AVAILABLE          connection_rx_slots_available;++   // Routine to report the RX slot size+   VCHI_CONNECTION_RX_SLOT_SIZE                connection_rx_slot_size;++   // Callback to indicate that the other side has added a buffer to the rx bulk DMA FIFO+   VCHI_CONNECTION_RX_BULK_BUFFER_ADDED        rx_bulk_buffer_added;++   // Callback to inform a service that a Xon or Xoff message has been received+   VCHI_CONNECTION_FLOW_CONTROL                flow_control;++   // Callback to inform a service that a server available reply message has been received+   VCHI_CONNECTION_SERVER_AVAILABLE_REPLY      server_available_reply;++   // Callback to indicate that bulk auxiliary messages have arrived+   VCHI_CONNECTION_BULK_AUX_RECEIVED           bulk_aux_received;++   // Callback to indicate that a bulk auxiliary message has been transmitted+   VCHI_CONNECTION_BULK_AUX_TRANSMITTED        bulk_aux_transmitted;++   // Callback to provide information about the connection+   VCHI_CONNECTION_INFO                        connection_info;++   // Callback to notify that peer has requested disconnect+   VCHI_CONNECTION_DISCONNECT                  disconnect;++   // Callback to notify that peer has requested power change+   VCHI_CONNECTION_POWER_CONTROL               power_control;++   // allocate memory suitably aligned for this connection+   VCHI_BUFFER_ALLOCATE                        buffer_allocate;++   // free memory allocated by buffer_allocate+   VCHI_BUFFER_FREE                            buffer_free;++};++struct vchi_connection_t {+   const VCHI_CONNECTION_API_T *api;+   VCHI_CONNECTION_STATE_T     *state;+#ifdef VCHI_COARSE_LOCKING+   struct semaphore             sem;+#endif+};+++#endif /* CONNECTION_H_ */++/****************************** End of file **********************************/diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h linux-3.11.10/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,204 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef _VCHI_MESSAGE_H_+#define _VCHI_MESSAGE_H_++#include <linux/kernel.h>+#include <linux/types.h>+#include <linux/semaphore.h>++#include "interface/vchi/vchi_cfg_internal.h"+#include "interface/vchi/vchi_common.h"+++typedef enum message_event_type {+   MESSAGE_EVENT_NONE,+   MESSAGE_EVENT_NOP,+   MESSAGE_EVENT_MESSAGE,+   MESSAGE_EVENT_SLOT_COMPLETE,+   MESSAGE_EVENT_RX_BULK_PAUSED,+   MESSAGE_EVENT_RX_BULK_COMPLETE,+   MESSAGE_EVENT_TX_COMPLETE,+   MESSAGE_EVENT_MSG_DISCARDED+} MESSAGE_EVENT_TYPE_T;++typedef enum vchi_msg_flags+{+   VCHI_MSG_FLAGS_NONE                  = 0x0,+   VCHI_MSG_FLAGS_TERMINATE_DMA         = 0x1+} VCHI_MSG_FLAGS_T;++typedef enum message_tx_channel+{+   MESSAGE_TX_CHANNEL_MESSAGE           = 0,+   MESSAGE_TX_CHANNEL_BULK              = 1 // drivers may provide multiple bulk channels, from 1 upwards+} MESSAGE_TX_CHANNEL_T;++// Macros used for cycling through bulk channels+#define MESSAGE_TX_CHANNEL_BULK_PREV(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION-1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION)+#define MESSAGE_TX_CHANNEL_BULK_NEXT(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION)++typedef enum message_rx_channel+{+   MESSAGE_RX_CHANNEL_MESSAGE           = 0,+   MESSAGE_RX_CHANNEL_BULK              = 1 // drivers may provide multiple bulk channels, from 1 upwards+} MESSAGE_RX_CHANNEL_T;++// Message receive slot information+typedef struct rx_msg_slot_info {++   struct rx_msg_slot_info *next;+   //struct slot_info *prev;+#if !defined VCHI_COARSE_LOCKING+   struct semaphore   sem;+#endif++   uint8_t           *addr;               // base address of slot+   uint32_t           len;                // length of slot in bytes++   uint32_t           write_ptr;          // hardware causes this to advance+   uint32_t           read_ptr;           // this module does the reading+   int                active;             // is this slot in the hardware dma fifo?+   uint32_t           msgs_parsed;        // count how many messages are in this slot+   uint32_t           msgs_released;      // how many messages have been released+   void              *state;              // connection state information+   uint8_t            ref_count[VCHI_MAX_SERVICES_PER_CONNECTION];          // reference count for slots held by services+} RX_MSG_SLOTINFO_T;++// The message driver no longer needs to know about the fields of RX_BULK_SLOTINFO_T - sort this out.+// In particular, it mustn't use addr and len - they're the client buffer, but the message+// driver will be tasked with sending the aligned core section.+typedef struct rx_bulk_slotinfo_t {+   struct rx_bulk_slotinfo_t *next;++   struct semaphore *blocking;++   // needed by DMA+   void        *addr;+   uint32_t     len;++   // needed for the callback+   void        *service;+   void        *handle;+   VCHI_FLAGS_T flags;+} RX_BULK_SLOTINFO_T;+++/* ----------------------------------------------------------------------+ * each connection driver will have a pool of the following struct.+ *+ * the pool will be managed by vchi_qman_*+ * this means there will be multiple queues (single linked lists)+ * a given struct message_info will be on exactly one of these queues+ * at any one time+ * -------------------------------------------------------------------- */+typedef struct rx_message_info {++   struct message_info *next;+   //struct message_info *prev;++   uint8_t    *addr;+   uint32_t   len;+   RX_MSG_SLOTINFO_T *slot; // points to whichever slot contains this message+   uint32_t   tx_timestamp;+   uint32_t   rx_timestamp;++} RX_MESSAGE_INFO_T;++typedef struct {+   MESSAGE_EVENT_TYPE_T type;++   struct {+      // for messages+      void    *addr;           // address of message+      uint16_t slot_delta;     // whether this message indicated slot delta+      uint32_t len;            // length of message+      RX_MSG_SLOTINFO_T *slot; // slot this message is in+      int32_t  service;   // service id this message is destined for+      uint32_t tx_timestamp;   // timestamp from the header+      uint32_t rx_timestamp;   // timestamp when we parsed it+   } message;++   // FIXME: cleanup slot reporting...+   RX_MSG_SLOTINFO_T *rx_msg;+   RX_BULK_SLOTINFO_T *rx_bulk;+   void *tx_handle;+   MESSAGE_TX_CHANNEL_T tx_channel;++} MESSAGE_EVENT_T;+++// callbacks+typedef void VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T( void *state );++typedef struct {+   VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T *event_callback;+} VCHI_MESSAGE_DRIVER_OPEN_T;+++// handle to this instance of message driver (as returned by ->open)+typedef struct opaque_mhandle_t *VCHI_MDRIVER_HANDLE_T;++struct opaque_vchi_message_driver_t {+   VCHI_MDRIVER_HANDLE_T *(*open)( VCHI_MESSAGE_DRIVER_OPEN_T *params, void *state );+   int32_t (*suspending)( VCHI_MDRIVER_HANDLE_T *handle );+   int32_t (*resumed)( VCHI_MDRIVER_HANDLE_T *handle );+   int32_t (*power_control)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T, int32_t enable );+   int32_t (*add_msg_rx_slot)( VCHI_MDRIVER_HANDLE_T *handle, RX_MSG_SLOTINFO_T *slot );      // rx message+   int32_t (*add_bulk_rx)( VCHI_MDRIVER_HANDLE_T *handle, void *data, uint32_t len, RX_BULK_SLOTINFO_T *slot );  // rx data (bulk)+   int32_t (*send)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, VCHI_MSG_FLAGS_T flags, void *send_handle );      // tx (message & bulk)+   void    (*next_event)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_EVENT_T *event );     // get the next event from message_driver+   int32_t (*enable)( VCHI_MDRIVER_HANDLE_T *handle );+   int32_t (*form_message)( VCHI_MDRIVER_HANDLE_T *handle, int32_t service_id, VCHI_MSG_VECTOR_T *vector, uint32_t count, void+                            *address, uint32_t length_avail, uint32_t max_total_length, int32_t pad_to_fill, int32_t allow_partial );++   int32_t (*update_message)( VCHI_MDRIVER_HANDLE_T *handle, void *dest, int16_t *slot_count );+   int32_t (*buffer_aligned)( VCHI_MDRIVER_HANDLE_T *handle, int tx, int uncached, const void *address, const uint32_t length );+   void *  (*allocate_buffer)( VCHI_MDRIVER_HANDLE_T *handle, uint32_t *length );+   void    (*free_buffer)( VCHI_MDRIVER_HANDLE_T *handle, void *address );+   int     (*rx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size );+   int     (*tx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size );++   int32_t  (*tx_supports_terminate)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel );+   uint32_t (*tx_bulk_chunk_size)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel );+   int     (*tx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel );+   int     (*rx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_RX_CHANNEL_T channel );+   void    (*form_bulk_aux)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, uint32_t chunk_size, const void **aux_data, int32_t *aux_len );+   void    (*debug)( VCHI_MDRIVER_HANDLE_T *handle );+};+++#endif // _VCHI_MESSAGE_H_++/****************************** End of file ***********************************/diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h linux-3.11.10/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,224 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef VCHI_CFG_H_+#define VCHI_CFG_H_++/****************************************************************************************+ * Defines in this first section are part of the VCHI API and may be examined by VCHI+ * services.+ ***************************************************************************************/++/* Required alignment of base addresses for bulk transfer, if unaligned transfers are not enabled */+/* Really determined by the message driver, and should be available from a run-time call. */+#ifndef VCHI_BULK_ALIGN+#   if __VCCOREVER__ >= 0x04000000+#       define VCHI_BULK_ALIGN 32 // Allows for the need to do cache cleans+#   else+#       define VCHI_BULK_ALIGN 16+#   endif+#endif++/* Required length multiple for bulk transfers, if unaligned transfers are not enabled */+/* May be less than or greater than VCHI_BULK_ALIGN */+/* Really determined by the message driver, and should be available from a run-time call. */+#ifndef VCHI_BULK_GRANULARITY+#   if __VCCOREVER__ >= 0x04000000+#       define VCHI_BULK_GRANULARITY 32 // Allows for the need to do cache cleans+#   else+#       define VCHI_BULK_GRANULARITY 16+#   endif+#endif++/* The largest possible message to be queued with vchi_msg_queue. */+#ifndef VCHI_MAX_MSG_SIZE+#   if defined VCHI_LOCAL_HOST_PORT+#       define VCHI_MAX_MSG_SIZE     16384         // makes file transfers fast, but should they be using bulk?+#   else+#       define VCHI_MAX_MSG_SIZE      4096 // NOTE: THIS MUST BE LARGER THAN OR EQUAL TO THE SIZE OF THE KHRONOS MERGE BUFFER!!+#   endif+#endif++/******************************************************************************************+ * Defines below are system configuration options, and should not be used by VCHI services.+ *****************************************************************************************/++/* How many connections can we support? A localhost implementation uses 2 connections,+ * 1 for host-app, 1 for VMCS, and these are hooked together by a loopback MPHI VCFW+ * driver. */+#ifndef VCHI_MAX_NUM_CONNECTIONS+#   define VCHI_MAX_NUM_CONNECTIONS 3+#endif++/* How many services can we open per connection? Extending this doesn't cost processing time, just a small+ * amount of static memory. */+#ifndef VCHI_MAX_SERVICES_PER_CONNECTION+#  define VCHI_MAX_SERVICES_PER_CONNECTION 36+#endif++/* Adjust if using a message driver that supports more logical TX channels */+#ifndef VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION+#   define VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION 9 // 1 MPHI + 8 CCP2 logical channels+#endif++/* Adjust if using a message driver that supports more logical RX channels */+#ifndef VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION+#   define VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION 1 // 1 MPHI+#endif++/* How many receive slots do we use. This times VCHI_MAX_MSG_SIZE gives the effective+ * receive queue space, less message headers. */+#ifndef VCHI_NUM_READ_SLOTS+#  if defined(VCHI_LOCAL_HOST_PORT)+#     define VCHI_NUM_READ_SLOTS 4+#  else+#     define VCHI_NUM_READ_SLOTS 48+#  endif+#endif++/* Do we utilise overrun facility for receive message slots? Can aid peer transmit+ * performance. Only define on VideoCore end, talking to host.+ */+//#define VCHI_MSG_RX_OVERRUN++/* How many transmit slots do we use. Generally don't need many, as the hardware driver+ * underneath VCHI will usually have its own buffering. */+#ifndef VCHI_NUM_WRITE_SLOTS+#  define VCHI_NUM_WRITE_SLOTS 4+#endif++/* If a service has held or queued received messages in VCHI_XOFF_THRESHOLD or more slots,+ * then it's taking up too much buffer space, and the peer service will be told to stop+ * transmitting with an XOFF message. For this to be effective, the VCHI_NUM_READ_SLOTS+ * needs to be considerably bigger than VCHI_NUM_WRITE_SLOTS, or the transmit latency+ * is too high. */+#ifndef VCHI_XOFF_THRESHOLD+#  define VCHI_XOFF_THRESHOLD (VCHI_NUM_READ_SLOTS / 2)+#endif++/* After we've sent an XOFF, the peer will be told to resume transmission once the local+ * service has dequeued/released enough messages that it's now occupying+ * VCHI_XON_THRESHOLD slots or fewer. */+#ifndef VCHI_XON_THRESHOLD+#  define VCHI_XON_THRESHOLD (VCHI_NUM_READ_SLOTS / 4)+#endif++/* A size below which a bulk transfer omits the handshake completely and always goes+ * via the message channel, if bulk auxiliary is being sent on that service. (The user+ * can guarantee this by enabling unaligned transmits).+ * Not API. */+#ifndef VCHI_MIN_BULK_SIZE+#  define VCHI_MIN_BULK_SIZE    ( VCHI_MAX_MSG_SIZE / 2 < 4096 ? VCHI_MAX_MSG_SIZE / 2 : 4096 )+#endif++/* Maximum size of bulk transmission chunks, for each interface type. A trade-off between+ * speed and latency; the smaller the chunk size the better change of messages and other+ * bulk transmissions getting in when big bulk transfers are happening. Set to 0 to not+ * break transmissions into chunks.+ */+#ifndef VCHI_MAX_BULK_CHUNK_SIZE_MPHI+#  define VCHI_MAX_BULK_CHUNK_SIZE_MPHI (16 * 1024)+#endif++/* NB Chunked CCP2 transmissions violate the letter of the CCP2 spec by using "JPEG8" mode+ * with multiple-line frames. Only use if the receiver can cope. */+#ifndef VCHI_MAX_BULK_CHUNK_SIZE_CCP2+#  define VCHI_MAX_BULK_CHUNK_SIZE_CCP2 0+#endif++/* How many TX messages can we have pending in our transmit slots. Once exhausted,+ * vchi_msg_queue will be blocked. */+#ifndef VCHI_TX_MSG_QUEUE_SIZE+#  define VCHI_TX_MSG_QUEUE_SIZE           256+#endif++/* How many RX messages can we have parsed in the receive slots. Once exhausted, parsing+ * will be suspended until older messages are dequeued/released. */+#ifndef VCHI_RX_MSG_QUEUE_SIZE+#  define VCHI_RX_MSG_QUEUE_SIZE           256+#endif++/* Really should be able to cope if we run out of received message descriptors, by+ * suspending parsing as the comment above says, but we don't. This sweeps the issue+ * under the carpet. */+#if VCHI_RX_MSG_QUEUE_SIZE < (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS+#  undef VCHI_RX_MSG_QUEUE_SIZE+#  define VCHI_RX_MSG_QUEUE_SIZE (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS+#endif++/* How many bulk transmits can we have pending. Once exhausted, vchi_bulk_queue_transmit+ * will be blocked. */+#ifndef VCHI_TX_BULK_QUEUE_SIZE+#  define VCHI_TX_BULK_QUEUE_SIZE           64+#endif++/* How many bulk receives can we have pending. Once exhausted, vchi_bulk_queue_receive+ * will be blocked. */+#ifndef VCHI_RX_BULK_QUEUE_SIZE+#  define VCHI_RX_BULK_QUEUE_SIZE           64+#endif++/* A limit on how many outstanding bulk requests we expect the peer to give us. If+ * the peer asks for more than this, VCHI will fail and assert. The number is determined+ * by the peer's hardware - it's the number of outstanding requests that can be queued+ * on all bulk channels. VC3's MPHI peripheral allows 16. */+#ifndef VCHI_MAX_PEER_BULK_REQUESTS+#  define VCHI_MAX_PEER_BULK_REQUESTS       32+#endif++/* Define VCHI_CCP2TX_MANUAL_POWER if the host tells us when to turn the CCP2+ * transmitter on and off.+ */+/*#define VCHI_CCP2TX_MANUAL_POWER*/++#ifndef VCHI_CCP2TX_MANUAL_POWER++/* Timeout (in milliseconds) for putting the CCP2TX interface into IDLE state. Set+ * negative for no IDLE.+ */+#  ifndef VCHI_CCP2TX_IDLE_TIMEOUT+#    define VCHI_CCP2TX_IDLE_TIMEOUT        5+#  endif++/* Timeout (in milliseconds) for putting the CCP2TX interface into OFF state. Set+ * negative for no OFF.+ */+#  ifndef VCHI_CCP2TX_OFF_TIMEOUT+#    define VCHI_CCP2TX_OFF_TIMEOUT         1000+#  endif++#endif /* VCHI_CCP2TX_MANUAL_POWER */++#endif /* VCHI_CFG_H_ */++/****************************** End of file **********************************/diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h linux-3.11.10/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,71 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef VCHI_CFG_INTERNAL_H_+#define VCHI_CFG_INTERNAL_H_++/****************************************************************************************+ * Control optimisation attempts.+ ***************************************************************************************/++// Don't use lots of short-term locks - use great long ones, reducing the overall locks-per-second+#define VCHI_COARSE_LOCKING++// Avoid lock then unlock on exit from blocking queue operations (msg tx, bulk rx/tx)+// (only relevant if VCHI_COARSE_LOCKING)+#define VCHI_ELIDE_BLOCK_EXIT_LOCK++// Avoid lock on non-blocking peek+// (only relevant if VCHI_COARSE_LOCKING)+#define VCHI_AVOID_PEEK_LOCK++// Use one slot-handler thread per connection, rather than 1 thread dealing with all connections in rotation.+#define VCHI_MULTIPLE_HANDLER_THREADS++// Put free descriptors onto the head of the free queue, rather than the tail, so that we don't thrash+// our way through the pool of descriptors.+#define VCHI_PUSH_FREE_DESCRIPTORS_ONTO_HEAD++// Don't issue a MSG_AVAILABLE callback for every single message. Possibly only safe if VCHI_COARSE_LOCKING.+#define VCHI_FEWER_MSG_AVAILABLE_CALLBACKS++// Don't use message descriptors for TX messages that don't need them+#define VCHI_MINIMISE_TX_MSG_DESCRIPTORS++// Nano-locks for multiqueue+//#define VCHI_MQUEUE_NANOLOCKS++// Lock-free(er) dequeuing+//#define VCHI_RX_NANOLOCKS++#endif /*VCHI_CFG_INTERNAL_H_*/diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchi/vchi_common.h linux-3.11.10/drivers/misc/vc04_services/interface/vchi/vchi_common.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchi/vchi_common.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchi/vchi_common.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,163 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef VCHI_COMMON_H_+#define VCHI_COMMON_H_+++//flags used when sending messages (must be bitmapped)+typedef enum+{+   VCHI_FLAGS_NONE                      = 0x0,+   VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE   = 0x1,   // waits for message to be received, or sent (NB. not the same as being seen on other side)+   VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE = 0x2,   // run a callback when message sent+   VCHI_FLAGS_BLOCK_UNTIL_QUEUED        = 0x4,   // return once the transfer is in a queue ready to go+   VCHI_FLAGS_ALLOW_PARTIAL             = 0x8,+   VCHI_FLAGS_BLOCK_UNTIL_DATA_READ     = 0x10,+   VCHI_FLAGS_CALLBACK_WHEN_DATA_READ   = 0x20,++   VCHI_FLAGS_ALIGN_SLOT            = 0x000080,  // internal use only+   VCHI_FLAGS_BULK_AUX_QUEUED       = 0x010000,  // internal use only+   VCHI_FLAGS_BULK_AUX_COMPLETE     = 0x020000,  // internal use only+   VCHI_FLAGS_BULK_DATA_QUEUED      = 0x040000,  // internal use only+   VCHI_FLAGS_BULK_DATA_COMPLETE    = 0x080000,  // internal use only+   VCHI_FLAGS_INTERNAL              = 0xFF0000+} VCHI_FLAGS_T;++// constants for vchi_crc_control()+typedef enum {+   VCHI_CRC_NOTHING = -1,+   VCHI_CRC_PER_SERVICE = 0,+   VCHI_CRC_EVERYTHING = 1,+} VCHI_CRC_CONTROL_T;++//callback reasons when an event occurs on a service+typedef enum+{+   VCHI_CALLBACK_REASON_MIN,++   //This indicates that there is data available+   //handle is the msg id that was transmitted with the data+   //    When a message is received and there was no FULL message available previously, send callback+   //    Tasks get kicked by the callback, reset their event and try and read from the fifo until it fails+   VCHI_CALLBACK_MSG_AVAILABLE,+   VCHI_CALLBACK_MSG_SENT,+   VCHI_CALLBACK_MSG_SPACE_AVAILABLE, // XXX not yet implemented++   // This indicates that a transfer from the other side has completed+   VCHI_CALLBACK_BULK_RECEIVED,+   //This indicates that data queued up to be sent has now gone+   //handle is the msg id that was used when sending the data+   VCHI_CALLBACK_BULK_SENT,+   VCHI_CALLBACK_BULK_RX_SPACE_AVAILABLE, // XXX not yet implemented+   VCHI_CALLBACK_BULK_TX_SPACE_AVAILABLE, // XXX not yet implemented++   VCHI_CALLBACK_SERVICE_CLOSED,++   // this side has sent XOFF to peer due to lack of data consumption by service+   // (suggests the service may need to take some recovery action if it has+   // been deliberately holding off consuming data)+   VCHI_CALLBACK_SENT_XOFF,+   VCHI_CALLBACK_SENT_XON,++   // indicates that a bulk transfer has finished reading the source buffer+   VCHI_CALLBACK_BULK_DATA_READ,++   // power notification events (currently host side only)+   VCHI_CALLBACK_PEER_OFF,+   VCHI_CALLBACK_PEER_SUSPENDED,+   VCHI_CALLBACK_PEER_ON,+   VCHI_CALLBACK_PEER_RESUMED,+   VCHI_CALLBACK_FORCED_POWER_OFF,++#ifdef USE_VCHIQ_ARM+   // some extra notifications provided by vchiq_arm+   VCHI_CALLBACK_SERVICE_OPENED,+   VCHI_CALLBACK_BULK_RECEIVE_ABORTED,+   VCHI_CALLBACK_BULK_TRANSMIT_ABORTED,+#endif++   VCHI_CALLBACK_REASON_MAX+} VCHI_CALLBACK_REASON_T;++//Calback used by all services / bulk transfers+typedef void (*VCHI_CALLBACK_T)( void *callback_param, //my service local param+                                 VCHI_CALLBACK_REASON_T reason,+                                 void *handle ); //for transmitting msg's only++++/*+ * Define vector struct for scatter-gather (vector) operations+ * Vectors can be nested - if a vector element has negative length, then+ * the data pointer is treated as pointing to another vector array, with+ * '-vec_len' elements. Thus to append a header onto an existing vector,+ * you can do this:+ *+ * void foo(const VCHI_MSG_VECTOR_T *v, int n)+ * {+ *    VCHI_MSG_VECTOR_T nv[2];+ *    nv[0].vec_base = my_header;+ *    nv[0].vec_len = sizeof my_header;+ *    nv[1].vec_base = v;+ *    nv[1].vec_len = -n;+ *    ...+ *+ */+typedef struct vchi_msg_vector {+   const void *vec_base;+   int32_t vec_len;+} VCHI_MSG_VECTOR_T;++// Opaque type for a connection API+typedef struct opaque_vchi_connection_api_t VCHI_CONNECTION_API_T;++// Opaque type for a message driver+typedef struct opaque_vchi_message_driver_t VCHI_MESSAGE_DRIVER_T;+++// Iterator structure for reading ahead through received message queue. Allocated by client,+// initialised by vchi_msg_look_ahead. Fields are for internal VCHI use only.+// Iterates over messages in queue at the instant of the call to vchi_msg_lookahead -+// will not proceed to messages received since. Behaviour is undefined if an iterator+// is used again after messages for that service are removed/dequeued by any+// means other than vchi_msg_iter_... calls on the iterator itself.+typedef struct {+   struct opaque_vchi_service_t *service;+   void *last;+   void *next;+   void *remove;+} VCHI_MSG_ITER_T;+++#endif // VCHI_COMMON_H_diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchi/vchi.h linux-3.11.10/drivers/misc/vc04_services/interface/vchi/vchi.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchi/vchi.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchi/vchi.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,373 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef VCHI_H_+#define VCHI_H_++#include "interface/vchi/vchi_cfg.h"+#include "interface/vchi/vchi_common.h"+#include "interface/vchi/connections/connection.h"+#include "vchi_mh.h"+++/******************************************************************************+ Global defs+ *****************************************************************************/++#define VCHI_BULK_ROUND_UP(x)     ((((unsigned long)(x))+VCHI_BULK_ALIGN-1) & ~(VCHI_BULK_ALIGN-1))+#define VCHI_BULK_ROUND_DOWN(x)   (((unsigned long)(x)) & ~(VCHI_BULK_ALIGN-1))+#define VCHI_BULK_ALIGN_NBYTES(x) (VCHI_BULK_ALIGNED(x) ? 0 : (VCHI_BULK_ALIGN - ((unsigned long)(x) & (VCHI_BULK_ALIGN-1))))++#ifdef USE_VCHIQ_ARM+#define VCHI_BULK_ALIGNED(x)      1+#else+#define VCHI_BULK_ALIGNED(x)      (((unsigned long)(x) & (VCHI_BULK_ALIGN-1)) == 0)+#endif++struct vchi_version {+	uint32_t version;+	uint32_t version_min;+};+#define VCHI_VERSION(v_) { v_, v_ }+#define VCHI_VERSION_EX(v_, m_) { v_, m_ }++typedef enum+{+   VCHI_VEC_POINTER,+   VCHI_VEC_HANDLE,+   VCHI_VEC_LIST+} VCHI_MSG_VECTOR_TYPE_T;++typedef struct vchi_msg_vector_ex {++   VCHI_MSG_VECTOR_TYPE_T type;+   union+   {+      // a memory handle+      struct+      {+         VCHI_MEM_HANDLE_T handle;+         uint32_t offset;+         int32_t vec_len;+      } handle;++      // an ordinary data pointer+      struct+      {+         const void *vec_base;+         int32_t vec_len;+      } ptr;++      // a nested vector list+      struct+      {+         struct vchi_msg_vector_ex *vec;+         uint32_t vec_len;+      } list;+   } u;+} VCHI_MSG_VECTOR_EX_T;+++// Construct an entry in a msg vector for a pointer (p) of length (l)+#define VCHI_VEC_POINTER(p,l)  VCHI_VEC_POINTER, { { (VCHI_MEM_HANDLE_T)(p), (l) } }++// Construct an entry in a msg vector for a message handle (h), starting at offset (o) of length (l)+#define VCHI_VEC_HANDLE(h,o,l) VCHI_VEC_HANDLE,  { { (h), (o), (l) } }++// Macros to manipulate 'FOURCC' values+#define MAKE_FOURCC(x) ((int32_t)( (x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3] ))+#define FOURCC_TO_CHAR(x) (x >> 24) & 0xFF,(x >> 16) & 0xFF,(x >> 8) & 0xFF, x & 0xFF+++// Opaque service information+struct opaque_vchi_service_t;++// Descriptor for a held message. Allocated by client, initialised by vchi_msg_hold,+// vchi_msg_iter_hold or vchi_msg_iter_hold_next. Fields are for internal VCHI use only.+typedef struct+{+   struct opaque_vchi_service_t *service;+   void *message;+} VCHI_HELD_MSG_T;++++// structure used to provide the information needed to open a server or a client+typedef struct {+	struct vchi_version version;+	int32_t service_id;+	VCHI_CONNECTION_T *connection;+	uint32_t rx_fifo_size;+	uint32_t tx_fifo_size;+	VCHI_CALLBACK_T callback;+	void *callback_param;+	/* client intends to receive bulk transfers of+		odd lengths or into unaligned buffers */+	int32_t want_unaligned_bulk_rx;+	/* client intends to transmit bulk transfers of+		odd lengths or out of unaligned buffers */+	int32_t want_unaligned_bulk_tx;+	/* client wants to check CRCs on (bulk) xfers.+		Only needs to be set at 1 end - will do both directions. */+	int32_t want_crc;+} SERVICE_CREATION_T;++// Opaque handle for a VCHI instance+typedef struct opaque_vchi_instance_handle_t *VCHI_INSTANCE_T;++// Opaque handle for a server or client+typedef struct opaque_vchi_service_handle_t *VCHI_SERVICE_HANDLE_T;++// Service registration & startup+typedef void (*VCHI_SERVICE_INIT)(VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections);++typedef struct service_info_tag {+   const char * const vll_filename; /* VLL to load to start this service. This is an empty string if VLL is "static" */+   VCHI_SERVICE_INIT init;          /* Service initialisation function */+   void *vll_handle;                /* VLL handle; NULL when unloaded or a "static VLL" in build */+} SERVICE_INFO_T;++/******************************************************************************+ Global funcs - implementation is specific to which side you are on (local / remote)+ *****************************************************************************/++#ifdef __cplusplus+extern "C" {+#endif++extern /*@observer@*/ VCHI_CONNECTION_T * vchi_create_connection( const VCHI_CONNECTION_API_T * function_table,+                                                   const VCHI_MESSAGE_DRIVER_T * low_level);+++// Routine used to initialise the vchi on both local + remote connections+extern int32_t vchi_initialise( VCHI_INSTANCE_T *instance_handle );++extern int32_t vchi_exit( void );++extern int32_t vchi_connect( VCHI_CONNECTION_T **connections,+                             const uint32_t num_connections,+                             VCHI_INSTANCE_T instance_handle );++//When this is called, ensure that all services have no data pending.+//Bulk transfers can remain 'queued'+extern int32_t vchi_disconnect( VCHI_INSTANCE_T instance_handle );++// Global control over bulk CRC checking+extern int32_t vchi_crc_control( VCHI_CONNECTION_T *connection,+                                 VCHI_CRC_CONTROL_T control );++// helper functions+extern void * vchi_allocate_buffer(VCHI_SERVICE_HANDLE_T handle, uint32_t *length);+extern void vchi_free_buffer(VCHI_SERVICE_HANDLE_T handle, void *address);+extern uint32_t vchi_current_time(VCHI_INSTANCE_T instance_handle);+++/******************************************************************************+ Global service API+ *****************************************************************************/+// Routine to create a named service+extern int32_t vchi_service_create( VCHI_INSTANCE_T instance_handle,+                                    SERVICE_CREATION_T *setup,+                                    VCHI_SERVICE_HANDLE_T *handle );++// Routine to destory a service+extern int32_t vchi_service_destroy( const VCHI_SERVICE_HANDLE_T handle );++// Routine to open a named service+extern int32_t vchi_service_open( VCHI_INSTANCE_T instance_handle,+                                  SERVICE_CREATION_T *setup,+                                  VCHI_SERVICE_HANDLE_T *handle);++extern int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle,+                                      short *peer_version );++// Routine to close a named service+extern int32_t vchi_service_close( const VCHI_SERVICE_HANDLE_T handle );++// Routine to increment ref count on a named service+extern int32_t vchi_service_use( const VCHI_SERVICE_HANDLE_T handle );++// Routine to decrement ref count on a named service+extern int32_t vchi_service_release( const VCHI_SERVICE_HANDLE_T handle );++// Routine to send a message accross a service+extern int32_t vchi_msg_queue( VCHI_SERVICE_HANDLE_T handle,+                               const void *data,+                               uint32_t data_size,+                               VCHI_FLAGS_T flags,+                               void *msg_handle );++// scatter-gather (vector) and send message+int32_t vchi_msg_queuev_ex( VCHI_SERVICE_HANDLE_T handle,+                            VCHI_MSG_VECTOR_EX_T *vector,+                            uint32_t count,+                            VCHI_FLAGS_T flags,+                            void *msg_handle );++// legacy scatter-gather (vector) and send message, only handles pointers+int32_t vchi_msg_queuev( VCHI_SERVICE_HANDLE_T handle,+                         VCHI_MSG_VECTOR_T *vector,+                         uint32_t count,+                         VCHI_FLAGS_T flags,+                         void *msg_handle );++// Routine to receive a msg from a service+// Dequeue is equivalent to hold, copy into client buffer, release+extern int32_t vchi_msg_dequeue( VCHI_SERVICE_HANDLE_T handle,+                                 void *data,+                                 uint32_t max_data_size_to_read,+                                 uint32_t *actual_msg_size,+                                 VCHI_FLAGS_T flags );++// Routine to look at a message in place.+// The message is not dequeued, so a subsequent call to peek or dequeue+// will return the same message.+extern int32_t vchi_msg_peek( VCHI_SERVICE_HANDLE_T handle,+                              void **data,+                              uint32_t *msg_size,+                              VCHI_FLAGS_T flags );++// Routine to remove a message after it has been read in place with peek+// The first message on the queue is dequeued.+extern int32_t vchi_msg_remove( VCHI_SERVICE_HANDLE_T handle );++// Routine to look at a message in place.+// The message is dequeued, so the caller is left holding it; the descriptor is+// filled in and must be released when the user has finished with the message.+extern int32_t vchi_msg_hold( VCHI_SERVICE_HANDLE_T handle,+                              void **data,        // } may be NULL, as info can be+                              uint32_t *msg_size, // } obtained from HELD_MSG_T+                              VCHI_FLAGS_T flags,+                              VCHI_HELD_MSG_T *message_descriptor );++// Initialise an iterator to look through messages in place+extern int32_t vchi_msg_look_ahead( VCHI_SERVICE_HANDLE_T handle,+                                    VCHI_MSG_ITER_T *iter,+                                    VCHI_FLAGS_T flags );++/******************************************************************************+ Global service support API - operations on held messages and message iterators+ *****************************************************************************/++// Routine to get the address of a held message+extern void *vchi_held_msg_ptr( const VCHI_HELD_MSG_T *message );++// Routine to get the size of a held message+extern int32_t vchi_held_msg_size( const VCHI_HELD_MSG_T *message );++// Routine to get the transmit timestamp as written into the header by the peer+extern uint32_t vchi_held_msg_tx_timestamp( const VCHI_HELD_MSG_T *message );++// Routine to get the reception timestamp, written as we parsed the header+extern uint32_t vchi_held_msg_rx_timestamp( const VCHI_HELD_MSG_T *message );++// Routine to release a held message after it has been processed+extern int32_t vchi_held_msg_release( VCHI_HELD_MSG_T *message );++// Indicates whether the iterator has a next message.+extern int32_t vchi_msg_iter_has_next( const VCHI_MSG_ITER_T *iter );++// Return the pointer and length for the next message and advance the iterator.+extern int32_t vchi_msg_iter_next( VCHI_MSG_ITER_T *iter,+                                   void **data,+                                   uint32_t *msg_size );++// Remove the last message returned by vchi_msg_iter_next.+// Can only be called once after each call to vchi_msg_iter_next.+extern int32_t vchi_msg_iter_remove( VCHI_MSG_ITER_T *iter );++// Hold the last message returned by vchi_msg_iter_next.+// Can only be called once after each call to vchi_msg_iter_next.+extern int32_t vchi_msg_iter_hold( VCHI_MSG_ITER_T *iter,+                                   VCHI_HELD_MSG_T *message );++// Return information for the next message, and hold it, advancing the iterator.+extern int32_t vchi_msg_iter_hold_next( VCHI_MSG_ITER_T *iter,+                                        void **data,        // } may be NULL+                                        uint32_t *msg_size, // }+                                        VCHI_HELD_MSG_T *message );+++/******************************************************************************+ Global bulk API+ *****************************************************************************/++// Routine to prepare interface for a transfer from the other side+extern int32_t vchi_bulk_queue_receive( VCHI_SERVICE_HANDLE_T handle,+                                        void *data_dst,+                                        uint32_t data_size,+                                        VCHI_FLAGS_T flags,+                                        void *transfer_handle );+++// Prepare interface for a transfer from the other side into relocatable memory.+int32_t vchi_bulk_queue_receive_reloc( const VCHI_SERVICE_HANDLE_T handle,+                                       VCHI_MEM_HANDLE_T h_dst,+                                       uint32_t offset,+                                       uint32_t data_size,+                                       const VCHI_FLAGS_T flags,+                                       void * const bulk_handle );++// Routine to queue up data ready for transfer to the other (once they have signalled they are ready)+extern int32_t vchi_bulk_queue_transmit( VCHI_SERVICE_HANDLE_T handle,+                                         const void *data_src,+                                         uint32_t data_size,+                                         VCHI_FLAGS_T flags,+                                         void *transfer_handle );+++/******************************************************************************+ Configuration plumbing+ *****************************************************************************/++// function prototypes for the different mid layers (the state info gives the different physical connections)+extern const VCHI_CONNECTION_API_T *single_get_func_table( void );+//extern const VCHI_CONNECTION_API_T *local_server_get_func_table( void );+//extern const VCHI_CONNECTION_API_T *local_client_get_func_table( void );++// declare all message drivers here+const VCHI_MESSAGE_DRIVER_T *vchi_mphi_message_driver_func_table( void );++#ifdef __cplusplus+}+#endif++extern int32_t vchi_bulk_queue_transmit_reloc( VCHI_SERVICE_HANDLE_T handle,+                                               VCHI_MEM_HANDLE_T h_src,+                                               uint32_t offset,+                                               uint32_t data_size,+                                               VCHI_FLAGS_T flags,+                                               void *transfer_handle );+#endif /* VCHI_H_ */++/****************************** End of file **********************************/diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchi/vchi_mh.h linux-3.11.10/drivers/misc/vc04_services/interface/vchi/vchi_mh.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchi/vchi_mh.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchi/vchi_mh.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,42 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef VCHI_MH_H_+#define VCHI_MH_H_++#include <linux/types.h>++typedef int32_t VCHI_MEM_HANDLE_T;+#define VCHI_MEM_HANDLE_INVALID 0++#endifdiff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,538 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#include <linux/kernel.h>+#include <linux/types.h>+#include <linux/errno.h>+#include <linux/interrupt.h>+#include <linux/irq.h>+#include <linux/pagemap.h>+#include <linux/dma-mapping.h>+#include <linux/version.h>+#include <linux/io.h>+#include <linux/uaccess.h>+#include <asm/pgtable.h>++#include <mach/irqs.h>++#include <mach/platform.h>+#include <mach/vcio.h>++#define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32)++#define VCHIQ_DOORBELL_IRQ IRQ_ARM_DOORBELL_0+#define VCHIQ_ARM_ADDRESS(x) ((void *)__virt_to_bus((unsigned)x))++#include "vchiq_arm.h"+#include "vchiq_2835.h"+#include "vchiq_connected.h"++#define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2)++typedef struct vchiq_2835_state_struct {+   int inited;+   VCHIQ_ARM_STATE_T arm_state;+} VCHIQ_2835_ARM_STATE_T;++static char *g_slot_mem;+static int g_slot_mem_size;+dma_addr_t g_slot_phys;+static FRAGMENTS_T *g_fragments_base;+static FRAGMENTS_T *g_free_fragments;+struct semaphore g_free_fragments_sema;++extern int vchiq_arm_log_level;++static DEFINE_SEMAPHORE(g_free_fragments_mutex);++static irqreturn_t+vchiq_doorbell_irq(int irq, void *dev_id);++static int+create_pagelist(char __user *buf, size_t count, unsigned short type,+                struct task_struct *task, PAGELIST_T ** ppagelist);++static void+free_pagelist(PAGELIST_T *pagelist, int actual);++int __init+vchiq_platform_init(VCHIQ_STATE_T *state)+{+	VCHIQ_SLOT_ZERO_T *vchiq_slot_zero;+	int frag_mem_size;+	int err;+	int i;++	/* Allocate space for the channels in coherent memory */+	g_slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE);+	frag_mem_size = PAGE_ALIGN(sizeof(FRAGMENTS_T) * MAX_FRAGMENTS);++	g_slot_mem = dma_alloc_coherent(NULL, g_slot_mem_size + frag_mem_size,+		&g_slot_phys, GFP_ATOMIC);++	if (!g_slot_mem) {+		vchiq_log_error(vchiq_arm_log_level,+			"Unable to allocate channel memory");+		err = -ENOMEM;+		goto failed_alloc;+	}++	WARN_ON(((int)g_slot_mem & (PAGE_SIZE - 1)) != 0);++	vchiq_slot_zero = vchiq_init_slots(g_slot_mem, g_slot_mem_size);+	if (!vchiq_slot_zero) {+		err = -EINVAL;+		goto failed_init_slots;+	}++	vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] =+		(int)g_slot_phys + g_slot_mem_size;+	vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] =+		MAX_FRAGMENTS;++	g_fragments_base = (FRAGMENTS_T *)(g_slot_mem + g_slot_mem_size);+	g_slot_mem_size += frag_mem_size;++	g_free_fragments = g_fragments_base;+	for (i = 0; i < (MAX_FRAGMENTS - 1); i++) {+		*(FRAGMENTS_T **)&g_fragments_base[i] =+			&g_fragments_base[i + 1];+	}+	*(FRAGMENTS_T **)&g_fragments_base[i] = NULL;+	sema_init(&g_free_fragments_sema, MAX_FRAGMENTS);++	if (vchiq_init_state(state, vchiq_slot_zero, 0/*slave*/) !=+		VCHIQ_SUCCESS) {+		err = -EINVAL;+		goto failed_vchiq_init;+	}++	err = request_irq(VCHIQ_DOORBELL_IRQ, vchiq_doorbell_irq,+		IRQF_IRQPOLL, "VCHIQ doorbell",+		state);+	if (err < 0) {+		vchiq_log_error(vchiq_arm_log_level, "%s: failed to register "+			"irq=%d err=%d", __func__,+			VCHIQ_DOORBELL_IRQ, err);+		goto failed_request_irq;+	}++	/* Send the base address of the slots to VideoCore */++	dsb(); /* Ensure all writes have completed */++	bcm_mailbox_write(MBOX_CHAN_VCHIQ, (unsigned int)g_slot_phys);++	vchiq_log_info(vchiq_arm_log_level,+		"vchiq_init - done (slots %x, phys %x)",+		(unsigned int)vchiq_slot_zero, g_slot_phys);++   vchiq_call_connected_callbacks();++   return 0;++failed_request_irq:+failed_vchiq_init:+failed_init_slots:+   dma_free_coherent(NULL, g_slot_mem_size, g_slot_mem, g_slot_phys);++failed_alloc:+   return err;+}++void __exit+vchiq_platform_exit(VCHIQ_STATE_T *state)+{+   free_irq(VCHIQ_DOORBELL_IRQ, state);+   dma_free_coherent(NULL, g_slot_mem_size,+                     g_slot_mem, g_slot_phys);+}+++VCHIQ_STATUS_T+vchiq_platform_init_state(VCHIQ_STATE_T *state)+{+   VCHIQ_STATUS_T status = VCHIQ_SUCCESS;+   state->platform_state = kzalloc(sizeof(VCHIQ_2835_ARM_STATE_T), GFP_KERNEL);+   ((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited = 1;+   status = vchiq_arm_init_state(state, &((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->arm_state);+   if(status != VCHIQ_SUCCESS)+   {+      ((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited = 0;+   }+   return status;+}++VCHIQ_ARM_STATE_T*+vchiq_platform_get_arm_state(VCHIQ_STATE_T *state)+{+   if(!((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited)+   {+      BUG();+   }+   return &((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->arm_state;+}++void+remote_event_signal(REMOTE_EVENT_T *event)+{+	wmb();++	event->fired = 1;++	dsb();         /* data barrier operation */++	if (event->armed) {+		/* trigger vc interrupt */++		writel(0, __io_address(ARM_0_BELL2));+	}+}++int+vchiq_copy_from_user(void *dst, const void *src, int size)+{+	if ((uint32_t)src < TASK_SIZE) {+		return copy_from_user(dst, src, size);+	} else {+		memcpy(dst, src, size);+		return 0;+	}+}++VCHIQ_STATUS_T+vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, VCHI_MEM_HANDLE_T memhandle,+	void *offset, int size, int dir)+{+	PAGELIST_T *pagelist;+	int ret;++	WARN_ON(memhandle != VCHI_MEM_HANDLE_INVALID);++	ret = create_pagelist((char __user *)offset, size,+			(dir == VCHIQ_BULK_RECEIVE)+			? PAGELIST_READ+			: PAGELIST_WRITE,+			current,+			&pagelist);+	if (ret != 0)+		return VCHIQ_ERROR;++	bulk->handle = memhandle;+	bulk->data = VCHIQ_ARM_ADDRESS(pagelist);++	/* Store the pagelist address in remote_data, which isn't used by the+	   slave. */+	bulk->remote_data = pagelist;++	return VCHIQ_SUCCESS;+}++void+vchiq_complete_bulk(VCHIQ_BULK_T *bulk)+{+	if (bulk && bulk->remote_data && bulk->actual)+		free_pagelist((PAGELIST_T *)bulk->remote_data, bulk->actual);+}++void+vchiq_transfer_bulk(VCHIQ_BULK_T *bulk)+{+	/*+	 * This should only be called on the master (VideoCore) side, but+	 * provide an implementation to avoid the need for ifdefery.+	 */+	BUG();+}++void+vchiq_dump_platform_state(void *dump_context)+{+	char buf[80];+	int len;+	len = snprintf(buf, sizeof(buf),+		"  Platform: 2835 (VC master)");+	vchiq_dump(dump_context, buf, len + 1);+}++VCHIQ_STATUS_T+vchiq_platform_suspend(VCHIQ_STATE_T *state)+{+   return VCHIQ_ERROR;+}++VCHIQ_STATUS_T+vchiq_platform_resume(VCHIQ_STATE_T *state)+{+   return VCHIQ_SUCCESS;+}++void+vchiq_platform_paused(VCHIQ_STATE_T *state)+{+}++void+vchiq_platform_resumed(VCHIQ_STATE_T *state)+{+}++int+vchiq_platform_videocore_wanted(VCHIQ_STATE_T* state)+{+   return 1; // autosuspend not supported - videocore always wanted+}++int+vchiq_platform_use_suspend_timer(void)+{+   return 0;+}+void+vchiq_dump_platform_use_state(VCHIQ_STATE_T *state)+{+	vchiq_log_info((vchiq_arm_log_level>=VCHIQ_LOG_INFO),"Suspend timer not in use");+}+void+vchiq_platform_handle_timeout(VCHIQ_STATE_T *state)+{+	(void)state;+}+/*+ * Local functions+ */++static irqreturn_t+vchiq_doorbell_irq(int irq, void *dev_id)+{+	VCHIQ_STATE_T *state = dev_id;+	irqreturn_t ret = IRQ_NONE;+	unsigned int status;++	/* Read (and clear) the doorbell */+	status = readl(__io_address(ARM_0_BELL0));++	if (status & 0x4) {  /* Was the doorbell rung? */+		remote_event_pollall(state);+		ret = IRQ_HANDLED;+	}++	return ret;+}++/* There is a potential problem with partial cache lines (pages?)+** at the ends of the block when reading. If the CPU accessed anything in+** the same line (page?) then it may have pulled old data into the cache,+** obscuring the new data underneath. We can solve this by transferring the+** partial cache lines separately, and allowing the ARM to copy into the+** cached area.++** N.B. This implementation plays slightly fast and loose with the Linux+** driver programming rules, e.g. its use of __virt_to_bus instead of+** dma_map_single, but it isn't a multi-platform driver and it benefits+** from increased speed as a result.+*/++static int+create_pagelist(char __user *buf, size_t count, unsigned short type,+	struct task_struct *task, PAGELIST_T ** ppagelist)+{+	PAGELIST_T *pagelist;+	struct page **pages;+	struct page *page;+	unsigned long *addrs;+	unsigned int num_pages, offset, i;+	char *addr, *base_addr, *next_addr;+	int run, addridx, actual_pages;++	offset = (unsigned int)buf & (PAGE_SIZE - 1);+	num_pages = (count + offset + PAGE_SIZE - 1) / PAGE_SIZE;++	*ppagelist = NULL;++	/* Allocate enough storage to hold the page pointers and the page+	** list+	*/+	pagelist = kmalloc(sizeof(PAGELIST_T) ++		(num_pages * sizeof(unsigned long)) ++		(num_pages * sizeof(pages[0])),+		GFP_KERNEL);++	vchiq_log_trace(vchiq_arm_log_level,+		"create_pagelist - %x", (unsigned int)pagelist);+	if (!pagelist)+		return -ENOMEM;++	addrs = pagelist->addrs;+	pages = (struct page **)(addrs + num_pages);++	down_read(&task->mm->mmap_sem);+	actual_pages = get_user_pages(task, task->mm,+		(unsigned long)buf & ~(PAGE_SIZE - 1), num_pages,+		(type == PAGELIST_READ) /*Write */ , 0 /*Force */ ,+		pages, NULL /*vmas */);+	up_read(&task->mm->mmap_sem);++   if (actual_pages != num_pages)+   {+      /* This is probably due to the process being killed */+      while (actual_pages > 0)+      {+         actual_pages--;+         page_cache_release(pages[actual_pages]);+      }+      kfree(pagelist);+      if (actual_pages == 0)+         actual_pages = -ENOMEM;+      return actual_pages;+   }++	pagelist->length = count;+	pagelist->type = type;+	pagelist->offset = offset;++	/* Group the pages into runs of contiguous pages */++	base_addr = VCHIQ_ARM_ADDRESS(page_address(pages[0]));+	next_addr = base_addr + PAGE_SIZE;+	addridx = 0;+	run = 0;++	for (i = 1; i < num_pages; i++) {+		addr = VCHIQ_ARM_ADDRESS(page_address(pages[i]));+		if ((addr == next_addr) && (run < (PAGE_SIZE - 1))) {+			next_addr += PAGE_SIZE;+			run++;+		} else {+			addrs[addridx] = (unsigned long)base_addr + run;+			addridx++;+			base_addr = addr;+			next_addr = addr + PAGE_SIZE;+			run = 0;+		}+	}++	addrs[addridx] = (unsigned long)base_addr + run;+	addridx++;++	/* Partial cache lines (fragments) require special measures */+	if ((type == PAGELIST_READ) &&+		((pagelist->offset & (CACHE_LINE_SIZE - 1)) ||+		((pagelist->offset + pagelist->length) &+		(CACHE_LINE_SIZE - 1)))) {+		FRAGMENTS_T *fragments;++		if (down_interruptible(&g_free_fragments_sema) != 0) {+			kfree(pagelist);+			return -EINTR;+		}++		WARN_ON(g_free_fragments == NULL);++		down(&g_free_fragments_mutex);+		fragments = (FRAGMENTS_T *) g_free_fragments;+		WARN_ON(fragments == NULL);+		g_free_fragments = *(FRAGMENTS_T **) g_free_fragments;+		up(&g_free_fragments_mutex);+		pagelist->type =+			 PAGELIST_READ_WITH_FRAGMENTS + (fragments -+							 g_fragments_base);+	}++	for (page = virt_to_page(pagelist);+		page <= virt_to_page(addrs + num_pages - 1); page++) {+		flush_dcache_page(page);+	}++	*ppagelist = pagelist;++	return 0;+}++static void+free_pagelist(PAGELIST_T *pagelist, int actual)+{+	struct page **pages;+	unsigned int num_pages, i;++	vchiq_log_trace(vchiq_arm_log_level,+		"free_pagelist - %x, %d", (unsigned int)pagelist, actual);++	num_pages =+		(pagelist->length + pagelist->offset + PAGE_SIZE - 1) /+		PAGE_SIZE;++	pages = (struct page **)(pagelist->addrs + num_pages);++	/* Deal with any partial cache lines (fragments) */+	if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS) {+		FRAGMENTS_T *fragments = g_fragments_base ++			(pagelist->type - PAGELIST_READ_WITH_FRAGMENTS);+		int head_bytes, tail_bytes;+		head_bytes = (CACHE_LINE_SIZE - pagelist->offset) &+			(CACHE_LINE_SIZE - 1);+		tail_bytes = (pagelist->offset + actual) &+			(CACHE_LINE_SIZE - 1);++		if ((actual >= 0) && (head_bytes != 0)) {+			if (head_bytes > actual)+				head_bytes = actual;++			memcpy((char *)page_address(pages[0]) ++				pagelist->offset,+				fragments->headbuf,+				head_bytes);+		}+		if ((actual >= 0) && (head_bytes < actual) &&+			(tail_bytes != 0)) {+			memcpy((char *)page_address(pages[num_pages - 1]) ++				((pagelist->offset + actual) &+				(PAGE_SIZE - 1) & ~(CACHE_LINE_SIZE - 1)),+				fragments->tailbuf, tail_bytes);+		}++		down(&g_free_fragments_mutex);+		*(FRAGMENTS_T **) fragments = g_free_fragments;+		g_free_fragments = fragments;+		up(&g_free_fragments_mutex);+		up(&g_free_fragments_sema);+	}++	for (i = 0; i < num_pages; i++) {+		if (pagelist->type != PAGELIST_WRITE)+			set_page_dirty(pages[i]);+		page_cache_release(pages[i]);+	}++	kfree(pagelist);+}diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,42 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef VCHIQ_2835_H+#define VCHIQ_2835_H++#include "vchiq_pagelist.h"++#define VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX 0+#define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX  1++#endif /* VCHIQ_2835_H */diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,2813 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#include <linux/kernel.h>+#include <linux/module.h>+#include <linux/types.h>+#include <linux/errno.h>+#include <linux/cdev.h>+#include <linux/fs.h>+#include <linux/device.h>+#include <linux/mm.h>+#include <linux/highmem.h>+#include <linux/pagemap.h>+#include <linux/bug.h>+#include <linux/semaphore.h>+#include <linux/list.h>+#include <linux/proc_fs.h>++#include "vchiq_core.h"+#include "vchiq_ioctl.h"+#include "vchiq_arm.h"++#define DEVICE_NAME "vchiq"++/* Override the default prefix, which would be vchiq_arm (from the filename) */+#undef MODULE_PARAM_PREFIX+#define MODULE_PARAM_PREFIX DEVICE_NAME "."++#define VCHIQ_MINOR 0++/* Some per-instance constants */+#define MAX_COMPLETIONS 16+#define MAX_SERVICES 64+#define MAX_ELEMENTS 8+#define MSG_QUEUE_SIZE 64++#define KEEPALIVE_VER 1+#define KEEPALIVE_VER_MIN KEEPALIVE_VER++/* Run time control of log level, based on KERN_XXX level. */+int vchiq_arm_log_level = VCHIQ_LOG_DEFAULT;+int vchiq_susp_log_level = VCHIQ_LOG_ERROR;++#define SUSPEND_TIMER_TIMEOUT_MS 100+#define SUSPEND_RETRY_TIMER_TIMEOUT_MS 1000++#define VC_SUSPEND_NUM_OFFSET 3 /* number of values before idle which are -ve */+static const char *const suspend_state_names[] = {+	"VC_SUSPEND_FORCE_CANCELED",+	"VC_SUSPEND_REJECTED",+	"VC_SUSPEND_FAILED",+	"VC_SUSPEND_IDLE",+	"VC_SUSPEND_REQUESTED",+	"VC_SUSPEND_IN_PROGRESS",+	"VC_SUSPEND_SUSPENDED"+};+#define VC_RESUME_NUM_OFFSET 1 /* number of values before idle which are -ve */+static const char *const resume_state_names[] = {+	"VC_RESUME_FAILED",+	"VC_RESUME_IDLE",+	"VC_RESUME_REQUESTED",+	"VC_RESUME_IN_PROGRESS",+	"VC_RESUME_RESUMED"+};+/* The number of times we allow force suspend to timeout before actually+** _forcing_ suspend.  This is to cater for SW which fails to release vchiq+** correctly - we don't want to prevent ARM suspend indefinitely in this case.+*/+#define FORCE_SUSPEND_FAIL_MAX 8++/* The time in ms allowed for videocore to go idle when force suspend has been+ * requested */+#define FORCE_SUSPEND_TIMEOUT_MS 200+++static void suspend_timer_callback(unsigned long context);+static int vchiq_proc_add_instance(VCHIQ_INSTANCE_T instance);+static void vchiq_proc_remove_instance(VCHIQ_INSTANCE_T instance);+++typedef struct user_service_struct {+	VCHIQ_SERVICE_T *service;+	void *userdata;+	VCHIQ_INSTANCE_T instance;+	int is_vchi;+	int dequeue_pending;+	int message_available_pos;+	int msg_insert;+	int msg_remove;+	struct semaphore insert_event;+	struct semaphore remove_event;+	VCHIQ_HEADER_T * msg_queue[MSG_QUEUE_SIZE];+} USER_SERVICE_T;++struct bulk_waiter_node {+	struct bulk_waiter bulk_waiter;+	int pid;+	struct list_head list;+};++struct vchiq_instance_struct {+	VCHIQ_STATE_T *state;+	VCHIQ_COMPLETION_DATA_T completions[MAX_COMPLETIONS];+	int completion_insert;+	int completion_remove;+	struct semaphore insert_event;+	struct semaphore remove_event;+	struct mutex completion_mutex;++	int connected;+	int closing;+	int pid;+	int mark;++	struct list_head bulk_waiter_list;+	struct mutex bulk_waiter_list_mutex;++	struct proc_dir_entry *proc_entry;+};++typedef struct dump_context_struct {+	char __user *buf;+	size_t actual;+	size_t space;+	loff_t offset;+} DUMP_CONTEXT_T;++static struct cdev    vchiq_cdev;+static dev_t          vchiq_devid;+static VCHIQ_STATE_T g_state;+static struct class  *vchiq_class;+static struct device *vchiq_dev;+static DEFINE_SPINLOCK(msg_queue_spinlock);++static const char *const ioctl_names[] = {+	"CONNECT",+	"SHUTDOWN",+	"CREATE_SERVICE",+	"REMOVE_SERVICE",+	"QUEUE_MESSAGE",+	"QUEUE_BULK_TRANSMIT",+	"QUEUE_BULK_RECEIVE",+	"AWAIT_COMPLETION",+	"DEQUEUE_MESSAGE",+	"GET_CLIENT_ID",+	"GET_CONFIG",+	"CLOSE_SERVICE",+	"USE_SERVICE",+	"RELEASE_SERVICE",+	"SET_SERVICE_OPTION",+	"DUMP_PHYS_MEM"+};++vchiq_static_assert((sizeof(ioctl_names)/sizeof(ioctl_names[0])) ==+	(VCHIQ_IOC_MAX + 1));++static void+dump_phys_mem(void *virt_addr, uint32_t num_bytes);++/****************************************************************************+*+*   add_completion+*+***************************************************************************/++static VCHIQ_STATUS_T+add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason,+	VCHIQ_HEADER_T *header, USER_SERVICE_T *user_service,+	void *bulk_userdata)+{+	VCHIQ_COMPLETION_DATA_T *completion;+	DEBUG_INITIALISE(g_state.local)++	while (instance->completion_insert ==+		(instance->completion_remove + MAX_COMPLETIONS)) {+		/* Out of space - wait for the client */+		DEBUG_TRACE(SERVICE_CALLBACK_LINE);+		vchiq_log_trace(vchiq_arm_log_level,+			"add_completion - completion queue full");+		DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT);+		if (down_interruptible(&instance->remove_event) != 0) {+			vchiq_log_info(vchiq_arm_log_level,+				"service_callback interrupted");+			return VCHIQ_RETRY;+		} else if (instance->closing) {+			vchiq_log_info(vchiq_arm_log_level,+				"service_callback closing");+			return VCHIQ_ERROR;+		}+		DEBUG_TRACE(SERVICE_CALLBACK_LINE);+	}++	completion =+		 &instance->completions[instance->completion_insert &+		 (MAX_COMPLETIONS - 1)];++	completion->header = header;+	completion->reason = reason;+	/* N.B. service_userdata is updated while processing AWAIT_COMPLETION */+	completion->service_userdata = user_service->service;+	completion->bulk_userdata = bulk_userdata;++	if (reason == VCHIQ_SERVICE_CLOSED)+		/* Take an extra reference, to be held until+		   this CLOSED notification is delivered. */+		lock_service(user_service->service);++	/* A write barrier is needed here to ensure that the entire completion+		record is written out before the insert point. */+	wmb();++	if (reason == VCHIQ_MESSAGE_AVAILABLE)+		user_service->message_available_pos =+			instance->completion_insert;+	instance->completion_insert++;++	up(&instance->insert_event);++	return VCHIQ_SUCCESS;+}++/****************************************************************************+*+*   service_callback+*+***************************************************************************/++static VCHIQ_STATUS_T+service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header,+	VCHIQ_SERVICE_HANDLE_T handle, void *bulk_userdata)+{+	/* How do we ensure the callback goes to the right client?+	** The service_user data points to a USER_SERVICE_T record containing+	** the original callback and the user state structure, which contains a+	** circular buffer for completion records.+	*/+	USER_SERVICE_T *user_service;+	VCHIQ_SERVICE_T *service;+	VCHIQ_INSTANCE_T instance;+	DEBUG_INITIALISE(g_state.local)++	DEBUG_TRACE(SERVICE_CALLBACK_LINE);++	service = handle_to_service(handle);+	BUG_ON(!service);+	user_service = (USER_SERVICE_T *)service->base.userdata;+	instance = user_service->instance;++	if (!instance || instance->closing)+		return VCHIQ_SUCCESS;++	vchiq_log_trace(vchiq_arm_log_level,+		"service_callback - service %lx(%d), reason %d, header %lx, "+		"instance %lx, bulk_userdata %lx",+		(unsigned long)user_service,+		service->localport,+		reason, (unsigned long)header,+		(unsigned long)instance, (unsigned long)bulk_userdata);++	if (header && user_service->is_vchi) {+		spin_lock(&msg_queue_spinlock);+		while (user_service->msg_insert ==+			(user_service->msg_remove + MSG_QUEUE_SIZE)) {+			spin_unlock(&msg_queue_spinlock);+			DEBUG_TRACE(SERVICE_CALLBACK_LINE);+			DEBUG_COUNT(MSG_QUEUE_FULL_COUNT);+			vchiq_log_trace(vchiq_arm_log_level,+				"service_callback - msg queue full");+			/* If there is no MESSAGE_AVAILABLE in the completion+			** queue, add one+			*/+			if ((user_service->message_available_pos -+				instance->completion_remove) < 0) {+				VCHIQ_STATUS_T status;+				vchiq_log_info(vchiq_arm_log_level,+					"Inserting extra MESSAGE_AVAILABLE");+				DEBUG_TRACE(SERVICE_CALLBACK_LINE);+				status = add_completion(instance, reason,+					NULL, user_service, bulk_userdata);+				if (status != VCHIQ_SUCCESS) {+					DEBUG_TRACE(SERVICE_CALLBACK_LINE);+					return status;+				}+			}++			DEBUG_TRACE(SERVICE_CALLBACK_LINE);+			if (down_interruptible(&user_service->remove_event)+				!= 0) {+				vchiq_log_info(vchiq_arm_log_level,+					"service_callback interrupted");+				DEBUG_TRACE(SERVICE_CALLBACK_LINE);+				return VCHIQ_RETRY;+			} else if (instance->closing) {+				vchiq_log_info(vchiq_arm_log_level,+					"service_callback closing");+				DEBUG_TRACE(SERVICE_CALLBACK_LINE);+				return VCHIQ_ERROR;+			}+			DEBUG_TRACE(SERVICE_CALLBACK_LINE);+			spin_lock(&msg_queue_spinlock);+		}++		user_service->msg_queue[user_service->msg_insert &+			(MSG_QUEUE_SIZE - 1)] = header;+		user_service->msg_insert++;+		spin_unlock(&msg_queue_spinlock);++		up(&user_service->insert_event);++		/* If there is a thread waiting in DEQUEUE_MESSAGE, or if+		** there is a MESSAGE_AVAILABLE in the completion queue then+		** bypass the completion queue.+		*/+		if (((user_service->message_available_pos -+			instance->completion_remove) >= 0) ||+			user_service->dequeue_pending) {+			DEBUG_TRACE(SERVICE_CALLBACK_LINE);+			user_service->dequeue_pending = 0;+			return VCHIQ_SUCCESS;+		}++		header = NULL;+	}+	DEBUG_TRACE(SERVICE_CALLBACK_LINE);++	return add_completion(instance, reason, header, user_service,+		bulk_userdata);+}++/****************************************************************************+*+*   user_service_free+*+***************************************************************************/+static void+user_service_free(void *userdata)+{+	kfree(userdata);+}++/****************************************************************************+*+*   vchiq_ioctl+*+***************************************************************************/++static long+vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)+{+	VCHIQ_INSTANCE_T instance = file->private_data;+	VCHIQ_STATUS_T status = VCHIQ_SUCCESS;+	VCHIQ_SERVICE_T *service = NULL;+	long ret = 0;+	int i, rc;+	DEBUG_INITIALISE(g_state.local)++	vchiq_log_trace(vchiq_arm_log_level,+		 "vchiq_ioctl - instance %x, cmd %s, arg %lx",+		(unsigned int)instance,+		((_IOC_TYPE(cmd) == VCHIQ_IOC_MAGIC) &&+		(_IOC_NR(cmd) <= VCHIQ_IOC_MAX)) ?+		ioctl_names[_IOC_NR(cmd)] : "<invalid>", arg);++	switch (cmd) {+	case VCHIQ_IOC_SHUTDOWN:+		if (!instance->connected)+			break;++		/* Remove all services */+		i = 0;+		while ((service = next_service_by_instance(instance->state,+			instance, &i)) != NULL) {+			status = vchiq_remove_service(service->handle);+			unlock_service(service);+			if (status != VCHIQ_SUCCESS)+				break;+		}+		service = NULL;++		if (status == VCHIQ_SUCCESS) {+			/* Wake the completion thread and ask it to exit */+			instance->closing = 1;+			up(&instance->insert_event);+		}++		break;++	case VCHIQ_IOC_CONNECT:+		if (instance->connected) {+			ret = -EINVAL;+			break;+		}+		rc = mutex_lock_interruptible(&instance->state->mutex);+		if (rc != 0) {+			vchiq_log_error(vchiq_arm_log_level,+				"vchiq: connect: could not lock mutex for "+				"state %d: %d",+				instance->state->id, rc);+			ret = -EINTR;+			break;+		}+		status = vchiq_connect_internal(instance->state, instance);+		mutex_unlock(&instance->state->mutex);++		if (status == VCHIQ_SUCCESS)+			instance->connected = 1;+		else+			vchiq_log_error(vchiq_arm_log_level,+				"vchiq: could not connect: %d", status);+		break;++	case VCHIQ_IOC_CREATE_SERVICE: {+		VCHIQ_CREATE_SERVICE_T args;+		USER_SERVICE_T *user_service = NULL;+		void *userdata;+		int srvstate;++		if (copy_from_user+			 (&args, (const void __user *)arg,+			  sizeof(args)) != 0) {+			ret = -EFAULT;+			break;+		}++		user_service = kmalloc(sizeof(USER_SERVICE_T), GFP_KERNEL);+		if (!user_service) {+			ret = -ENOMEM;+			break;+		}++		if (args.is_open) {+			if (!instance->connected) {+				ret = -ENOTCONN;+				kfree(user_service);+				break;+			}+			srvstate = VCHIQ_SRVSTATE_OPENING;+		} else {+			srvstate =+				 instance->connected ?+				 VCHIQ_SRVSTATE_LISTENING :+				 VCHIQ_SRVSTATE_HIDDEN;+		}++		userdata = args.params.userdata;+		args.params.callback = service_callback;+		args.params.userdata = user_service;+		service = vchiq_add_service_internal(+				instance->state,+				&args.params, srvstate,+				instance, user_service_free);++		if (service != NULL) {+			user_service->service = service;+			user_service->userdata = userdata;+			user_service->instance = instance;+			user_service->is_vchi = args.is_vchi;+			user_service->dequeue_pending = 0;+			user_service->message_available_pos =+				instance->completion_remove - 1;+			user_service->msg_insert = 0;+			user_service->msg_remove = 0;+			sema_init(&user_service->insert_event, 0);+			sema_init(&user_service->remove_event, 0);++			if (args.is_open) {+				status = vchiq_open_service_internal+					(service, instance->pid);+				if (status != VCHIQ_SUCCESS) {+					vchiq_remove_service(service->handle);+					service = NULL;+					ret = (status == VCHIQ_RETRY) ?+						-EINTR : -EIO;+					break;+				}+			}++			if (copy_to_user((void __user *)+				&(((VCHIQ_CREATE_SERVICE_T __user *)+					arg)->handle),+				(const void *)&service->handle,+				sizeof(service->handle)) != 0) {+				ret = -EFAULT;+				vchiq_remove_service(service->handle);+			}++			service = NULL;+		} else {+			ret = -EEXIST;+			kfree(user_service);+		}+	} break;++	case VCHIQ_IOC_CLOSE_SERVICE: {+		VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg;++		service = find_service_for_instance(instance, handle);+		if (service != NULL)+			status = vchiq_close_service(service->handle);+		else+			ret = -EINVAL;+	} break;++	case VCHIQ_IOC_REMOVE_SERVICE: {+		VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg;++		service = find_service_for_instance(instance, handle);+		if (service != NULL)+			status = vchiq_remove_service(service->handle);+		else+			ret = -EINVAL;+	} break;++	case VCHIQ_IOC_USE_SERVICE:+	case VCHIQ_IOC_RELEASE_SERVICE:	{+		VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg;++		service = find_service_for_instance(instance, handle);+		if (service != NULL) {+			status = (cmd == VCHIQ_IOC_USE_SERVICE)	?+				vchiq_use_service_internal(service) :+				vchiq_release_service_internal(service);+			if (status != VCHIQ_SUCCESS) {+				vchiq_log_error(vchiq_susp_log_level,+					"%s: cmd %s returned error %d for "+					"service %c%c%c%c:%03d",+					__func__,+					(cmd == VCHIQ_IOC_USE_SERVICE) ?+						"VCHIQ_IOC_USE_SERVICE" :+						"VCHIQ_IOC_RELEASE_SERVICE",+					status,+					VCHIQ_FOURCC_AS_4CHARS(+						service->base.fourcc),+					service->client_id);+				ret = -EINVAL;+			}+		} else+			ret = -EINVAL;+	} break;++	case VCHIQ_IOC_QUEUE_MESSAGE: {+		VCHIQ_QUEUE_MESSAGE_T args;+		if (copy_from_user+			 (&args, (const void __user *)arg,+			  sizeof(args)) != 0) {+			ret = -EFAULT;+			break;+		}++		service = find_service_for_instance(instance, args.handle);++		if ((service != NULL) && (args.count <= MAX_ELEMENTS)) {+			/* Copy elements into kernel space */+			VCHIQ_ELEMENT_T elements[MAX_ELEMENTS];+			if (copy_from_user(elements, args.elements,+				args.count * sizeof(VCHIQ_ELEMENT_T)) == 0)+				status = vchiq_queue_message+					(args.handle,+					elements, args.count);+			else+				ret = -EFAULT;+		} else {+			ret = -EINVAL;+		}+	} break;++	case VCHIQ_IOC_QUEUE_BULK_TRANSMIT:+	case VCHIQ_IOC_QUEUE_BULK_RECEIVE: {+		VCHIQ_QUEUE_BULK_TRANSFER_T args;+		struct bulk_waiter_node *waiter = NULL;+		VCHIQ_BULK_DIR_T dir =+			(cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT) ?+			VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE;++		if (copy_from_user+			(&args, (const void __user *)arg,+			sizeof(args)) != 0) {+			ret = -EFAULT;+			break;+		}++		service = find_service_for_instance(instance, args.handle);+		if (!service) {+			ret = -EINVAL;+			break;+		}++		if (args.mode == VCHIQ_BULK_MODE_BLOCKING) {+			waiter = kzalloc(sizeof(struct bulk_waiter_node),+				GFP_KERNEL);+			if (!waiter) {+				ret = -ENOMEM;+				break;+			}+			args.userdata = &waiter->bulk_waiter;+		} else if (args.mode == VCHIQ_BULK_MODE_WAITING) {+			struct list_head *pos;+			mutex_lock(&instance->bulk_waiter_list_mutex);+			list_for_each(pos, &instance->bulk_waiter_list) {+				if (list_entry(pos, struct bulk_waiter_node,+					list)->pid == current->pid) {+					waiter = list_entry(pos,+						struct bulk_waiter_node,+						list);+					list_del(pos);+					break;+				}++			}+			mutex_unlock(&instance->bulk_waiter_list_mutex);+			if (!waiter) {+				vchiq_log_error(vchiq_arm_log_level,+					"no bulk_waiter found for pid %d",+					current->pid);+				ret = -ESRCH;+				break;+			}+			vchiq_log_info(vchiq_arm_log_level,+				"found bulk_waiter %x for pid %d",+				(unsigned int)waiter, current->pid);+			args.userdata = &waiter->bulk_waiter;+		}+		status = vchiq_bulk_transfer+			(args.handle,+			 VCHI_MEM_HANDLE_INVALID,+			 args.data, args.size,+			 args.userdata, args.mode,+			 dir);+		if (!waiter)+			break;+		if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) ||+			!waiter->bulk_waiter.bulk) {+			if (waiter->bulk_waiter.bulk) {+				/* Cancel the signal when the transfer+				** completes. */+				spin_lock(&bulk_waiter_spinlock);+				waiter->bulk_waiter.bulk->userdata = NULL;+				spin_unlock(&bulk_waiter_spinlock);+			}+			kfree(waiter);+		} else {+			const VCHIQ_BULK_MODE_T mode_waiting =+				VCHIQ_BULK_MODE_WAITING;+			waiter->pid = current->pid;+			mutex_lock(&instance->bulk_waiter_list_mutex);+			list_add(&waiter->list, &instance->bulk_waiter_list);+			mutex_unlock(&instance->bulk_waiter_list_mutex);+			vchiq_log_info(vchiq_arm_log_level,+				"saved bulk_waiter %x for pid %d",+				(unsigned int)waiter, current->pid);++			if (copy_to_user((void __user *)+				&(((VCHIQ_QUEUE_BULK_TRANSFER_T __user *)+					arg)->mode),+				(const void *)&mode_waiting,+				sizeof(mode_waiting)) != 0)+				ret = -EFAULT;+		}+	} break;++	case VCHIQ_IOC_AWAIT_COMPLETION: {+		VCHIQ_AWAIT_COMPLETION_T args;++		DEBUG_TRACE(AWAIT_COMPLETION_LINE);+		if (!instance->connected) {+			ret = -ENOTCONN;+			break;+		}++		if (copy_from_user(&args, (const void __user *)arg,+			sizeof(args)) != 0) {+			ret = -EFAULT;+			break;+		}++		mutex_lock(&instance->completion_mutex);++		DEBUG_TRACE(AWAIT_COMPLETION_LINE);+		while ((instance->completion_remove ==+			instance->completion_insert)+			&& !instance->closing) {+			int rc;+			DEBUG_TRACE(AWAIT_COMPLETION_LINE);+			mutex_unlock(&instance->completion_mutex);+			rc = down_interruptible(&instance->insert_event);+			mutex_lock(&instance->completion_mutex);+			if (rc != 0) {+				DEBUG_TRACE(AWAIT_COMPLETION_LINE);+				vchiq_log_info(vchiq_arm_log_level,+					"AWAIT_COMPLETION interrupted");+				ret = -EINTR;+				break;+			}+		}+		DEBUG_TRACE(AWAIT_COMPLETION_LINE);++		/* A read memory barrier is needed to stop prefetch of a stale+		** completion record+		*/+		rmb();++		if (ret == 0) {+			int msgbufcount = args.msgbufcount;+			for (ret = 0; ret < args.count; ret++) {+				VCHIQ_COMPLETION_DATA_T *completion;+				VCHIQ_SERVICE_T *service;+				USER_SERVICE_T *user_service;+				VCHIQ_HEADER_T *header;+				if (instance->completion_remove ==+					instance->completion_insert)+					break;+				completion = &instance->completions[+					instance->completion_remove &+					(MAX_COMPLETIONS - 1)];++				service = completion->service_userdata;+				user_service = service->base.userdata;+				completion->service_userdata =+					user_service->userdata;++				header = completion->header;+				if (header) {+					void __user *msgbuf;+					int msglen;++					msglen = header->size ++						sizeof(VCHIQ_HEADER_T);+					/* This must be a VCHIQ-style service */+					if (args.msgbufsize < msglen) {+						vchiq_log_error(+							vchiq_arm_log_level,+							"header %x: msgbufsize"+							" %x < msglen %x",+							(unsigned int)header,+							args.msgbufsize,+							msglen);+						WARN(1, "invalid message "+							"size\n");+						if (ret == 0)+							ret = -EMSGSIZE;+						break;+					}+					if (msgbufcount <= 0)+						/* Stall here for lack of a+						** buffer for the message. */+						break;+					/* Get the pointer from user space */+					msgbufcount--;+					if (copy_from_user(&msgbuf,+						(const void __user *)+						&args.msgbufs[msgbufcount],+						sizeof(msgbuf)) != 0) {+						if (ret == 0)+							ret = -EFAULT;+						break;+					}++					/* Copy the message to user space */+					if (copy_to_user(msgbuf, header,+						msglen) != 0) {+						if (ret == 0)+							ret = -EFAULT;+						break;+					}++					/* Now it has been copied, the message+					** can be released. */+					vchiq_release_message(service->handle,+						header);++					/* The completion must point to the+					** msgbuf. */+					completion->header = msgbuf;+				}++				if (completion->reason ==+					VCHIQ_SERVICE_CLOSED)+					unlock_service(service);++				if (copy_to_user((void __user *)(+					(size_t)args.buf ++					ret * sizeof(VCHIQ_COMPLETION_DATA_T)),+					completion,+					sizeof(VCHIQ_COMPLETION_DATA_T)) != 0) {+						if (ret == 0)+							ret = -EFAULT;+					break;+				}++				instance->completion_remove++;+			}++			if (msgbufcount != args.msgbufcount) {+				if (copy_to_user((void __user *)+					&((VCHIQ_AWAIT_COMPLETION_T *)arg)->+						msgbufcount,+					&msgbufcount,+					sizeof(msgbufcount)) != 0) {+					ret = -EFAULT;+				}+			}+		}++		if (ret != 0)+			up(&instance->remove_event);+		mutex_unlock(&instance->completion_mutex);+		DEBUG_TRACE(AWAIT_COMPLETION_LINE);+	} break;++	case VCHIQ_IOC_DEQUEUE_MESSAGE: {+		VCHIQ_DEQUEUE_MESSAGE_T args;+		USER_SERVICE_T *user_service;+		VCHIQ_HEADER_T *header;++		DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);+		if (copy_from_user+			 (&args, (const void __user *)arg,+			  sizeof(args)) != 0) {+			ret = -EFAULT;+			break;+		}+		service = find_service_for_instance(instance, args.handle);+		if (!service) {+			ret = -EINVAL;+			break;+		}+		user_service = (USER_SERVICE_T *)service->base.userdata;+		if (user_service->is_vchi == 0) {+			ret = -EINVAL;+			break;+		}++		spin_lock(&msg_queue_spinlock);+		if (user_service->msg_remove == user_service->msg_insert) {+			if (!args.blocking) {+				spin_unlock(&msg_queue_spinlock);+				DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);+				ret = -EWOULDBLOCK;+				break;+			}+			user_service->dequeue_pending = 1;+			do {+				spin_unlock(&msg_queue_spinlock);+				DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);+				if (down_interruptible(+					&user_service->insert_event) != 0) {+					vchiq_log_info(vchiq_arm_log_level,+						"DEQUEUE_MESSAGE interrupted");+					ret = -EINTR;+					break;+				}+				spin_lock(&msg_queue_spinlock);+			} while (user_service->msg_remove ==+				user_service->msg_insert);++			if (ret)+				break;+		}++		BUG_ON((int)(user_service->msg_insert -+			user_service->msg_remove) < 0);++		header = user_service->msg_queue[user_service->msg_remove &+			(MSG_QUEUE_SIZE - 1)];+		user_service->msg_remove++;+		spin_unlock(&msg_queue_spinlock);++		up(&user_service->remove_event);+		if (header == NULL)+			ret = -ENOTCONN;+		else if (header->size <= args.bufsize) {+			/* Copy to user space if msgbuf is not NULL */+			if ((args.buf == NULL) ||+				(copy_to_user((void __user *)args.buf,+				header->data,+				header->size) == 0)) {+				ret = header->size;+				vchiq_release_message(+					service->handle,+					header);+			} else+				ret = -EFAULT;+		} else {+			vchiq_log_error(vchiq_arm_log_level,+				"header %x: bufsize %x < size %x",+				(unsigned int)header, args.bufsize,+				header->size);+			WARN(1, "invalid size\n");+			ret = -EMSGSIZE;+		}+		DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);+	} break;++	case VCHIQ_IOC_GET_CLIENT_ID: {+		VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg;++		ret = vchiq_get_client_id(handle);+	} break;++	case VCHIQ_IOC_GET_CONFIG: {+		VCHIQ_GET_CONFIG_T args;+		VCHIQ_CONFIG_T config;++		if (copy_from_user(&args, (const void __user *)arg,+			sizeof(args)) != 0) {+			ret = -EFAULT;+			break;+		}+		if (args.config_size > sizeof(config)) {+			ret = -EINVAL;+			break;+		}+		status = vchiq_get_config(instance, args.config_size, &config);+		if (status == VCHIQ_SUCCESS) {+			if (copy_to_user((void __user *)args.pconfig,+				    &config, args.config_size) != 0) {+				ret = -EFAULT;+				break;+			}+		}+	} break;++	case VCHIQ_IOC_SET_SERVICE_OPTION: {+		VCHIQ_SET_SERVICE_OPTION_T args;++		if (copy_from_user(+			&args, (const void __user *)arg,+			sizeof(args)) != 0) {+			ret = -EFAULT;+			break;+		}++		service = find_service_for_instance(instance, args.handle);+		if (!service) {+			ret = -EINVAL;+			break;+		}++		status = vchiq_set_service_option(+				args.handle, args.option, args.value);+	} break;++	case VCHIQ_IOC_DUMP_PHYS_MEM: {+		VCHIQ_DUMP_MEM_T  args;++		if (copy_from_user+			 (&args, (const void __user *)arg,+			  sizeof(args)) != 0) {+			ret = -EFAULT;+			break;+		}+		dump_phys_mem(args.virt_addr, args.num_bytes);+	} break;++	default:+		ret = -ENOTTY;+		break;+	}++	if (service)+		unlock_service(service);++	if (ret == 0) {+		if (status == VCHIQ_ERROR)+			ret = -EIO;+		else if (status == VCHIQ_RETRY)+			ret = -EINTR;+	}++	if ((status == VCHIQ_SUCCESS) && (ret < 0) && (ret != -EINTR) &&+		(ret != -EWOULDBLOCK))+		vchiq_log_info(vchiq_arm_log_level,+			"  ioctl instance %lx, cmd %s -> status %d, %ld",+			(unsigned long)instance,+			(_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ?+				ioctl_names[_IOC_NR(cmd)] :+				"<invalid>",+			status, ret);+	else+		vchiq_log_trace(vchiq_arm_log_level,+			"  ioctl instance %lx, cmd %s -> status %d, %ld",+			(unsigned long)instance,+			(_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ?+				ioctl_names[_IOC_NR(cmd)] :+				"<invalid>",+			status, ret);++	return ret;+}++/****************************************************************************+*+*   vchiq_open+*+***************************************************************************/++static int+vchiq_open(struct inode *inode, struct file *file)+{+	int dev = iminor(inode) & 0x0f;+	vchiq_log_info(vchiq_arm_log_level, "vchiq_open");+	switch (dev) {+	case VCHIQ_MINOR: {+		int ret;+		VCHIQ_STATE_T *state = vchiq_get_state();+		VCHIQ_INSTANCE_T instance;++		if (!state) {+			vchiq_log_error(vchiq_arm_log_level,+				"vchiq has no connection to VideoCore");+			return -ENOTCONN;+		}++		instance = kzalloc(sizeof(*instance), GFP_KERNEL);+		if (!instance)+			return -ENOMEM;++		instance->state = state;+		instance->pid = current->tgid;++		ret = vchiq_proc_add_instance(instance);+		if (ret != 0) {+			kfree(instance);+			return ret;+		}++		sema_init(&instance->insert_event, 0);+		sema_init(&instance->remove_event, 0);+		mutex_init(&instance->completion_mutex);+		mutex_init(&instance->bulk_waiter_list_mutex);+		INIT_LIST_HEAD(&instance->bulk_waiter_list);++		file->private_data = instance;+	} break;++	default:+		vchiq_log_error(vchiq_arm_log_level,+			"Unknown minor device: %d", dev);+		return -ENXIO;+	}++	return 0;+}++/****************************************************************************+*+*   vchiq_release+*+***************************************************************************/++static int+vchiq_release(struct inode *inode, struct file *file)+{+	int dev = iminor(inode) & 0x0f;+	int ret = 0;+	switch (dev) {+	case VCHIQ_MINOR: {+		VCHIQ_INSTANCE_T instance = file->private_data;+		VCHIQ_STATE_T *state = vchiq_get_state();+		VCHIQ_SERVICE_T *service;+		int i;++		vchiq_log_info(vchiq_arm_log_level,+			"vchiq_release: instance=%lx",+			(unsigned long)instance);++		if (!state) {+			ret = -EPERM;+			goto out;+		}++		/* Ensure videocore is awake to allow termination. */+		vchiq_use_internal(instance->state, NULL,+				USE_TYPE_VCHIQ);++		mutex_lock(&instance->completion_mutex);++		/* Wake the completion thread and ask it to exit */+		instance->closing = 1;+		up(&instance->insert_event);++		mutex_unlock(&instance->completion_mutex);++		/* Wake the slot handler if the completion queue is full. */+		up(&instance->remove_event);++		/* Mark all services for termination... */+		i = 0;+		while ((service = next_service_by_instance(state, instance,+			&i)) !=	NULL) {+			USER_SERVICE_T *user_service = service->base.userdata;++			/* Wake the slot handler if the msg queue is full. */+			up(&user_service->remove_event);++			vchiq_terminate_service_internal(service);+			unlock_service(service);+		}++		/* ...and wait for them to die */+		i = 0;+		while ((service = next_service_by_instance(state, instance, &i))+			!= NULL) {+			USER_SERVICE_T *user_service = service->base.userdata;++			down(&service->remove_event);++			BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE);++			spin_lock(&msg_queue_spinlock);++			while (user_service->msg_remove !=+				user_service->msg_insert) {+				VCHIQ_HEADER_T *header = user_service->+					msg_queue[user_service->msg_remove &+						(MSG_QUEUE_SIZE - 1)];+				user_service->msg_remove++;+				spin_unlock(&msg_queue_spinlock);++				if (header)+					vchiq_release_message(+						service->handle,+						header);+				spin_lock(&msg_queue_spinlock);+			}++			spin_unlock(&msg_queue_spinlock);++			unlock_service(service);+		}++		/* Release any closed services */+		while (instance->completion_remove !=+			instance->completion_insert) {+			VCHIQ_COMPLETION_DATA_T *completion;+			VCHIQ_SERVICE_T *service;+			completion = &instance->completions[+				instance->completion_remove &+				(MAX_COMPLETIONS - 1)];+			service = completion->service_userdata;+			if (completion->reason == VCHIQ_SERVICE_CLOSED)+				unlock_service(service);+			instance->completion_remove++;+		}++		/* Release the PEER service count. */+		vchiq_release_internal(instance->state, NULL);++		{+			struct list_head *pos, *next;+			list_for_each_safe(pos, next,+				&instance->bulk_waiter_list) {+				struct bulk_waiter_node *waiter;+				waiter = list_entry(pos,+					struct bulk_waiter_node,+					list);+				list_del(pos);+				vchiq_log_info(vchiq_arm_log_level,+					"bulk_waiter - cleaned up %x "+					"for pid %d",+					(unsigned int)waiter, waiter->pid);+				kfree(waiter);+			}+		}++		vchiq_proc_remove_instance(instance);++		kfree(instance);+		file->private_data = NULL;+	} break;++	default:+		vchiq_log_error(vchiq_arm_log_level,+			"Unknown minor device: %d", dev);+		ret = -ENXIO;+	}++out:+	return ret;+}++/****************************************************************************+*+*   vchiq_dump+*+***************************************************************************/++void+vchiq_dump(void *dump_context, const char *str, int len)+{+	DUMP_CONTEXT_T *context = (DUMP_CONTEXT_T *)dump_context;++	if (context->actual < context->space) {+		int copy_bytes;+		if (context->offset > 0) {+			int skip_bytes = min(len, (int)context->offset);+			str += skip_bytes;+			len -= skip_bytes;+			context->offset -= skip_bytes;+			if (context->offset > 0)+				return;+		}+		copy_bytes = min(len, (int)(context->space - context->actual));+		if (copy_bytes == 0)+			return;+		if (copy_to_user(context->buf + context->actual, str,+			copy_bytes))+			context->actual = -EFAULT;+		context->actual += copy_bytes;+		len -= copy_bytes;++		/* If tne terminating NUL is included in the length, then it+		** marks the end of a line and should be replaced with a+		** carriage return. */+		if ((len == 0) && (str[copy_bytes - 1] == '\0')) {+			char cr = '\n';+			if (copy_to_user(context->buf + context->actual - 1,+				&cr, 1))+				context->actual = -EFAULT;+		}+	}+}++/****************************************************************************+*+*   vchiq_dump_platform_instance_state+*+***************************************************************************/++void+vchiq_dump_platform_instances(void *dump_context)+{+	VCHIQ_STATE_T *state = vchiq_get_state();+	char buf[80];+	int len;+	int i;++	/* There is no list of instances, so instead scan all services,+		marking those that have been dumped. */++	for (i = 0; i < state->unused_service; i++) {+		VCHIQ_SERVICE_T *service = state->services[i];+		VCHIQ_INSTANCE_T instance;++		if (service && (service->base.callback == service_callback)) {+			instance = service->instance;+			if (instance)+				instance->mark = 0;+		}+	}++	for (i = 0; i < state->unused_service; i++) {+		VCHIQ_SERVICE_T *service = state->services[i];+		VCHIQ_INSTANCE_T instance;++		if (service && (service->base.callback == service_callback)) {+			instance = service->instance;+			if (instance && !instance->mark) {+				len = snprintf(buf, sizeof(buf),+					"Instance %x: pid %d,%s completions "+						"%d/%d",+					(unsigned int)instance, instance->pid,+					instance->connected ? " connected, " :+						"",+					instance->completion_insert -+						instance->completion_remove,+					MAX_COMPLETIONS);++				vchiq_dump(dump_context, buf, len + 1);++				instance->mark = 1;+			}+		}+	}+}++/****************************************************************************+*+*   vchiq_dump_platform_service_state+*+***************************************************************************/++void+vchiq_dump_platform_service_state(void *dump_context, VCHIQ_SERVICE_T *service)+{+	USER_SERVICE_T *user_service = (USER_SERVICE_T *)service->base.userdata;+	char buf[80];+	int len;++	len = snprintf(buf, sizeof(buf), "  instance %x",+		(unsigned int)service->instance);++	if ((service->base.callback == service_callback) &&+		user_service->is_vchi) {+		len += snprintf(buf + len, sizeof(buf) - len,+			", %d/%d messages",+			user_service->msg_insert - user_service->msg_remove,+			MSG_QUEUE_SIZE);++		if (user_service->dequeue_pending)+			len += snprintf(buf + len, sizeof(buf) - len,+				" (dequeue pending)");+	}++	vchiq_dump(dump_context, buf, len + 1);+}++/****************************************************************************+*+*   dump_user_mem+*+***************************************************************************/++static void+dump_phys_mem(void *virt_addr, uint32_t num_bytes)+{+	int            rc;+	uint8_t       *end_virt_addr = virt_addr + num_bytes;+	int            num_pages;+	int            offset;+	int            end_offset;+	int            page_idx;+	int            prev_idx;+	struct page   *page;+	struct page  **pages;+	uint8_t       *kmapped_virt_ptr;++	/* Align virtAddr and endVirtAddr to 16 byte boundaries. */++	virt_addr = (void *)((unsigned long)virt_addr & ~0x0fuL);+	end_virt_addr = (void *)(((unsigned long)end_virt_addr + 15uL) &+		~0x0fuL);++	offset = (int)(long)virt_addr & (PAGE_SIZE - 1);+	end_offset = (int)(long)end_virt_addr & (PAGE_SIZE - 1);++	num_pages = (offset + num_bytes + PAGE_SIZE - 1) / PAGE_SIZE;++	pages = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL);+	if (pages == NULL) {+		vchiq_log_error(vchiq_arm_log_level,+			"Unable to allocation memory for %d pages\n",+			num_pages);+		return;+	}++	down_read(¤t->mm->mmap_sem);+	rc = get_user_pages(current,      /* task */+		current->mm,              /* mm */+		(unsigned long)virt_addr, /* start */+		num_pages,                /* len */+		0,                        /* write */+		0,                        /* force */+		pages,                    /* pages (array of page pointers) */+		NULL);                    /* vmas */+	up_read(¤t->mm->mmap_sem);++	prev_idx = -1;+	page = NULL;++	while (offset < end_offset) {++		int page_offset = offset % PAGE_SIZE;+		page_idx = offset / PAGE_SIZE;++		if (page_idx != prev_idx) {++			if (page != NULL)+				kunmap(page);+			page = pages[page_idx];+			kmapped_virt_ptr = kmap(page);++			prev_idx = page_idx;+		}++		if (vchiq_arm_log_level >= VCHIQ_LOG_TRACE)+			vchiq_log_dump_mem("ph",+				(uint32_t)(unsigned long)&kmapped_virt_ptr[+					page_offset],+				&kmapped_virt_ptr[page_offset], 16);++		offset += 16;+	}+	if (page != NULL)+		kunmap(page);++	for (page_idx = 0; page_idx < num_pages; page_idx++)+		page_cache_release(pages[page_idx]);++	kfree(pages);+}++/****************************************************************************+*+*   vchiq_read+*+***************************************************************************/++static ssize_t+vchiq_read(struct file *file, char __user *buf,+	size_t count, loff_t *ppos)+{+	DUMP_CONTEXT_T context;+	context.buf = buf;+	context.actual = 0;+	context.space = count;+	context.offset = *ppos;++	vchiq_dump_state(&context, &g_state);++	*ppos += context.actual;++	return context.actual;+}++VCHIQ_STATE_T *+vchiq_get_state(void)+{++	if (g_state.remote == NULL)+		printk(KERN_ERR "%s: g_state.remote == NULL\n", __func__);+	else if (g_state.remote->initialised != 1)+		printk(KERN_NOTICE "%s: g_state.remote->initialised != 1 (%d)\n",+			__func__, g_state.remote->initialised);++	return ((g_state.remote != NULL) &&+		(g_state.remote->initialised == 1)) ? &g_state : NULL;+}++static const struct file_operations+vchiq_fops = {+	.owner = THIS_MODULE,+	.unlocked_ioctl = vchiq_ioctl,+	.open = vchiq_open,+	.release = vchiq_release,+	.read = vchiq_read+};++/*+ * Autosuspend related functionality+ */++int+vchiq_videocore_wanted(VCHIQ_STATE_T *state)+{+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);+	if (!arm_state)+		/* autosuspend not supported - always return wanted */+		return 1;+	else if (arm_state->blocked_count)+		return 1;+	else if (!arm_state->videocore_use_count)+		/* usage count zero - check for override unless we're forcing */+		if (arm_state->resume_blocked)+			return 0;+		else+			return vchiq_platform_videocore_wanted(state);+	else+		/* non-zero usage count - videocore still required */+		return 1;+}++static VCHIQ_STATUS_T+vchiq_keepalive_vchiq_callback(VCHIQ_REASON_T reason,+	VCHIQ_HEADER_T *header,+	VCHIQ_SERVICE_HANDLE_T service_user,+	void *bulk_user)+{+	vchiq_log_error(vchiq_susp_log_level,+		"%s callback reason %d", __func__, reason);+	return 0;+}++static int+vchiq_keepalive_thread_func(void *v)+{+	VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v;+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);++	VCHIQ_STATUS_T status;+	VCHIQ_INSTANCE_T instance;+	VCHIQ_SERVICE_HANDLE_T ka_handle;++	VCHIQ_SERVICE_PARAMS_T params = {+		.fourcc      = VCHIQ_MAKE_FOURCC('K', 'E', 'E', 'P'),+		.callback    = vchiq_keepalive_vchiq_callback,+		.version     = KEEPALIVE_VER,+		.version_min = KEEPALIVE_VER_MIN+	};++	status = vchiq_initialise(&instance);+	if (status != VCHIQ_SUCCESS) {+		vchiq_log_error(vchiq_susp_log_level,+			"%s vchiq_initialise failed %d", __func__, status);+		goto exit;+	}++	status = vchiq_connect(instance);+	if (status != VCHIQ_SUCCESS) {+		vchiq_log_error(vchiq_susp_log_level,+			"%s vchiq_connect failed %d", __func__, status);+		goto shutdown;+	}++	status = vchiq_add_service(instance, ¶ms, &ka_handle);+	if (status != VCHIQ_SUCCESS) {+		vchiq_log_error(vchiq_susp_log_level,+			"%s vchiq_open_service failed %d", __func__, status);+		goto shutdown;+	}++	while (1) {+		long rc = 0, uc = 0;+		if (wait_for_completion_interruptible(&arm_state->ka_evt)+				!= 0) {+			vchiq_log_error(vchiq_susp_log_level,+				"%s interrupted", __func__);+			flush_signals(current);+			continue;+		}++		/* read and clear counters.  Do release_count then use_count to+		 * prevent getting more releases than uses */+		rc = atomic_xchg(&arm_state->ka_release_count, 0);+		uc = atomic_xchg(&arm_state->ka_use_count, 0);++		/* Call use/release service the requisite number of times.+		 * Process use before release so use counts don't go negative */+		while (uc--) {+			atomic_inc(&arm_state->ka_use_ack_count);+			status = vchiq_use_service(ka_handle);+			if (status != VCHIQ_SUCCESS) {+				vchiq_log_error(vchiq_susp_log_level,+					"%s vchiq_use_service error %d",+					__func__, status);+			}+		}+		while (rc--) {+			status = vchiq_release_service(ka_handle);+			if (status != VCHIQ_SUCCESS) {+				vchiq_log_error(vchiq_susp_log_level,+					"%s vchiq_release_service error %d",+					__func__, status);+			}+		}+	}++shutdown:+	vchiq_shutdown(instance);+exit:+	return 0;+}++++VCHIQ_STATUS_T+vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state)+{+	VCHIQ_STATUS_T status = VCHIQ_SUCCESS;++	if (arm_state) {+		rwlock_init(&arm_state->susp_res_lock);++		init_completion(&arm_state->ka_evt);+		atomic_set(&arm_state->ka_use_count, 0);+		atomic_set(&arm_state->ka_use_ack_count, 0);+		atomic_set(&arm_state->ka_release_count, 0);++		init_completion(&arm_state->vc_suspend_complete);++		init_completion(&arm_state->vc_resume_complete);+		/* Initialise to 'done' state.  We only want to block on resume+		 * completion while videocore is suspended. */+		set_resume_state(arm_state, VC_RESUME_RESUMED);++		init_completion(&arm_state->resume_blocker);+		/* Initialise to 'done' state.  We only want to block on this+		 * completion while resume is blocked */+		complete_all(&arm_state->resume_blocker);++		init_completion(&arm_state->blocked_blocker);+		/* Initialise to 'done' state.  We only want to block on this+		 * completion while things are waiting on the resume blocker */+		complete_all(&arm_state->blocked_blocker);++		arm_state->suspend_timer_timeout = SUSPEND_TIMER_TIMEOUT_MS;+		arm_state->suspend_timer_running = 0;+		init_timer(&arm_state->suspend_timer);+		arm_state->suspend_timer.data = (unsigned long)(state);+		arm_state->suspend_timer.function = suspend_timer_callback;++		arm_state->first_connect = 0;++	}+	return status;+}++/*+** Functions to modify the state variables;+**	set_suspend_state+**	set_resume_state+**+** There are more state variables than we might like, so ensure they remain in+** step.  Suspend and resume state are maintained separately, since most of+** these state machines can operate independently.  However, there are a few+** states where state transitions in one state machine cause a reset to the+** other state machine.  In addition, there are some completion events which+** need to occur on state machine reset and end-state(s), so these are also+** dealt with in these functions.+**+** In all states we set the state variable according to the input, but in some+** cases we perform additional steps outlined below;+**+** VC_SUSPEND_IDLE - Initialise the suspend completion at the same time.+**			The suspend completion is completed after any suspend+**			attempt.  When we reset the state machine we also reset+**			the completion.  This reset occurs when videocore is+**			resumed, and also if we initiate suspend after a suspend+**			failure.+**+** VC_SUSPEND_IN_PROGRESS - This state is considered the point of no return for+**			suspend - ie from this point on we must try to suspend+**			before resuming can occur.  We therefore also reset the+**			resume state machine to VC_RESUME_IDLE in this state.+**+** VC_SUSPEND_SUSPENDED - Suspend has completed successfully. Also call+**			complete_all on the suspend completion to notify+**			anything waiting for suspend to happen.+**+** VC_SUSPEND_REJECTED - Videocore rejected suspend. Videocore will also+**			initiate resume, so no need to alter resume state.+**			We call complete_all on the suspend completion to notify+**			of suspend rejection.+**+** VC_SUSPEND_FAILED - We failed to initiate videocore suspend.  We notify the+**			suspend completion and reset the resume state machine.+**+** VC_RESUME_IDLE - Initialise the resume completion at the same time.  The+**			resume completion is in it's 'done' state whenever+**			videcore is running.  Therfore, the VC_RESUME_IDLE state+**			implies that videocore is suspended.+**			Hence, any thread which needs to wait until videocore is+**			running can wait on this completion - it will only block+**			if videocore is suspended.+**+** VC_RESUME_RESUMED - Resume has completed successfully.  Videocore is running.+**			Call complete_all on the resume completion to unblock+**			any threads waiting for resume.	 Also reset the suspend+**			state machine to it's idle state.+**+** VC_RESUME_FAILED - Currently unused - no mechanism to fail resume exists.+*/++inline void+set_suspend_state(VCHIQ_ARM_STATE_T *arm_state,+	enum vc_suspend_status new_state)+{+	/* set the state in all cases */+	arm_state->vc_suspend_state = new_state;++	/* state specific additional actions */+	switch (new_state) {+	case VC_SUSPEND_FORCE_CANCELED:+		complete_all(&arm_state->vc_suspend_complete);+		break;+	case VC_SUSPEND_REJECTED:+		complete_all(&arm_state->vc_suspend_complete);+		break;+	case VC_SUSPEND_FAILED:+		complete_all(&arm_state->vc_suspend_complete);+		arm_state->vc_resume_state = VC_RESUME_RESUMED;+		complete_all(&arm_state->vc_resume_complete);+		break;+	case VC_SUSPEND_IDLE:+		INIT_COMPLETION(arm_state->vc_suspend_complete);+		break;+	case VC_SUSPEND_REQUESTED:+		break;+	case VC_SUSPEND_IN_PROGRESS:+		set_resume_state(arm_state, VC_RESUME_IDLE);+		break;+	case VC_SUSPEND_SUSPENDED:+		complete_all(&arm_state->vc_suspend_complete);+		break;+	default:+		BUG();+		break;+	}+}++inline void+set_resume_state(VCHIQ_ARM_STATE_T *arm_state,+	enum vc_resume_status new_state)+{+	/* set the state in all cases */+	arm_state->vc_resume_state = new_state;++	/* state specific additional actions */+	switch (new_state) {+	case VC_RESUME_FAILED:+		break;+	case VC_RESUME_IDLE:+		INIT_COMPLETION(arm_state->vc_resume_complete);+		break;+	case VC_RESUME_REQUESTED:+		break;+	case VC_RESUME_IN_PROGRESS:+		break;+	case VC_RESUME_RESUMED:+		complete_all(&arm_state->vc_resume_complete);+		set_suspend_state(arm_state, VC_SUSPEND_IDLE);+		break;+	default:+		BUG();+		break;+	}+}+++/* should be called with the write lock held */+inline void+start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state)+{+	del_timer(&arm_state->suspend_timer);+	arm_state->suspend_timer.expires = jiffies ++		msecs_to_jiffies(arm_state->+			suspend_timer_timeout);+	add_timer(&arm_state->suspend_timer);+	arm_state->suspend_timer_running = 1;+}++/* should be called with the write lock held */+static inline void+stop_suspend_timer(VCHIQ_ARM_STATE_T *arm_state)+{+	if (arm_state->suspend_timer_running) {+		del_timer(&arm_state->suspend_timer);+		arm_state->suspend_timer_running = 0;+	}+}++static inline int+need_resume(VCHIQ_STATE_T *state)+{+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);+	return (arm_state->vc_suspend_state > VC_SUSPEND_IDLE) &&+			(arm_state->vc_resume_state < VC_RESUME_REQUESTED) &&+			vchiq_videocore_wanted(state);+}++static int+block_resume(VCHIQ_ARM_STATE_T *arm_state)+{+	int status = VCHIQ_SUCCESS;+	const unsigned long timeout_val =+				msecs_to_jiffies(FORCE_SUSPEND_TIMEOUT_MS);+	int resume_count = 0;++	/* Allow any threads which were blocked by the last force suspend to+	 * complete if they haven't already.  Only give this one shot; if+	 * blocked_count is incremented after blocked_blocker is completed+	 * (which only happens when blocked_count hits 0) then those threads+	 * will have to wait until next time around */+	if (arm_state->blocked_count) {+		INIT_COMPLETION(arm_state->blocked_blocker);+		write_unlock_bh(&arm_state->susp_res_lock);+		vchiq_log_info(vchiq_susp_log_level, "%s wait for previously "+			"blocked clients", __func__);+		if (wait_for_completion_interruptible_timeout(+				&arm_state->blocked_blocker, timeout_val)+					<= 0) {+			vchiq_log_error(vchiq_susp_log_level, "%s wait for "+				"previously blocked clients failed" , __func__);+			status = VCHIQ_ERROR;+			write_lock_bh(&arm_state->susp_res_lock);+			goto out;+		}+		vchiq_log_info(vchiq_susp_log_level, "%s previously blocked "+			"clients resumed", __func__);+		write_lock_bh(&arm_state->susp_res_lock);+	}++	/* We need to wait for resume to complete if it's in process */+	while (arm_state->vc_resume_state != VC_RESUME_RESUMED &&+			arm_state->vc_resume_state > VC_RESUME_IDLE) {+		if (resume_count > 1) {+			status = VCHIQ_ERROR;+			vchiq_log_error(vchiq_susp_log_level, "%s waited too "+				"many times for resume" , __func__);+			goto out;+		}+		write_unlock_bh(&arm_state->susp_res_lock);+		vchiq_log_info(vchiq_susp_log_level, "%s wait for resume",+			__func__);+		if (wait_for_completion_interruptible_timeout(+				&arm_state->vc_resume_complete, timeout_val)+					<= 0) {+			vchiq_log_error(vchiq_susp_log_level, "%s wait for "+				"resume failed (%s)", __func__,+				resume_state_names[arm_state->vc_resume_state ++							VC_RESUME_NUM_OFFSET]);+			status = VCHIQ_ERROR;+			write_lock_bh(&arm_state->susp_res_lock);+			goto out;+		}+		vchiq_log_info(vchiq_susp_log_level, "%s resumed", __func__);+		write_lock_bh(&arm_state->susp_res_lock);+		resume_count++;+	}+	INIT_COMPLETION(arm_state->resume_blocker);+	arm_state->resume_blocked = 1;++out:+	return status;+}++static inline void+unblock_resume(VCHIQ_ARM_STATE_T *arm_state)+{+	complete_all(&arm_state->resume_blocker);+	arm_state->resume_blocked = 0;+}++/* Initiate suspend via slot handler. Should be called with the write lock+ * held */+VCHIQ_STATUS_T+vchiq_arm_vcsuspend(VCHIQ_STATE_T *state)+{+	VCHIQ_STATUS_T status = VCHIQ_ERROR;+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);++	if (!arm_state)+		goto out;++	vchiq_log_trace(vchiq_susp_log_level, "%s", __func__);+	status = VCHIQ_SUCCESS;+++	switch (arm_state->vc_suspend_state) {+	case VC_SUSPEND_REQUESTED:+		vchiq_log_info(vchiq_susp_log_level, "%s: suspend already "+			"requested", __func__);+		break;+	case VC_SUSPEND_IN_PROGRESS:+		vchiq_log_info(vchiq_susp_log_level, "%s: suspend already in "+			"progress", __func__);+		break;++	default:+		/* We don't expect to be in other states, so log but continue+		 * anyway */+		vchiq_log_error(vchiq_susp_log_level,+			"%s unexpected suspend state %s", __func__,+			suspend_state_names[arm_state->vc_suspend_state ++						VC_SUSPEND_NUM_OFFSET]);+		/* fall through */+	case VC_SUSPEND_REJECTED:+	case VC_SUSPEND_FAILED:+		/* Ensure any idle state actions have been run */+		set_suspend_state(arm_state, VC_SUSPEND_IDLE);+		/* fall through */+	case VC_SUSPEND_IDLE:+		vchiq_log_info(vchiq_susp_log_level,+			"%s: suspending", __func__);+		set_suspend_state(arm_state, VC_SUSPEND_REQUESTED);+		/* kick the slot handler thread to initiate suspend */+		request_poll(state, NULL, 0);+		break;+	}++out:+	vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, status);+	return status;+}++void+vchiq_platform_check_suspend(VCHIQ_STATE_T *state)+{+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);+	int susp = 0;++	if (!arm_state)+		goto out;++	vchiq_log_trace(vchiq_susp_log_level, "%s", __func__);++	write_lock_bh(&arm_state->susp_res_lock);+	if (arm_state->vc_suspend_state == VC_SUSPEND_REQUESTED &&+			arm_state->vc_resume_state == VC_RESUME_RESUMED) {+		set_suspend_state(arm_state, VC_SUSPEND_IN_PROGRESS);+		susp = 1;+	}+	write_unlock_bh(&arm_state->susp_res_lock);++	if (susp)+		vchiq_platform_suspend(state);++out:+	vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__);+	return;+}+++static void+output_timeout_error(VCHIQ_STATE_T *state)+{+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);+	char service_err[50] = "";+	int vc_use_count = arm_state->videocore_use_count;+	int active_services = state->unused_service;+	int i;++	if (!arm_state->videocore_use_count) {+		snprintf(service_err, 50, " Videocore usecount is 0");+		goto output_msg;+	}+	for (i = 0; i < active_services; i++) {+		VCHIQ_SERVICE_T *service_ptr = state->services[i];+		if (service_ptr && service_ptr->service_use_count &&+			(service_ptr->srvstate != VCHIQ_SRVSTATE_FREE)) {+			snprintf(service_err, 50, " %c%c%c%c(%d) service has "+				"use count %d%s", VCHIQ_FOURCC_AS_4CHARS(+					service_ptr->base.fourcc),+				 service_ptr->client_id,+				 service_ptr->service_use_count,+				 service_ptr->service_use_count ==+					 vc_use_count ? "" : " (+ more)");+			break;+		}+	}++output_msg:+	vchiq_log_error(vchiq_susp_log_level,+		"timed out waiting for vc suspend (%d).%s",+		 arm_state->autosuspend_override, service_err);++}++/* Try to get videocore into suspended state, regardless of autosuspend state.+** We don't actually force suspend, since videocore may get into a bad state+** if we force suspend at a bad time.  Instead, we wait for autosuspend to+** determine a good point to suspend.  If this doesn't happen within 100ms we+** report failure.+**+** Returns VCHIQ_SUCCESS if videocore suspended successfully, VCHIQ_RETRY if+** videocore failed to suspend in time or VCHIQ_ERROR if interrupted.+*/+VCHIQ_STATUS_T+vchiq_arm_force_suspend(VCHIQ_STATE_T *state)+{+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);+	VCHIQ_STATUS_T status = VCHIQ_ERROR;+	long rc = 0;+	int repeat = -1;++	if (!arm_state)+		goto out;++	vchiq_log_trace(vchiq_susp_log_level, "%s", __func__);++	write_lock_bh(&arm_state->susp_res_lock);++	status = block_resume(arm_state);+	if (status != VCHIQ_SUCCESS)+		goto unlock;+	if (arm_state->vc_suspend_state == VC_SUSPEND_SUSPENDED) {+		/* Already suspended - just block resume and exit */+		vchiq_log_info(vchiq_susp_log_level, "%s already suspended",+			__func__);+		status = VCHIQ_SUCCESS;+		goto unlock;+	} else if (arm_state->vc_suspend_state <= VC_SUSPEND_IDLE) {+		/* initiate suspend immediately in the case that we're waiting+		 * for the timeout */+		stop_suspend_timer(arm_state);+		if (!vchiq_videocore_wanted(state)) {+			vchiq_log_info(vchiq_susp_log_level, "%s videocore "+				"idle, initiating suspend", __func__);+			status = vchiq_arm_vcsuspend(state);+		} else if (arm_state->autosuspend_override <+						FORCE_SUSPEND_FAIL_MAX) {+			vchiq_log_info(vchiq_susp_log_level, "%s letting "+				"videocore go idle", __func__);+			status = VCHIQ_SUCCESS;+		} else {+			vchiq_log_warning(vchiq_susp_log_level, "%s failed too "+				"many times - attempting suspend", __func__);+			status = vchiq_arm_vcsuspend(state);+		}+	} else {+		vchiq_log_info(vchiq_susp_log_level, "%s videocore suspend "+			"in progress - wait for completion", __func__);+		status = VCHIQ_SUCCESS;+	}++	/* Wait for suspend to happen due to system idle (not forced..) */+	if (status != VCHIQ_SUCCESS)+		goto unblock_resume;++	do {+		write_unlock_bh(&arm_state->susp_res_lock);++		rc = wait_for_completion_interruptible_timeout(+				&arm_state->vc_suspend_complete,+				msecs_to_jiffies(FORCE_SUSPEND_TIMEOUT_MS));++		write_lock_bh(&arm_state->susp_res_lock);+		if (rc < 0) {+			vchiq_log_warning(vchiq_susp_log_level, "%s "+				"interrupted waiting for suspend", __func__);+			status = VCHIQ_ERROR;+			goto unblock_resume;+		} else if (rc == 0) {+			if (arm_state->vc_suspend_state > VC_SUSPEND_IDLE) {+				/* Repeat timeout once if in progress */+				if (repeat < 0) {+					repeat = 1;+					continue;+				}+			}+			arm_state->autosuspend_override++;+			output_timeout_error(state);++			status = VCHIQ_RETRY;+			goto unblock_resume;+		}+	} while (0 < (repeat--));++	/* Check and report state in case we need to abort ARM suspend */+	if (arm_state->vc_suspend_state != VC_SUSPEND_SUSPENDED) {+		status = VCHIQ_RETRY;+		vchiq_log_error(vchiq_susp_log_level,+			"%s videocore suspend failed (state %s)", __func__,+			suspend_state_names[arm_state->vc_suspend_state ++						VC_SUSPEND_NUM_OFFSET]);+		/* Reset the state only if it's still in an error state.+		 * Something could have already initiated another suspend. */+		if (arm_state->vc_suspend_state < VC_SUSPEND_IDLE)+			set_suspend_state(arm_state, VC_SUSPEND_IDLE);++		goto unblock_resume;+	}++	/* successfully suspended - unlock and exit */+	goto unlock;++unblock_resume:+	/* all error states need to unblock resume before exit */+	unblock_resume(arm_state);++unlock:+	write_unlock_bh(&arm_state->susp_res_lock);++out:+	vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, status);+	return status;+}++void+vchiq_check_suspend(VCHIQ_STATE_T *state)+{+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);++	if (!arm_state)+		goto out;++	vchiq_log_trace(vchiq_susp_log_level, "%s", __func__);++	write_lock_bh(&arm_state->susp_res_lock);+	if (arm_state->vc_suspend_state != VC_SUSPEND_SUSPENDED &&+			arm_state->first_connect &&+			!vchiq_videocore_wanted(state)) {+		vchiq_arm_vcsuspend(state);+	}+	write_unlock_bh(&arm_state->susp_res_lock);++out:+	vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__);+	return;+}+++int+vchiq_arm_allow_resume(VCHIQ_STATE_T *state)+{+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);+	int resume = 0;+	int ret = -1;++	if (!arm_state)+		goto out;++	vchiq_log_trace(vchiq_susp_log_level, "%s", __func__);++	write_lock_bh(&arm_state->susp_res_lock);+	unblock_resume(arm_state);+	resume = vchiq_check_resume(state);+	write_unlock_bh(&arm_state->susp_res_lock);++	if (resume) {+		if (wait_for_completion_interruptible(+			&arm_state->vc_resume_complete) < 0) {+			vchiq_log_error(vchiq_susp_log_level,+				"%s interrupted", __func__);+			/* failed, cannot accurately derive suspend+			 * state, so exit early. */+			goto out;+		}+	}++	read_lock_bh(&arm_state->susp_res_lock);+	if (arm_state->vc_suspend_state == VC_SUSPEND_SUSPENDED) {+		vchiq_log_info(vchiq_susp_log_level,+				"%s: Videocore remains suspended", __func__);+	} else {+		vchiq_log_info(vchiq_susp_log_level,+				"%s: Videocore resumed", __func__);+		ret = 0;+	}+	read_unlock_bh(&arm_state->susp_res_lock);+out:+	vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, ret);+	return ret;+}++/* This function should be called with the write lock held */+int+vchiq_check_resume(VCHIQ_STATE_T *state)+{+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);+	int resume = 0;++	if (!arm_state)+		goto out;++	vchiq_log_trace(vchiq_susp_log_level, "%s", __func__);++	if (need_resume(state)) {+		set_resume_state(arm_state, VC_RESUME_REQUESTED);+		request_poll(state, NULL, 0);+		resume = 1;+	}++out:+	vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__);+	return resume;+}++void+vchiq_platform_check_resume(VCHIQ_STATE_T *state)+{+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);+	int res = 0;++	if (!arm_state)+		goto out;++	vchiq_log_trace(vchiq_susp_log_level, "%s", __func__);++	write_lock_bh(&arm_state->susp_res_lock);+	if (arm_state->wake_address == 0) {+		vchiq_log_info(vchiq_susp_log_level,+					"%s: already awake", __func__);+		goto unlock;+	}+	if (arm_state->vc_resume_state == VC_RESUME_IN_PROGRESS) {+		vchiq_log_info(vchiq_susp_log_level,+					"%s: already resuming", __func__);+		goto unlock;+	}++	if (arm_state->vc_resume_state == VC_RESUME_REQUESTED) {+		set_resume_state(arm_state, VC_RESUME_IN_PROGRESS);+		res = 1;+	} else+		vchiq_log_trace(vchiq_susp_log_level,+				"%s: not resuming (resume state %s)", __func__,+				resume_state_names[arm_state->vc_resume_state ++							VC_RESUME_NUM_OFFSET]);++unlock:+	write_unlock_bh(&arm_state->susp_res_lock);++	if (res)+		vchiq_platform_resume(state);++out:+	vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__);+	return;++}++++VCHIQ_STATUS_T+vchiq_use_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,+		enum USE_TYPE_E use_type)+{+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);+	VCHIQ_STATUS_T ret = VCHIQ_SUCCESS;+	char entity[16];+	int *entity_uc;+	int local_uc, local_entity_uc;++	if (!arm_state)+		goto out;++	vchiq_log_trace(vchiq_susp_log_level, "%s", __func__);++	if (use_type == USE_TYPE_VCHIQ) {+		sprintf(entity, "VCHIQ:   ");+		entity_uc = &arm_state->peer_use_count;+	} else if (service) {+		sprintf(entity, "%c%c%c%c:%03d",+			VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc),+			service->client_id);+		entity_uc = &service->service_use_count;+	} else {+		vchiq_log_error(vchiq_susp_log_level, "%s null service "+				"ptr", __func__);+		ret = VCHIQ_ERROR;+		goto out;+	}++	write_lock_bh(&arm_state->susp_res_lock);+	while (arm_state->resume_blocked) {+		/* If we call 'use' while force suspend is waiting for suspend,+		 * then we're about to block the thread which the force is+		 * waiting to complete, so we're bound to just time out. In this+		 * case, set the suspend state such that the wait will be+		 * canceled, so we can complete as quickly as possible. */+		if (arm_state->resume_blocked && arm_state->vc_suspend_state ==+				VC_SUSPEND_IDLE) {+			set_suspend_state(arm_state, VC_SUSPEND_FORCE_CANCELED);+			break;+		}+		/* If suspend is already in progress then we need to block */+		if (!try_wait_for_completion(&arm_state->resume_blocker)) {+			/* Indicate that there are threads waiting on the resume+			 * blocker.  These need to be allowed to complete before+			 * a _second_ call to force suspend can complete,+			 * otherwise low priority threads might never actually+			 * continue */+			arm_state->blocked_count++;+			write_unlock_bh(&arm_state->susp_res_lock);+			vchiq_log_info(vchiq_susp_log_level, "%s %s resume "+				"blocked - waiting...", __func__, entity);+			if (wait_for_completion_killable(+					&arm_state->resume_blocker) != 0) {+				vchiq_log_error(vchiq_susp_log_level, "%s %s "+					"wait for resume blocker interrupted",+					__func__, entity);+				ret = VCHIQ_ERROR;+				write_lock_bh(&arm_state->susp_res_lock);+				arm_state->blocked_count--;+				write_unlock_bh(&arm_state->susp_res_lock);+				goto out;+			}+			vchiq_log_info(vchiq_susp_log_level, "%s %s resume "+				"unblocked", __func__, entity);+			write_lock_bh(&arm_state->susp_res_lock);+			if (--arm_state->blocked_count == 0)+				complete_all(&arm_state->blocked_blocker);+		}+	}++	stop_suspend_timer(arm_state);++	local_uc = ++arm_state->videocore_use_count;+	local_entity_uc = ++(*entity_uc);++	/* If there's a pending request which hasn't yet been serviced then+	 * just clear it.  If we're past VC_SUSPEND_REQUESTED state then+	 * vc_resume_complete will block until we either resume or fail to+	 * suspend */+	if (arm_state->vc_suspend_state <= VC_SUSPEND_REQUESTED)+		set_suspend_state(arm_state, VC_SUSPEND_IDLE);++	if ((use_type != USE_TYPE_SERVICE_NO_RESUME) && need_resume(state)) {+		set_resume_state(arm_state, VC_RESUME_REQUESTED);+		vchiq_log_info(vchiq_susp_log_level,+			"%s %s count %d, state count %d",+			__func__, entity, local_entity_uc, local_uc);+		request_poll(state, NULL, 0);+	} else+		vchiq_log_trace(vchiq_susp_log_level,+			"%s %s count %d, state count %d",+			__func__, entity, *entity_uc, local_uc);+++	write_unlock_bh(&arm_state->susp_res_lock);++	/* Completion is in a done state when we're not suspended, so this won't+	 * block for the non-suspended case. */+	if (!try_wait_for_completion(&arm_state->vc_resume_complete)) {+		vchiq_log_info(vchiq_susp_log_level, "%s %s wait for resume",+			__func__, entity);+		if (wait_for_completion_killable(+				&arm_state->vc_resume_complete) != 0) {+			vchiq_log_error(vchiq_susp_log_level, "%s %s wait for "+				"resume interrupted", __func__, entity);+			ret = VCHIQ_ERROR;+			goto out;+		}+		vchiq_log_info(vchiq_susp_log_level, "%s %s resumed", __func__,+			entity);+	}++	if (ret == VCHIQ_SUCCESS) {+		VCHIQ_STATUS_T status = VCHIQ_SUCCESS;+		long ack_cnt = atomic_xchg(&arm_state->ka_use_ack_count, 0);+		while (ack_cnt && (status == VCHIQ_SUCCESS)) {+			/* Send the use notify to videocore */+			status = vchiq_send_remote_use_active(state);+			if (status == VCHIQ_SUCCESS)+				ack_cnt--;+			else+				atomic_add(ack_cnt,+					&arm_state->ka_use_ack_count);+		}+	}++out:+	vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, ret);+	return ret;+}++VCHIQ_STATUS_T+vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service)+{+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);+	VCHIQ_STATUS_T ret = VCHIQ_SUCCESS;+	char entity[16];+	int *entity_uc;+	int local_uc, local_entity_uc;++	if (!arm_state)+		goto out;++	vchiq_log_trace(vchiq_susp_log_level, "%s", __func__);++	if (service) {+		sprintf(entity, "%c%c%c%c:%03d",+			VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc),+			service->client_id);+		entity_uc = &service->service_use_count;+	} else {+		sprintf(entity, "PEER:   ");+		entity_uc = &arm_state->peer_use_count;+	}++	write_lock_bh(&arm_state->susp_res_lock);+	if (!arm_state->videocore_use_count || !(*entity_uc)) {+		/* Don't use BUG_ON - don't allow user thread to crash kernel */+		WARN_ON(!arm_state->videocore_use_count);+		WARN_ON(!(*entity_uc));+		ret = VCHIQ_ERROR;+		goto unlock;+	}+	local_uc = --arm_state->videocore_use_count;+	local_entity_uc = --(*entity_uc);++	if (!vchiq_videocore_wanted(state)) {+		if (vchiq_platform_use_suspend_timer() &&+				!arm_state->resume_blocked) {+			/* Only use the timer if we're not trying to force+			 * suspend (=> resume_blocked) */+			start_suspend_timer(arm_state);+		} else {+			vchiq_log_info(vchiq_susp_log_level,+				"%s %s count %d, state count %d - suspending",+				__func__, entity, *entity_uc,+				arm_state->videocore_use_count);+			vchiq_arm_vcsuspend(state);+		}+	} else+		vchiq_log_trace(vchiq_susp_log_level,+			"%s %s count %d, state count %d",+			__func__, entity, *entity_uc,+			arm_state->videocore_use_count);++unlock:+	write_unlock_bh(&arm_state->susp_res_lock);++out:+	vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, ret);+	return ret;+}++void+vchiq_on_remote_use(VCHIQ_STATE_T *state)+{+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);+	vchiq_log_trace(vchiq_susp_log_level, "%s", __func__);+	atomic_inc(&arm_state->ka_use_count);+	complete(&arm_state->ka_evt);+}++void+vchiq_on_remote_release(VCHIQ_STATE_T *state)+{+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);+	vchiq_log_trace(vchiq_susp_log_level, "%s", __func__);+	atomic_inc(&arm_state->ka_release_count);+	complete(&arm_state->ka_evt);+}++VCHIQ_STATUS_T+vchiq_use_service_internal(VCHIQ_SERVICE_T *service)+{+	return vchiq_use_internal(service->state, service, USE_TYPE_SERVICE);+}++VCHIQ_STATUS_T+vchiq_release_service_internal(VCHIQ_SERVICE_T *service)+{+	return vchiq_release_internal(service->state, service);+}++static void suspend_timer_callback(unsigned long context)+{+	VCHIQ_STATE_T *state = (VCHIQ_STATE_T *)context;+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);+	if (!arm_state)+		goto out;+	vchiq_log_info(vchiq_susp_log_level,+		"%s - suspend timer expired - check suspend", __func__);+	vchiq_check_suspend(state);+out:+	return;+}++VCHIQ_STATUS_T+vchiq_use_service_no_resume(VCHIQ_SERVICE_HANDLE_T handle)+{+	VCHIQ_STATUS_T ret = VCHIQ_ERROR;+	VCHIQ_SERVICE_T *service = find_service_by_handle(handle);+	if (service) {+		ret = vchiq_use_internal(service->state, service,+				USE_TYPE_SERVICE_NO_RESUME);+		unlock_service(service);+	}+	return ret;+}++VCHIQ_STATUS_T+vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle)+{+	VCHIQ_STATUS_T ret = VCHIQ_ERROR;+	VCHIQ_SERVICE_T *service = find_service_by_handle(handle);+	if (service) {+		ret = vchiq_use_internal(service->state, service,+				USE_TYPE_SERVICE);+		unlock_service(service);+	}+	return ret;+}++VCHIQ_STATUS_T+vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle)+{+	VCHIQ_STATUS_T ret = VCHIQ_ERROR;+	VCHIQ_SERVICE_T *service = find_service_by_handle(handle);+	if (service) {+		ret = vchiq_release_internal(service->state, service);+		unlock_service(service);+	}+	return ret;+}++void+vchiq_dump_service_use_state(VCHIQ_STATE_T *state)+{+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);+	int i, j = 0;+	/* Only dump 64 services */+	static const int local_max_services = 64;+	/* If there's more than 64 services, only dump ones with+	 * non-zero counts */+	int only_nonzero = 0;+	static const char *nz = "<-- preventing suspend";++	enum vc_suspend_status vc_suspend_state;+	enum vc_resume_status  vc_resume_state;+	int peer_count;+	int vc_use_count;+	int active_services;+	struct service_data_struct {+		int fourcc;+		int clientid;+		int use_count;+	} service_data[local_max_services];++	if (!arm_state)+		return;++	read_lock_bh(&arm_state->susp_res_lock);+	vc_suspend_state = arm_state->vc_suspend_state;+	vc_resume_state  = arm_state->vc_resume_state;+	peer_count = arm_state->peer_use_count;+	vc_use_count = arm_state->videocore_use_count;+	active_services = state->unused_service;+	if (active_services > local_max_services)+		only_nonzero = 1;++	for (i = 0; (i < active_services) && (j < local_max_services); i++) {+		VCHIQ_SERVICE_T *service_ptr = state->services[i];+		if (!service_ptr)+			continue;++		if (only_nonzero && !service_ptr->service_use_count)+			continue;++		if (service_ptr->srvstate != VCHIQ_SRVSTATE_FREE) {+			service_data[j].fourcc = service_ptr->base.fourcc;+			service_data[j].clientid = service_ptr->client_id;+			service_data[j++].use_count = service_ptr->+							service_use_count;+		}+	}++	read_unlock_bh(&arm_state->susp_res_lock);++	vchiq_log_warning(vchiq_susp_log_level,+		"-- Videcore suspend state: %s --",+		suspend_state_names[vc_suspend_state + VC_SUSPEND_NUM_OFFSET]);+	vchiq_log_warning(vchiq_susp_log_level,+		"-- Videcore resume state: %s --",+		resume_state_names[vc_resume_state + VC_RESUME_NUM_OFFSET]);++	if (only_nonzero)+		vchiq_log_warning(vchiq_susp_log_level, "Too many active "+			"services (%d).  Only dumping up to first %d services "+			"with non-zero use-count", active_services,+			local_max_services);++	for (i = 0; i < j; i++) {+		vchiq_log_warning(vchiq_susp_log_level,+			"----- %c%c%c%c:%d service count %d %s",+			VCHIQ_FOURCC_AS_4CHARS(service_data[i].fourcc),+			service_data[i].clientid,+			service_data[i].use_count,+			service_data[i].use_count ? nz : "");+	}+	vchiq_log_warning(vchiq_susp_log_level,+		"----- VCHIQ use count count %d", peer_count);+	vchiq_log_warning(vchiq_susp_log_level,+		"--- Overall vchiq instance use count %d", vc_use_count);++	vchiq_dump_platform_use_state(state);+}++VCHIQ_STATUS_T+vchiq_check_service(VCHIQ_SERVICE_T *service)+{+	VCHIQ_ARM_STATE_T *arm_state;+	VCHIQ_STATUS_T ret = VCHIQ_ERROR;++	if (!service || !service->state)+		goto out;++	vchiq_log_trace(vchiq_susp_log_level, "%s", __func__);++	arm_state = vchiq_platform_get_arm_state(service->state);++	read_lock_bh(&arm_state->susp_res_lock);+	if (service->service_use_count)+		ret = VCHIQ_SUCCESS;+	read_unlock_bh(&arm_state->susp_res_lock);++	if (ret == VCHIQ_ERROR) {+		vchiq_log_error(vchiq_susp_log_level,+			"%s ERROR - %c%c%c%c:%d service count %d, "+			"state count %d, videocore suspend state %s", __func__,+			VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc),+			service->client_id, service->service_use_count,+			arm_state->videocore_use_count,+			suspend_state_names[arm_state->vc_suspend_state ++						VC_SUSPEND_NUM_OFFSET]);+		vchiq_dump_service_use_state(service->state);+	}+out:+	return ret;+}++/* stub functions */+void vchiq_on_remote_use_active(VCHIQ_STATE_T *state)+{+	(void)state;+}++void vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state,+	VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate)+{+	VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);+	vchiq_log_info(vchiq_susp_log_level, "%d: %s->%s", state->id,+		get_conn_state_name(oldstate), get_conn_state_name(newstate));+	if (state->conn_state == VCHIQ_CONNSTATE_CONNECTED) {+		write_lock_bh(&arm_state->susp_res_lock);+		if (!arm_state->first_connect) {+			char threadname[10];+			arm_state->first_connect = 1;+			write_unlock_bh(&arm_state->susp_res_lock);+			snprintf(threadname, sizeof(threadname), "VCHIQka-%d",+				state->id);+			arm_state->ka_thread = kthread_create(+				&vchiq_keepalive_thread_func,+				(void *)state,+				threadname);+			if (arm_state->ka_thread == NULL) {+				vchiq_log_error(vchiq_susp_log_level,+					"vchiq: FATAL: couldn't create thread %s",+					threadname);+			} else {+				wake_up_process(arm_state->ka_thread);+			}+		} else+			write_unlock_bh(&arm_state->susp_res_lock);+	}+}+++/****************************************************************************+*+*   vchiq_init - called when the module is loaded.+*+***************************************************************************/++static int __init+vchiq_init(void)+{+	int err;+	void *ptr_err;++	/* create proc entries */+	err = vchiq_proc_init();+	if (err != 0)+		goto failed_proc_init;++	err = alloc_chrdev_region(&vchiq_devid, VCHIQ_MINOR, 1, DEVICE_NAME);+	if (err != 0) {+		vchiq_log_error(vchiq_arm_log_level,+			"Unable to allocate device number");+		goto failed_alloc_chrdev;+	}+	cdev_init(&vchiq_cdev, &vchiq_fops);+	vchiq_cdev.owner = THIS_MODULE;+	err = cdev_add(&vchiq_cdev, vchiq_devid, 1);+	if (err != 0) {+		vchiq_log_error(vchiq_arm_log_level,+			"Unable to register device");+		goto failed_cdev_add;+	}++	/* create sysfs entries */+	vchiq_class = class_create(THIS_MODULE, DEVICE_NAME);+	ptr_err = vchiq_class;+	if (IS_ERR(ptr_err))+		goto failed_class_create;++	vchiq_dev = device_create(vchiq_class, NULL,+		vchiq_devid, NULL, "vchiq");+	ptr_err = vchiq_dev;+	if (IS_ERR(ptr_err))+		goto failed_device_create;++	err = vchiq_platform_init(&g_state);+	if (err != 0)+		goto failed_platform_init;++	vchiq_log_info(vchiq_arm_log_level,+		"vchiq: initialised - version %d (min %d), device %d.%d",+		VCHIQ_VERSION, VCHIQ_VERSION_MIN,+		MAJOR(vchiq_devid), MINOR(vchiq_devid));++	return 0;++failed_platform_init:+	device_destroy(vchiq_class, vchiq_devid);+failed_device_create:+	class_destroy(vchiq_class);+failed_class_create:+	cdev_del(&vchiq_cdev);+	err = PTR_ERR(ptr_err);+failed_cdev_add:+	unregister_chrdev_region(vchiq_devid, 1);+failed_alloc_chrdev:+	vchiq_proc_deinit();+failed_proc_init:+	vchiq_log_warning(vchiq_arm_log_level, "could not load vchiq");+	return err;+}++static int vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance)+{+	VCHIQ_SERVICE_T *service;+	int use_count = 0, i;+	i = 0;+	while ((service = next_service_by_instance(instance->state,+		instance, &i)) != NULL) {+		use_count += service->service_use_count;+		unlock_service(service);+	}+	return use_count;+}++/* read the per-process use-count */+static int proc_read_use_count(char *page, char **start,+			       off_t off, int count,+			       int *eof, void *data)+{+	VCHIQ_INSTANCE_T instance = data;+	int len, use_count;++	use_count = vchiq_instance_get_use_count(instance);+	len = snprintf(page+off, count, "%d\n", use_count);++	return len;+}++/* add an instance (process) to the proc entries */+static int vchiq_proc_add_instance(VCHIQ_INSTANCE_T instance)+{+#if 1+	return 0;+#else+	char pidstr[32];+	struct proc_dir_entry *top, *use_count;+	struct proc_dir_entry *clients = vchiq_clients_top();+	int pid = instance->pid;++	snprintf(pidstr, sizeof(pidstr), "%d", pid);+	top = proc_mkdir(pidstr, clients);+	if (!top)+		goto fail_top;++	use_count = create_proc_read_entry("use_count",+					   0444, top,+					   proc_read_use_count,+					   instance);+	if (!use_count)+		goto fail_use_count;++	instance->proc_entry = top;++	return 0;++fail_use_count:+	remove_proc_entry(top->name, clients);+fail_top:+	return -ENOMEM;+#endif+}++static void vchiq_proc_remove_instance(VCHIQ_INSTANCE_T instance)+{+#if 0+	struct proc_dir_entry *clients = vchiq_clients_top();+	remove_proc_entry("use_count", instance->proc_entry);+	remove_proc_entry(instance->proc_entry->name, clients);+#endif+}++/****************************************************************************+*+*   vchiq_exit - called when the module is unloaded.+*+***************************************************************************/++static void __exit+vchiq_exit(void)+{+	vchiq_platform_exit(&g_state);+	device_destroy(vchiq_class, vchiq_devid);+	class_destroy(vchiq_class);+	cdev_del(&vchiq_cdev);+	unregister_chrdev_region(vchiq_devid, 1);+}++module_init(vchiq_init);+module_exit(vchiq_exit);+MODULE_LICENSE("GPL");+MODULE_AUTHOR("Broadcom Corporation");diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,212 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef VCHIQ_ARM_H+#define VCHIQ_ARM_H++#include <linux/mutex.h>+#include <linux/semaphore.h>+#include <linux/atomic.h>+#include "vchiq_core.h"+++enum vc_suspend_status {+	VC_SUSPEND_FORCE_CANCELED = -3, /* Force suspend canceled, too busy */+	VC_SUSPEND_REJECTED = -2,  /* Videocore rejected suspend request */+	VC_SUSPEND_FAILED = -1,    /* Videocore suspend failed */+	VC_SUSPEND_IDLE = 0,       /* VC active, no suspend actions */+	VC_SUSPEND_REQUESTED,      /* User has requested suspend */+	VC_SUSPEND_IN_PROGRESS,    /* Slot handler has recvd suspend request */+	VC_SUSPEND_SUSPENDED       /* Videocore suspend succeeded */+};++enum vc_resume_status {+	VC_RESUME_FAILED = -1, /* Videocore resume failed */+	VC_RESUME_IDLE = 0,    /* VC suspended, no resume actions */+	VC_RESUME_REQUESTED,   /* User has requested resume */+	VC_RESUME_IN_PROGRESS, /* Slot handler has received resume request */+	VC_RESUME_RESUMED      /* Videocore resumed successfully (active) */+};+++enum USE_TYPE_E {+	USE_TYPE_SERVICE,+	USE_TYPE_SERVICE_NO_RESUME,+	USE_TYPE_VCHIQ+};++++typedef struct vchiq_arm_state_struct {+	/* Keepalive-related data */+	struct task_struct *ka_thread;+	struct completion ka_evt;+	atomic_t ka_use_count;+	atomic_t ka_use_ack_count;+	atomic_t ka_release_count;++	struct completion vc_suspend_complete;+	struct completion vc_resume_complete;++	rwlock_t susp_res_lock;+	enum vc_suspend_status vc_suspend_state;+	enum vc_resume_status vc_resume_state;++	unsigned int wake_address;++	struct timer_list suspend_timer;+	int suspend_timer_timeout;+	int suspend_timer_running;++	/* Global use count for videocore.+	** This is equal to the sum of the use counts for all services.  When+	** this hits zero the videocore suspend procedure will be initiated.+	*/+	int videocore_use_count;++	/* Use count to track requests from videocore peer.+	** This use count is not associated with a service, so needs to be+	** tracked separately with the state.+	*/+	int peer_use_count;++	/* Flag to indicate whether resume is blocked.  This happens when the+	** ARM is suspending+	*/+	struct completion resume_blocker;+	int resume_blocked;+	struct completion blocked_blocker;+	int blocked_count;++	int autosuspend_override;++	/* Flag to indicate that the first vchiq connect has made it through.+	** This means that both sides should be fully ready, and we should+	** be able to suspend after this point.+	*/+	int first_connect;++	unsigned long long suspend_start_time;+	unsigned long long sleep_start_time;+	unsigned long long resume_start_time;+	unsigned long long last_wake_time;++} VCHIQ_ARM_STATE_T;++extern int vchiq_arm_log_level;+extern int vchiq_susp_log_level;++extern int __init+vchiq_platform_init(VCHIQ_STATE_T *state);++extern void __exit+vchiq_platform_exit(VCHIQ_STATE_T *state);++extern VCHIQ_STATE_T *+vchiq_get_state(void);++extern VCHIQ_STATUS_T+vchiq_arm_vcsuspend(VCHIQ_STATE_T *state);++extern VCHIQ_STATUS_T+vchiq_arm_force_suspend(VCHIQ_STATE_T *state);++extern int+vchiq_arm_allow_resume(VCHIQ_STATE_T *state);++extern VCHIQ_STATUS_T+vchiq_arm_vcresume(VCHIQ_STATE_T *state);++extern VCHIQ_STATUS_T+vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state);++extern int+vchiq_check_resume(VCHIQ_STATE_T *state);++extern void+vchiq_check_suspend(VCHIQ_STATE_T *state);++extern VCHIQ_STATUS_T+vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle);++extern VCHIQ_STATUS_T+vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle);++extern VCHIQ_STATUS_T+vchiq_check_service(VCHIQ_SERVICE_T *service);++extern VCHIQ_STATUS_T+vchiq_platform_suspend(VCHIQ_STATE_T *state);++extern int+vchiq_platform_videocore_wanted(VCHIQ_STATE_T *state);++extern int+vchiq_platform_use_suspend_timer(void);++extern void+vchiq_dump_platform_use_state(VCHIQ_STATE_T *state);++extern void+vchiq_dump_service_use_state(VCHIQ_STATE_T *state);++extern VCHIQ_ARM_STATE_T*+vchiq_platform_get_arm_state(VCHIQ_STATE_T *state);++extern int+vchiq_videocore_wanted(VCHIQ_STATE_T *state);++extern VCHIQ_STATUS_T+vchiq_use_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,+		enum USE_TYPE_E use_type);+extern VCHIQ_STATUS_T+vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service);++void+set_suspend_state(VCHIQ_ARM_STATE_T *arm_state,+	enum vc_suspend_status new_state);++void+set_resume_state(VCHIQ_ARM_STATE_T *arm_state,+	enum vc_resume_status new_state);++void+start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state);++extern int vchiq_proc_init(void);+extern void vchiq_proc_deinit(void);+extern struct proc_dir_entry *vchiq_proc_top(void);+extern struct proc_dir_entry *vchiq_clients_top(void);+++#endif /* VCHIQ_ARM_H */diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,37 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++const char *vchiq_get_build_hostname(void);+const char *vchiq_get_build_version(void);+const char *vchiq_get_build_time(void);+const char *vchiq_get_build_date(void);diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,60 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef VCHIQ_CFG_H+#define VCHIQ_CFG_H++#define VCHIQ_MAGIC              VCHIQ_MAKE_FOURCC('V', 'C', 'H', 'I')+/* The version of VCHIQ - change with any non-trivial change */+#define VCHIQ_VERSION            6+/* The minimum compatible version - update to match VCHIQ_VERSION with any+** incompatible change */+#define VCHIQ_VERSION_MIN        3++#define VCHIQ_MAX_STATES         1+#define VCHIQ_MAX_SERVICES       4096+#define VCHIQ_MAX_SLOTS          128+#define VCHIQ_MAX_SLOTS_PER_SIDE 64++#define VCHIQ_NUM_CURRENT_BULKS        32+#define VCHIQ_NUM_SERVICE_BULKS        4++#ifndef VCHIQ_ENABLE_DEBUG+#define VCHIQ_ENABLE_DEBUG             1+#endif++#ifndef VCHIQ_ENABLE_STATS+#define VCHIQ_ENABLE_STATS             1+#endif++#endif /* VCHIQ_CFG_H */diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,119 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#include "vchiq_connected.h"+#include "vchiq_core.h"+#include <linux/module.h>+#include <linux/mutex.h>++#define  MAX_CALLBACKS  10++static   int                        g_connected;+static   int                        g_num_deferred_callbacks;+static   VCHIQ_CONNECTED_CALLBACK_T g_deferred_callback[MAX_CALLBACKS];+static   int                        g_once_init;+static   struct mutex               g_connected_mutex;++/****************************************************************************+*+* Function to initialize our lock.+*+***************************************************************************/++static void connected_init(void)+{+	if (!g_once_init) {+		mutex_init(&g_connected_mutex);+		g_once_init = 1;+	}+}++/****************************************************************************+*+* This function is used to defer initialization until the vchiq stack is+* initialized. If the stack is already initialized, then the callback will+* be made immediately, otherwise it will be deferred until+* vchiq_call_connected_callbacks is called.+*+***************************************************************************/++void vchiq_add_connected_callback(VCHIQ_CONNECTED_CALLBACK_T callback)+{+	connected_init();++	if (mutex_lock_interruptible(&g_connected_mutex) != 0)+		return;++	if (g_connected)+		/* We're already connected. Call the callback immediately. */++		callback();+	else {+		if (g_num_deferred_callbacks >= MAX_CALLBACKS)+			vchiq_log_error(vchiq_core_log_level,+				"There already %d callback registered - "+				"please increase MAX_CALLBACKS",+				g_num_deferred_callbacks);+		else {+			g_deferred_callback[g_num_deferred_callbacks] =+				callback;+			g_num_deferred_callbacks++;+		}+	}+	mutex_unlock(&g_connected_mutex);+}++/****************************************************************************+*+* This function is called by the vchiq stack once it has been connected to+* the videocore and clients can start to use the stack.+*+***************************************************************************/++void vchiq_call_connected_callbacks(void)+{+	int i;++	connected_init();++	if (mutex_lock_interruptible(&g_connected_mutex) != 0)+		return;++	for (i = 0; i <  g_num_deferred_callbacks; i++)+		g_deferred_callback[i]();++	g_num_deferred_callbacks = 0;+	g_connected = 1;+	mutex_unlock(&g_connected_mutex);+}+EXPORT_SYMBOL(vchiq_add_connected_callback);diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,50 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef VCHIQ_CONNECTED_H+#define VCHIQ_CONNECTED_H++/* ---- Include Files ----------------------------------------------------- */++/* ---- Constants and Types ---------------------------------------------- */++typedef void (*VCHIQ_CONNECTED_CALLBACK_T)(void);++/* ---- Variable Externs ------------------------------------------------- */++/* ---- Function Prototypes ---------------------------------------------- */++void vchiq_add_connected_callback(VCHIQ_CONNECTED_CALLBACK_T callback);+void vchiq_call_connected_callbacks(void);++#endif /* VCHIQ_CONNECTED_H */diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,3824 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#include "vchiq_core.h"++#define VCHIQ_SLOT_HANDLER_STACK 8192++#define HANDLE_STATE_SHIFT 12++#define SLOT_INFO_FROM_INDEX(state, index) (state->slot_info + (index))+#define SLOT_DATA_FROM_INDEX(state, index) (state->slot_data + (index))+#define SLOT_INDEX_FROM_DATA(state, data) \+	(((unsigned int)((char *)data - (char *)state->slot_data)) / \+	VCHIQ_SLOT_SIZE)+#define SLOT_INDEX_FROM_INFO(state, info) \+	((unsigned int)(info - state->slot_info))+#define SLOT_QUEUE_INDEX_FROM_POS(pos) \+	((int)((unsigned int)(pos) / VCHIQ_SLOT_SIZE))+++#define BULK_INDEX(x) (x & (VCHIQ_NUM_SERVICE_BULKS - 1))+++struct vchiq_open_payload {+	int fourcc;+	int client_id;+	short version;+	short version_min;+};++struct vchiq_openack_payload {+	short version;+};++/* we require this for consistency between endpoints */+vchiq_static_assert(sizeof(VCHIQ_HEADER_T) == 8);+vchiq_static_assert(IS_POW2(sizeof(VCHIQ_HEADER_T)));+vchiq_static_assert(IS_POW2(VCHIQ_NUM_CURRENT_BULKS));+vchiq_static_assert(IS_POW2(VCHIQ_NUM_SERVICE_BULKS));+vchiq_static_assert(IS_POW2(VCHIQ_MAX_SERVICES));+vchiq_static_assert(VCHIQ_VERSION >= VCHIQ_VERSION_MIN);++/* Run time control of log level, based on KERN_XXX level. */+int vchiq_core_log_level = VCHIQ_LOG_DEFAULT;+int vchiq_core_msg_log_level = VCHIQ_LOG_DEFAULT;+int vchiq_sync_log_level = VCHIQ_LOG_DEFAULT;++static atomic_t pause_bulks_count = ATOMIC_INIT(0);++static DEFINE_SPINLOCK(service_spinlock);+DEFINE_SPINLOCK(bulk_waiter_spinlock);+DEFINE_SPINLOCK(quota_spinlock);++VCHIQ_STATE_T *vchiq_states[VCHIQ_MAX_STATES];+static unsigned int handle_seq;++static const char *const srvstate_names[] = {+	"FREE",+	"HIDDEN",+	"LISTENING",+	"OPENING",+	"OPEN",+	"OPENSYNC",+	"CLOSESENT",+	"CLOSERECVD",+	"CLOSEWAIT",+	"CLOSED"+};++static const char *const reason_names[] = {+	"SERVICE_OPENED",+	"SERVICE_CLOSED",+	"MESSAGE_AVAILABLE",+	"BULK_TRANSMIT_DONE",+	"BULK_RECEIVE_DONE",+	"BULK_TRANSMIT_ABORTED",+	"BULK_RECEIVE_ABORTED"+};++static const char *const conn_state_names[] = {+	"DISCONNECTED",+	"CONNECTING",+	"CONNECTED",+	"PAUSING",+	"PAUSE_SENT",+	"PAUSED",+	"RESUMING",+	"PAUSE_TIMEOUT",+	"RESUME_TIMEOUT"+};+++static void+release_message_sync(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header);++static const char *msg_type_str(unsigned int msg_type)+{+	switch (msg_type) {+	case VCHIQ_MSG_PADDING:       return "PADDING";+	case VCHIQ_MSG_CONNECT:       return "CONNECT";+	case VCHIQ_MSG_OPEN:          return "OPEN";+	case VCHIQ_MSG_OPENACK:       return "OPENACK";+	case VCHIQ_MSG_CLOSE:         return "CLOSE";+	case VCHIQ_MSG_DATA:          return "DATA";+	case VCHIQ_MSG_BULK_RX:       return "BULK_RX";+	case VCHIQ_MSG_BULK_TX:       return "BULK_TX";+	case VCHIQ_MSG_BULK_RX_DONE:  return "BULK_RX_DONE";+	case VCHIQ_MSG_BULK_TX_DONE:  return "BULK_TX_DONE";+	case VCHIQ_MSG_PAUSE:         return "PAUSE";+	case VCHIQ_MSG_RESUME:        return "RESUME";+	case VCHIQ_MSG_REMOTE_USE:    return "REMOTE_USE";+	case VCHIQ_MSG_REMOTE_RELEASE:      return "REMOTE_RELEASE";+	case VCHIQ_MSG_REMOTE_USE_ACTIVE:   return "REMOTE_USE_ACTIVE";+	}+	return "???";+}++static inline void+vchiq_set_service_state(VCHIQ_SERVICE_T *service, int newstate)+{+	vchiq_log_info(vchiq_core_log_level, "%d: srv:%d %s->%s",+		service->state->id, service->localport,+		srvstate_names[service->srvstate],+		srvstate_names[newstate]);+	service->srvstate = newstate;+}++VCHIQ_SERVICE_T *+find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle)+{+	VCHIQ_SERVICE_T *service;++	spin_lock(&service_spinlock);+	service = handle_to_service(handle);+	if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE) &&+		(service->handle == handle)) {+		BUG_ON(service->ref_count == 0);+		service->ref_count++;+	} else+		service = NULL;+	spin_unlock(&service_spinlock);++	if (!service)+		vchiq_log_info(vchiq_core_log_level,+			"Invalid service handle 0x%x", handle);++	return service;+}++VCHIQ_SERVICE_T *+find_service_by_port(VCHIQ_STATE_T *state, int localport)+{+	VCHIQ_SERVICE_T *service = NULL;+	if ((unsigned int)localport <= VCHIQ_PORT_MAX) {+		spin_lock(&service_spinlock);+		service = state->services[localport];+		if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE)) {+			BUG_ON(service->ref_count == 0);+			service->ref_count++;+		} else+			service = NULL;+		spin_unlock(&service_spinlock);+	}++	if (!service)+		vchiq_log_info(vchiq_core_log_level,+			"Invalid port %d", localport);++	return service;+}++VCHIQ_SERVICE_T *+find_service_for_instance(VCHIQ_INSTANCE_T instance,+	VCHIQ_SERVICE_HANDLE_T handle) {+	VCHIQ_SERVICE_T *service;++	spin_lock(&service_spinlock);+	service = handle_to_service(handle);+	if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE) &&+		(service->handle == handle) &&+		(service->instance == instance)) {+		BUG_ON(service->ref_count == 0);+		service->ref_count++;+	} else+		service = NULL;+	spin_unlock(&service_spinlock);++	if (!service)+		vchiq_log_info(vchiq_core_log_level,+			"Invalid service handle 0x%x", handle);++	return service;+}++VCHIQ_SERVICE_T *+next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance,+	int *pidx)+{+	VCHIQ_SERVICE_T *service = NULL;+	int idx = *pidx;++	spin_lock(&service_spinlock);+	while (idx < state->unused_service) {+		VCHIQ_SERVICE_T *srv = state->services[idx++];+		if (srv && (srv->srvstate != VCHIQ_SRVSTATE_FREE) &&+			(srv->instance == instance)) {+			service = srv;+			BUG_ON(service->ref_count == 0);+			service->ref_count++;+			break;+		}+	}+	spin_unlock(&service_spinlock);++	*pidx = idx;++	return service;+}++void+lock_service(VCHIQ_SERVICE_T *service)+{+	spin_lock(&service_spinlock);+	BUG_ON(!service || (service->ref_count == 0));+	if (service)+		service->ref_count++;+	spin_unlock(&service_spinlock);+}++void+unlock_service(VCHIQ_SERVICE_T *service)+{+	VCHIQ_STATE_T *state = service->state;+	spin_lock(&service_spinlock);+	BUG_ON(!service || (service->ref_count == 0));+	if (service && service->ref_count) {+		service->ref_count--;+		if (!service->ref_count) {+			BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE);+			state->services[service->localport] = NULL;+		} else+			service = NULL;+	}+	spin_unlock(&service_spinlock);++	if (service && service->userdata_term)+		service->userdata_term(service->base.userdata);++	kfree(service);+}++int+vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T handle)+{+	VCHIQ_SERVICE_T *service = find_service_by_handle(handle);+	int id;++	id = service ? service->client_id : 0;+	if (service)+		unlock_service(service);++	return id;+}++void *+vchiq_get_service_userdata(VCHIQ_SERVICE_HANDLE_T handle)+{+	VCHIQ_SERVICE_T *service = handle_to_service(handle);++	return service ? service->base.userdata : NULL;+}++int+vchiq_get_service_fourcc(VCHIQ_SERVICE_HANDLE_T handle)+{+	VCHIQ_SERVICE_T *service = handle_to_service(handle);++	return service ? service->base.fourcc : 0;+}++static void+mark_service_closing_internal(VCHIQ_SERVICE_T *service, int sh_thread)+{+	VCHIQ_STATE_T *state = service->state;+	VCHIQ_SERVICE_QUOTA_T *service_quota;++	service->closing = 1;++	/* Synchronise with other threads. */+	mutex_lock(&state->recycle_mutex);+	mutex_unlock(&state->recycle_mutex);+	if (!sh_thread || (state->conn_state != VCHIQ_CONNSTATE_PAUSE_SENT)) {+		/* If we're pausing then the slot_mutex is held until resume+		 * by the slot handler.  Therefore don't try to acquire this+		 * mutex if we're the slot handler and in the pause sent state.+		 * We don't need to in this case anyway. */+		mutex_lock(&state->slot_mutex);+		mutex_unlock(&state->slot_mutex);+	}++	/* Unblock any sending thread. */+	service_quota = &state->service_quotas[service->localport];+	up(&service_quota->quota_event);+}++static void+mark_service_closing(VCHIQ_SERVICE_T *service)+{+	mark_service_closing_internal(service, 0);+}++static inline VCHIQ_STATUS_T+make_service_callback(VCHIQ_SERVICE_T *service, VCHIQ_REASON_T reason,+	VCHIQ_HEADER_T *header, void *bulk_userdata)+{+	VCHIQ_STATUS_T status;+	vchiq_log_trace(vchiq_core_log_level, "%d: callback:%d (%s, %x, %x)",+		service->state->id, service->localport, reason_names[reason],+		(unsigned int)header, (unsigned int)bulk_userdata);+	status = service->base.callback(reason, header, service->handle,+		bulk_userdata);+	if (status == VCHIQ_ERROR) {+		vchiq_log_warning(vchiq_core_log_level,+			"%d: ignoring ERROR from callback to service %x",+			service->state->id, service->handle);+		status = VCHIQ_SUCCESS;+	}+	return status;+}++inline void+vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate)+{+	VCHIQ_CONNSTATE_T oldstate = state->conn_state;+	vchiq_log_info(vchiq_core_log_level, "%d: %s->%s", state->id,+		conn_state_names[oldstate],+		conn_state_names[newstate]);+	state->conn_state = newstate;+	vchiq_platform_conn_state_changed(state, oldstate, newstate);+}++static inline void+remote_event_create(REMOTE_EVENT_T *event)+{+	event->armed = 0;+	/* Don't clear the 'fired' flag because it may already have been set+	** by the other side. */+	sema_init(event->event, 0);+}++static inline void+remote_event_destroy(REMOTE_EVENT_T *event)+{+	(void)event;+}++static inline int+remote_event_wait(REMOTE_EVENT_T *event)+{+	if (!event->fired) {+		event->armed = 1;+		dsb();+		if (!event->fired) {+			if (down_interruptible(event->event) != 0) {+				event->armed = 0;+				return 0;+			}+		}+		event->armed = 0;+		wmb();+	}++	event->fired = 0;+	return 1;+}++static inline void+remote_event_signal_local(REMOTE_EVENT_T *event)+{+	event->armed = 0;+	up(event->event);+}++static inline void+remote_event_poll(REMOTE_EVENT_T *event)+{+	if (event->fired && event->armed)+		remote_event_signal_local(event);+}++void+remote_event_pollall(VCHIQ_STATE_T *state)+{+	remote_event_poll(&state->local->sync_trigger);+	remote_event_poll(&state->local->sync_release);+	remote_event_poll(&state->local->trigger);+	remote_event_poll(&state->local->recycle);+}++/* Round up message sizes so that any space at the end of a slot is always big+** enough for a header. This relies on header size being a power of two, which+** has been verified earlier by a static assertion. */++static inline unsigned int+calc_stride(unsigned int size)+{+	/* Allow room for the header */+	size += sizeof(VCHIQ_HEADER_T);++	/* Round up */+	return (size + sizeof(VCHIQ_HEADER_T) - 1) & ~(sizeof(VCHIQ_HEADER_T)+		- 1);+}++/* Called by the slot handler thread */+static VCHIQ_SERVICE_T *+get_listening_service(VCHIQ_STATE_T *state, int fourcc)+{+	int i;++	WARN_ON(fourcc == VCHIQ_FOURCC_INVALID);++	for (i = 0; i < state->unused_service; i++) {+		VCHIQ_SERVICE_T *service = state->services[i];+		if (service &&+			(service->public_fourcc == fourcc) &&+			((service->srvstate == VCHIQ_SRVSTATE_LISTENING) ||+			((service->srvstate == VCHIQ_SRVSTATE_OPEN) &&+			(service->remoteport == VCHIQ_PORT_FREE)))) {+			lock_service(service);+			return service;+		}+	}++	return NULL;+}++/* Called by the slot handler thread */+static VCHIQ_SERVICE_T *+get_connected_service(VCHIQ_STATE_T *state, unsigned int port)+{+	int i;+	for (i = 0; i < state->unused_service; i++) {+		VCHIQ_SERVICE_T *service = state->services[i];+		if (service && (service->srvstate == VCHIQ_SRVSTATE_OPEN)+			&& (service->remoteport == port)) {+			lock_service(service);+			return service;+		}+	}+	return NULL;+}++inline void+request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type)+{+	uint32_t value;++	if (service) {+		do {+			value = atomic_read(&service->poll_flags);+		} while (atomic_cmpxchg(&service->poll_flags, value,+			value | (1 << poll_type)) != value);++		do {+			value = atomic_read(&state->poll_services[+				service->localport>>5]);+		} while (atomic_cmpxchg(+			&state->poll_services[service->localport>>5],+			value, value | (1 << (service->localport & 0x1f)))+			!= value);+	}++	state->poll_needed = 1;+	wmb();++	/* ... and ensure the slot handler runs. */+	remote_event_signal_local(&state->local->trigger);+}++/* Called from queue_message, by the slot handler and application threads,+** with slot_mutex held */+static VCHIQ_HEADER_T *+reserve_space(VCHIQ_STATE_T *state, int space, int is_blocking)+{+	VCHIQ_SHARED_STATE_T *local = state->local;+	int tx_pos = state->local_tx_pos;+	int slot_space = VCHIQ_SLOT_SIZE - (tx_pos & VCHIQ_SLOT_MASK);++	if (space > slot_space) {+		VCHIQ_HEADER_T *header;+		/* Fill the remaining space with padding */+		WARN_ON(state->tx_data == NULL);+		header = (VCHIQ_HEADER_T *)+			(state->tx_data + (tx_pos & VCHIQ_SLOT_MASK));+		header->msgid = VCHIQ_MSGID_PADDING;+		header->size = slot_space - sizeof(VCHIQ_HEADER_T);++		tx_pos += slot_space;+	}++	/* If necessary, get the next slot. */+	if ((tx_pos & VCHIQ_SLOT_MASK) == 0) {+		int slot_index;++		/* If there is no free slot... */++		if (down_trylock(&state->slot_available_event) != 0) {+			/* ...wait for one. */++			VCHIQ_STATS_INC(state, slot_stalls);++			/* But first, flush through the last slot. */+			state->local_tx_pos = tx_pos;+			local->tx_pos = tx_pos;+			remote_event_signal(&state->remote->trigger);++			if (!is_blocking ||+				(down_interruptible(+				&state->slot_available_event) != 0))+				return NULL; /* No space available */+		}++		BUG_ON(tx_pos ==+			(state->slot_queue_available * VCHIQ_SLOT_SIZE));++		slot_index = local->slot_queue[+			SLOT_QUEUE_INDEX_FROM_POS(tx_pos) &+			VCHIQ_SLOT_QUEUE_MASK];+		state->tx_data =+			(char *)SLOT_DATA_FROM_INDEX(state, slot_index);+	}++	state->local_tx_pos = tx_pos + space;++	return (VCHIQ_HEADER_T *)(state->tx_data + (tx_pos & VCHIQ_SLOT_MASK));+}++/* Called by the recycle thread. */+static void+process_free_queue(VCHIQ_STATE_T *state)+{+	VCHIQ_SHARED_STATE_T *local = state->local;+	BITSET_T service_found[BITSET_SIZE(VCHIQ_MAX_SERVICES)];+	int slot_queue_available;++	/* Use a read memory barrier to ensure that any state that may have+	** been modified by another thread is not masked by stale prefetched+	** values. */+	rmb();++	/* Find slots which have been freed by the other side, and return them+	** to the available queue. */+	slot_queue_available = state->slot_queue_available;++	while (slot_queue_available != local->slot_queue_recycle) {+		unsigned int pos;+		int slot_index = local->slot_queue[slot_queue_available++ &+			VCHIQ_SLOT_QUEUE_MASK];+		char *data = (char *)SLOT_DATA_FROM_INDEX(state, slot_index);+		int data_found = 0;++		vchiq_log_trace(vchiq_core_log_level, "%d: pfq %d=%x %x %x",+			state->id, slot_index, (unsigned int)data,+			local->slot_queue_recycle, slot_queue_available);++		/* Initialise the bitmask for services which have used this+		** slot */+		BITSET_ZERO(service_found);++		pos = 0;++		while (pos < VCHIQ_SLOT_SIZE) {+			VCHIQ_HEADER_T *header =+				(VCHIQ_HEADER_T *)(data + pos);+			int msgid = header->msgid;+			if (VCHIQ_MSG_TYPE(msgid) == VCHIQ_MSG_DATA) {+				int port = VCHIQ_MSG_SRCPORT(msgid);+				VCHIQ_SERVICE_QUOTA_T *service_quota =+					&state->service_quotas[port];+				int count;+				spin_lock("a_spinlock);+				count = service_quota->message_use_count;+				if (count > 0)+					service_quota->message_use_count =+						count - 1;+				spin_unlock("a_spinlock);++				if (count == service_quota->message_quota)+					/* Signal the service that it+					** has dropped below its quota+					*/+					up(&service_quota->quota_event);+				else if (count == 0) {+					vchiq_log_error(vchiq_core_log_level,+						"service %d "+						"message_use_count=%d "+						"(header %x, msgid %x, "+						"header->msgid %x, "+						"header->size %x)",+						port,+						service_quota->+							message_use_count,+						(unsigned int)header, msgid,+						header->msgid,+						header->size);+					WARN(1, "invalid message use count\n");+				}+				if (!BITSET_IS_SET(service_found, port)) {+					/* Set the found bit for this service */+					BITSET_SET(service_found, port);++					spin_lock("a_spinlock);+					count = service_quota->slot_use_count;+					if (count > 0)+						service_quota->slot_use_count =+							count - 1;+					spin_unlock("a_spinlock);++					if (count > 0) {+						/* Signal the service in case+						** it has dropped below its+						** quota */+						up(&service_quota->quota_event);+						vchiq_log_trace(+							vchiq_core_log_level,+							"%d: pfq:%d %x@%x - "+							"slot_use->%d",+							state->id, port,+							header->size,+							(unsigned int)header,+							count - 1);+					} else {+						vchiq_log_error(+							vchiq_core_log_level,+								"service %d "+								"slot_use_count"+								"=%d (header %x"+								", msgid %x, "+								"header->msgid"+								" %x, header->"+								"size %x)",+							port, count,+							(unsigned int)header,+							msgid,+							header->msgid,+							header->size);+						WARN(1, "bad slot use count\n");+					}+				}++				data_found = 1;+			}++			pos += calc_stride(header->size);+			if (pos > VCHIQ_SLOT_SIZE) {+				vchiq_log_error(vchiq_core_log_level,+					"pfq - pos %x: header %x, msgid %x, "+					"header->msgid %x, header->size %x",+					pos, (unsigned int)header, msgid,+					header->msgid, header->size);+				WARN(1, "invalid slot position\n");+			}+		}++		if (data_found) {+			int count;+			spin_lock("a_spinlock);+			count = state->data_use_count;+			if (count > 0)+				state->data_use_count =+					count - 1;+			spin_unlock("a_spinlock);+			if (count == state->data_quota)+				up(&state->data_quota_event);+		}++		state->slot_queue_available = slot_queue_available;+		up(&state->slot_available_event);+	}+}++/* Called by the slot handler and application threads */+static VCHIQ_STATUS_T+queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,+	int msgid, const VCHIQ_ELEMENT_T *elements,+	int count, int size, int is_blocking)+{+	VCHIQ_SHARED_STATE_T *local;+	VCHIQ_SERVICE_QUOTA_T *service_quota = NULL;+	VCHIQ_HEADER_T *header;+	int type = VCHIQ_MSG_TYPE(msgid);++	unsigned int stride;++	local = state->local;++	stride = calc_stride(size);++	WARN_ON(!(stride <= VCHIQ_SLOT_SIZE));++	if ((type != VCHIQ_MSG_RESUME) &&+		(mutex_lock_interruptible(&state->slot_mutex) != 0))+		return VCHIQ_RETRY;++	if (type == VCHIQ_MSG_DATA) {+		int tx_end_index;++		BUG_ON(!service);++		if (service->closing) {+			/* The service has been closed */+			mutex_unlock(&state->slot_mutex);+			return VCHIQ_ERROR;+		}++		service_quota = &state->service_quotas[service->localport];++		spin_lock("a_spinlock);++		/* Ensure this service doesn't use more than its quota of+		** messages or slots */+		tx_end_index = SLOT_QUEUE_INDEX_FROM_POS(+			state->local_tx_pos + stride - 1);++		/* Ensure data messages don't use more than their quota of+		** slots */+		while ((tx_end_index != state->previous_data_index) &&+			(state->data_use_count == state->data_quota)) {+			VCHIQ_STATS_INC(state, data_stalls);+			spin_unlock("a_spinlock);+			mutex_unlock(&state->slot_mutex);++			if (down_interruptible(&state->data_quota_event)+				!= 0)+				return VCHIQ_RETRY;++			mutex_lock(&state->slot_mutex);+			spin_lock("a_spinlock);+			tx_end_index = SLOT_QUEUE_INDEX_FROM_POS(+				state->local_tx_pos + stride - 1);+			if ((tx_end_index == state->previous_data_index) ||+				(state->data_use_count < state->data_quota)) {+				/* Pass the signal on to other waiters */+				up(&state->data_quota_event);+				break;+			}+		}++		while ((service_quota->message_use_count ==+				service_quota->message_quota) ||+			((tx_end_index != service_quota->previous_tx_index) &&+			(service_quota->slot_use_count ==+				service_quota->slot_quota))) {+			spin_unlock("a_spinlock);+			vchiq_log_trace(vchiq_core_log_level,+				"%d: qm:%d %s,%x - quota stall "+				"(msg %d, slot %d)",+				state->id, service->localport,+				msg_type_str(type), size,+				service_quota->message_use_count,+				service_quota->slot_use_count);+			VCHIQ_SERVICE_STATS_INC(service, quota_stalls);+			mutex_unlock(&state->slot_mutex);+			if (down_interruptible(&service_quota->quota_event)+				!= 0)+				return VCHIQ_RETRY;+			if (service->closing)+				return VCHIQ_ERROR;+			if (mutex_lock_interruptible(&state->slot_mutex) != 0)+				return VCHIQ_RETRY;+			if (service->srvstate != VCHIQ_SRVSTATE_OPEN) {+				/* The service has been closed */+				mutex_unlock(&state->slot_mutex);+				return VCHIQ_ERROR;+			}+			spin_lock("a_spinlock);+			tx_end_index = SLOT_QUEUE_INDEX_FROM_POS(+				state->local_tx_pos + stride - 1);+		}++		spin_unlock("a_spinlock);+	}++	header = reserve_space(state, stride, is_blocking);++	if (!header) {+		if (service)+			VCHIQ_SERVICE_STATS_INC(service, slot_stalls);+		mutex_unlock(&state->slot_mutex);+		return VCHIQ_RETRY;+	}++	if (type == VCHIQ_MSG_DATA) {+		int i, pos;+		int tx_end_index;+		int slot_use_count;++		vchiq_log_info(vchiq_core_log_level,+			"%d: qm %s@%x,%x (%d->%d)",+			state->id,+			msg_type_str(VCHIQ_MSG_TYPE(msgid)),+			(unsigned int)header, size,+			VCHIQ_MSG_SRCPORT(msgid),+			VCHIQ_MSG_DSTPORT(msgid));++		BUG_ON(!service);++		for (i = 0, pos = 0; i < (unsigned int)count;+			pos += elements[i++].size)+			if (elements[i].size) {+				if (vchiq_copy_from_user+					(header->data + pos, elements[i].data,+					(size_t) elements[i].size) !=+					VCHIQ_SUCCESS) {+					mutex_unlock(&state->slot_mutex);+					VCHIQ_SERVICE_STATS_INC(service,+						error_count);+					return VCHIQ_ERROR;+				}+				if (i == 0) {+					if (vchiq_core_msg_log_level >=+						VCHIQ_LOG_INFO)+						vchiq_log_dump_mem("Sent", 0,+							header->data + pos,+							min(64u,+							elements[0].size));+				}+			}++		spin_lock("a_spinlock);+		service_quota->message_use_count++;++		tx_end_index =+			SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos - 1);++		/* If this transmission can't fit in the last slot used by any+		** service, the data_use_count must be increased. */+		if (tx_end_index != state->previous_data_index) {+			state->previous_data_index = tx_end_index;+			state->data_use_count++;+		}++		/* If this isn't the same slot last used by this service,+		** the service's slot_use_count must be increased. */+		if (tx_end_index != service_quota->previous_tx_index) {+			service_quota->previous_tx_index = tx_end_index;+			slot_use_count = ++service_quota->slot_use_count;+		} else {+			slot_use_count = 0;+		}++		spin_unlock("a_spinlock);++		if (slot_use_count)+			vchiq_log_trace(vchiq_core_log_level,+				"%d: qm:%d %s,%x - slot_use->%d (hdr %p)",+				state->id, service->localport,+				msg_type_str(VCHIQ_MSG_TYPE(msgid)), size,+				slot_use_count, header);++		VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count);+		VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size);+	} else {+		vchiq_log_info(vchiq_core_log_level,+			"%d: qm %s@%x,%x (%d->%d)", state->id,+			msg_type_str(VCHIQ_MSG_TYPE(msgid)),+			(unsigned int)header, size,+			VCHIQ_MSG_SRCPORT(msgid),+			VCHIQ_MSG_DSTPORT(msgid));+		if (size != 0) {+			WARN_ON(!((count == 1) && (size == elements[0].size)));+			memcpy(header->data, elements[0].data,+				elements[0].size);+		}+		VCHIQ_STATS_INC(state, ctrl_tx_count);+	}++	header->msgid = msgid;+	header->size = size;++	{+		int svc_fourcc;++		svc_fourcc = service+			? service->base.fourcc+			: VCHIQ_MAKE_FOURCC('?', '?', '?', '?');++		vchiq_log_info(vchiq_core_msg_log_level,+			"Sent Msg %s(%u) to %c%c%c%c s:%u d:%d len:%d",+			msg_type_str(VCHIQ_MSG_TYPE(msgid)),+			VCHIQ_MSG_TYPE(msgid),+			VCHIQ_FOURCC_AS_4CHARS(svc_fourcc),+			VCHIQ_MSG_SRCPORT(msgid),+			VCHIQ_MSG_DSTPORT(msgid),+			size);+	}++	/* Make sure the new header is visible to the peer. */+	wmb();++	/* Make the new tx_pos visible to the peer. */+	local->tx_pos = state->local_tx_pos;+	wmb();++	if (service && (type == VCHIQ_MSG_CLOSE))+		vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSESENT);++	if (VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_PAUSE)+		mutex_unlock(&state->slot_mutex);++	remote_event_signal(&state->remote->trigger);++	return VCHIQ_SUCCESS;+}++/* Called by the slot handler and application threads */+static VCHIQ_STATUS_T+queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,+	int msgid, const VCHIQ_ELEMENT_T *elements,+	int count, int size, int is_blocking)+{+	VCHIQ_SHARED_STATE_T *local;+	VCHIQ_HEADER_T *header;++	local = state->local;++	if ((VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_RESUME) &&+		(mutex_lock_interruptible(&state->sync_mutex) != 0))+		return VCHIQ_RETRY;++	remote_event_wait(&local->sync_release);++	rmb();++	header = (VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state,+		local->slot_sync);++	{+		int oldmsgid = header->msgid;+		if (oldmsgid != VCHIQ_MSGID_PADDING)+			vchiq_log_error(vchiq_core_log_level,+				"%d: qms - msgid %x, not PADDING",+				state->id, oldmsgid);+	}++	if (service) {+		int i, pos;++		vchiq_log_info(vchiq_sync_log_level,+			"%d: qms %s@%x,%x (%d->%d)", state->id,+			msg_type_str(VCHIQ_MSG_TYPE(msgid)),+			(unsigned int)header, size,+			VCHIQ_MSG_SRCPORT(msgid),+			VCHIQ_MSG_DSTPORT(msgid));++		for (i = 0, pos = 0; i < (unsigned int)count;+			pos += elements[i++].size)+			if (elements[i].size) {+				if (vchiq_copy_from_user+					(header->data + pos, elements[i].data,+					(size_t) elements[i].size) !=+					VCHIQ_SUCCESS) {+					mutex_unlock(&state->sync_mutex);+					VCHIQ_SERVICE_STATS_INC(service,+						error_count);+					return VCHIQ_ERROR;+				}+				if (i == 0) {+					if (vchiq_sync_log_level >=+						VCHIQ_LOG_TRACE)+						vchiq_log_dump_mem("Sent Sync",+							0, header->data + pos,+							min(64u,+							elements[0].size));+				}+			}++		VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count);+		VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size);+	} else {+		vchiq_log_info(vchiq_sync_log_level,+			"%d: qms %s@%x,%x (%d->%d)", state->id,+			msg_type_str(VCHIQ_MSG_TYPE(msgid)),+			(unsigned int)header, size,+			VCHIQ_MSG_SRCPORT(msgid),+			VCHIQ_MSG_DSTPORT(msgid));+		if (size != 0) {+			WARN_ON(!((count == 1) && (size == elements[0].size)));+			memcpy(header->data, elements[0].data,+				elements[0].size);+		}+		VCHIQ_STATS_INC(state, ctrl_tx_count);+	}++	header->size = size;+	header->msgid = msgid;++	if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE) {+		int svc_fourcc;++		svc_fourcc = service+			? service->base.fourcc+			: VCHIQ_MAKE_FOURCC('?', '?', '?', '?');++		vchiq_log_trace(vchiq_sync_log_level,+			"Sent Sync Msg %s(%u) to %c%c%c%c s:%u d:%d len:%d",+			msg_type_str(VCHIQ_MSG_TYPE(msgid)),+			VCHIQ_MSG_TYPE(msgid),+			VCHIQ_FOURCC_AS_4CHARS(svc_fourcc),+			VCHIQ_MSG_SRCPORT(msgid),+			VCHIQ_MSG_DSTPORT(msgid),+			size);+	}++	/* Make sure the new header is visible to the peer. */+	wmb();++	remote_event_signal(&state->remote->sync_trigger);++	if (VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_PAUSE)+		mutex_unlock(&state->sync_mutex);++	return VCHIQ_SUCCESS;+}++static inline void+claim_slot(VCHIQ_SLOT_INFO_T *slot)+{+	slot->use_count++;+}++static void+release_slot(VCHIQ_STATE_T *state, VCHIQ_SLOT_INFO_T *slot_info,+	VCHIQ_HEADER_T *header, VCHIQ_SERVICE_T *service)+{+	int release_count;++	mutex_lock(&state->recycle_mutex);++	if (header) {+		int msgid = header->msgid;+		if (((msgid & VCHIQ_MSGID_CLAIMED) == 0) ||+			(service && service->closing)) {+			mutex_unlock(&state->recycle_mutex);+			return;+		}++		/* Rewrite the message header to prevent a double+		** release */+		header->msgid = msgid & ~VCHIQ_MSGID_CLAIMED;+	}++	release_count = slot_info->release_count;+	slot_info->release_count = ++release_count;++	if (release_count == slot_info->use_count) {+		int slot_queue_recycle;+		/* Add to the freed queue */++		/* A read barrier is necessary here to prevent speculative+		** fetches of remote->slot_queue_recycle from overtaking the+		** mutex. */+		rmb();++		slot_queue_recycle = state->remote->slot_queue_recycle;+		state->remote->slot_queue[slot_queue_recycle &+			VCHIQ_SLOT_QUEUE_MASK] =+			SLOT_INDEX_FROM_INFO(state, slot_info);+		state->remote->slot_queue_recycle = slot_queue_recycle + 1;+		vchiq_log_info(vchiq_core_log_level,+			"%d: release_slot %d - recycle->%x",+			state->id, SLOT_INDEX_FROM_INFO(state, slot_info),+			state->remote->slot_queue_recycle);++		/* A write barrier is necessary, but remote_event_signal+		** contains one. */+		remote_event_signal(&state->remote->recycle);+	}++	mutex_unlock(&state->recycle_mutex);+}++/* Called by the slot handler - don't hold the bulk mutex */+static VCHIQ_STATUS_T+notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue,+	int retry_poll)+{+	VCHIQ_STATUS_T status = VCHIQ_SUCCESS;++	vchiq_log_trace(vchiq_core_log_level,+		"%d: nb:%d %cx - p=%x rn=%x r=%x",+		service->state->id, service->localport,+		(queue == &service->bulk_tx) ? 't' : 'r',+		queue->process, queue->remote_notify, queue->remove);++	if (service->state->is_master) {+		while (queue->remote_notify != queue->process) {+			VCHIQ_BULK_T *bulk =+				&queue->bulks[BULK_INDEX(queue->remote_notify)];+			int msgtype = (bulk->dir == VCHIQ_BULK_TRANSMIT) ?+				VCHIQ_MSG_BULK_RX_DONE : VCHIQ_MSG_BULK_TX_DONE;+			int msgid = VCHIQ_MAKE_MSG(msgtype, service->localport,+				service->remoteport);+			VCHIQ_ELEMENT_T element = { &bulk->actual, 4 };+			/* Only reply to non-dummy bulk requests */+			if (bulk->remote_data) {+				status = queue_message(service->state, NULL,+					msgid, &element, 1, 4, 0);+				if (status != VCHIQ_SUCCESS)+					break;+			}+			queue->remote_notify++;+		}+	} else {+		queue->remote_notify = queue->process;+	}++	if (status == VCHIQ_SUCCESS) {+		while (queue->remove != queue->remote_notify) {+			VCHIQ_BULK_T *bulk =+				&queue->bulks[BULK_INDEX(queue->remove)];++			/* Only generate callbacks for non-dummy bulk+			** requests, and non-terminated services */+			if (bulk->data && service->instance) {+				if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) {+					if (bulk->dir == VCHIQ_BULK_TRANSMIT) {+						VCHIQ_SERVICE_STATS_INC(service,+							bulk_tx_count);+						VCHIQ_SERVICE_STATS_ADD(service,+							bulk_tx_bytes,+							bulk->actual);+					} else {+						VCHIQ_SERVICE_STATS_INC(service,+							bulk_rx_count);+						VCHIQ_SERVICE_STATS_ADD(service,+							bulk_rx_bytes,+							bulk->actual);+					}+				} else {+					VCHIQ_SERVICE_STATS_INC(service,+						bulk_aborted_count);+				}+				if (bulk->mode == VCHIQ_BULK_MODE_BLOCKING) {+					struct bulk_waiter *waiter;+					spin_lock(&bulk_waiter_spinlock);+					waiter = bulk->userdata;+					if (waiter) {+						waiter->actual = bulk->actual;+						up(&waiter->event);+					}+					spin_unlock(&bulk_waiter_spinlock);+				} else if (bulk->mode ==+					VCHIQ_BULK_MODE_CALLBACK) {+					VCHIQ_REASON_T reason = (bulk->dir ==+						VCHIQ_BULK_TRANSMIT) ?+						((bulk->actual ==+						VCHIQ_BULK_ACTUAL_ABORTED) ?+						VCHIQ_BULK_TRANSMIT_ABORTED :+						VCHIQ_BULK_TRANSMIT_DONE) :+						((bulk->actual ==+						VCHIQ_BULK_ACTUAL_ABORTED) ?+						VCHIQ_BULK_RECEIVE_ABORTED :+						VCHIQ_BULK_RECEIVE_DONE);+					status = make_service_callback(service,+						reason,	NULL, bulk->userdata);+					if (status == VCHIQ_RETRY)+						break;+				}+			}++			queue->remove++;+			up(&service->bulk_remove_event);+		}+		if (!retry_poll)+			status = VCHIQ_SUCCESS;+	}++	if (status == VCHIQ_RETRY)+		request_poll(service->state, service,+			(queue == &service->bulk_tx) ?+			VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY);++	return status;+}++/* Called by the slot handler thread */+static void+poll_services(VCHIQ_STATE_T *state)+{+	int group, i;++	for (group = 0; group < BITSET_SIZE(state->unused_service); group++) {+		uint32_t flags;+		flags = atomic_xchg(&state->poll_services[group], 0);+		for (i = 0; flags; i++) {+			if (flags & (1 << i)) {+				VCHIQ_SERVICE_T *service =+					find_service_by_port(state,+						(group<<5) + i);+				uint32_t service_flags;+				flags &= ~(1 << i);+				if (!service)+					continue;+				service_flags =+					atomic_xchg(&service->poll_flags, 0);+				if (service_flags &+					(1 << VCHIQ_POLL_REMOVE)) {+					vchiq_log_info(vchiq_core_log_level,+						"%d: ps - remove %d<->%d",+						state->id, service->localport,+						service->remoteport);++					/* Make it look like a client, because+					   it must be removed and not left in+					   the LISTENING state. */+					service->public_fourcc =+						VCHIQ_FOURCC_INVALID;++					if (vchiq_close_service_internal(+						service, 0/*!close_recvd*/) !=+						VCHIQ_SUCCESS)+						request_poll(state, service,+							VCHIQ_POLL_REMOVE);+				} else if (service_flags &+					(1 << VCHIQ_POLL_TERMINATE)) {+					vchiq_log_info(vchiq_core_log_level,+						"%d: ps - terminate %d<->%d",+						state->id, service->localport,+						service->remoteport);+					if (vchiq_close_service_internal(+						service, 0/*!close_recvd*/) !=+						VCHIQ_SUCCESS)+						request_poll(state, service,+							VCHIQ_POLL_TERMINATE);+				}+				if (service_flags & (1 << VCHIQ_POLL_TXNOTIFY))+					notify_bulks(service,+						&service->bulk_tx,+						1/*retry_poll*/);+				if (service_flags & (1 << VCHIQ_POLL_RXNOTIFY))+					notify_bulks(service,+						&service->bulk_rx,+						1/*retry_poll*/);+				unlock_service(service);+			}+		}+	}+}++/* Called by the slot handler or application threads, holding the bulk mutex. */+static int+resolve_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue)+{+	VCHIQ_STATE_T *state = service->state;+	int resolved = 0;+	int rc;++	while ((queue->process != queue->local_insert) &&+		(queue->process != queue->remote_insert)) {+		VCHIQ_BULK_T *bulk = &queue->bulks[BULK_INDEX(queue->process)];++		vchiq_log_trace(vchiq_core_log_level,+			"%d: rb:%d %cx - li=%x ri=%x p=%x",+			state->id, service->localport,+			(queue == &service->bulk_tx) ? 't' : 'r',+			queue->local_insert, queue->remote_insert,+			queue->process);++		WARN_ON(!((int)(queue->local_insert - queue->process) > 0));+		WARN_ON(!((int)(queue->remote_insert - queue->process) > 0));++		rc = mutex_lock_interruptible(&state->bulk_transfer_mutex);+		if (rc != 0)+			break;++		vchiq_transfer_bulk(bulk);+		mutex_unlock(&state->bulk_transfer_mutex);++		if (vchiq_core_msg_log_level >= VCHIQ_LOG_INFO) {+			const char *header = (queue == &service->bulk_tx) ?+				"Send Bulk to" : "Recv Bulk from";+			if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED)+				vchiq_log_info(vchiq_core_msg_log_level,+					"%s %c%c%c%c d:%d len:%d %x<->%x",+					header,+					VCHIQ_FOURCC_AS_4CHARS(+						service->base.fourcc),+					service->remoteport,+					bulk->size,+					(unsigned int)bulk->data,+					(unsigned int)bulk->remote_data);+			else+				vchiq_log_info(vchiq_core_msg_log_level,+					"%s %c%c%c%c d:%d ABORTED - tx len:%d,"+					" rx len:%d %x<->%x",+					header,+					VCHIQ_FOURCC_AS_4CHARS(+						service->base.fourcc),+					service->remoteport,+					bulk->size,+					bulk->remote_size,+					(unsigned int)bulk->data,+					(unsigned int)bulk->remote_data);+		}++		vchiq_complete_bulk(bulk);+		queue->process++;+		resolved++;+	}+	return resolved;+}++/* Called with the bulk_mutex held */+static void+abort_outstanding_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue)+{+	int is_tx = (queue == &service->bulk_tx);+	vchiq_log_trace(vchiq_core_log_level,+		"%d: aob:%d %cx - li=%x ri=%x p=%x",+		service->state->id, service->localport, is_tx ? 't' : 'r',+		queue->local_insert, queue->remote_insert, queue->process);++	WARN_ON(!((int)(queue->local_insert - queue->process) >= 0));+	WARN_ON(!((int)(queue->remote_insert - queue->process) >= 0));++	while ((queue->process != queue->local_insert) ||+		(queue->process != queue->remote_insert)) {+		VCHIQ_BULK_T *bulk = &queue->bulks[BULK_INDEX(queue->process)];++		if (queue->process == queue->remote_insert) {+			/* fabricate a matching dummy bulk */+			bulk->remote_data = NULL;+			bulk->remote_size = 0;+			queue->remote_insert++;+		}++		if (queue->process != queue->local_insert) {+			vchiq_complete_bulk(bulk);++			vchiq_log_info(vchiq_core_msg_log_level,+				"%s %c%c%c%c d:%d ABORTED - tx len:%d, "+				"rx len:%d",+				is_tx ? "Send Bulk to" : "Recv Bulk from",+				VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc),+				service->remoteport,+				bulk->size,+				bulk->remote_size);+		} else {+			/* fabricate a matching dummy bulk */+			bulk->data = NULL;+			bulk->size = 0;+			bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED;+			bulk->dir = is_tx ? VCHIQ_BULK_TRANSMIT :+				VCHIQ_BULK_RECEIVE;+			queue->local_insert++;+		}++		queue->process++;+	}+}++/* Called from the slot handler thread */+static void+pause_bulks(VCHIQ_STATE_T *state)+{+	if (unlikely(atomic_inc_return(&pause_bulks_count) != 1)) {+		WARN_ON_ONCE(1);+		atomic_set(&pause_bulks_count, 1);+		return;+	}++	/* Block bulk transfers from all services */+	mutex_lock(&state->bulk_transfer_mutex);+}++/* Called from the slot handler thread */+static void+resume_bulks(VCHIQ_STATE_T *state)+{+	int i;+	if (unlikely(atomic_dec_return(&pause_bulks_count) != 0)) {+		WARN_ON_ONCE(1);+		atomic_set(&pause_bulks_count, 0);+		return;+	}++	/* Allow bulk transfers from all services */+	mutex_unlock(&state->bulk_transfer_mutex);++	if (state->deferred_bulks == 0)+		return;++	/* Deal with any bulks which had to be deferred due to being in+	 * paused state.  Don't try to match up to number of deferred bulks+	 * in case we've had something come and close the service in the+	 * interim - just process all bulk queues for all services */+	vchiq_log_info(vchiq_core_log_level, "%s: processing %d deferred bulks",+		__func__, state->deferred_bulks);++	for (i = 0; i < state->unused_service; i++) {+		VCHIQ_SERVICE_T *service = state->services[i];+		int resolved_rx = 0;+		int resolved_tx = 0;+		if (!service || (service->srvstate != VCHIQ_SRVSTATE_OPEN))+			continue;++		mutex_lock(&service->bulk_mutex);+		resolved_rx = resolve_bulks(service, &service->bulk_rx);+		resolved_tx = resolve_bulks(service, &service->bulk_tx);+		mutex_unlock(&service->bulk_mutex);+		if (resolved_rx)+			notify_bulks(service, &service->bulk_rx, 1);+		if (resolved_tx)+			notify_bulks(service, &service->bulk_tx, 1);+	}+	state->deferred_bulks = 0;+}++static int+parse_open(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header)+{+	VCHIQ_SERVICE_T *service = NULL;+	int msgid, size;+	int type;+	unsigned int localport, remoteport;++	msgid = header->msgid;+	size = header->size;+	type = VCHIQ_MSG_TYPE(msgid);+	localport = VCHIQ_MSG_DSTPORT(msgid);+	remoteport = VCHIQ_MSG_SRCPORT(msgid);+	if (size >= sizeof(struct vchiq_open_payload)) {+		const struct vchiq_open_payload *payload =+			(struct vchiq_open_payload *)header->data;+		unsigned int fourcc;++		fourcc = payload->fourcc;+		vchiq_log_info(vchiq_core_log_level,+			"%d: prs OPEN@%x (%d->'%c%c%c%c')",+			state->id, (unsigned int)header,+			localport,+			VCHIQ_FOURCC_AS_4CHARS(fourcc));++		service = get_listening_service(state, fourcc);++		if (service) {+			/* A matching service exists */+			short version = payload->version;+			short version_min = payload->version_min;+			if ((service->version < version_min) ||+				(version < service->version_min)) {+				/* Version mismatch */+				vchiq_loud_error_header();+				vchiq_loud_error("%d: service %d (%c%c%c%c) "+					"version mismatch - local (%d, min %d)"+					" vs. remote (%d, min %d)",+					state->id, service->localport,+					VCHIQ_FOURCC_AS_4CHARS(fourcc),+					service->version, service->version_min,+					version, version_min);+				vchiq_loud_error_footer();+				unlock_service(service);+				service = NULL;+				goto fail_open;+			}+			service->peer_version = version;++			if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) {+				struct vchiq_openack_payload ack_payload = {+					service->version+				};+				VCHIQ_ELEMENT_T body = {+					&ack_payload,+					sizeof(ack_payload)+				};++				/* Acknowledge the OPEN */+				if (service->sync) {+					if (queue_message_sync(state, NULL,+						VCHIQ_MAKE_MSG(+							VCHIQ_MSG_OPENACK,+							service->localport,+							remoteport),+						&body, 1, sizeof(ack_payload),+						0) == VCHIQ_RETRY)+						goto bail_not_ready;+				} else {+					if (queue_message(state, NULL,+						VCHIQ_MAKE_MSG(+							VCHIQ_MSG_OPENACK,+							service->localport,+							remoteport),+						&body, 1, sizeof(ack_payload),+						0) == VCHIQ_RETRY)+						goto bail_not_ready;+				}++				/* The service is now open */+				vchiq_set_service_state(service,+					service->sync ? VCHIQ_SRVSTATE_OPENSYNC+					: VCHIQ_SRVSTATE_OPEN);+			}++			service->remoteport = remoteport;+			service->client_id = ((int *)header->data)[1];+			if (make_service_callback(service, VCHIQ_SERVICE_OPENED,+				NULL, NULL) == VCHIQ_RETRY) {+				/* Bail out if not ready */+				service->remoteport = VCHIQ_PORT_FREE;+				goto bail_not_ready;+			}++			/* Success - the message has been dealt with */+			unlock_service(service);+			return 1;+		}+	}++fail_open:+	/* No available service, or an invalid request - send a CLOSE */+	if (queue_message(state, NULL,+		VCHIQ_MAKE_MSG(VCHIQ_MSG_CLOSE, 0, VCHIQ_MSG_SRCPORT(msgid)),+		NULL, 0, 0, 0) == VCHIQ_RETRY)+		goto bail_not_ready;++	return 1;++bail_not_ready:+	if (service)+		unlock_service(service);++	return 0;+}++/* Called by the slot handler thread */+static void+parse_rx_slots(VCHIQ_STATE_T *state)+{+	VCHIQ_SHARED_STATE_T *remote = state->remote;+	VCHIQ_SERVICE_T *service = NULL;+	int tx_pos;+	DEBUG_INITIALISE(state->local)++	tx_pos = remote->tx_pos;++	while (state->rx_pos != tx_pos) {+		VCHIQ_HEADER_T *header;+		int msgid, size;+		int type;+		unsigned int localport, remoteport;++		DEBUG_TRACE(PARSE_LINE);+		if (!state->rx_data) {+			int rx_index;+			WARN_ON(!((state->rx_pos & VCHIQ_SLOT_MASK) == 0));+			rx_index = remote->slot_queue[+				SLOT_QUEUE_INDEX_FROM_POS(state->rx_pos) &+				VCHIQ_SLOT_QUEUE_MASK];+			state->rx_data = (char *)SLOT_DATA_FROM_INDEX(state,+				rx_index);+			state->rx_info = SLOT_INFO_FROM_INDEX(state, rx_index);++			/* Initialise use_count to one, and increment+			** release_count at the end of the slot to avoid+			** releasing the slot prematurely. */+			state->rx_info->use_count = 1;+			state->rx_info->release_count = 0;+		}++		header = (VCHIQ_HEADER_T *)(state->rx_data ++			(state->rx_pos & VCHIQ_SLOT_MASK));+		DEBUG_VALUE(PARSE_HEADER, (int)header);+		msgid = header->msgid;+		DEBUG_VALUE(PARSE_MSGID, msgid);+		size = header->size;+		type = VCHIQ_MSG_TYPE(msgid);+		localport = VCHIQ_MSG_DSTPORT(msgid);+		remoteport = VCHIQ_MSG_SRCPORT(msgid);++		if (type != VCHIQ_MSG_DATA)+			VCHIQ_STATS_INC(state, ctrl_rx_count);++		switch (type) {+		case VCHIQ_MSG_OPENACK:+		case VCHIQ_MSG_CLOSE:+		case VCHIQ_MSG_DATA:+		case VCHIQ_MSG_BULK_RX:+		case VCHIQ_MSG_BULK_TX:+		case VCHIQ_MSG_BULK_RX_DONE:+		case VCHIQ_MSG_BULK_TX_DONE:+			service = find_service_by_port(state, localport);+			if ((!service || service->remoteport != remoteport) &&+				(localport == 0) &&+				(type == VCHIQ_MSG_CLOSE)) {+				/* This could be a CLOSE from a client which+				   hadn't yet received the OPENACK - look for+				   the connected service */+				if (service)+					unlock_service(service);+				service = get_connected_service(state,+					remoteport);+				if (service)+					vchiq_log_warning(vchiq_core_log_level,+						"%d: prs %s@%x (%d->%d) - "+						"found connected service %d",+						state->id, msg_type_str(type),+						(unsigned int)header,+						remoteport, localport,+						service->localport);+			}++			if (!service) {+				vchiq_log_error(vchiq_core_log_level,+					"%d: prs %s@%x (%d->%d) - "+					"invalid/closed service %d",+					state->id, msg_type_str(type),+					(unsigned int)header,+					remoteport, localport, localport);+				goto skip_message;+			}+			break;+		default:+			break;+		}++		if (vchiq_core_msg_log_level >= VCHIQ_LOG_INFO) {+			int svc_fourcc;++			svc_fourcc = service+				? service->base.fourcc+				: VCHIQ_MAKE_FOURCC('?', '?', '?', '?');+			vchiq_log_info(vchiq_core_msg_log_level,+				"Rcvd Msg %s(%u) from %c%c%c%c s:%d d:%d "+				"len:%d",+				msg_type_str(type), type,+				VCHIQ_FOURCC_AS_4CHARS(svc_fourcc),+				remoteport, localport, size);+			if (size > 0)+				vchiq_log_dump_mem("Rcvd", 0, header->data,+					min(64, size));+		}++		if (((unsigned int)header & VCHIQ_SLOT_MASK) + calc_stride(size)+			> VCHIQ_SLOT_SIZE) {+			vchiq_log_error(vchiq_core_log_level,+				"header %x (msgid %x) - size %x too big for "+				"slot",+				(unsigned int)header, (unsigned int)msgid,+				(unsigned int)size);+			WARN(1, "oversized for slot\n");+		}++		switch (type) {+		case VCHIQ_MSG_OPEN:+			WARN_ON(!(VCHIQ_MSG_DSTPORT(msgid) == 0));+			if (!parse_open(state, header))+				goto bail_not_ready;+			break;+		case VCHIQ_MSG_OPENACK:+			if (size >= sizeof(struct vchiq_openack_payload)) {+				const struct vchiq_openack_payload *payload =+					(struct vchiq_openack_payload *)+					header->data;+				service->peer_version = payload->version;+			}+			vchiq_log_info(vchiq_core_log_level,+				"%d: prs OPENACK@%x,%x (%d->%d) v:%d",+				state->id, (unsigned int)header, size,+				remoteport, localport, service->peer_version);+			if (service->srvstate ==+				VCHIQ_SRVSTATE_OPENING) {+				service->remoteport = remoteport;+				vchiq_set_service_state(service,+					VCHIQ_SRVSTATE_OPEN);+				up(&service->remove_event);+			} else+				vchiq_log_error(vchiq_core_log_level,+					"OPENACK received in state %s",+					srvstate_names[service->srvstate]);+			break;+		case VCHIQ_MSG_CLOSE:+			WARN_ON(size != 0); /* There should be no data */++			vchiq_log_info(vchiq_core_log_level,+				"%d: prs CLOSE@%x (%d->%d)",+				state->id, (unsigned int)header,+				remoteport, localport);++			mark_service_closing_internal(service, 1);++			if (vchiq_close_service_internal(service,+				1/*close_recvd*/) == VCHIQ_RETRY)+				goto bail_not_ready;++			vchiq_log_info(vchiq_core_log_level,+				"Close Service %c%c%c%c s:%u d:%d",+				VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc),+				service->localport,+				service->remoteport);+			break;+		case VCHIQ_MSG_DATA:+			vchiq_log_trace(vchiq_core_log_level,+				"%d: prs DATA@%x,%x (%d->%d)",+				state->id, (unsigned int)header, size,+				remoteport, localport);++			if ((service->remoteport == remoteport)+				&& (service->srvstate ==+				VCHIQ_SRVSTATE_OPEN)) {+				header->msgid = msgid | VCHIQ_MSGID_CLAIMED;+				claim_slot(state->rx_info);+				DEBUG_TRACE(PARSE_LINE);+				if (make_service_callback(service,+					VCHIQ_MESSAGE_AVAILABLE, header,+					NULL) == VCHIQ_RETRY) {+					DEBUG_TRACE(PARSE_LINE);+					goto bail_not_ready;+				}+				VCHIQ_SERVICE_STATS_INC(service, ctrl_rx_count);+				VCHIQ_SERVICE_STATS_ADD(service, ctrl_rx_bytes,+					size);+			} else {+				VCHIQ_STATS_INC(state, error_count);+			}+			break;+		case VCHIQ_MSG_CONNECT:+			vchiq_log_info(vchiq_core_log_level,+				"%d: prs CONNECT@%x",+				state->id, (unsigned int)header);+			up(&state->connect);+			break;+		case VCHIQ_MSG_BULK_RX:+		case VCHIQ_MSG_BULK_TX: {+			VCHIQ_BULK_QUEUE_T *queue;+			WARN_ON(!state->is_master);+			queue = (type == VCHIQ_MSG_BULK_RX) ?+				&service->bulk_tx : &service->bulk_rx;+			if ((service->remoteport == remoteport)+				&& (service->srvstate ==+				VCHIQ_SRVSTATE_OPEN)) {+				VCHIQ_BULK_T *bulk;+				int resolved = 0;++				DEBUG_TRACE(PARSE_LINE);+				if (mutex_lock_interruptible(+					&service->bulk_mutex) != 0) {+					DEBUG_TRACE(PARSE_LINE);+					goto bail_not_ready;+				}++				WARN_ON(!(queue->remote_insert < queue->remove ++					VCHIQ_NUM_SERVICE_BULKS));+				bulk = &queue->bulks[+					BULK_INDEX(queue->remote_insert)];+				bulk->remote_data =+					(void *)((int *)header->data)[0];+				bulk->remote_size = ((int *)header->data)[1];+				wmb();++				vchiq_log_info(vchiq_core_log_level,+					"%d: prs %s@%x (%d->%d) %x@%x",+					state->id, msg_type_str(type),+					(unsigned int)header,+					remoteport, localport,+					bulk->remote_size,+					(unsigned int)bulk->remote_data);++				queue->remote_insert++;++				if (atomic_read(&pause_bulks_count)) {+					state->deferred_bulks++;+					vchiq_log_info(vchiq_core_log_level,+						"%s: deferring bulk (%d)",+						__func__,+						state->deferred_bulks);+					if (state->conn_state !=+						VCHIQ_CONNSTATE_PAUSE_SENT)+						vchiq_log_error(+							vchiq_core_log_level,+							"%s: bulks paused in "+							"unexpected state %s",+							__func__,+							conn_state_names[+							state->conn_state]);+				} else if (state->conn_state ==+					VCHIQ_CONNSTATE_CONNECTED) {+					DEBUG_TRACE(PARSE_LINE);+					resolved = resolve_bulks(service,+						queue);+				}++				mutex_unlock(&service->bulk_mutex);+				if (resolved)+					notify_bulks(service, queue,+						1/*retry_poll*/);+			}+		} break;+		case VCHIQ_MSG_BULK_RX_DONE:+		case VCHIQ_MSG_BULK_TX_DONE:+			WARN_ON(state->is_master);+			if ((service->remoteport == remoteport)+				&& (service->srvstate !=+				VCHIQ_SRVSTATE_FREE)) {+				VCHIQ_BULK_QUEUE_T *queue;+				VCHIQ_BULK_T *bulk;++				queue = (type == VCHIQ_MSG_BULK_RX_DONE) ?+					&service->bulk_rx : &service->bulk_tx;++				DEBUG_TRACE(PARSE_LINE);+				if (mutex_lock_interruptible(+					&service->bulk_mutex) != 0) {+					DEBUG_TRACE(PARSE_LINE);+					goto bail_not_ready;+				}+				if ((int)(queue->remote_insert -+					queue->local_insert) >= 0) {+					vchiq_log_error(vchiq_core_log_level,+						"%d: prs %s@%x (%d->%d) "+						"unexpected (ri=%d,li=%d)",+						state->id, msg_type_str(type),+						(unsigned int)header,+						remoteport, localport,+						queue->remote_insert,+						queue->local_insert);+					mutex_unlock(&service->bulk_mutex);+					break;+				}++				BUG_ON(queue->process == queue->local_insert);+				BUG_ON(queue->process != queue->remote_insert);++				bulk = &queue->bulks[+					BULK_INDEX(queue->remote_insert)];+				bulk->actual = *(int *)header->data;+				queue->remote_insert++;++				vchiq_log_info(vchiq_core_log_level,+					"%d: prs %s@%x (%d->%d) %x@%x",+					state->id, msg_type_str(type),+					(unsigned int)header,+					remoteport, localport,+					bulk->actual, (unsigned int)bulk->data);++				vchiq_log_trace(vchiq_core_log_level,+					"%d: prs:%d %cx li=%x ri=%x p=%x",+					state->id, localport,+					(type == VCHIQ_MSG_BULK_RX_DONE) ?+						'r' : 't',+					queue->local_insert,+					queue->remote_insert, queue->process);++				DEBUG_TRACE(PARSE_LINE);+				WARN_ON(queue->process == queue->local_insert);+				vchiq_complete_bulk(bulk);+				queue->process++;+				mutex_unlock(&service->bulk_mutex);+				DEBUG_TRACE(PARSE_LINE);+				notify_bulks(service, queue, 1/*retry_poll*/);+				DEBUG_TRACE(PARSE_LINE);+			}+			break;+		case VCHIQ_MSG_PADDING:+			vchiq_log_trace(vchiq_core_log_level,+				"%d: prs PADDING@%x,%x",+				state->id, (unsigned int)header, size);+			break;+		case VCHIQ_MSG_PAUSE:+			/* If initiated, signal the application thread */+			vchiq_log_trace(vchiq_core_log_level,+				"%d: prs PAUSE@%x,%x",+				state->id, (unsigned int)header, size);+			if (state->conn_state == VCHIQ_CONNSTATE_PAUSED) {+				vchiq_log_error(vchiq_core_log_level,+					"%d: PAUSE received in state PAUSED",+					state->id);+				break;+			}+			if (state->conn_state != VCHIQ_CONNSTATE_PAUSE_SENT) {+				/* Send a PAUSE in response */+				if (queue_message(state, NULL,+					VCHIQ_MAKE_MSG(VCHIQ_MSG_PAUSE, 0, 0),+					NULL, 0, 0, 0) == VCHIQ_RETRY)+					goto bail_not_ready;+				if (state->is_master)+					pause_bulks(state);+			}+			/* At this point slot_mutex is held */+			vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSED);+			vchiq_platform_paused(state);+			break;+		case VCHIQ_MSG_RESUME:+			vchiq_log_trace(vchiq_core_log_level,+				"%d: prs RESUME@%x,%x",+				state->id, (unsigned int)header, size);+			/* Release the slot mutex */+			mutex_unlock(&state->slot_mutex);+			if (state->is_master)+				resume_bulks(state);+			vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED);+			vchiq_platform_resumed(state);+			break;++		case VCHIQ_MSG_REMOTE_USE:+			vchiq_on_remote_use(state);+			break;+		case VCHIQ_MSG_REMOTE_RELEASE:+			vchiq_on_remote_release(state);+			break;+		case VCHIQ_MSG_REMOTE_USE_ACTIVE:+			vchiq_on_remote_use_active(state);+			break;++		default:+			vchiq_log_error(vchiq_core_log_level,+				"%d: prs invalid msgid %x@%x,%x",+				state->id, msgid, (unsigned int)header, size);+			WARN(1, "invalid message\n");+			break;+		}++skip_message:+		if (service) {+			unlock_service(service);+			service = NULL;+		}++		state->rx_pos += calc_stride(size);++		DEBUG_TRACE(PARSE_LINE);+		/* Perform some housekeeping when the end of the slot is+		** reached. */+		if ((state->rx_pos & VCHIQ_SLOT_MASK) == 0) {+			/* Remove the extra reference count. */+			release_slot(state, state->rx_info, NULL, NULL);+			state->rx_data = NULL;+		}+	}++bail_not_ready:+	if (service)+		unlock_service(service);+}++/* Called by the slot handler thread */+static int+slot_handler_func(void *v)+{+	VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v;+	VCHIQ_SHARED_STATE_T *local = state->local;+	DEBUG_INITIALISE(local)++	while (1) {+		DEBUG_COUNT(SLOT_HANDLER_COUNT);+		DEBUG_TRACE(SLOT_HANDLER_LINE);+		remote_event_wait(&local->trigger);++		rmb();++		DEBUG_TRACE(SLOT_HANDLER_LINE);+		if (state->poll_needed) {+			/* Check if we need to suspend - may change our+			 * conn_state */+			vchiq_platform_check_suspend(state);++			state->poll_needed = 0;++			/* Handle service polling and other rare conditions here+			** out of the mainline code */+			switch (state->conn_state) {+			case VCHIQ_CONNSTATE_CONNECTED:+				/* Poll the services as requested */+				poll_services(state);+				break;++			case VCHIQ_CONNSTATE_PAUSING:+				if (state->is_master)+					pause_bulks(state);+				if (queue_message(state, NULL,+					VCHIQ_MAKE_MSG(VCHIQ_MSG_PAUSE, 0, 0),+					NULL, 0, 0, 0) != VCHIQ_RETRY) {+					vchiq_set_conn_state(state,+						VCHIQ_CONNSTATE_PAUSE_SENT);+				} else {+					if (state->is_master)+						resume_bulks(state);+					/* Retry later */+					state->poll_needed = 1;+				}+				break;++			case VCHIQ_CONNSTATE_PAUSED:+				vchiq_platform_resume(state);+				break;++			case VCHIQ_CONNSTATE_RESUMING:+				if (queue_message(state, NULL,+					VCHIQ_MAKE_MSG(VCHIQ_MSG_RESUME, 0, 0),+					NULL, 0, 0, 0) != VCHIQ_RETRY) {+					if (state->is_master)+						resume_bulks(state);+					vchiq_set_conn_state(state,+						VCHIQ_CONNSTATE_CONNECTED);+					vchiq_platform_resumed(state);+				} else {+					/* This should really be impossible,+					** since the PAUSE should have flushed+					** through outstanding messages. */+					vchiq_log_error(vchiq_core_log_level,+						"Failed to send RESUME "+						"message");+					BUG();+				}+				break;++			case VCHIQ_CONNSTATE_PAUSE_TIMEOUT:+			case VCHIQ_CONNSTATE_RESUME_TIMEOUT:+				vchiq_platform_handle_timeout(state);+				break;+			default:+				break;+			}+++		}++		DEBUG_TRACE(SLOT_HANDLER_LINE);+		parse_rx_slots(state);+	}+	return 0;+}+++/* Called by the recycle thread */+static int+recycle_func(void *v)+{+	VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v;+	VCHIQ_SHARED_STATE_T *local = state->local;++	while (1) {+		remote_event_wait(&local->recycle);++		process_free_queue(state);+	}+	return 0;+}+++/* Called by the sync thread */+static int+sync_func(void *v)+{+	VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v;+	VCHIQ_SHARED_STATE_T *local = state->local;+	VCHIQ_HEADER_T *header = (VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state,+		state->remote->slot_sync);++	while (1) {+		VCHIQ_SERVICE_T *service;+		int msgid, size;+		int type;+		unsigned int localport, remoteport;++		remote_event_wait(&local->sync_trigger);++		rmb();++		msgid = header->msgid;+		size = header->size;+		type = VCHIQ_MSG_TYPE(msgid);+		localport = VCHIQ_MSG_DSTPORT(msgid);+		remoteport = VCHIQ_MSG_SRCPORT(msgid);++		service = find_service_by_port(state, localport);++		if (!service) {+			vchiq_log_error(vchiq_sync_log_level,+				"%d: sf %s@%x (%d->%d) - "+				"invalid/closed service %d",+				state->id, msg_type_str(type),+				(unsigned int)header,+				remoteport, localport, localport);+			release_message_sync(state, header);+			continue;+		}++		if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE) {+			int svc_fourcc;++			svc_fourcc = service+				? service->base.fourcc+				: VCHIQ_MAKE_FOURCC('?', '?', '?', '?');+			vchiq_log_trace(vchiq_sync_log_level,+				"Rcvd Msg %s from %c%c%c%c s:%d d:%d len:%d",+				msg_type_str(type),+				VCHIQ_FOURCC_AS_4CHARS(svc_fourcc),+				remoteport, localport, size);+			if (size > 0)+				vchiq_log_dump_mem("Rcvd", 0, header->data,+					min(64, size));+		}++		switch (type) {+		case VCHIQ_MSG_OPENACK:+			if (size >= sizeof(struct vchiq_openack_payload)) {+				const struct vchiq_openack_payload *payload =+					(struct vchiq_openack_payload *)+					header->data;+				service->peer_version = payload->version;+			}+			vchiq_log_info(vchiq_sync_log_level,+				"%d: sf OPENACK@%x,%x (%d->%d) v:%d",+				state->id, (unsigned int)header, size,+				remoteport, localport, service->peer_version);+			if (service->srvstate == VCHIQ_SRVSTATE_OPENING) {+				service->remoteport = remoteport;+				vchiq_set_service_state(service,+					VCHIQ_SRVSTATE_OPENSYNC);+				up(&service->remove_event);+			}+			release_message_sync(state, header);+			break;++		case VCHIQ_MSG_DATA:+			vchiq_log_trace(vchiq_sync_log_level,+				"%d: sf DATA@%x,%x (%d->%d)",+				state->id, (unsigned int)header, size,+				remoteport, localport);++			if ((service->remoteport == remoteport) &&+				(service->srvstate ==+				VCHIQ_SRVSTATE_OPENSYNC)) {+				if (make_service_callback(service,+					VCHIQ_MESSAGE_AVAILABLE, header,+					NULL) == VCHIQ_RETRY)+					vchiq_log_error(vchiq_sync_log_level,+						"synchronous callback to "+						"service %d returns "+						"VCHIQ_RETRY",+						localport);+			}+			break;++		default:+			vchiq_log_error(vchiq_sync_log_level,+				"%d: sf unexpected msgid %x@%x,%x",+				state->id, msgid, (unsigned int)header, size);+			release_message_sync(state, header);+			break;+		}++		unlock_service(service);+	}++	return 0;+}+++static void+init_bulk_queue(VCHIQ_BULK_QUEUE_T *queue)+{+	queue->local_insert = 0;+	queue->remote_insert = 0;+	queue->process = 0;+	queue->remote_notify = 0;+	queue->remove = 0;+}+++inline const char *+get_conn_state_name(VCHIQ_CONNSTATE_T conn_state)+{+	return conn_state_names[conn_state];+}+++VCHIQ_SLOT_ZERO_T *+vchiq_init_slots(void *mem_base, int mem_size)+{+	int mem_align = (VCHIQ_SLOT_SIZE - (int)mem_base) & VCHIQ_SLOT_MASK;+	VCHIQ_SLOT_ZERO_T *slot_zero =+		(VCHIQ_SLOT_ZERO_T *)((char *)mem_base + mem_align);+	int num_slots = (mem_size - mem_align)/VCHIQ_SLOT_SIZE;+	int first_data_slot = VCHIQ_SLOT_ZERO_SLOTS;++	/* Ensure there is enough memory to run an absolutely minimum system */+	num_slots -= first_data_slot;++	if (num_slots < 4) {+		vchiq_log_error(vchiq_core_log_level,+			"vchiq_init_slots - insufficient memory %x bytes",+			mem_size);+		return NULL;+	}++	memset(slot_zero, 0, sizeof(VCHIQ_SLOT_ZERO_T));++	slot_zero->magic = VCHIQ_MAGIC;+	slot_zero->version = VCHIQ_VERSION;+	slot_zero->version_min = VCHIQ_VERSION_MIN;+	slot_zero->slot_zero_size = sizeof(VCHIQ_SLOT_ZERO_T);+	slot_zero->slot_size = VCHIQ_SLOT_SIZE;+	slot_zero->max_slots = VCHIQ_MAX_SLOTS;+	slot_zero->max_slots_per_side = VCHIQ_MAX_SLOTS_PER_SIDE;++	slot_zero->master.slot_sync = first_data_slot;+	slot_zero->master.slot_first = first_data_slot + 1;+	slot_zero->master.slot_last = first_data_slot + (num_slots/2) - 1;+	slot_zero->slave.slot_sync = first_data_slot + (num_slots/2);+	slot_zero->slave.slot_first = first_data_slot + (num_slots/2) + 1;+	slot_zero->slave.slot_last = first_data_slot + num_slots - 1;++	return slot_zero;+}++VCHIQ_STATUS_T+vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero,+		 int is_master)+{+	VCHIQ_SHARED_STATE_T *local;+	VCHIQ_SHARED_STATE_T *remote;+	VCHIQ_STATUS_T status;+	char threadname[10];+	static int id;+	int i;++	vchiq_log_warning(vchiq_core_log_level,+		"%s: slot_zero = 0x%08lx, is_master = %d",+		__func__, (unsigned long)slot_zero, is_master);++	/* Check the input configuration */++	if (slot_zero->magic != VCHIQ_MAGIC) {+		vchiq_loud_error_header();+		vchiq_loud_error("Invalid VCHIQ magic value found.");+		vchiq_loud_error("slot_zero=%x: magic=%x (expected %x)",+			(unsigned int)slot_zero, slot_zero->magic, VCHIQ_MAGIC);+		vchiq_loud_error_footer();+		return VCHIQ_ERROR;+	}++	if (slot_zero->version < VCHIQ_VERSION_MIN) {+		vchiq_loud_error_header();+		vchiq_loud_error("Incompatible VCHIQ versions found.");+		vchiq_loud_error("slot_zero=%x: VideoCore version=%d "+			"(minimum %d)",+			(unsigned int)slot_zero, slot_zero->version,+			VCHIQ_VERSION_MIN);+		vchiq_loud_error("Restart with a newer VideoCore image.");+		vchiq_loud_error_footer();+		return VCHIQ_ERROR;+	}++	if (VCHIQ_VERSION < slot_zero->version_min) {+		vchiq_loud_error_header();+		vchiq_loud_error("Incompatible VCHIQ versions found.");+		vchiq_loud_error("slot_zero=%x: version=%d (VideoCore "+			"minimum %d)",+			(unsigned int)slot_zero, VCHIQ_VERSION,+			slot_zero->version_min);+		vchiq_loud_error("Restart with a newer kernel.");+		vchiq_loud_error_footer();+		return VCHIQ_ERROR;+	}++	if ((slot_zero->slot_zero_size != sizeof(VCHIQ_SLOT_ZERO_T)) ||+		 (slot_zero->slot_size != VCHIQ_SLOT_SIZE) ||+		 (slot_zero->max_slots != VCHIQ_MAX_SLOTS) ||+		 (slot_zero->max_slots_per_side != VCHIQ_MAX_SLOTS_PER_SIDE)) {+		vchiq_loud_error_header();+		if (slot_zero->slot_zero_size != sizeof(VCHIQ_SLOT_ZERO_T))+			vchiq_loud_error("slot_zero=%x: slot_zero_size=%x "+				"(expected %x)",+				(unsigned int)slot_zero,+				slot_zero->slot_zero_size,+				sizeof(VCHIQ_SLOT_ZERO_T));+		if (slot_zero->slot_size != VCHIQ_SLOT_SIZE)+			vchiq_loud_error("slot_zero=%x: slot_size=%d "+				"(expected %d",+				(unsigned int)slot_zero, slot_zero->slot_size,+				VCHIQ_SLOT_SIZE);+		if (slot_zero->max_slots != VCHIQ_MAX_SLOTS)+			vchiq_loud_error("slot_zero=%x: max_slots=%d "+				"(expected %d)",+				(unsigned int)slot_zero, slot_zero->max_slots,+				VCHIQ_MAX_SLOTS);+		if (slot_zero->max_slots_per_side != VCHIQ_MAX_SLOTS_PER_SIDE)+			vchiq_loud_error("slot_zero=%x: max_slots_per_side=%d "+				"(expected %d)",+				(unsigned int)slot_zero,+				slot_zero->max_slots_per_side,+				VCHIQ_MAX_SLOTS_PER_SIDE);+		vchiq_loud_error_footer();+		return VCHIQ_ERROR;+	}++	if (is_master) {+		local = &slot_zero->master;+		remote = &slot_zero->slave;+	} else {+		local = &slot_zero->slave;+		remote = &slot_zero->master;+	}++	if (local->initialised) {+		vchiq_loud_error_header();+		if (remote->initialised)+			vchiq_loud_error("local state has already been "+				"initialised");+		else+			vchiq_loud_error("master/slave mismatch - two %ss",+				is_master ? "master" : "slave");+		vchiq_loud_error_footer();+		return VCHIQ_ERROR;+	}++	memset(state, 0, sizeof(VCHIQ_STATE_T));++	state->id = id++;+	state->is_master = is_master;++	/*+		initialize shared state pointers+	 */++	state->local = local;+	state->remote = remote;+	state->slot_data = (VCHIQ_SLOT_T *)slot_zero;++	/*+		initialize events and mutexes+	 */++	sema_init(&state->connect, 0);+	mutex_init(&state->mutex);+	sema_init(&state->trigger_event, 0);+	sema_init(&state->recycle_event, 0);+	sema_init(&state->sync_trigger_event, 0);+	sema_init(&state->sync_release_event, 0);++	mutex_init(&state->slot_mutex);+	mutex_init(&state->recycle_mutex);+	mutex_init(&state->sync_mutex);+	mutex_init(&state->bulk_transfer_mutex);++	sema_init(&state->slot_available_event, 0);+	sema_init(&state->slot_remove_event, 0);+	sema_init(&state->data_quota_event, 0);++	state->slot_queue_available = 0;++	for (i = 0; i < VCHIQ_MAX_SERVICES; i++) {+		VCHIQ_SERVICE_QUOTA_T *service_quota =+			&state->service_quotas[i];+		sema_init(&service_quota->quota_event, 0);+	}++	for (i = local->slot_first; i <= local->slot_last; i++) {+		local->slot_queue[state->slot_queue_available++] = i;+		up(&state->slot_available_event);+	}++	state->default_slot_quota = state->slot_queue_available/2;+	state->default_message_quota =+		min((unsigned short)(state->default_slot_quota * 256),+		(unsigned short)~0);++	state->previous_data_index = -1;+	state->data_use_count = 0;+	state->data_quota = state->slot_queue_available - 1;++	local->trigger.event = &state->trigger_event;+	remote_event_create(&local->trigger);+	local->tx_pos = 0;++	local->recycle.event = &state->recycle_event;+	remote_event_create(&local->recycle);+	local->slot_queue_recycle = state->slot_queue_available;++	local->sync_trigger.event = &state->sync_trigger_event;+	remote_event_create(&local->sync_trigger);++	local->sync_release.event = &state->sync_release_event;+	remote_event_create(&local->sync_release);++	/* At start-of-day, the slot is empty and available */+	((VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, local->slot_sync))->msgid+		= VCHIQ_MSGID_PADDING;+	remote_event_signal_local(&local->sync_release);++	local->debug[DEBUG_ENTRIES] = DEBUG_MAX;++	status = vchiq_platform_init_state(state);++	/*+		bring up slot handler thread+	 */+	snprintf(threadname, sizeof(threadname), "VCHIQ-%d", state->id);+	state->slot_handler_thread = kthread_create(&slot_handler_func,+		(void *)state,+		threadname);++	if (state->slot_handler_thread == NULL) {+		vchiq_loud_error_header();+		vchiq_loud_error("couldn't create thread %s", threadname);+		vchiq_loud_error_footer();+		return VCHIQ_ERROR;+	}+	set_user_nice(state->slot_handler_thread, -19);+	wake_up_process(state->slot_handler_thread);++	snprintf(threadname, sizeof(threadname), "VCHIQr-%d", state->id);+	state->recycle_thread = kthread_create(&recycle_func,+		(void *)state,+		threadname);+	if (state->recycle_thread == NULL) {+		vchiq_loud_error_header();+		vchiq_loud_error("couldn't create thread %s", threadname);+		vchiq_loud_error_footer();+		return VCHIQ_ERROR;+	}+	set_user_nice(state->recycle_thread, -19);+	wake_up_process(state->recycle_thread);++	snprintf(threadname, sizeof(threadname), "VCHIQs-%d", state->id);+	state->sync_thread = kthread_create(&sync_func,+		(void *)state,+		threadname);+	if (state->sync_thread == NULL) {+		vchiq_loud_error_header();+		vchiq_loud_error("couldn't create thread %s", threadname);+		vchiq_loud_error_footer();+		return VCHIQ_ERROR;+	}+	set_user_nice(state->sync_thread, -20);+	wake_up_process(state->sync_thread);++	BUG_ON(state->id >= VCHIQ_MAX_STATES);+	vchiq_states[state->id] = state;++	/* Indicate readiness to the other side */+	local->initialised = 1;++	return status;+}++/* Called from application thread when a client or server service is created. */+VCHIQ_SERVICE_T *+vchiq_add_service_internal(VCHIQ_STATE_T *state,+	const VCHIQ_SERVICE_PARAMS_T *params, int srvstate,+	VCHIQ_INSTANCE_T instance, VCHIQ_USERDATA_TERM_T userdata_term)+{+	VCHIQ_SERVICE_T *service;++	service = kmalloc(sizeof(VCHIQ_SERVICE_T), GFP_KERNEL);+	if (service) {+		service->base.fourcc   = params->fourcc;+		service->base.callback = params->callback;+		service->base.userdata = params->userdata;+		service->handle        = VCHIQ_SERVICE_HANDLE_INVALID;+		service->ref_count     = 1;+		service->srvstate      = VCHIQ_SRVSTATE_FREE;+		service->userdata_term = userdata_term;+		service->localport     = VCHIQ_PORT_FREE;+		service->remoteport    = VCHIQ_PORT_FREE;++		service->public_fourcc = (srvstate == VCHIQ_SRVSTATE_OPENING) ?+			VCHIQ_FOURCC_INVALID : params->fourcc;+		service->client_id     = 0;+		service->auto_close    = 1;+		service->sync          = 0;+		service->closing       = 0;+		atomic_set(&service->poll_flags, 0);+		service->version       = params->version;+		service->version_min   = params->version_min;+		service->state         = state;+		service->instance      = instance;+		service->service_use_count = 0;+		init_bulk_queue(&service->bulk_tx);+		init_bulk_queue(&service->bulk_rx);+		sema_init(&service->remove_event, 0);+		sema_init(&service->bulk_remove_event, 0);+		mutex_init(&service->bulk_mutex);+		memset(&service->stats, 0, sizeof(service->stats));+	} else {+		vchiq_log_error(vchiq_core_log_level,+			"Out of memory");+	}++	if (service) {+		VCHIQ_SERVICE_T **pservice = NULL;+		int i;++		/* Although it is perfectly possible to use service_spinlock+		** to protect the creation of services, it is overkill as it+		** disables interrupts while the array is searched.+		** The only danger is of another thread trying to create a+		** service - service deletion is safe.+		** Therefore it is preferable to use state->mutex which,+		** although slower to claim, doesn't block interrupts while+		** it is held.+		*/++		mutex_lock(&state->mutex);++		/* Prepare to use a previously unused service */+		if (state->unused_service < VCHIQ_MAX_SERVICES)+			pservice = &state->services[state->unused_service];++		if (srvstate == VCHIQ_SRVSTATE_OPENING) {+			for (i = 0; i < state->unused_service; i++) {+				VCHIQ_SERVICE_T *srv = state->services[i];+				if (!srv) {+					pservice = &state->services[i];+					break;+				}+			}+		} else {+			for (i = (state->unused_service - 1); i >= 0; i--) {+				VCHIQ_SERVICE_T *srv = state->services[i];+				if (!srv)+					pservice = &state->services[i];+				else if ((srv->public_fourcc == params->fourcc)+					&& ((srv->instance != instance) ||+					(srv->base.callback !=+					params->callback))) {+					/* There is another server using this+					** fourcc which doesn't match. */+					pservice = NULL;+					break;+				}+			}+		}++		if (pservice) {+			service->localport = (pservice - state->services);+			if (!handle_seq)+				handle_seq = VCHIQ_MAX_STATES *+					 VCHIQ_MAX_SERVICES;+			service->handle = handle_seq |+				(state->id * VCHIQ_MAX_SERVICES) |+				service->localport;+			handle_seq += VCHIQ_MAX_STATES * VCHIQ_MAX_SERVICES;+			*pservice = service;+			if (pservice == &state->services[state->unused_service])+				state->unused_service++;+		}++		mutex_unlock(&state->mutex);++		if (!pservice) {+			kfree(service);+			service = NULL;+		}+	}++	if (service) {+		VCHIQ_SERVICE_QUOTA_T *service_quota =+			&state->service_quotas[service->localport];+		service_quota->slot_quota = state->default_slot_quota;+		service_quota->message_quota = state->default_message_quota;+		if (service_quota->slot_use_count == 0)+			service_quota->previous_tx_index =+				SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos)+				- 1;++		/* Bring this service online */+		vchiq_set_service_state(service, srvstate);++		vchiq_log_info(vchiq_core_msg_log_level,+			"%s Service %c%c%c%c SrcPort:%d",+			(srvstate == VCHIQ_SRVSTATE_OPENING)+			? "Open" : "Add",+			VCHIQ_FOURCC_AS_4CHARS(params->fourcc),+			service->localport);+	}++	/* Don't unlock the service - leave it with a ref_count of 1. */++	return service;+}++VCHIQ_STATUS_T+vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id)+{+	struct vchiq_open_payload payload = {+		service->base.fourcc,+		client_id,+		service->version,+		service->version_min+	};+	VCHIQ_ELEMENT_T body = { &payload, sizeof(payload) };+	VCHIQ_STATUS_T status = VCHIQ_SUCCESS;++	service->client_id = client_id;+	vchiq_use_service_internal(service);+	status = queue_message(service->state, NULL,+		VCHIQ_MAKE_MSG(VCHIQ_MSG_OPEN, service->localport, 0),+		&body, 1, sizeof(payload), 1);+	if (status == VCHIQ_SUCCESS) {+		if (down_interruptible(&service->remove_event) != 0) {+			status = VCHIQ_RETRY;+			vchiq_release_service_internal(service);+		} else if ((service->srvstate != VCHIQ_SRVSTATE_OPEN) &&+			(service->srvstate != VCHIQ_SRVSTATE_OPENSYNC)) {+			if (service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT)+				vchiq_log_error(vchiq_core_log_level,+					"%d: osi - srvstate = %s (ref %d)",+					service->state->id,+					srvstate_names[service->srvstate],+					service->ref_count);+			status = VCHIQ_ERROR;+			VCHIQ_SERVICE_STATS_INC(service, error_count);+			vchiq_release_service_internal(service);+		}+	}+	return status;+}++static void+release_service_messages(VCHIQ_SERVICE_T *service)+{+	VCHIQ_STATE_T *state = service->state;+	int slot_last = state->remote->slot_last;+	int i;++	/* Release any claimed messages */+	for (i = state->remote->slot_first; i <= slot_last; i++) {+		VCHIQ_SLOT_INFO_T *slot_info =+			SLOT_INFO_FROM_INDEX(state, i);+		if (slot_info->release_count != slot_info->use_count) {+			char *data =+				(char *)SLOT_DATA_FROM_INDEX(state, i);+			unsigned int pos, end;++			end = VCHIQ_SLOT_SIZE;+			if (data == state->rx_data)+				/* This buffer is still being read from - stop+				** at the current read position */+				end = state->rx_pos & VCHIQ_SLOT_MASK;++			pos = 0;++			while (pos < end) {+				VCHIQ_HEADER_T *header =+					(VCHIQ_HEADER_T *)(data + pos);+				int msgid = header->msgid;+				int port = VCHIQ_MSG_DSTPORT(msgid);+				if ((port == service->localport) &&+					(msgid & VCHIQ_MSGID_CLAIMED)) {+					vchiq_log_info(vchiq_core_log_level,+						"  fsi - hdr %x",+						(unsigned int)header);+					release_slot(state, slot_info, header,+						NULL);+				}+				pos += calc_stride(header->size);+				if (pos > VCHIQ_SLOT_SIZE) {+					vchiq_log_error(vchiq_core_log_level,+						"fsi - pos %x: header %x, "+						"msgid %x, header->msgid %x, "+						"header->size %x",+						pos, (unsigned int)header,+						msgid, header->msgid,+						header->size);+					WARN(1, "invalid slot position\n");+				}+			}+		}+	}+}++static int+do_abort_bulks(VCHIQ_SERVICE_T *service)+{+	VCHIQ_STATUS_T status;++	/* Abort any outstanding bulk transfers */+	if (mutex_lock_interruptible(&service->bulk_mutex) != 0)+		return 0;+	abort_outstanding_bulks(service, &service->bulk_tx);+	abort_outstanding_bulks(service, &service->bulk_rx);+	mutex_unlock(&service->bulk_mutex);++	status = notify_bulks(service, &service->bulk_tx, 0/*!retry_poll*/);+	if (status == VCHIQ_SUCCESS)+		status = notify_bulks(service, &service->bulk_rx,+			0/*!retry_poll*/);+	return (status == VCHIQ_SUCCESS);+}++static VCHIQ_STATUS_T+close_service_complete(VCHIQ_SERVICE_T *service, int failstate)+{+	VCHIQ_STATUS_T status;+	int is_server = (service->public_fourcc != VCHIQ_FOURCC_INVALID);+	int newstate;++	switch (service->srvstate) {+	case VCHIQ_SRVSTATE_OPEN:+	case VCHIQ_SRVSTATE_CLOSESENT:+	case VCHIQ_SRVSTATE_CLOSERECVD:+		if (is_server) {+			if (service->auto_close) {+				service->client_id = 0;+				service->remoteport = VCHIQ_PORT_FREE;+				newstate = VCHIQ_SRVSTATE_LISTENING;+			} else+				newstate = VCHIQ_SRVSTATE_CLOSEWAIT;+		} else+			newstate = VCHIQ_SRVSTATE_CLOSED;+		vchiq_set_service_state(service, newstate);+		break;+	case VCHIQ_SRVSTATE_LISTENING:+		break;+	default:+		vchiq_log_error(vchiq_core_log_level,+			"close_service_complete(%x) called in state %s",+			service->handle, srvstate_names[service->srvstate]);+		WARN(1, "close_service_complete in unexpected state\n");+		return VCHIQ_ERROR;+	}++	status = make_service_callback(service,+		VCHIQ_SERVICE_CLOSED, NULL, NULL);++	if (status != VCHIQ_RETRY) {+		int uc = service->service_use_count;+		int i;+		/* Complete the close process */+		for (i = 0; i < uc; i++)+			/* cater for cases where close is forced and the+			** client may not close all it's handles */+			vchiq_release_service_internal(service);++		service->client_id = 0;+		service->remoteport = VCHIQ_PORT_FREE;++		if (service->srvstate == VCHIQ_SRVSTATE_CLOSED)+			vchiq_free_service_internal(service);+		else if (service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT) {+			if (is_server)+				service->closing = 0;++			up(&service->remove_event);+		}+	} else+		vchiq_set_service_state(service, failstate);++	return status;+}++/* Called by the slot handler */+VCHIQ_STATUS_T+vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd)+{+	VCHIQ_STATE_T *state = service->state;+	VCHIQ_STATUS_T status = VCHIQ_SUCCESS;+	int is_server = (service->public_fourcc != VCHIQ_FOURCC_INVALID);++	vchiq_log_info(vchiq_core_log_level, "%d: csi:%d,%d (%s)",+		service->state->id, service->localport, close_recvd,+		srvstate_names[service->srvstate]);++	switch (service->srvstate) {+	case VCHIQ_SRVSTATE_CLOSED:+	case VCHIQ_SRVSTATE_HIDDEN:+	case VCHIQ_SRVSTATE_LISTENING:+	case VCHIQ_SRVSTATE_CLOSEWAIT:+		if (close_recvd)+			vchiq_log_error(vchiq_core_log_level,+				"vchiq_close_service_internal(1) called "+				"in state %s",+				srvstate_names[service->srvstate]);+		else if (is_server) {+			if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) {+				status = VCHIQ_ERROR;+			} else {+				service->client_id = 0;+				service->remoteport = VCHIQ_PORT_FREE;+				if (service->srvstate ==+					VCHIQ_SRVSTATE_CLOSEWAIT)+					vchiq_set_service_state(service,+						VCHIQ_SRVSTATE_LISTENING);+			}+			up(&service->remove_event);+		} else+			vchiq_free_service_internal(service);+		break;+	case VCHIQ_SRVSTATE_OPENING:+		if (close_recvd) {+			/* The open was rejected - tell the user */+			vchiq_set_service_state(service,+				VCHIQ_SRVSTATE_CLOSEWAIT);+			up(&service->remove_event);+		} else {+			/* Shutdown mid-open - let the other side know */+			status = queue_message(state, service,+				VCHIQ_MAKE_MSG+				(VCHIQ_MSG_CLOSE,+				service->localport,+				VCHIQ_MSG_DSTPORT(service->remoteport)),+				NULL, 0, 0, 0);+		}+		break;++	case VCHIQ_SRVSTATE_OPENSYNC:+		mutex_lock(&state->sync_mutex);+		/* Drop through */++	case VCHIQ_SRVSTATE_OPEN:+		if (state->is_master || close_recvd) {+			if (!do_abort_bulks(service))+				status = VCHIQ_RETRY;+		}++		release_service_messages(service);++		if (status == VCHIQ_SUCCESS)+			status = queue_message(state, service,+				VCHIQ_MAKE_MSG+				(VCHIQ_MSG_CLOSE,+				service->localport,+				VCHIQ_MSG_DSTPORT(service->remoteport)),+				NULL, 0, 0, 0);++		if (status == VCHIQ_SUCCESS) {+			if (!close_recvd)+				break;+		} else if (service->srvstate == VCHIQ_SRVSTATE_OPENSYNC) {+			mutex_unlock(&state->sync_mutex);+			break;+		} else+			break;++		status = close_service_complete(service,+				VCHIQ_SRVSTATE_CLOSERECVD);+		break;++	case VCHIQ_SRVSTATE_CLOSESENT:+		if (!close_recvd)+			/* This happens when a process is killed mid-close */+			break;++		if (!state->is_master) {+			if (!do_abort_bulks(service)) {+				status = VCHIQ_RETRY;+				break;+			}+		}++		if (status == VCHIQ_SUCCESS)+			status = close_service_complete(service,+				VCHIQ_SRVSTATE_CLOSERECVD);+		break;++	case VCHIQ_SRVSTATE_CLOSERECVD:+		if (!close_recvd && is_server)+			/* Force into LISTENING mode */+			vchiq_set_service_state(service,+				VCHIQ_SRVSTATE_LISTENING);+		status = close_service_complete(service,+			VCHIQ_SRVSTATE_CLOSERECVD);+		break;++	default:+		vchiq_log_error(vchiq_core_log_level,+			"vchiq_close_service_internal(%d) called in state %s",+			close_recvd, srvstate_names[service->srvstate]);+		break;+	}++	return status;+}++/* Called from the application process upon process death */+void+vchiq_terminate_service_internal(VCHIQ_SERVICE_T *service)+{+	VCHIQ_STATE_T *state = service->state;++	vchiq_log_info(vchiq_core_log_level, "%d: tsi - (%d<->%d)",+		state->id, service->localport, service->remoteport);++	mark_service_closing(service);++	/* Mark the service for removal by the slot handler */+	request_poll(state, service, VCHIQ_POLL_REMOVE);+}++/* Called from the slot handler */+void+vchiq_free_service_internal(VCHIQ_SERVICE_T *service)+{+	VCHIQ_STATE_T *state = service->state;++	vchiq_log_info(vchiq_core_log_level, "%d: fsi - (%d)",+		state->id, service->localport);++	switch (service->srvstate) {+	case VCHIQ_SRVSTATE_OPENING:+	case VCHIQ_SRVSTATE_CLOSED:+	case VCHIQ_SRVSTATE_HIDDEN:+	case VCHIQ_SRVSTATE_LISTENING:+	case VCHIQ_SRVSTATE_CLOSEWAIT:+		break;+	default:+		vchiq_log_error(vchiq_core_log_level,+			"%d: fsi - (%d) in state %s",+			state->id, service->localport,+			srvstate_names[service->srvstate]);+		return;+	}++	vchiq_set_service_state(service, VCHIQ_SRVSTATE_FREE);++	up(&service->remove_event);++	/* Release the initial lock */+	unlock_service(service);+}++VCHIQ_STATUS_T+vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance)+{+	VCHIQ_SERVICE_T *service;+	int i;++	/* Find all services registered to this client and enable them. */+	i = 0;+	while ((service = next_service_by_instance(state, instance,+		&i)) !=	NULL) {+		if (service->srvstate == VCHIQ_SRVSTATE_HIDDEN)+			vchiq_set_service_state(service,+				VCHIQ_SRVSTATE_LISTENING);+		unlock_service(service);+	}++	if (state->conn_state == VCHIQ_CONNSTATE_DISCONNECTED) {+		if (queue_message(state, NULL,+			VCHIQ_MAKE_MSG(VCHIQ_MSG_CONNECT, 0, 0), NULL, 0,+			0, 1) == VCHIQ_RETRY)+			return VCHIQ_RETRY;++		vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTING);+	}++	if (state->conn_state == VCHIQ_CONNSTATE_CONNECTING) {+		if (down_interruptible(&state->connect) != 0)+			return VCHIQ_RETRY;++		vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED);+		up(&state->connect);+	}++	return VCHIQ_SUCCESS;+}++VCHIQ_STATUS_T+vchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance)+{+	VCHIQ_SERVICE_T *service;+	int i;++	/* Find all services registered to this client and enable them. */+	i = 0;+	while ((service = next_service_by_instance(state, instance,+		&i)) !=	NULL) {+		(void)vchiq_remove_service(service->handle);+		unlock_service(service);+	}++	return VCHIQ_SUCCESS;+}++VCHIQ_STATUS_T+vchiq_pause_internal(VCHIQ_STATE_T *state)+{+	VCHIQ_STATUS_T status = VCHIQ_SUCCESS;++	switch (state->conn_state) {+	case VCHIQ_CONNSTATE_CONNECTED:+		/* Request a pause */+		vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSING);+		request_poll(state, NULL, 0);+		break;+	default:+		vchiq_log_error(vchiq_core_log_level,+			"vchiq_pause_internal in state %s\n",+			conn_state_names[state->conn_state]);+		status = VCHIQ_ERROR;+		VCHIQ_STATS_INC(state, error_count);+		break;+	}++	return status;+}++VCHIQ_STATUS_T+vchiq_resume_internal(VCHIQ_STATE_T *state)+{+	VCHIQ_STATUS_T status = VCHIQ_SUCCESS;++	if (state->conn_state == VCHIQ_CONNSTATE_PAUSED) {+		vchiq_set_conn_state(state, VCHIQ_CONNSTATE_RESUMING);+		request_poll(state, NULL, 0);+	} else {+		status = VCHIQ_ERROR;+		VCHIQ_STATS_INC(state, error_count);+	}++	return status;+}++VCHIQ_STATUS_T+vchiq_close_service(VCHIQ_SERVICE_HANDLE_T handle)+{+	/* Unregister the service */+	VCHIQ_SERVICE_T *service = find_service_by_handle(handle);+	VCHIQ_STATUS_T status = VCHIQ_SUCCESS;++	if (!service)+		return VCHIQ_ERROR;++	vchiq_log_info(vchiq_core_log_level,+		"%d: close_service:%d",+		service->state->id, service->localport);++	if ((service->srvstate == VCHIQ_SRVSTATE_FREE) ||+		(service->srvstate == VCHIQ_SRVSTATE_LISTENING) ||+		(service->srvstate == VCHIQ_SRVSTATE_HIDDEN)) {+		unlock_service(service);+		return VCHIQ_ERROR;+	}++	mark_service_closing(service);++	if (current == service->state->slot_handler_thread) {+		status = vchiq_close_service_internal(service,+			0/*!close_recvd*/);+		BUG_ON(status == VCHIQ_RETRY);+	} else {+	/* Mark the service for termination by the slot handler */+		request_poll(service->state, service, VCHIQ_POLL_TERMINATE);+	}++	while (1) {+		if (down_interruptible(&service->remove_event) != 0) {+			status = VCHIQ_RETRY;+			break;+		}++		if ((service->srvstate == VCHIQ_SRVSTATE_FREE) ||+			(service->srvstate == VCHIQ_SRVSTATE_LISTENING) ||+			(service->srvstate == VCHIQ_SRVSTATE_OPEN))+			break;++		vchiq_log_warning(vchiq_core_log_level,+			"%d: close_service:%d - waiting in state %s",+			service->state->id, service->localport,+			srvstate_names[service->srvstate]);+	}++	if ((status == VCHIQ_SUCCESS) &&+		(service->srvstate != VCHIQ_SRVSTATE_FREE) &&+		(service->srvstate != VCHIQ_SRVSTATE_LISTENING))+		status = VCHIQ_ERROR;++	unlock_service(service);++	return status;+}++VCHIQ_STATUS_T+vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T handle)+{+	/* Unregister the service */+	VCHIQ_SERVICE_T *service = find_service_by_handle(handle);+	VCHIQ_STATUS_T status = VCHIQ_SUCCESS;++	if (!service)+		return VCHIQ_ERROR;++	vchiq_log_info(vchiq_core_log_level,+		"%d: remove_service:%d",+		service->state->id, service->localport);++	if (service->srvstate == VCHIQ_SRVSTATE_FREE) {+		unlock_service(service);+		return VCHIQ_ERROR;+	}++	mark_service_closing(service);++	if ((service->srvstate == VCHIQ_SRVSTATE_HIDDEN) ||+		(current == service->state->slot_handler_thread)) {+		/* Make it look like a client, because it must be removed and+		   not left in the LISTENING state. */+		service->public_fourcc = VCHIQ_FOURCC_INVALID;++		status = vchiq_close_service_internal(service,+			0/*!close_recvd*/);+		BUG_ON(status == VCHIQ_RETRY);+	} else {+		/* Mark the service for removal by the slot handler */+		request_poll(service->state, service, VCHIQ_POLL_REMOVE);+	}+	while (1) {+		if (down_interruptible(&service->remove_event) != 0) {+			status = VCHIQ_RETRY;+			break;+		}++		if ((service->srvstate == VCHIQ_SRVSTATE_FREE) ||+			(service->srvstate == VCHIQ_SRVSTATE_OPEN))+			break;++		vchiq_log_warning(vchiq_core_log_level,+			"%d: remove_service:%d - waiting in state %s",+			service->state->id, service->localport,+			srvstate_names[service->srvstate]);+	}++	if ((status == VCHIQ_SUCCESS) &&+		(service->srvstate != VCHIQ_SRVSTATE_FREE))+		status = VCHIQ_ERROR;++	unlock_service(service);++	return status;+}+++/* This function may be called by kernel threads or user threads.+ * User threads may receive VCHIQ_RETRY to indicate that a signal has been+ * received and the call should be retried after being returned to user+ * context.+ * When called in blocking mode, the userdata field points to a bulk_waiter+ * structure.+ */+VCHIQ_STATUS_T+vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle,+	VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata,+	VCHIQ_BULK_MODE_T mode, VCHIQ_BULK_DIR_T dir)+{+	VCHIQ_SERVICE_T *service = find_service_by_handle(handle);+	VCHIQ_BULK_QUEUE_T *queue;+	VCHIQ_BULK_T *bulk;+	VCHIQ_STATE_T *state;+	struct bulk_waiter *bulk_waiter = NULL;+	const char dir_char = (dir == VCHIQ_BULK_TRANSMIT) ? 't' : 'r';+	const int dir_msgtype = (dir == VCHIQ_BULK_TRANSMIT) ?+		VCHIQ_MSG_BULK_TX : VCHIQ_MSG_BULK_RX;+	VCHIQ_STATUS_T status = VCHIQ_ERROR;++	if (!service ||+		 (service->srvstate != VCHIQ_SRVSTATE_OPEN) ||+		 ((memhandle == VCHI_MEM_HANDLE_INVALID) && (offset == NULL)) ||+		 (vchiq_check_service(service) != VCHIQ_SUCCESS))+		goto error_exit;++	switch (mode) {+	case VCHIQ_BULK_MODE_NOCALLBACK:+	case VCHIQ_BULK_MODE_CALLBACK:+		break;+	case VCHIQ_BULK_MODE_BLOCKING:+		bulk_waiter = (struct bulk_waiter *)userdata;+		sema_init(&bulk_waiter->event, 0);+		bulk_waiter->actual = 0;+		bulk_waiter->bulk = NULL;+		break;+	case VCHIQ_BULK_MODE_WAITING:+		bulk_waiter = (struct bulk_waiter *)userdata;+		bulk = bulk_waiter->bulk;+		goto waiting;+	default:+		goto error_exit;+	}++	state = service->state;++	queue = (dir == VCHIQ_BULK_TRANSMIT) ?+		&service->bulk_tx : &service->bulk_rx;++	if (mutex_lock_interruptible(&service->bulk_mutex) != 0) {+		status = VCHIQ_RETRY;+		goto error_exit;+	}++	if (queue->local_insert == queue->remove + VCHIQ_NUM_SERVICE_BULKS) {+		VCHIQ_SERVICE_STATS_INC(service, bulk_stalls);+		do {+			mutex_unlock(&service->bulk_mutex);+			if (down_interruptible(&service->bulk_remove_event)+				!= 0) {+				status = VCHIQ_RETRY;+				goto error_exit;+			}+			if (mutex_lock_interruptible(&service->bulk_mutex)+				!= 0) {+				status = VCHIQ_RETRY;+				goto error_exit;+			}+		} while (queue->local_insert == queue->remove ++				VCHIQ_NUM_SERVICE_BULKS);+	}++	bulk = &queue->bulks[BULK_INDEX(queue->local_insert)];++	bulk->mode = mode;+	bulk->dir = dir;+	bulk->userdata = userdata;+	bulk->size = size;+	bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED;++	if (vchiq_prepare_bulk_data(bulk, memhandle, offset, size, dir) !=+		VCHIQ_SUCCESS)+		goto unlock_error_exit;++	wmb();++	vchiq_log_info(vchiq_core_log_level,+		"%d: bt (%d->%d) %cx %x@%x %x",+		state->id,+		service->localport, service->remoteport, dir_char,+		size, (unsigned int)bulk->data, (unsigned int)userdata);++	if (state->is_master) {+		queue->local_insert++;+		if (resolve_bulks(service, queue))+			request_poll(state, service,+				(dir == VCHIQ_BULK_TRANSMIT) ?+				VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY);+	} else {+		int payload[2] = { (int)bulk->data, bulk->size };+		VCHIQ_ELEMENT_T element = { payload, sizeof(payload) };++		status = queue_message(state, NULL,+			VCHIQ_MAKE_MSG(dir_msgtype,+				service->localport, service->remoteport),+			&element, 1, sizeof(payload), 1);+		if (status != VCHIQ_SUCCESS) {+			vchiq_complete_bulk(bulk);+			goto unlock_error_exit;+		}+		queue->local_insert++;+	}++	mutex_unlock(&service->bulk_mutex);++	vchiq_log_trace(vchiq_core_log_level,+		"%d: bt:%d %cx li=%x ri=%x p=%x",+		state->id,+		service->localport, dir_char,+		queue->local_insert, queue->remote_insert, queue->process);++waiting:+	unlock_service(service);++	status = VCHIQ_SUCCESS;++	if (bulk_waiter) {+		bulk_waiter->bulk = bulk;+		if (down_interruptible(&bulk_waiter->event) != 0)+			status = VCHIQ_RETRY;+		else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED)+			status = VCHIQ_ERROR;+	}++	return status;++unlock_error_exit:+	mutex_unlock(&service->bulk_mutex);++error_exit:+	if (service)+		unlock_service(service);+	return status;+}++VCHIQ_STATUS_T+vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T handle,+	const VCHIQ_ELEMENT_T *elements, unsigned int count)+{+	VCHIQ_SERVICE_T *service = find_service_by_handle(handle);+	VCHIQ_STATUS_T status = VCHIQ_ERROR;++	unsigned int size = 0;+	unsigned int i;++	if (!service ||+		(vchiq_check_service(service) != VCHIQ_SUCCESS))+		goto error_exit;++	for (i = 0; i < (unsigned int)count; i++) {+		if (elements[i].size) {+			if (elements[i].data == NULL) {+				VCHIQ_SERVICE_STATS_INC(service, error_count);+				goto error_exit;+			}+			size += elements[i].size;+		}+	}++	if (size > VCHIQ_MAX_MSG_SIZE) {+		VCHIQ_SERVICE_STATS_INC(service, error_count);+		goto error_exit;+	}++	switch (service->srvstate) {+	case VCHIQ_SRVSTATE_OPEN:+		status = queue_message(service->state, service,+				VCHIQ_MAKE_MSG(VCHIQ_MSG_DATA,+					service->localport,+					service->remoteport),+				elements, count, size, 1);+		break;+	case VCHIQ_SRVSTATE_OPENSYNC:+		status = queue_message_sync(service->state, service,+				VCHIQ_MAKE_MSG(VCHIQ_MSG_DATA,+					service->localport,+					service->remoteport),+				elements, count, size, 1);+		break;+	default:+		status = VCHIQ_ERROR;+		break;+	}++error_exit:+	if (service)+		unlock_service(service);++	return status;+}++void+vchiq_release_message(VCHIQ_SERVICE_HANDLE_T handle, VCHIQ_HEADER_T *header)+{+	VCHIQ_SERVICE_T *service = find_service_by_handle(handle);+	VCHIQ_SHARED_STATE_T *remote;+	VCHIQ_STATE_T *state;+	int slot_index;++	if (!service)+		return;++	state = service->state;+	remote = state->remote;++	slot_index = SLOT_INDEX_FROM_DATA(state, (void *)header);++	if ((slot_index >= remote->slot_first) &&+		(slot_index <= remote->slot_last)) {+		int msgid = header->msgid;+		if (msgid & VCHIQ_MSGID_CLAIMED) {+			VCHIQ_SLOT_INFO_T *slot_info =+				SLOT_INFO_FROM_INDEX(state, slot_index);++			release_slot(state, slot_info, header, service);+		}+	} else if (slot_index == remote->slot_sync)+		release_message_sync(state, header);++	unlock_service(service);+}++static void+release_message_sync(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header)+{+	header->msgid = VCHIQ_MSGID_PADDING;+	wmb();+	remote_event_signal(&state->remote->sync_release);+}++VCHIQ_STATUS_T+vchiq_get_peer_version(VCHIQ_SERVICE_HANDLE_T handle, short *peer_version)+{+   VCHIQ_STATUS_T status = VCHIQ_ERROR;+   VCHIQ_SERVICE_T *service = find_service_by_handle(handle);++   if (!service ||+      (vchiq_check_service(service) != VCHIQ_SUCCESS) ||+      !peer_version)+      goto exit;+   *peer_version = service->peer_version;+   status = VCHIQ_SUCCESS;++exit:+   if (service)+      unlock_service(service);+   return status;+}++VCHIQ_STATUS_T+vchiq_get_config(VCHIQ_INSTANCE_T instance,+	int config_size, VCHIQ_CONFIG_T *pconfig)+{+	VCHIQ_CONFIG_T config;++	(void)instance;++	config.max_msg_size           = VCHIQ_MAX_MSG_SIZE;+	config.bulk_threshold         = VCHIQ_MAX_MSG_SIZE;+	config.max_outstanding_bulks  = VCHIQ_NUM_SERVICE_BULKS;+	config.max_services           = VCHIQ_MAX_SERVICES;+	config.version                = VCHIQ_VERSION;+	config.version_min            = VCHIQ_VERSION_MIN;++	if (config_size > sizeof(VCHIQ_CONFIG_T))+		return VCHIQ_ERROR;++	memcpy(pconfig, &config,+		min(config_size, (int)(sizeof(VCHIQ_CONFIG_T))));++	return VCHIQ_SUCCESS;+}++VCHIQ_STATUS_T+vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle,+	VCHIQ_SERVICE_OPTION_T option, int value)+{+	VCHIQ_SERVICE_T *service = find_service_by_handle(handle);+	VCHIQ_STATUS_T status = VCHIQ_ERROR;++	if (service) {+		switch (option) {+		case VCHIQ_SERVICE_OPTION_AUTOCLOSE:+			service->auto_close = value;+			status = VCHIQ_SUCCESS;+			break;++		case VCHIQ_SERVICE_OPTION_SLOT_QUOTA: {+			VCHIQ_SERVICE_QUOTA_T *service_quota =+				&service->state->service_quotas[+					service->localport];+			if (value == 0)+				value = service->state->default_slot_quota;+			if ((value >= service_quota->slot_use_count) &&+				 (value < (unsigned short)~0)) {+				service_quota->slot_quota = value;+				if ((value >= service_quota->slot_use_count) &&+					(service_quota->message_quota >=+					 service_quota->message_use_count)) {+					/* Signal the service that it may have+					** dropped below its quota */+					up(&service_quota->quota_event);+				}+				status = VCHIQ_SUCCESS;+			}+		} break;++		case VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA: {+			VCHIQ_SERVICE_QUOTA_T *service_quota =+				&service->state->service_quotas[+					service->localport];+			if (value == 0)+				value = service->state->default_message_quota;+			if ((value >= service_quota->message_use_count) &&+				 (value < (unsigned short)~0)) {+				service_quota->message_quota = value;+				if ((value >=+					service_quota->message_use_count) &&+					(service_quota->slot_quota >=+					service_quota->slot_use_count))+					/* Signal the service that it may have+					** dropped below its quota */+					up(&service_quota->quota_event);+				status = VCHIQ_SUCCESS;+			}+		} break;++		case VCHIQ_SERVICE_OPTION_SYNCHRONOUS:+			if ((service->srvstate == VCHIQ_SRVSTATE_HIDDEN) ||+				(service->srvstate ==+				VCHIQ_SRVSTATE_LISTENING)) {+				service->sync = value;+				status = VCHIQ_SUCCESS;+			}+			break;++		default:+			break;+		}+		unlock_service(service);+	}++	return status;+}++void+vchiq_dump_shared_state(void *dump_context, VCHIQ_STATE_T *state,+	VCHIQ_SHARED_STATE_T *shared, const char *label)+{+	static const char *const debug_names[] = {+		"<entries>",+		"SLOT_HANDLER_COUNT",+		"SLOT_HANDLER_LINE",+		"PARSE_LINE",+		"PARSE_HEADER",+		"PARSE_MSGID",+		"AWAIT_COMPLETION_LINE",+		"DEQUEUE_MESSAGE_LINE",+		"SERVICE_CALLBACK_LINE",+		"MSG_QUEUE_FULL_COUNT",+		"COMPLETION_QUEUE_FULL_COUNT"+	};+	int i;++	char buf[80];+	int len;+	len = snprintf(buf, sizeof(buf),+		"  %s: slots %d-%d tx_pos=%x recycle=%x",+		label, shared->slot_first, shared->slot_last,+		shared->tx_pos, shared->slot_queue_recycle);+	vchiq_dump(dump_context, buf, len + 1);++	len = snprintf(buf, sizeof(buf),+		"    Slots claimed:");+	vchiq_dump(dump_context, buf, len + 1);++	for (i = shared->slot_first; i <= shared->slot_last; i++) {+		VCHIQ_SLOT_INFO_T slot_info = *SLOT_INFO_FROM_INDEX(state, i);+		if (slot_info.use_count != slot_info.release_count) {+			len = snprintf(buf, sizeof(buf),+				"      %d: %d/%d", i, slot_info.use_count,+				slot_info.release_count);+			vchiq_dump(dump_context, buf, len + 1);+		}+	}++	for (i = 1; i < shared->debug[DEBUG_ENTRIES]; i++) {+		len = snprintf(buf, sizeof(buf), "    DEBUG: %s = %d(%x)",+			debug_names[i], shared->debug[i], shared->debug[i]);+		vchiq_dump(dump_context, buf, len + 1);+	}+}++void+vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state)+{+	char buf[80];+	int len;+	int i;++	len = snprintf(buf, sizeof(buf), "State %d: %s", state->id,+		conn_state_names[state->conn_state]);+	vchiq_dump(dump_context, buf, len + 1);++	len = snprintf(buf, sizeof(buf),+		"  tx_pos=%x(@%x), rx_pos=%x(@%x)",+		state->local->tx_pos,+		(uint32_t)state->tx_data ++			(state->local_tx_pos & VCHIQ_SLOT_MASK),+		state->rx_pos,+		(uint32_t)state->rx_data ++			(state->rx_pos & VCHIQ_SLOT_MASK));+	vchiq_dump(dump_context, buf, len + 1);++	len = snprintf(buf, sizeof(buf),+		"  Version: %d (min %d)",+		VCHIQ_VERSION, VCHIQ_VERSION_MIN);+	vchiq_dump(dump_context, buf, len + 1);++	if (VCHIQ_ENABLE_STATS) {+		len = snprintf(buf, sizeof(buf),+			"  Stats: ctrl_tx_count=%d, ctrl_rx_count=%d, "+			"error_count=%d",+			state->stats.ctrl_tx_count, state->stats.ctrl_rx_count,+			state->stats.error_count);+		vchiq_dump(dump_context, buf, len + 1);+	}++	len = snprintf(buf, sizeof(buf),+		"  Slots: %d available (%d data), %d recyclable, %d stalls "+		"(%d data)",+		((state->slot_queue_available * VCHIQ_SLOT_SIZE) -+			state->local_tx_pos) / VCHIQ_SLOT_SIZE,+		state->data_quota - state->data_use_count,+		state->local->slot_queue_recycle - state->slot_queue_available,+		state->stats.slot_stalls, state->stats.data_stalls);+	vchiq_dump(dump_context, buf, len + 1);++	vchiq_dump_platform_state(dump_context);++	vchiq_dump_shared_state(dump_context, state, state->local, "Local");+	vchiq_dump_shared_state(dump_context, state, state->remote, "Remote");++	vchiq_dump_platform_instances(dump_context);++	for (i = 0; i < state->unused_service; i++) {+		VCHIQ_SERVICE_T *service = find_service_by_port(state, i);++		if (service) {+			vchiq_dump_service_state(dump_context, service);+			unlock_service(service);+		}+	}+}++void+vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service)+{+	char buf[80];+	int len;++	len = snprintf(buf, sizeof(buf), "Service %d: %s (ref %u)",+		service->localport, srvstate_names[service->srvstate],+		service->ref_count - 1); /*Don't include the lock just taken*/++	if (service->srvstate != VCHIQ_SRVSTATE_FREE) {+		char remoteport[30];+		VCHIQ_SERVICE_QUOTA_T *service_quota =+			&service->state->service_quotas[service->localport];+		int fourcc = service->base.fourcc;+		int tx_pending, rx_pending;+		if (service->remoteport != VCHIQ_PORT_FREE) {+			int len2 = snprintf(remoteport, sizeof(remoteport),+				"%d", service->remoteport);+			if (service->public_fourcc != VCHIQ_FOURCC_INVALID)+				snprintf(remoteport + len2,+					sizeof(remoteport) - len2,+					" (client %x)", service->client_id);+		} else+			strcpy(remoteport, "n/a");++		len += snprintf(buf + len, sizeof(buf) - len,+			" '%c%c%c%c' remote %s (msg use %d/%d, slot use %d/%d)",+			VCHIQ_FOURCC_AS_4CHARS(fourcc),+			remoteport,+			service_quota->message_use_count,+			service_quota->message_quota,+			service_quota->slot_use_count,+			service_quota->slot_quota);++		vchiq_dump(dump_context, buf, len + 1);++		tx_pending = service->bulk_tx.local_insert -+			service->bulk_tx.remote_insert;++		rx_pending = service->bulk_rx.local_insert -+			service->bulk_rx.remote_insert;++		len = snprintf(buf, sizeof(buf),+			"  Bulk: tx_pending=%d (size %d),"+			" rx_pending=%d (size %d)",+			tx_pending,+			tx_pending ? service->bulk_tx.bulks[+			BULK_INDEX(service->bulk_tx.remove)].size : 0,+			rx_pending,+			rx_pending ? service->bulk_rx.bulks[+			BULK_INDEX(service->bulk_rx.remove)].size : 0);++		if (VCHIQ_ENABLE_STATS) {+			vchiq_dump(dump_context, buf, len + 1);++			len = snprintf(buf, sizeof(buf),+				"  Ctrl: tx_count=%d, tx_bytes=%llu, "+				"rx_count=%d, rx_bytes=%llu",+				service->stats.ctrl_tx_count,+				service->stats.ctrl_tx_bytes,+				service->stats.ctrl_rx_count,+				service->stats.ctrl_rx_bytes);+			vchiq_dump(dump_context, buf, len + 1);++			len = snprintf(buf, sizeof(buf),+				"  Bulk: tx_count=%d, tx_bytes=%llu, "+				"rx_count=%d, rx_bytes=%llu",+				service->stats.bulk_tx_count,+				service->stats.bulk_tx_bytes,+				service->stats.bulk_rx_count,+				service->stats.bulk_rx_bytes);+			vchiq_dump(dump_context, buf, len + 1);++			len = snprintf(buf, sizeof(buf),+				"  %d quota stalls, %d slot stalls, "+				"%d bulk stalls, %d aborted, %d errors",+				service->stats.quota_stalls,+				service->stats.slot_stalls,+				service->stats.bulk_stalls,+				service->stats.bulk_aborted_count,+				service->stats.error_count);+		 }+	}++	vchiq_dump(dump_context, buf, len + 1);++	if (service->srvstate != VCHIQ_SRVSTATE_FREE)+		vchiq_dump_platform_service_state(dump_context, service);+}+++void+vchiq_loud_error_header(void)+{+	vchiq_log_error(vchiq_core_log_level,+		"============================================================"+		"================");+	vchiq_log_error(vchiq_core_log_level,+		"============================================================"+		"================");+	vchiq_log_error(vchiq_core_log_level, "=====");+}++void+vchiq_loud_error_footer(void)+{+	vchiq_log_error(vchiq_core_log_level, "=====");+	vchiq_log_error(vchiq_core_log_level,+		"============================================================"+		"================");+	vchiq_log_error(vchiq_core_log_level,+		"============================================================"+		"================");+}+++VCHIQ_STATUS_T vchiq_send_remote_use(VCHIQ_STATE_T *state)+{+	VCHIQ_STATUS_T status = VCHIQ_RETRY;+	if (state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED)+		status = queue_message(state, NULL,+			VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_USE, 0, 0),+			NULL, 0, 0, 0);+	return status;+}++VCHIQ_STATUS_T vchiq_send_remote_release(VCHIQ_STATE_T *state)+{+	VCHIQ_STATUS_T status = VCHIQ_RETRY;+	if (state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED)+		status = queue_message(state, NULL,+			VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_RELEASE, 0, 0),+			NULL, 0, 0, 0);+	return status;+}++VCHIQ_STATUS_T vchiq_send_remote_use_active(VCHIQ_STATE_T *state)+{+	VCHIQ_STATUS_T status = VCHIQ_RETRY;+	if (state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED)+		status = queue_message(state, NULL,+			VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_USE_ACTIVE, 0, 0),+			NULL, 0, 0, 0);+	return status;+}++void vchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem,+	size_t numBytes)+{+	const uint8_t  *mem = (const uint8_t *)voidMem;+	size_t          offset;+	char            lineBuf[100];+	char           *s;++	while (numBytes > 0) {+		s = lineBuf;++		for (offset = 0; offset < 16; offset++) {+			if (offset < numBytes)+				s += snprintf(s, 4, "%02x ", mem[offset]);+			else+				s += snprintf(s, 4, "   ");+		}++		for (offset = 0; offset < 16; offset++) {+			if (offset < numBytes) {+				uint8_t ch = mem[offset];++				if ((ch < ' ') || (ch > '~'))+					ch = '.';+				*s++ = (char)ch;+			}+		}+		*s++ = '\0';++		if ((label != NULL) && (*label != '\0'))+			vchiq_log_trace(VCHIQ_LOG_TRACE,+				"%s: %08x: %s", label, addr, lineBuf);+		else+			vchiq_log_trace(VCHIQ_LOG_TRACE,+				"%08x: %s", addr, lineBuf);++		addr += 16;+		mem += 16;+		if (numBytes > 16)+			numBytes -= 16;+		else+			numBytes = 0;+	}+}diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,706 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef VCHIQ_CORE_H+#define VCHIQ_CORE_H++#include <linux/mutex.h>+#include <linux/semaphore.h>+#include <linux/kthread.h>++#include "vchiq_cfg.h"++#include "vchiq.h"++/* Run time control of log level, based on KERN_XXX level. */+#define VCHIQ_LOG_DEFAULT  4+#define VCHIQ_LOG_ERROR    3+#define VCHIQ_LOG_WARNING  4+#define VCHIQ_LOG_INFO     6+#define VCHIQ_LOG_TRACE    7++#define VCHIQ_LOG_PREFIX   KERN_INFO "vchiq: "++#ifndef vchiq_log_error+#define vchiq_log_error(cat, fmt, ...) \+	do { if (cat >= VCHIQ_LOG_ERROR) \+		printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)+#endif+#ifndef vchiq_log_warning+#define vchiq_log_warning(cat, fmt, ...) \+	do { if (cat >= VCHIQ_LOG_WARNING) \+		 printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)+#endif+#ifndef vchiq_log_info+#define vchiq_log_info(cat, fmt, ...) \+	do { if (cat >= VCHIQ_LOG_INFO) \+		printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)+#endif+#ifndef vchiq_log_trace+#define vchiq_log_trace(cat, fmt, ...) \+	do { if (cat >= VCHIQ_LOG_TRACE) \+		printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)+#endif++#define vchiq_loud_error(...) \+	vchiq_log_error(vchiq_core_log_level, "===== " __VA_ARGS__)++#ifndef vchiq_static_assert+#define vchiq_static_assert(cond) __attribute__((unused)) \+	extern int vchiq_static_assert[(cond) ? 1 : -1]+#endif++#define IS_POW2(x) (x && ((x & (x - 1)) == 0))++/* Ensure that the slot size and maximum number of slots are powers of 2 */+vchiq_static_assert(IS_POW2(VCHIQ_SLOT_SIZE));+vchiq_static_assert(IS_POW2(VCHIQ_MAX_SLOTS));+vchiq_static_assert(IS_POW2(VCHIQ_MAX_SLOTS_PER_SIDE));++#define VCHIQ_SLOT_MASK        (VCHIQ_SLOT_SIZE - 1)+#define VCHIQ_SLOT_QUEUE_MASK  (VCHIQ_MAX_SLOTS_PER_SIDE - 1)+#define VCHIQ_SLOT_ZERO_SLOTS  ((sizeof(VCHIQ_SLOT_ZERO_T) + \+	VCHIQ_SLOT_SIZE - 1) / VCHIQ_SLOT_SIZE)++#define VCHIQ_MSG_PADDING            0  /* -                                 */+#define VCHIQ_MSG_CONNECT            1  /* -                                 */+#define VCHIQ_MSG_OPEN               2  /* + (srcport, -), fourcc, client_id */+#define VCHIQ_MSG_OPENACK            3  /* + (srcport, dstport)              */+#define VCHIQ_MSG_CLOSE              4  /* + (srcport, dstport)              */+#define VCHIQ_MSG_DATA               5  /* + (srcport, dstport)              */+#define VCHIQ_MSG_BULK_RX            6  /* + (srcport, dstport), data, size  */+#define VCHIQ_MSG_BULK_TX            7  /* + (srcport, dstport), data, size  */+#define VCHIQ_MSG_BULK_RX_DONE       8  /* + (srcport, dstport), actual      */+#define VCHIQ_MSG_BULK_TX_DONE       9  /* + (srcport, dstport), actual      */+#define VCHIQ_MSG_PAUSE             10  /* -                                 */+#define VCHIQ_MSG_RESUME            11  /* -                                 */+#define VCHIQ_MSG_REMOTE_USE        12  /* -                                 */+#define VCHIQ_MSG_REMOTE_RELEASE    13  /* -                                 */+#define VCHIQ_MSG_REMOTE_USE_ACTIVE 14  /* -                                 */++#define VCHIQ_PORT_MAX                 (VCHIQ_MAX_SERVICES - 1)+#define VCHIQ_PORT_FREE                0x1000+#define VCHIQ_PORT_IS_VALID(port)      (port < VCHIQ_PORT_FREE)+#define VCHIQ_MAKE_MSG(type, srcport, dstport) \+	((type<<24) | (srcport<<12) | (dstport<<0))+#define VCHIQ_MSG_TYPE(msgid)          ((unsigned int)msgid >> 24)+#define VCHIQ_MSG_SRCPORT(msgid) \+	(unsigned short)(((unsigned int)msgid >> 12) & 0xfff)+#define VCHIQ_MSG_DSTPORT(msgid) \+	((unsigned short)msgid & 0xfff)++#define VCHIQ_FOURCC_AS_4CHARS(fourcc)	\+	((fourcc) >> 24) & 0xff, \+	((fourcc) >> 16) & 0xff, \+	((fourcc) >>  8) & 0xff, \+	(fourcc) & 0xff++/* Ensure the fields are wide enough */+vchiq_static_assert(VCHIQ_MSG_SRCPORT(VCHIQ_MAKE_MSG(0, 0, VCHIQ_PORT_MAX))+	== 0);+vchiq_static_assert(VCHIQ_MSG_TYPE(VCHIQ_MAKE_MSG(0, VCHIQ_PORT_MAX, 0)) == 0);+vchiq_static_assert((unsigned int)VCHIQ_PORT_MAX <+	(unsigned int)VCHIQ_PORT_FREE);++#define VCHIQ_MSGID_PADDING            VCHIQ_MAKE_MSG(VCHIQ_MSG_PADDING, 0, 0)+#define VCHIQ_MSGID_CLAIMED            0x40000000++#define VCHIQ_FOURCC_INVALID           0x00000000+#define VCHIQ_FOURCC_IS_LEGAL(fourcc)  (fourcc != VCHIQ_FOURCC_INVALID)++#define VCHIQ_BULK_ACTUAL_ABORTED -1++typedef uint32_t BITSET_T;++vchiq_static_assert((sizeof(BITSET_T) * 8) == 32);++#define BITSET_SIZE(b)        ((b + 31) >> 5)+#define BITSET_WORD(b)        (b >> 5)+#define BITSET_BIT(b)         (1 << (b & 31))+#define BITSET_ZERO(bs)       memset(bs, 0, sizeof(bs))+#define BITSET_IS_SET(bs, b)  (bs[BITSET_WORD(b)] & BITSET_BIT(b))+#define BITSET_SET(bs, b)     (bs[BITSET_WORD(b)] |= BITSET_BIT(b))+#define BITSET_CLR(bs, b)     (bs[BITSET_WORD(b)] &= ~BITSET_BIT(b))++#if VCHIQ_ENABLE_STATS+#define VCHIQ_STATS_INC(state, stat) (state->stats. stat++)+#define VCHIQ_SERVICE_STATS_INC(service, stat) (service->stats. stat++)+#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) \+	(service->stats. stat += addend)+#else+#define VCHIQ_STATS_INC(state, stat) ((void)0)+#define VCHIQ_SERVICE_STATS_INC(service, stat) ((void)0)+#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) ((void)0)+#endif++enum {+	DEBUG_ENTRIES,+#if VCHIQ_ENABLE_DEBUG+	DEBUG_SLOT_HANDLER_COUNT,+	DEBUG_SLOT_HANDLER_LINE,+	DEBUG_PARSE_LINE,+	DEBUG_PARSE_HEADER,+	DEBUG_PARSE_MSGID,+	DEBUG_AWAIT_COMPLETION_LINE,+	DEBUG_DEQUEUE_MESSAGE_LINE,+	DEBUG_SERVICE_CALLBACK_LINE,+	DEBUG_MSG_QUEUE_FULL_COUNT,+	DEBUG_COMPLETION_QUEUE_FULL_COUNT,+#endif+	DEBUG_MAX+};++#if VCHIQ_ENABLE_DEBUG++#define DEBUG_INITIALISE(local) int *debug_ptr = (local)->debug;+#define DEBUG_TRACE(d) \+	do { debug_ptr[DEBUG_ ## d] = __LINE__; dsb(); } while (0)+#define DEBUG_VALUE(d, v) \+	do { debug_ptr[DEBUG_ ## d] = (v); dsb(); } while (0)+#define DEBUG_COUNT(d) \+	do { debug_ptr[DEBUG_ ## d]++; dsb(); } while (0)++#else /* VCHIQ_ENABLE_DEBUG */++#define DEBUG_INITIALISE(local)+#define DEBUG_TRACE(d)+#define DEBUG_VALUE(d, v)+#define DEBUG_COUNT(d)++#endif /* VCHIQ_ENABLE_DEBUG */++typedef enum {+	VCHIQ_CONNSTATE_DISCONNECTED,+	VCHIQ_CONNSTATE_CONNECTING,+	VCHIQ_CONNSTATE_CONNECTED,+	VCHIQ_CONNSTATE_PAUSING,+	VCHIQ_CONNSTATE_PAUSE_SENT,+	VCHIQ_CONNSTATE_PAUSED,+	VCHIQ_CONNSTATE_RESUMING,+	VCHIQ_CONNSTATE_PAUSE_TIMEOUT,+	VCHIQ_CONNSTATE_RESUME_TIMEOUT+} VCHIQ_CONNSTATE_T;++enum {+	VCHIQ_SRVSTATE_FREE,+	VCHIQ_SRVSTATE_HIDDEN,+	VCHIQ_SRVSTATE_LISTENING,+	VCHIQ_SRVSTATE_OPENING,+	VCHIQ_SRVSTATE_OPEN,+	VCHIQ_SRVSTATE_OPENSYNC,+	VCHIQ_SRVSTATE_CLOSESENT,+	VCHIQ_SRVSTATE_CLOSERECVD,+	VCHIQ_SRVSTATE_CLOSEWAIT,+	VCHIQ_SRVSTATE_CLOSED+};++enum {+	VCHIQ_POLL_TERMINATE,+	VCHIQ_POLL_REMOVE,+	VCHIQ_POLL_TXNOTIFY,+	VCHIQ_POLL_RXNOTIFY,+	VCHIQ_POLL_COUNT+};++typedef enum {+	VCHIQ_BULK_TRANSMIT,+	VCHIQ_BULK_RECEIVE+} VCHIQ_BULK_DIR_T;++typedef void (*VCHIQ_USERDATA_TERM_T)(void *userdata);++typedef struct vchiq_bulk_struct {+	short mode;+	short dir;+	void *userdata;+	VCHI_MEM_HANDLE_T handle;+	void *data;+	int size;+	void *remote_data;+	int remote_size;+	int actual;+} VCHIQ_BULK_T;++typedef struct vchiq_bulk_queue_struct {+	int local_insert;  /* Where to insert the next local bulk */+	int remote_insert; /* Where to insert the next remote bulk (master) */+	int process;       /* Bulk to transfer next */+	int remote_notify; /* Bulk to notify the remote client of next (mstr) */+	int remove;        /* Bulk to notify the local client of, and remove,+			   ** next */+	VCHIQ_BULK_T bulks[VCHIQ_NUM_SERVICE_BULKS];+} VCHIQ_BULK_QUEUE_T;++typedef struct remote_event_struct {+	int armed;+	int fired;+	struct semaphore *event;+} REMOTE_EVENT_T;++typedef struct opaque_platform_state_t *VCHIQ_PLATFORM_STATE_T;++typedef struct vchiq_state_struct VCHIQ_STATE_T;++typedef struct vchiq_slot_struct {+	char data[VCHIQ_SLOT_SIZE];+} VCHIQ_SLOT_T;++typedef struct vchiq_slot_info_struct {+	/* Use two counters rather than one to avoid the need for a mutex. */+	short use_count;+	short release_count;+} VCHIQ_SLOT_INFO_T;++typedef struct vchiq_service_struct {+	VCHIQ_SERVICE_BASE_T base;+	VCHIQ_SERVICE_HANDLE_T handle;+	unsigned int ref_count;+	int srvstate;+	VCHIQ_USERDATA_TERM_T userdata_term;+	unsigned int localport;+	unsigned int remoteport;+	int public_fourcc;+	int client_id;+	char auto_close;+	char sync;+	char closing;+	atomic_t poll_flags;+	short version;+	short version_min;+	short peer_version;++	VCHIQ_STATE_T *state;+	VCHIQ_INSTANCE_T instance;++	int service_use_count;++	VCHIQ_BULK_QUEUE_T bulk_tx;+	VCHIQ_BULK_QUEUE_T bulk_rx;++	struct semaphore remove_event;+	struct semaphore bulk_remove_event;+	struct mutex bulk_mutex;++	struct service_stats_struct {+		int quota_stalls;+		int slot_stalls;+		int bulk_stalls;+		int error_count;+		int ctrl_tx_count;+		int ctrl_rx_count;+		int bulk_tx_count;+		int bulk_rx_count;+		int bulk_aborted_count;+		uint64_t ctrl_tx_bytes;+		uint64_t ctrl_rx_bytes;+		uint64_t bulk_tx_bytes;+		uint64_t bulk_rx_bytes;+	} stats;+} VCHIQ_SERVICE_T;++/* The quota information is outside VCHIQ_SERVICE_T so that it can be+	statically allocated, since for accounting reasons a service's slot+	usage is carried over between users of the same port number.+ */+typedef struct vchiq_service_quota_struct {+	unsigned short slot_quota;+	unsigned short slot_use_count;+	unsigned short message_quota;+	unsigned short message_use_count;+	struct semaphore quota_event;+	int previous_tx_index;+} VCHIQ_SERVICE_QUOTA_T;++typedef struct vchiq_shared_state_struct {++	/* A non-zero value here indicates that the content is valid. */+	int initialised;++	/* The first and last (inclusive) slots allocated to the owner. */+	int slot_first;+	int slot_last;++	/* The slot allocated to synchronous messages from the owner. */+	int slot_sync;++	/* Signalling this event indicates that owner's slot handler thread+	** should run. */+	REMOTE_EVENT_T trigger;++	/* Indicates the byte position within the stream where the next message+	** will be written. The least significant bits are an index into the+	** slot. The next bits are the index of the slot in slot_queue. */+	int tx_pos;++	/* This event should be signalled when a slot is recycled. */+	REMOTE_EVENT_T recycle;++	/* The slot_queue index where the next recycled slot will be written. */+	int slot_queue_recycle;++	/* This event should be signalled when a synchronous message is sent. */+	REMOTE_EVENT_T sync_trigger;++	/* This event should be signalled when a synchronous message has been+	** released. */+	REMOTE_EVENT_T sync_release;++	/* A circular buffer of slot indexes. */+	int slot_queue[VCHIQ_MAX_SLOTS_PER_SIDE];++	/* Debugging state */+	int debug[DEBUG_MAX];+} VCHIQ_SHARED_STATE_T;++typedef struct vchiq_slot_zero_struct {+	int magic;+	short version;+	short version_min;+	int slot_zero_size;+	int slot_size;+	int max_slots;+	int max_slots_per_side;+	int platform_data[2];+	VCHIQ_SHARED_STATE_T master;+	VCHIQ_SHARED_STATE_T slave;+	VCHIQ_SLOT_INFO_T slots[VCHIQ_MAX_SLOTS];+} VCHIQ_SLOT_ZERO_T;++struct vchiq_state_struct {+	int id;+	int initialised;+	VCHIQ_CONNSTATE_T conn_state;+	int is_master;++	VCHIQ_SHARED_STATE_T *local;+	VCHIQ_SHARED_STATE_T *remote;+	VCHIQ_SLOT_T *slot_data;++	unsigned short default_slot_quota;+	unsigned short default_message_quota;++	/* Event indicating connect message received */+	struct semaphore connect;++	/* Mutex protecting services */+	struct mutex mutex;+	VCHIQ_INSTANCE_T *instance;++	/* Processes incoming messages */+	struct task_struct *slot_handler_thread;++	/* Processes recycled slots */+	struct task_struct *recycle_thread;++	/* Processes synchronous messages */+	struct task_struct *sync_thread;++	/* Local implementation of the trigger remote event */+	struct semaphore trigger_event;++	/* Local implementation of the recycle remote event */+	struct semaphore recycle_event;++	/* Local implementation of the sync trigger remote event */+	struct semaphore sync_trigger_event;++	/* Local implementation of the sync release remote event */+	struct semaphore sync_release_event;++	char *tx_data;+	char *rx_data;+	VCHIQ_SLOT_INFO_T *rx_info;++	struct mutex slot_mutex;++	struct mutex recycle_mutex;++	struct mutex sync_mutex;++	struct mutex bulk_transfer_mutex;++	/* Indicates the byte position within the stream from where the next+	** message will be read. The least significant bits are an index into+	** the slot.The next bits are the index of the slot in+	** remote->slot_queue. */+	int rx_pos;++	/* A cached copy of local->tx_pos. Only write to local->tx_pos, and read+		from remote->tx_pos. */+	int local_tx_pos;++	/* The slot_queue index of the slot to become available next. */+	int slot_queue_available;++	/* A flag to indicate if any poll has been requested */+	int poll_needed;++	/* Ths index of the previous slot used for data messages. */+	int previous_data_index;++	/* The number of slots occupied by data messages. */+	unsigned short data_use_count;++	/* The maximum number of slots to be occupied by data messages. */+	unsigned short data_quota;++	/* An array of bit sets indicating which services must be polled. */+	atomic_t poll_services[BITSET_SIZE(VCHIQ_MAX_SERVICES)];++	/* The number of the first unused service */+	int unused_service;++	/* Signalled when a free slot becomes available. */+	struct semaphore slot_available_event;++	struct semaphore slot_remove_event;++	/* Signalled when a free data slot becomes available. */+	struct semaphore data_quota_event;++	/* Incremented when there are bulk transfers which cannot be processed+	 * whilst paused and must be processed on resume */+	int deferred_bulks;++	struct state_stats_struct {+		int slot_stalls;+		int data_stalls;+		int ctrl_tx_count;+		int ctrl_rx_count;+		int error_count;+	} stats;++	VCHIQ_SERVICE_T * services[VCHIQ_MAX_SERVICES];+	VCHIQ_SERVICE_QUOTA_T service_quotas[VCHIQ_MAX_SERVICES];+	VCHIQ_SLOT_INFO_T slot_info[VCHIQ_MAX_SLOTS];++	VCHIQ_PLATFORM_STATE_T platform_state;+};++struct bulk_waiter {+	VCHIQ_BULK_T *bulk;+	struct semaphore event;+	int actual;+};++extern spinlock_t bulk_waiter_spinlock;++extern int vchiq_core_log_level;+extern int vchiq_core_msg_log_level;+extern int vchiq_sync_log_level;++extern VCHIQ_STATE_T *vchiq_states[VCHIQ_MAX_STATES];++extern const char *+get_conn_state_name(VCHIQ_CONNSTATE_T conn_state);++extern VCHIQ_SLOT_ZERO_T *+vchiq_init_slots(void *mem_base, int mem_size);++extern VCHIQ_STATUS_T+vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero,+	int is_master);++extern VCHIQ_STATUS_T+vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance);++extern VCHIQ_SERVICE_T *+vchiq_add_service_internal(VCHIQ_STATE_T *state,+	const VCHIQ_SERVICE_PARAMS_T *params, int srvstate,+	VCHIQ_INSTANCE_T instance, VCHIQ_USERDATA_TERM_T userdata_term);++extern VCHIQ_STATUS_T+vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id);++extern VCHIQ_STATUS_T+vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd);++extern void+vchiq_terminate_service_internal(VCHIQ_SERVICE_T *service);++extern void+vchiq_free_service_internal(VCHIQ_SERVICE_T *service);++extern VCHIQ_STATUS_T+vchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance);++extern VCHIQ_STATUS_T+vchiq_pause_internal(VCHIQ_STATE_T *state);++extern VCHIQ_STATUS_T+vchiq_resume_internal(VCHIQ_STATE_T *state);++extern void+remote_event_pollall(VCHIQ_STATE_T *state);++extern VCHIQ_STATUS_T+vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle,+	VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata,+	VCHIQ_BULK_MODE_T mode, VCHIQ_BULK_DIR_T dir);++extern void+vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state);++extern void+vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service);++extern void+vchiq_loud_error_header(void);++extern void+vchiq_loud_error_footer(void);++extern void+request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type);++static inline VCHIQ_SERVICE_T *+handle_to_service(VCHIQ_SERVICE_HANDLE_T handle)+{+	VCHIQ_STATE_T *state = vchiq_states[(handle / VCHIQ_MAX_SERVICES) &+		(VCHIQ_MAX_STATES - 1)];+	if (!state)+		return NULL;++	return state->services[handle & (VCHIQ_MAX_SERVICES - 1)];+}++extern VCHIQ_SERVICE_T *+find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle);++extern VCHIQ_SERVICE_T *+find_service_by_port(VCHIQ_STATE_T *state, int localport);++extern VCHIQ_SERVICE_T *+find_service_for_instance(VCHIQ_INSTANCE_T instance,+	VCHIQ_SERVICE_HANDLE_T handle);++extern VCHIQ_SERVICE_T *+next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance,+	int *pidx);++extern void+lock_service(VCHIQ_SERVICE_T *service);++extern void+unlock_service(VCHIQ_SERVICE_T *service);++/* The following functions are called from vchiq_core, and external+** implementations must be provided. */++extern VCHIQ_STATUS_T+vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk,+	VCHI_MEM_HANDLE_T memhandle, void *offset, int size, int dir);++extern void+vchiq_transfer_bulk(VCHIQ_BULK_T *bulk);++extern void+vchiq_complete_bulk(VCHIQ_BULK_T *bulk);++extern VCHIQ_STATUS_T+vchiq_copy_from_user(void *dst, const void *src, int size);++extern void+remote_event_signal(REMOTE_EVENT_T *event);++void+vchiq_platform_check_suspend(VCHIQ_STATE_T *state);++extern void+vchiq_platform_paused(VCHIQ_STATE_T *state);++extern VCHIQ_STATUS_T+vchiq_platform_resume(VCHIQ_STATE_T *state);++extern void+vchiq_platform_resumed(VCHIQ_STATE_T *state);++extern void+vchiq_dump(void *dump_context, const char *str, int len);++extern void+vchiq_dump_platform_state(void *dump_context);++extern void+vchiq_dump_platform_instances(void *dump_context);++extern void+vchiq_dump_platform_service_state(void *dump_context,+	VCHIQ_SERVICE_T *service);++extern VCHIQ_STATUS_T+vchiq_use_service_internal(VCHIQ_SERVICE_T *service);++extern VCHIQ_STATUS_T+vchiq_release_service_internal(VCHIQ_SERVICE_T *service);++extern void+vchiq_on_remote_use(VCHIQ_STATE_T *state);++extern void+vchiq_on_remote_release(VCHIQ_STATE_T *state);++extern VCHIQ_STATUS_T+vchiq_platform_init_state(VCHIQ_STATE_T *state);++extern VCHIQ_STATUS_T+vchiq_check_service(VCHIQ_SERVICE_T *service);++extern void+vchiq_on_remote_use_active(VCHIQ_STATE_T *state);++extern VCHIQ_STATUS_T+vchiq_send_remote_use(VCHIQ_STATE_T *state);++extern VCHIQ_STATUS_T+vchiq_send_remote_release(VCHIQ_STATE_T *state);++extern VCHIQ_STATUS_T+vchiq_send_remote_use_active(VCHIQ_STATE_T *state);++extern void+vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state,+	VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate);++extern void+vchiq_platform_handle_timeout(VCHIQ_STATE_T *state);++extern void+vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate);+++extern void+vchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem,+	size_t numBytes);++#endifdiff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,87 @@+#!/usr/bin/perl -w++use strict;++#+# Generate a version from available information+#++my $prefix = shift @ARGV;+my $root = shift @ARGV;+++if ( not defined $root ) {+	die "usage: $0 prefix root-dir\n";+}++if ( ! -d $root ) {+	die "root directory $root not found\n";+}++my $version = "unknown";+my $tainted = "";++if ( -d "$root/.git" ) {+	# attempt to work out git version. only do so+	# on a linux build host, as cygwin builds are+	# already slow enough++	if ( -f "/usr/bin/git" || -f "/usr/local/bin/git" ) {+		if (not open(F, "git --git-dir $root/.git rev-parse --verify HEAD|")) {+			$version = "no git version";+		}+		else {+			$version = <F>;+			$version =~ s/[ \r\n]*$//;     # chomp may not be enough (cygwin).+			$version =~ s/^[ \r\n]*//;     # chomp may not be enough (cygwin).+		}++		if (open(G, "git --git-dir $root/.git status --porcelain|")) {+			$tainted = <G>;+			$tainted =~ s/[ \r\n]*$//;     # chomp may not be enough (cygwin).+			$tainted =~ s/^[ \r\n]*//;     # chomp may not be enough (cygwin).+			if (length $tainted) {+			$version = join ' ', $version, "(tainted)";+		}+		else {+			$version = join ' ', $version, "(clean)";+         }+		}+	}+}++my $hostname = `hostname`;+$hostname =~ s/[ \r\n]*$//;     # chomp may not be enough (cygwin).+$hostname =~ s/^[ \r\n]*//;     # chomp may not be enough (cygwin).+++print STDERR "Version $version\n";+print <<EOF;+#include "${prefix}_build_info.h"+#include <linux/broadcom/vc_debug_sym.h>++VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_hostname, "$hostname" );+VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_version, "$version" );+VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_time,    __TIME__ );+VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_date,    __DATE__ );++const char *vchiq_get_build_hostname( void )+{+   return vchiq_build_hostname;+}++const char *vchiq_get_build_version( void )+{+   return vchiq_build_version;+}++const char *vchiq_get_build_date( void )+{+   return vchiq_build_date;+}++const char *vchiq_get_build_time( void )+{+   return vchiq_build_time;+}+EOFdiff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,40 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef VCHIQ_VCHIQ_H+#define VCHIQ_VCHIQ_H++#include "vchiq_if.h"+#include "vchiq_util.h"++#endifdiff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,188 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef VCHIQ_IF_H+#define VCHIQ_IF_H++#include "interface/vchi/vchi_mh.h"++#define VCHIQ_SERVICE_HANDLE_INVALID 0++#define VCHIQ_SLOT_SIZE     4096+#define VCHIQ_MAX_MSG_SIZE  (VCHIQ_SLOT_SIZE - sizeof(VCHIQ_HEADER_T))+#define VCHIQ_CHANNEL_SIZE  VCHIQ_MAX_MSG_SIZE /* For backwards compatibility */++#define VCHIQ_MAKE_FOURCC(x0, x1, x2, x3) \+			(((x0) << 24) | ((x1) << 16) | ((x2) << 8) | (x3))+#define VCHIQ_GET_SERVICE_USERDATA(service) vchiq_get_service_userdata(service)+#define VCHIQ_GET_SERVICE_FOURCC(service)   vchiq_get_service_fourcc(service)++typedef enum {+	VCHIQ_SERVICE_OPENED,         /* service, -, -             */+	VCHIQ_SERVICE_CLOSED,         /* service, -, -             */+	VCHIQ_MESSAGE_AVAILABLE,      /* service, header, -        */+	VCHIQ_BULK_TRANSMIT_DONE,     /* service, -, bulk_userdata */+	VCHIQ_BULK_RECEIVE_DONE,      /* service, -, bulk_userdata */+	VCHIQ_BULK_TRANSMIT_ABORTED,  /* service, -, bulk_userdata */+	VCHIQ_BULK_RECEIVE_ABORTED    /* service, -, bulk_userdata */+} VCHIQ_REASON_T;++typedef enum {+	VCHIQ_ERROR   = -1,+	VCHIQ_SUCCESS = 0,+	VCHIQ_RETRY   = 1+} VCHIQ_STATUS_T;++typedef enum {+	VCHIQ_BULK_MODE_CALLBACK,+	VCHIQ_BULK_MODE_BLOCKING,+	VCHIQ_BULK_MODE_NOCALLBACK,+	VCHIQ_BULK_MODE_WAITING		/* Reserved for internal use */+} VCHIQ_BULK_MODE_T;++typedef enum {+	VCHIQ_SERVICE_OPTION_AUTOCLOSE,+	VCHIQ_SERVICE_OPTION_SLOT_QUOTA,+	VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA,+	VCHIQ_SERVICE_OPTION_SYNCHRONOUS+} VCHIQ_SERVICE_OPTION_T;++typedef struct vchiq_header_struct {+	/* The message identifier - opaque to applications. */+	int msgid;++	/* Size of message data. */+	unsigned int size;++	char data[0];           /* message */+} VCHIQ_HEADER_T;++typedef struct {+	const void *data;+	unsigned int size;+} VCHIQ_ELEMENT_T;++typedef unsigned int VCHIQ_SERVICE_HANDLE_T;++typedef VCHIQ_STATUS_T (*VCHIQ_CALLBACK_T)(VCHIQ_REASON_T, VCHIQ_HEADER_T *,+	VCHIQ_SERVICE_HANDLE_T, void *);++typedef struct vchiq_service_base_struct {+	int fourcc;+	VCHIQ_CALLBACK_T callback;+	void *userdata;+} VCHIQ_SERVICE_BASE_T;++typedef struct vchiq_service_params_struct {+	int fourcc;+	VCHIQ_CALLBACK_T callback;+	void *userdata;+	short version;       /* Increment for non-trivial changes */+	short version_min;   /* Update for incompatible changes */+} VCHIQ_SERVICE_PARAMS_T;++typedef struct vchiq_config_struct {+	unsigned int max_msg_size;+	unsigned int bulk_threshold; /* The message size above which it+					is better to use a bulk transfer+					(<= max_msg_size) */+	unsigned int max_outstanding_bulks;+	unsigned int max_services;+	short version;      /* The version of VCHIQ */+	short version_min;  /* The minimum compatible version of VCHIQ */+} VCHIQ_CONFIG_T;++typedef struct vchiq_instance_struct *VCHIQ_INSTANCE_T;+typedef void (*VCHIQ_REMOTE_USE_CALLBACK_T)(void *cb_arg);++extern VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *pinstance);+extern VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance);+extern VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance);+extern VCHIQ_STATUS_T vchiq_add_service(VCHIQ_INSTANCE_T instance,+	const VCHIQ_SERVICE_PARAMS_T *params,+	VCHIQ_SERVICE_HANDLE_T *pservice);+extern VCHIQ_STATUS_T vchiq_open_service(VCHIQ_INSTANCE_T instance,+	const VCHIQ_SERVICE_PARAMS_T *params,+	VCHIQ_SERVICE_HANDLE_T *pservice);+extern VCHIQ_STATUS_T vchiq_close_service(VCHIQ_SERVICE_HANDLE_T service);+extern VCHIQ_STATUS_T vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T service);+extern VCHIQ_STATUS_T vchiq_use_service(VCHIQ_SERVICE_HANDLE_T service);+extern VCHIQ_STATUS_T vchiq_use_service_no_resume(+	VCHIQ_SERVICE_HANDLE_T service);+extern VCHIQ_STATUS_T vchiq_release_service(VCHIQ_SERVICE_HANDLE_T service);++extern VCHIQ_STATUS_T vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T service,+	const VCHIQ_ELEMENT_T *elements, unsigned int count);+extern void           vchiq_release_message(VCHIQ_SERVICE_HANDLE_T service,+	VCHIQ_HEADER_T *header);+extern VCHIQ_STATUS_T vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service,+	const void *data, unsigned int size, void *userdata);+extern VCHIQ_STATUS_T vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T service,+	void *data, unsigned int size, void *userdata);+extern VCHIQ_STATUS_T vchiq_queue_bulk_transmit_handle(+	VCHIQ_SERVICE_HANDLE_T service, VCHI_MEM_HANDLE_T handle,+	const void *offset, unsigned int size, void *userdata);+extern VCHIQ_STATUS_T vchiq_queue_bulk_receive_handle(+	VCHIQ_SERVICE_HANDLE_T service, VCHI_MEM_HANDLE_T handle,+	void *offset, unsigned int size, void *userdata);+extern VCHIQ_STATUS_T vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service,+	const void *data, unsigned int size, void *userdata,+	VCHIQ_BULK_MODE_T mode);+extern VCHIQ_STATUS_T vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T service,+	void *data, unsigned int size, void *userdata,+	VCHIQ_BULK_MODE_T mode);+extern VCHIQ_STATUS_T vchiq_bulk_transmit_handle(VCHIQ_SERVICE_HANDLE_T service,+	VCHI_MEM_HANDLE_T handle, const void *offset, unsigned int size,+	void *userdata,	VCHIQ_BULK_MODE_T mode);+extern VCHIQ_STATUS_T vchiq_bulk_receive_handle(VCHIQ_SERVICE_HANDLE_T service,+	VCHI_MEM_HANDLE_T handle, void *offset, unsigned int size,+	void *userdata, VCHIQ_BULK_MODE_T mode);+extern int   vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T service);+extern void *vchiq_get_service_userdata(VCHIQ_SERVICE_HANDLE_T service);+extern int   vchiq_get_service_fourcc(VCHIQ_SERVICE_HANDLE_T service);+extern VCHIQ_STATUS_T vchiq_get_config(VCHIQ_INSTANCE_T instance,+	int config_size, VCHIQ_CONFIG_T *pconfig);+extern VCHIQ_STATUS_T vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T service,+	VCHIQ_SERVICE_OPTION_T option, int value);++extern VCHIQ_STATUS_T vchiq_remote_use(VCHIQ_INSTANCE_T instance,+	VCHIQ_REMOTE_USE_CALLBACK_T callback, void *cb_arg);+extern VCHIQ_STATUS_T vchiq_remote_release(VCHIQ_INSTANCE_T instance);++extern VCHIQ_STATUS_T vchiq_dump_phys_mem(VCHIQ_SERVICE_HANDLE_T service,+	void *ptr, size_t num_bytes);++extern VCHIQ_STATUS_T vchiq_get_peer_version(VCHIQ_SERVICE_HANDLE_T handle,+      short *peer_version);++#endif /* VCHIQ_IF_H */diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,129 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef VCHIQ_IOCTLS_H+#define VCHIQ_IOCTLS_H++#include <linux/ioctl.h>+#include "vchiq_if.h"++#define VCHIQ_IOC_MAGIC 0xc4+#define VCHIQ_INVALID_HANDLE (~0)++typedef struct {+	VCHIQ_SERVICE_PARAMS_T params;+	int is_open;+	int is_vchi;+	unsigned int handle;       /* OUT */+} VCHIQ_CREATE_SERVICE_T;++typedef struct {+	unsigned int handle;+	unsigned int count;+	const VCHIQ_ELEMENT_T *elements;+} VCHIQ_QUEUE_MESSAGE_T;++typedef struct {+	unsigned int handle;+	void *data;+	unsigned int size;+	void *userdata;+	VCHIQ_BULK_MODE_T mode;+} VCHIQ_QUEUE_BULK_TRANSFER_T;++typedef struct {+	VCHIQ_REASON_T reason;+	VCHIQ_HEADER_T *header;+	void *service_userdata;+	void *bulk_userdata;+} VCHIQ_COMPLETION_DATA_T;++typedef struct {+	unsigned int count;+	VCHIQ_COMPLETION_DATA_T *buf;+	unsigned int msgbufsize;+	unsigned int msgbufcount; /* IN/OUT */+	void **msgbufs;+} VCHIQ_AWAIT_COMPLETION_T;++typedef struct {+	unsigned int handle;+	int blocking;+	unsigned int bufsize;+	void *buf;+} VCHIQ_DEQUEUE_MESSAGE_T;++typedef struct {+	unsigned int config_size;+	VCHIQ_CONFIG_T *pconfig;+} VCHIQ_GET_CONFIG_T;++typedef struct {+	unsigned int handle;+	VCHIQ_SERVICE_OPTION_T option;+	int value;+} VCHIQ_SET_SERVICE_OPTION_T;++typedef struct {+	void     *virt_addr;+	size_t    num_bytes;+} VCHIQ_DUMP_MEM_T;++#define VCHIQ_IOC_CONNECT              _IO(VCHIQ_IOC_MAGIC,   0)+#define VCHIQ_IOC_SHUTDOWN             _IO(VCHIQ_IOC_MAGIC,   1)+#define VCHIQ_IOC_CREATE_SERVICE \+	_IOWR(VCHIQ_IOC_MAGIC, 2, VCHIQ_CREATE_SERVICE_T)+#define VCHIQ_IOC_REMOVE_SERVICE       _IO(VCHIQ_IOC_MAGIC,   3)+#define VCHIQ_IOC_QUEUE_MESSAGE \+	_IOW(VCHIQ_IOC_MAGIC,  4, VCHIQ_QUEUE_MESSAGE_T)+#define VCHIQ_IOC_QUEUE_BULK_TRANSMIT \+	_IOWR(VCHIQ_IOC_MAGIC, 5, VCHIQ_QUEUE_BULK_TRANSFER_T)+#define VCHIQ_IOC_QUEUE_BULK_RECEIVE \+	_IOWR(VCHIQ_IOC_MAGIC, 6, VCHIQ_QUEUE_BULK_TRANSFER_T)+#define VCHIQ_IOC_AWAIT_COMPLETION \+	_IOWR(VCHIQ_IOC_MAGIC, 7, VCHIQ_AWAIT_COMPLETION_T)+#define VCHIQ_IOC_DEQUEUE_MESSAGE \+	_IOWR(VCHIQ_IOC_MAGIC, 8, VCHIQ_DEQUEUE_MESSAGE_T)+#define VCHIQ_IOC_GET_CLIENT_ID        _IO(VCHIQ_IOC_MAGIC,   9)+#define VCHIQ_IOC_GET_CONFIG \+	_IOWR(VCHIQ_IOC_MAGIC, 10, VCHIQ_GET_CONFIG_T)+#define VCHIQ_IOC_CLOSE_SERVICE        _IO(VCHIQ_IOC_MAGIC,   11)+#define VCHIQ_IOC_USE_SERVICE          _IO(VCHIQ_IOC_MAGIC,   12)+#define VCHIQ_IOC_RELEASE_SERVICE      _IO(VCHIQ_IOC_MAGIC,   13)+#define VCHIQ_IOC_SET_SERVICE_OPTION \+	_IOW(VCHIQ_IOC_MAGIC,  14, VCHIQ_SET_SERVICE_OPTION_T)+#define VCHIQ_IOC_DUMP_PHYS_MEM \+	_IOW(VCHIQ_IOC_MAGIC,  15, VCHIQ_DUMP_MEM_T)+#define VCHIQ_IOC_MAX                  15++#endifdiff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,456 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++/* ---- Include Files ---------------------------------------------------- */++#include <linux/kernel.h>+#include <linux/module.h>+#include <linux/mutex.h>++#include "vchiq_core.h"+#include "vchiq_arm.h"++/* ---- Public Variables ------------------------------------------------- */++/* ---- Private Constants and Types -------------------------------------- */++struct bulk_waiter_node {+	struct bulk_waiter bulk_waiter;+	int pid;+	struct list_head list;+};++struct vchiq_instance_struct {+	VCHIQ_STATE_T *state;++	int connected;++	struct list_head bulk_waiter_list;+	struct mutex bulk_waiter_list_mutex;+};++static VCHIQ_STATUS_T+vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data,+	unsigned int size, VCHIQ_BULK_DIR_T dir);++/****************************************************************************+*+*   vchiq_initialise+*+***************************************************************************/+#define VCHIQ_INIT_RETRIES 10+VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instanceOut)+{+	VCHIQ_STATUS_T status = VCHIQ_ERROR;+	VCHIQ_STATE_T *state;+	VCHIQ_INSTANCE_T instance = NULL;+        int i;++	vchiq_log_trace(vchiq_core_log_level, "%s called", __func__);++        /* VideoCore may not be ready due to boot up timing.+           It may never be ready if kernel and firmware are mismatched, so don't block forever. */+        for (i=0; i<VCHIQ_INIT_RETRIES; i++) {+		state = vchiq_get_state();+		if (state)+			break;+		udelay(500);+	}+	if (i==VCHIQ_INIT_RETRIES) {+		vchiq_log_error(vchiq_core_log_level,+			"%s: videocore not initialized\n", __func__);+		goto failed;+	} else if (i>0) {+		vchiq_log_warning(vchiq_core_log_level,+			"%s: videocore initialized after %d retries\n", __func__, i);+	}++	instance = kzalloc(sizeof(*instance), GFP_KERNEL);+	if (!instance) {+		vchiq_log_error(vchiq_core_log_level,+			"%s: error allocating vchiq instance\n", __func__);+		goto failed;+	}++	instance->connected = 0;+	instance->state = state;+	mutex_init(&instance->bulk_waiter_list_mutex);+	INIT_LIST_HEAD(&instance->bulk_waiter_list);++	*instanceOut = instance;++	status = VCHIQ_SUCCESS;++failed:+	vchiq_log_trace(vchiq_core_log_level,+		"%s(%p): returning %d", __func__, instance, status);++	return status;+}+EXPORT_SYMBOL(vchiq_initialise);++/****************************************************************************+*+*   vchiq_shutdown+*+***************************************************************************/++VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance)+{+	VCHIQ_STATUS_T status;+	VCHIQ_STATE_T *state = instance->state;++	vchiq_log_trace(vchiq_core_log_level,+		"%s(%p) called", __func__, instance);++	if (mutex_lock_interruptible(&state->mutex) != 0)+		return VCHIQ_RETRY;++	/* Remove all services */+	status = vchiq_shutdown_internal(state, instance);++	mutex_unlock(&state->mutex);++	vchiq_log_trace(vchiq_core_log_level,+		"%s(%p): returning %d", __func__, instance, status);++	if (status == VCHIQ_SUCCESS) {+		struct list_head *pos, *next;+		list_for_each_safe(pos, next,+				&instance->bulk_waiter_list) {+			struct bulk_waiter_node *waiter;+			waiter = list_entry(pos,+					struct bulk_waiter_node,+					list);+			list_del(pos);+			vchiq_log_info(vchiq_arm_log_level,+					"bulk_waiter - cleaned up %x "+					"for pid %d",+					(unsigned int)waiter, waiter->pid);+			kfree(waiter);+		}+		kfree(instance);+	}++	return status;+}+EXPORT_SYMBOL(vchiq_shutdown);++/****************************************************************************+*+*   vchiq_is_connected+*+***************************************************************************/++int vchiq_is_connected(VCHIQ_INSTANCE_T instance)+{+	return instance->connected;+}++/****************************************************************************+*+*   vchiq_connect+*+***************************************************************************/++VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance)+{+	VCHIQ_STATUS_T status;+	VCHIQ_STATE_T *state = instance->state;++	vchiq_log_trace(vchiq_core_log_level,+		"%s(%p) called", __func__, instance);++	if (mutex_lock_interruptible(&state->mutex) != 0) {+		vchiq_log_trace(vchiq_core_log_level,+			"%s: call to mutex_lock failed", __func__);+		status = VCHIQ_RETRY;+		goto failed;+	}+	status = vchiq_connect_internal(state, instance);++	if (status == VCHIQ_SUCCESS)+		instance->connected = 1;++	mutex_unlock(&state->mutex);++failed:+	vchiq_log_trace(vchiq_core_log_level,+		"%s(%p): returning %d", __func__, instance, status);++	return status;+}+EXPORT_SYMBOL(vchiq_connect);++/****************************************************************************+*+*   vchiq_add_service+*+***************************************************************************/++VCHIQ_STATUS_T vchiq_add_service(+	VCHIQ_INSTANCE_T              instance,+	const VCHIQ_SERVICE_PARAMS_T *params,+	VCHIQ_SERVICE_HANDLE_T       *phandle)+{+	VCHIQ_STATUS_T status;+	VCHIQ_STATE_T *state = instance->state;+	VCHIQ_SERVICE_T *service = NULL;+	int srvstate;++	vchiq_log_trace(vchiq_core_log_level,+		"%s(%p) called", __func__, instance);++	*phandle = VCHIQ_SERVICE_HANDLE_INVALID;++	srvstate = vchiq_is_connected(instance)+		? VCHIQ_SRVSTATE_LISTENING+		: VCHIQ_SRVSTATE_HIDDEN;++	service = vchiq_add_service_internal(+		state,+		params,+		srvstate,+		instance,+		NULL);++	if (service) {+		*phandle = service->handle;+		status = VCHIQ_SUCCESS;+	} else+		status = VCHIQ_ERROR;++	vchiq_log_trace(vchiq_core_log_level,+		"%s(%p): returning %d", __func__, instance, status);++	return status;+}+EXPORT_SYMBOL(vchiq_add_service);++/****************************************************************************+*+*   vchiq_open_service+*+***************************************************************************/++VCHIQ_STATUS_T vchiq_open_service(+	VCHIQ_INSTANCE_T              instance,+	const VCHIQ_SERVICE_PARAMS_T *params,+	VCHIQ_SERVICE_HANDLE_T       *phandle)+{+	VCHIQ_STATUS_T   status = VCHIQ_ERROR;+	VCHIQ_STATE_T   *state = instance->state;+	VCHIQ_SERVICE_T *service = NULL;++	vchiq_log_trace(vchiq_core_log_level,+		"%s(%p) called", __func__, instance);++	*phandle = VCHIQ_SERVICE_HANDLE_INVALID;++	if (!vchiq_is_connected(instance))+		goto failed;++	service = vchiq_add_service_internal(state,+		params,+		VCHIQ_SRVSTATE_OPENING,+		instance,+		NULL);++	if (service) {+		status = vchiq_open_service_internal(service, current->pid);+		if (status == VCHIQ_SUCCESS)+			*phandle = service->handle;+		else+			vchiq_remove_service(service->handle);+	}++failed:+	vchiq_log_trace(vchiq_core_log_level,+		"%s(%p): returning %d", __func__, instance, status);++	return status;+}+EXPORT_SYMBOL(vchiq_open_service);++VCHIQ_STATUS_T+vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle,+	const void *data, unsigned int size, void *userdata)+{+	return vchiq_bulk_transfer(handle,+		VCHI_MEM_HANDLE_INVALID, (void *)data, size, userdata,+		VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_TRANSMIT);+}+EXPORT_SYMBOL(vchiq_queue_bulk_transmit);++VCHIQ_STATUS_T+vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data,+	unsigned int size, void *userdata)+{+	return vchiq_bulk_transfer(handle,+		VCHI_MEM_HANDLE_INVALID, data, size, userdata,+		VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_RECEIVE);+}+EXPORT_SYMBOL(vchiq_queue_bulk_receive);++VCHIQ_STATUS_T+vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, const void *data,+	unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode)+{+	VCHIQ_STATUS_T status;++	switch (mode) {+	case VCHIQ_BULK_MODE_NOCALLBACK:+	case VCHIQ_BULK_MODE_CALLBACK:+		status = vchiq_bulk_transfer(handle,+			VCHI_MEM_HANDLE_INVALID, (void *)data, size, userdata,+			mode, VCHIQ_BULK_TRANSMIT);+		break;+	case VCHIQ_BULK_MODE_BLOCKING:+		status = vchiq_blocking_bulk_transfer(handle,+			(void *)data, size, VCHIQ_BULK_TRANSMIT);+		break;+	default:+		return VCHIQ_ERROR;+	}++	return status;+}+EXPORT_SYMBOL(vchiq_bulk_transmit);++VCHIQ_STATUS_T+vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data,+	unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode)+{+	VCHIQ_STATUS_T status;++	switch (mode) {+	case VCHIQ_BULK_MODE_NOCALLBACK:+	case VCHIQ_BULK_MODE_CALLBACK:+		status = vchiq_bulk_transfer(handle,+			VCHI_MEM_HANDLE_INVALID, data, size, userdata,+			mode, VCHIQ_BULK_RECEIVE);+		break;+	case VCHIQ_BULK_MODE_BLOCKING:+		status = vchiq_blocking_bulk_transfer(handle,+			(void *)data, size, VCHIQ_BULK_RECEIVE);+		break;+	default:+		return VCHIQ_ERROR;+	}++	return status;+}+EXPORT_SYMBOL(vchiq_bulk_receive);++static VCHIQ_STATUS_T+vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data,+	unsigned int size, VCHIQ_BULK_DIR_T dir)+{+	VCHIQ_INSTANCE_T instance;+	VCHIQ_SERVICE_T *service;+	VCHIQ_STATUS_T status;+	struct bulk_waiter_node *waiter = NULL;+	struct list_head *pos;++	service = find_service_by_handle(handle);+	if (!service)+		return VCHIQ_ERROR;++	instance = service->instance;++	unlock_service(service);++	mutex_lock(&instance->bulk_waiter_list_mutex);+	list_for_each(pos, &instance->bulk_waiter_list) {+		if (list_entry(pos, struct bulk_waiter_node,+				list)->pid == current->pid) {+			waiter = list_entry(pos,+				struct bulk_waiter_node,+				list);+			list_del(pos);+			break;+		}+	}+	mutex_unlock(&instance->bulk_waiter_list_mutex);++	if (waiter) {+		VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk;+		if (bulk) {+			/* This thread has an outstanding bulk transfer. */+			if ((bulk->data != data) ||+				(bulk->size != size)) {+				/* This is not a retry of the previous one.+				** Cancel the signal when the transfer+				** completes. */+				spin_lock(&bulk_waiter_spinlock);+				bulk->userdata = NULL;+				spin_unlock(&bulk_waiter_spinlock);+			}+		}+	}++	if (!waiter) {+		waiter = kzalloc(sizeof(struct bulk_waiter_node), GFP_KERNEL);+		if (!waiter) {+			vchiq_log_error(vchiq_core_log_level,+				"%s - out of memory", __func__);+			return VCHIQ_ERROR;+		}+	}++	status = vchiq_bulk_transfer(handle, VCHI_MEM_HANDLE_INVALID,+		data, size, &waiter->bulk_waiter, VCHIQ_BULK_MODE_BLOCKING,+		dir);+	if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) ||+		!waiter->bulk_waiter.bulk) {+		VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk;+		if (bulk) {+			/* Cancel the signal when the transfer+			 ** completes. */+			spin_lock(&bulk_waiter_spinlock);+			bulk->userdata = NULL;+			spin_unlock(&bulk_waiter_spinlock);+		}+		kfree(waiter);+	} else {+		waiter->pid = current->pid;+		mutex_lock(&instance->bulk_waiter_list_mutex);+		list_add(&waiter->list, &instance->bulk_waiter_list);+		mutex_unlock(&instance->bulk_waiter_list_mutex);+		vchiq_log_info(vchiq_arm_log_level,+				"saved bulk_waiter %x for pid %d",+				(unsigned int)waiter, current->pid);+	}++	return status;+}diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,71 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef VCHIQ_MEMDRV_H+#define VCHIQ_MEMDRV_H++/* ---- Include Files ----------------------------------------------------- */++#include <linux/kernel.h>+#include "vchiq_if.h"++/* ---- Constants and Types ---------------------------------------------- */++typedef struct {+	 void                   *armSharedMemVirt;+	 dma_addr_t              armSharedMemPhys;+	 size_t                  armSharedMemSize;++	 void                   *vcSharedMemVirt;+	 dma_addr_t              vcSharedMemPhys;+	 size_t                  vcSharedMemSize;+} VCHIQ_SHARED_MEM_INFO_T;++/* ---- Variable Externs ------------------------------------------------- */++/* ---- Function Prototypes ---------------------------------------------- */++void vchiq_get_shared_mem_info(VCHIQ_SHARED_MEM_INFO_T *info);++VCHIQ_STATUS_T vchiq_memdrv_initialise(void);++VCHIQ_STATUS_T vchiq_userdrv_create_instance(+	const VCHIQ_PLATFORM_DATA_T * platform_data);++VCHIQ_STATUS_T vchiq_userdrv_suspend(+	const VCHIQ_PLATFORM_DATA_T * platform_data);++VCHIQ_STATUS_T vchiq_userdrv_resume(+	const VCHIQ_PLATFORM_DATA_T * platform_data);++#endifdiff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,58 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef VCHIQ_PAGELIST_H+#define VCHIQ_PAGELIST_H++#ifndef PAGE_SIZE+#define PAGE_SIZE 4096+#endif+#define CACHE_LINE_SIZE 32+#define PAGELIST_WRITE 0+#define PAGELIST_READ 1+#define PAGELIST_READ_WITH_FRAGMENTS 2++typedef struct pagelist_struct {+	unsigned long length;+	unsigned short type;+	unsigned short offset;+	unsigned long addrs[1];	/* N.B. 12 LSBs hold the number of following+				   pages at consecutive addresses. */+} PAGELIST_T;++typedef struct fragments_struct {+	char headbuf[CACHE_LINE_SIZE];+	char tailbuf[CACHE_LINE_SIZE];+} FRAGMENTS_T;++#endif /* VCHIQ_PAGELIST_H */diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,253 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */+++#include <linux/proc_fs.h>+#include "vchiq_core.h"+#include "vchiq_arm.h"++#if 1++int vchiq_proc_init(void)+{+	return 0;+}++void vchiq_proc_deinit(void)+{+}++#else++struct vchiq_proc_info {+	/* Global 'vc' proc entry used by all instances */+	struct proc_dir_entry *vc_cfg_dir;++	/* one entry per client process */+	struct proc_dir_entry *clients;++	/* log categories */+	struct proc_dir_entry *log_categories;+};++static struct vchiq_proc_info proc_info;++struct proc_dir_entry *vchiq_proc_top(void)+{+	BUG_ON(proc_info.vc_cfg_dir == NULL);+	return proc_info.vc_cfg_dir;+}++/****************************************************************************+*+*   log category entries+*+***************************************************************************/+#define PROC_WRITE_BUF_SIZE 256++#define VCHIQ_LOG_ERROR_STR   "error"+#define VCHIQ_LOG_WARNING_STR "warning"+#define VCHIQ_LOG_INFO_STR    "info"+#define VCHIQ_LOG_TRACE_STR   "trace"++static int log_cfg_read(char *buffer,+	char **start,+	off_t off,+	int count,+	int *eof,+	void *data)+{+	int len = 0;+	char *log_value = NULL;++	switch (*((int *)data)) {+	case VCHIQ_LOG_ERROR:+		log_value = VCHIQ_LOG_ERROR_STR;+		break;+	case VCHIQ_LOG_WARNING:+		log_value = VCHIQ_LOG_WARNING_STR;+		break;+	case VCHIQ_LOG_INFO:+		log_value = VCHIQ_LOG_INFO_STR;+		break;+	case VCHIQ_LOG_TRACE:+		log_value = VCHIQ_LOG_TRACE_STR;+		break;+	default:+		break;+	}++	len += sprintf(buffer + len,+		"%s\n",+		log_value ? log_value : "(null)");++	return len;+}+++static int log_cfg_write(struct file *file,+	const char __user *buffer,+	unsigned long count,+	void *data)+{+	int *log_module = data;+	char kbuf[PROC_WRITE_BUF_SIZE + 1];++	(void)file;++	memset(kbuf, 0, PROC_WRITE_BUF_SIZE + 1);+	if (count >= PROC_WRITE_BUF_SIZE)+		count = PROC_WRITE_BUF_SIZE;++	if (copy_from_user(kbuf,+		buffer,+		count) != 0)+		return -EFAULT;+	kbuf[count - 1] = 0;++	if (strncmp("error", kbuf, strlen("error")) == 0)+		*log_module = VCHIQ_LOG_ERROR;+	else if (strncmp("warning", kbuf, strlen("warning")) == 0)+		*log_module = VCHIQ_LOG_WARNING;+	else if (strncmp("info", kbuf, strlen("info")) == 0)+		*log_module = VCHIQ_LOG_INFO;+	else if (strncmp("trace", kbuf, strlen("trace")) == 0)+		*log_module = VCHIQ_LOG_TRACE;+	else+		*log_module = VCHIQ_LOG_DEFAULT;++	return count;+}++/* Log category proc entries */+struct vchiq_proc_log_entry {+	const char *name;+	int *plevel;+	struct proc_dir_entry *dir;+};++static struct vchiq_proc_log_entry vchiq_proc_log_entries[] = {+	{ "core", &vchiq_core_log_level },+	{ "msg",  &vchiq_core_msg_log_level },+	{ "sync", &vchiq_sync_log_level },+	{ "susp", &vchiq_susp_log_level },+	{ "arm",  &vchiq_arm_log_level },+};+static int n_log_entries =+	sizeof(vchiq_proc_log_entries)/sizeof(vchiq_proc_log_entries[0]);++/* create an entry under /proc/vc/log for each log category */+static int vchiq_proc_create_log_entries(struct proc_dir_entry *top)+{+	struct proc_dir_entry *dir;+	size_t i;+	int ret = 0;+	dir = proc_mkdir("log", proc_info.vc_cfg_dir);+	if (!dir)+		return -ENOMEM;+	proc_info.log_categories = dir;++	for (i = 0; i < n_log_entries; i++) {+		dir = create_proc_entry(vchiq_proc_log_entries[i].name,+					0644,+					proc_info.log_categories);+		if (!dir) {+			ret = -ENOMEM;+			break;+		}++		dir->read_proc = &log_cfg_read;+		dir->write_proc = &log_cfg_write;+		dir->data = (void *)vchiq_proc_log_entries[i].plevel;++		vchiq_proc_log_entries[i].dir = dir;+	}+	return ret;+}+++int vchiq_proc_init(void)+{+	BUG_ON(proc_info.vc_cfg_dir != NULL);++	proc_info.vc_cfg_dir = proc_mkdir("vc", NULL);+	if (proc_info.vc_cfg_dir == NULL)+		goto fail;++	proc_info.clients = proc_mkdir("clients",+				proc_info.vc_cfg_dir);+	if (!proc_info.clients)+		goto fail;++	if (vchiq_proc_create_log_entries(proc_info.vc_cfg_dir) != 0)+		goto fail;++	return 0;++fail:+	vchiq_proc_deinit();+	vchiq_log_error(vchiq_arm_log_level,+		"%s: failed to create proc directory",+		__func__);++	return -ENOMEM;+}++/* remove all the proc entries */+void vchiq_proc_deinit(void)+{+	/* log category entries */+	if (proc_info.log_categories) {+		size_t i;+		for (i = 0; i < n_log_entries; i++)+			if (vchiq_proc_log_entries[i].dir)+				remove_proc_entry(+					vchiq_proc_log_entries[i].name,+					proc_info.log_categories);++		remove_proc_entry(proc_info.log_categories->name,+				  proc_info.vc_cfg_dir);+	}+	if (proc_info.clients)+		remove_proc_entry(proc_info.clients->name,+				  proc_info.vc_cfg_dir);+	if (proc_info.vc_cfg_dir)+		remove_proc_entry(proc_info.vc_cfg_dir->name, NULL);+}++struct proc_dir_entry *vchiq_clients_top(void)+{+	return proc_info.clients;+}++#endifdiff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,815 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */+#include <linux/module.h>+#include <linux/types.h>++#include "interface/vchi/vchi.h"+#include "vchiq.h"+#include "vchiq_core.h"++#include "vchiq_util.h"++#include <stddef.h>++#define vchiq_status_to_vchi(status) ((int32_t)status)++typedef struct {+	VCHIQ_SERVICE_HANDLE_T handle;++	VCHIU_QUEUE_T queue;++	VCHI_CALLBACK_T callback;+	void *callback_param;+} SHIM_SERVICE_T;++/* ----------------------------------------------------------------------+ * return pointer to the mphi message driver function table+ * -------------------------------------------------------------------- */+const VCHI_MESSAGE_DRIVER_T *+vchi_mphi_message_driver_func_table(void)+{+	return NULL;+}++/* ----------------------------------------------------------------------+ * return a pointer to the 'single' connection driver fops+ * -------------------------------------------------------------------- */+const VCHI_CONNECTION_API_T *+single_get_func_table(void)+{+	return NULL;+}++VCHI_CONNECTION_T *vchi_create_connection(+	const VCHI_CONNECTION_API_T *function_table,+	const VCHI_MESSAGE_DRIVER_T *low_level)+{+	(void)function_table;+	(void)low_level;+	return NULL;+}++/***********************************************************+ * Name: vchi_msg_peek+ *+ * Arguments:  const VCHI_SERVICE_HANDLE_T handle,+ *             void **data,+ *             uint32_t *msg_size,+++ *             VCHI_FLAGS_T flags+ *+ * Description: Routine to return a pointer to the current message (to allow in+ *              place processing). The message can be removed using+ *              vchi_msg_remove when you're finished+ *+ * Returns: int32_t - success == 0+ *+ ***********************************************************/+int32_t vchi_msg_peek(VCHI_SERVICE_HANDLE_T handle,+	void **data,+	uint32_t *msg_size,+	VCHI_FLAGS_T flags)+{+	SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;+	VCHIQ_HEADER_T *header;++	WARN_ON((flags != VCHI_FLAGS_NONE) &&+		(flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));++	if (flags == VCHI_FLAGS_NONE)+		if (vchiu_queue_is_empty(&service->queue))+			return -1;++	header = vchiu_queue_peek(&service->queue);++	*data = header->data;+	*msg_size = header->size;++	return 0;+}+EXPORT_SYMBOL(vchi_msg_peek);++/***********************************************************+ * Name: vchi_msg_remove+ *+ * Arguments:  const VCHI_SERVICE_HANDLE_T handle,+ *+ * Description: Routine to remove a message (after it has been read with+ *              vchi_msg_peek)+ *+ * Returns: int32_t - success == 0+ *+ ***********************************************************/+int32_t vchi_msg_remove(VCHI_SERVICE_HANDLE_T handle)+{+	SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;+	VCHIQ_HEADER_T *header;++	header = vchiu_queue_pop(&service->queue);++	vchiq_release_message(service->handle, header);++	return 0;+}+EXPORT_SYMBOL(vchi_msg_remove);++/***********************************************************+ * Name: vchi_msg_queue+ *+ * Arguments:  VCHI_SERVICE_HANDLE_T handle,+ *             const void *data,+ *             uint32_t data_size,+ *             VCHI_FLAGS_T flags,+ *             void *msg_handle,+ *+ * Description: Thin wrapper to queue a message onto a connection+ *+ * Returns: int32_t - success == 0+ *+ ***********************************************************/+int32_t vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle,+	const void *data,+	uint32_t data_size,+	VCHI_FLAGS_T flags,+	void *msg_handle)+{+	SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;+	VCHIQ_ELEMENT_T element = {data, data_size};+	VCHIQ_STATUS_T status;++	(void)msg_handle;++	WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED);++	status = vchiq_queue_message(service->handle, &element, 1);++	/* vchiq_queue_message() may return VCHIQ_RETRY, so we need to+	** implement a retry mechanism since this function is supposed+	** to block until queued+	*/+	while (status == VCHIQ_RETRY) {+		msleep(1);+		status = vchiq_queue_message(service->handle, &element, 1);+	}++	return vchiq_status_to_vchi(status);+}+EXPORT_SYMBOL(vchi_msg_queue);++/***********************************************************+ * Name: vchi_bulk_queue_receive+ *+ * Arguments:  VCHI_BULK_HANDLE_T handle,+ *             void *data_dst,+ *             const uint32_t data_size,+ *             VCHI_FLAGS_T flags+ *             void *bulk_handle+ *+ * Description: Routine to setup a rcv buffer+ *+ * Returns: int32_t - success == 0+ *+ ***********************************************************/+int32_t vchi_bulk_queue_receive(VCHI_SERVICE_HANDLE_T handle,+	void *data_dst,+	uint32_t data_size,+	VCHI_FLAGS_T flags,+	void *bulk_handle)+{+	SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;+	VCHIQ_BULK_MODE_T mode;+	VCHIQ_STATUS_T status;++	switch ((int)flags) {+	case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE+		| VCHI_FLAGS_BLOCK_UNTIL_QUEUED:+		WARN_ON(!service->callback);+		mode = VCHIQ_BULK_MODE_CALLBACK;+		break;+	case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:+		mode = VCHIQ_BULK_MODE_BLOCKING;+		break;+	case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:+	case VCHI_FLAGS_NONE:+		mode = VCHIQ_BULK_MODE_NOCALLBACK;+		break;+	default:+		WARN(1, "unsupported message\n");+		return vchiq_status_to_vchi(VCHIQ_ERROR);+	}++	status = vchiq_bulk_receive(service->handle, data_dst, data_size,+		bulk_handle, mode);++	/* vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to+	** implement a retry mechanism since this function is supposed+	** to block until queued+	*/+	while (status == VCHIQ_RETRY) {+		msleep(1);+		status = vchiq_bulk_receive(service->handle, data_dst,+			data_size, bulk_handle, mode);+	}++	return vchiq_status_to_vchi(status);+}+EXPORT_SYMBOL(vchi_bulk_queue_receive);++/***********************************************************+ * Name: vchi_bulk_queue_transmit+ *+ * Arguments:  VCHI_BULK_HANDLE_T handle,+ *             const void *data_src,+ *             uint32_t data_size,+ *             VCHI_FLAGS_T flags,+ *             void *bulk_handle+ *+ * Description: Routine to transmit some data+ *+ * Returns: int32_t - success == 0+ *+ ***********************************************************/+int32_t vchi_bulk_queue_transmit(VCHI_SERVICE_HANDLE_T handle,+	const void *data_src,+	uint32_t data_size,+	VCHI_FLAGS_T flags,+	void *bulk_handle)+{+	SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;+	VCHIQ_BULK_MODE_T mode;+	VCHIQ_STATUS_T status;++	switch ((int)flags) {+	case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE+		| VCHI_FLAGS_BLOCK_UNTIL_QUEUED:+		WARN_ON(!service->callback);+		mode = VCHIQ_BULK_MODE_CALLBACK;+		break;+	case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ:+	case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:+		mode = VCHIQ_BULK_MODE_BLOCKING;+		break;+	case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:+	case VCHI_FLAGS_NONE:+		mode = VCHIQ_BULK_MODE_NOCALLBACK;+		break;+	default:+		WARN(1, "unsupported message\n");+		return vchiq_status_to_vchi(VCHIQ_ERROR);+	}++	status = vchiq_bulk_transmit(service->handle, data_src, data_size,+		bulk_handle, mode);++	/* vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to+	** implement a retry mechanism since this function is supposed+	** to block until queued+	*/+	while (status == VCHIQ_RETRY) {+		msleep(1);+		status = vchiq_bulk_transmit(service->handle, data_src,+			data_size, bulk_handle, mode);+	}++	return vchiq_status_to_vchi(status);+}+EXPORT_SYMBOL(vchi_bulk_queue_transmit);++/***********************************************************+ * Name: vchi_msg_dequeue+ *+ * Arguments:  VCHI_SERVICE_HANDLE_T handle,+ *             void *data,+ *             uint32_t max_data_size_to_read,+ *             uint32_t *actual_msg_size+ *             VCHI_FLAGS_T flags+ *+ * Description: Routine to dequeue a message into the supplied buffer+ *+ * Returns: int32_t - success == 0+ *+ ***********************************************************/+int32_t vchi_msg_dequeue(VCHI_SERVICE_HANDLE_T handle,+	void *data,+	uint32_t max_data_size_to_read,+	uint32_t *actual_msg_size,+	VCHI_FLAGS_T flags)+{+	SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;+	VCHIQ_HEADER_T *header;++	WARN_ON((flags != VCHI_FLAGS_NONE) &&+		(flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));++	if (flags == VCHI_FLAGS_NONE)+		if (vchiu_queue_is_empty(&service->queue))+			return -1;++	header = vchiu_queue_pop(&service->queue);++	memcpy(data, header->data, header->size < max_data_size_to_read ?+		header->size : max_data_size_to_read);++	*actual_msg_size = header->size;++	vchiq_release_message(service->handle, header);++	return 0;+}+EXPORT_SYMBOL(vchi_msg_dequeue);++/***********************************************************+ * Name: vchi_msg_queuev+ *+ * Arguments:  VCHI_SERVICE_HANDLE_T handle,+ *             VCHI_MSG_VECTOR_T *vector,+ *             uint32_t count,+ *             VCHI_FLAGS_T flags,+ *             void *msg_handle+ *+ * Description: Thin wrapper to queue a message onto a connection+ *+ * Returns: int32_t - success == 0+ *+ ***********************************************************/++vchiq_static_assert(sizeof(VCHI_MSG_VECTOR_T) == sizeof(VCHIQ_ELEMENT_T));+vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_base) ==+	offsetof(VCHIQ_ELEMENT_T, data));+vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_len) ==+	offsetof(VCHIQ_ELEMENT_T, size));++int32_t vchi_msg_queuev(VCHI_SERVICE_HANDLE_T handle,+	VCHI_MSG_VECTOR_T *vector,+	uint32_t count,+	VCHI_FLAGS_T flags,+	void *msg_handle)+{+	SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;++	(void)msg_handle;++	WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED);++	return vchiq_status_to_vchi(vchiq_queue_message(service->handle,+		(const VCHIQ_ELEMENT_T *)vector, count));+}+EXPORT_SYMBOL(vchi_msg_queuev);++/***********************************************************+ * Name: vchi_held_msg_release+ *+ * Arguments:  VCHI_HELD_MSG_T *message+ *+ * Description: Routine to release a held message (after it has been read with+ *              vchi_msg_hold)+ *+ * Returns: int32_t - success == 0+ *+ ***********************************************************/+int32_t vchi_held_msg_release(VCHI_HELD_MSG_T *message)+{+	vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)message->service,+		(VCHIQ_HEADER_T *)message->message);++	return 0;+}++/***********************************************************+ * Name: vchi_msg_hold+ *+ * Arguments:  VCHI_SERVICE_HANDLE_T handle,+ *             void **data,+ *             uint32_t *msg_size,+ *             VCHI_FLAGS_T flags,+ *             VCHI_HELD_MSG_T *message_handle+ *+ * Description: Routine to return a pointer to the current message (to allow+ *              in place processing). The message is dequeued - don't forget+ *              to release the message using vchi_held_msg_release when you're+ *              finished.+ *+ * Returns: int32_t - success == 0+ *+ ***********************************************************/+int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle,+	void **data,+	uint32_t *msg_size,+	VCHI_FLAGS_T flags,+	VCHI_HELD_MSG_T *message_handle)+{+	SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;+	VCHIQ_HEADER_T *header;++	WARN_ON((flags != VCHI_FLAGS_NONE) &&+		(flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));++	if (flags == VCHI_FLAGS_NONE)+		if (vchiu_queue_is_empty(&service->queue))+			return -1;++	header = vchiu_queue_pop(&service->queue);++	*data = header->data;+	*msg_size = header->size;++	message_handle->service =+		(struct opaque_vchi_service_t *)service->handle;+	message_handle->message = header;++	return 0;+}++/***********************************************************+ * Name: vchi_initialise+ *+ * Arguments: VCHI_INSTANCE_T *instance_handle+ *            VCHI_CONNECTION_T **connections+ *            const uint32_t num_connections+ *+ * Description: Initialises the hardware but does not transmit anything+ *              When run as a Host App this will be called twice hence the need+ *              to malloc the state information+ *+ * Returns: 0 if successful, failure otherwise+ *+ ***********************************************************/++int32_t vchi_initialise(VCHI_INSTANCE_T *instance_handle)+{+	VCHIQ_INSTANCE_T instance;+	VCHIQ_STATUS_T status;++	status = vchiq_initialise(&instance);++	*instance_handle = (VCHI_INSTANCE_T)instance;++	return vchiq_status_to_vchi(status);+}+EXPORT_SYMBOL(vchi_initialise);++/***********************************************************+ * Name: vchi_connect+ *+ * Arguments: VCHI_CONNECTION_T **connections+ *            const uint32_t num_connections+ *            VCHI_INSTANCE_T instance_handle)+ *+ * Description: Starts the command service on each connection,+ *              causing INIT messages to be pinged back and forth+ *+ * Returns: 0 if successful, failure otherwise+ *+ ***********************************************************/+int32_t vchi_connect(VCHI_CONNECTION_T **connections,+	const uint32_t num_connections,+	VCHI_INSTANCE_T instance_handle)+{+	VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;++	(void)connections;+	(void)num_connections;++	return vchiq_connect(instance);+}+EXPORT_SYMBOL(vchi_connect);+++/***********************************************************+ * Name: vchi_disconnect+ *+ * Arguments: VCHI_INSTANCE_T instance_handle+ *+ * Description: Stops the command service on each connection,+ *              causing DE-INIT messages to be pinged back and forth+ *+ * Returns: 0 if successful, failure otherwise+ *+ ***********************************************************/+int32_t vchi_disconnect(VCHI_INSTANCE_T instance_handle)+{+	VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;+	return vchiq_status_to_vchi(vchiq_shutdown(instance));+}+EXPORT_SYMBOL(vchi_disconnect);+++/***********************************************************+ * Name: vchi_service_open+ * Name: vchi_service_create+ *+ * Arguments: VCHI_INSTANCE_T *instance_handle+ *            SERVICE_CREATION_T *setup,+ *            VCHI_SERVICE_HANDLE_T *handle+ *+ * Description: Routine to open a service+ *+ * Returns: int32_t - success == 0+ *+ ***********************************************************/++static VCHIQ_STATUS_T shim_callback(VCHIQ_REASON_T reason,+	VCHIQ_HEADER_T *header, VCHIQ_SERVICE_HANDLE_T handle, void *bulk_user)+{+	SHIM_SERVICE_T *service =+		(SHIM_SERVICE_T *)VCHIQ_GET_SERVICE_USERDATA(handle);++	switch (reason) {+	case VCHIQ_MESSAGE_AVAILABLE:+		vchiu_queue_push(&service->queue, header);++		if (service->callback)+			service->callback(service->callback_param,+				VCHI_CALLBACK_MSG_AVAILABLE, NULL);+		break;+	case VCHIQ_BULK_TRANSMIT_DONE:+		if (service->callback)+			service->callback(service->callback_param,+				VCHI_CALLBACK_BULK_SENT, bulk_user);+		break;+	case VCHIQ_BULK_RECEIVE_DONE:+		if (service->callback)+			service->callback(service->callback_param,+				VCHI_CALLBACK_BULK_RECEIVED, bulk_user);+		break;+	case VCHIQ_SERVICE_CLOSED:+		if (service->callback)+			service->callback(service->callback_param,+				VCHI_CALLBACK_SERVICE_CLOSED, NULL);+		break;+	case VCHIQ_SERVICE_OPENED:+		/* No equivalent VCHI reason */+		break;+	case VCHIQ_BULK_TRANSMIT_ABORTED:+		if (service->callback)+			service->callback(service->callback_param,+				VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, bulk_user);+		break;+	case VCHIQ_BULK_RECEIVE_ABORTED:+		if (service->callback)+			service->callback(service->callback_param,+				VCHI_CALLBACK_BULK_RECEIVE_ABORTED, bulk_user);+		break;+	default:+		WARN(1, "not supported\n");+		break;+	}++	return VCHIQ_SUCCESS;+}++static SHIM_SERVICE_T *service_alloc(VCHIQ_INSTANCE_T instance,+	SERVICE_CREATION_T *setup)+{+	SHIM_SERVICE_T *service = kzalloc(sizeof(SHIM_SERVICE_T), GFP_KERNEL);++	(void)instance;++	if (service) {+		if (vchiu_queue_init(&service->queue, 64)) {+			service->callback = setup->callback;+			service->callback_param = setup->callback_param;+		} else {+			kfree(service);+			service = NULL;+		}+	}++	return service;+}++static void service_free(SHIM_SERVICE_T *service)+{+	if (service) {+		vchiu_queue_delete(&service->queue);+		kfree(service);+	}+}++int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle,+	SERVICE_CREATION_T *setup,+	VCHI_SERVICE_HANDLE_T *handle)+{+	VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;+	SHIM_SERVICE_T *service = service_alloc(instance, setup);+	if (service) {+		VCHIQ_SERVICE_PARAMS_T params;+		VCHIQ_STATUS_T status;++		memset(¶ms, 0, sizeof(params));+		params.fourcc = setup->service_id;+		params.callback = shim_callback;+		params.userdata = service;+		params.version = setup->version.version;+		params.version_min = setup->version.version_min;++		status = vchiq_open_service(instance, ¶ms,+			&service->handle);+		if (status != VCHIQ_SUCCESS) {+			service_free(service);+			service = NULL;+		}+	}++	*handle = (VCHI_SERVICE_HANDLE_T)service;++	return (service != NULL) ? 0 : -1;+}+EXPORT_SYMBOL(vchi_service_open);++int32_t vchi_service_create(VCHI_INSTANCE_T instance_handle,+	SERVICE_CREATION_T *setup,+	VCHI_SERVICE_HANDLE_T *handle)+{+	VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;+	SHIM_SERVICE_T *service = service_alloc(instance, setup);+	if (service) {+		VCHIQ_SERVICE_PARAMS_T params;+		VCHIQ_STATUS_T status;++		memset(¶ms, 0, sizeof(params));+		params.fourcc = setup->service_id;+		params.callback = shim_callback;+		params.userdata = service;+		params.version = setup->version.version;+		params.version_min = setup->version.version_min;+		status = vchiq_add_service(instance, ¶ms, &service->handle);++		if (status != VCHIQ_SUCCESS) {+			service_free(service);+			service = NULL;+		}+	}++	*handle = (VCHI_SERVICE_HANDLE_T)service;++	return (service != NULL) ? 0 : -1;+}+EXPORT_SYMBOL(vchi_service_create);++int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle)+{+	int32_t ret = -1;+	SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;+	if (service) {+		VCHIQ_STATUS_T status = vchiq_close_service(service->handle);+		if (status == VCHIQ_SUCCESS) {+			service_free(service);+			service = NULL;+		}++		ret = vchiq_status_to_vchi(status);+	}+	return ret;+}+EXPORT_SYMBOL(vchi_service_close);++int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle)+{+	int32_t ret = -1;+	SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;+	if (service) {+		VCHIQ_STATUS_T status = vchiq_remove_service(service->handle);+		if (status == VCHIQ_SUCCESS) {+			service_free(service);+			service = NULL;+		}++		ret = vchiq_status_to_vchi(status);+	}+	return ret;+}+EXPORT_SYMBOL(vchi_service_destroy);++int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle, short *peer_version )+{+   int32_t ret = -1;+   SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;+   if(service)+   {+      VCHIQ_STATUS_T status = vchiq_get_peer_version(service->handle, peer_version);+      ret = vchiq_status_to_vchi( status );+   }+   return ret;+}+EXPORT_SYMBOL(vchi_get_peer_version);++/* ----------------------------------------------------------------------+ * read a uint32_t from buffer.+ * network format is defined to be little endian+ * -------------------------------------------------------------------- */+uint32_t+vchi_readbuf_uint32(const void *_ptr)+{+	const unsigned char *ptr = _ptr;+	return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);+}++/* ----------------------------------------------------------------------+ * write a uint32_t to buffer.+ * network format is defined to be little endian+ * -------------------------------------------------------------------- */+void+vchi_writebuf_uint32(void *_ptr, uint32_t value)+{+	unsigned char *ptr = _ptr;+	ptr[0] = (unsigned char)((value >> 0)  & 0xFF);+	ptr[1] = (unsigned char)((value >> 8)  & 0xFF);+	ptr[2] = (unsigned char)((value >> 16) & 0xFF);+	ptr[3] = (unsigned char)((value >> 24) & 0xFF);+}++/* ----------------------------------------------------------------------+ * read a uint16_t from buffer.+ * network format is defined to be little endian+ * -------------------------------------------------------------------- */+uint16_t+vchi_readbuf_uint16(const void *_ptr)+{+	const unsigned char *ptr = _ptr;+	return ptr[0] | (ptr[1] << 8);+}++/* ----------------------------------------------------------------------+ * write a uint16_t into the buffer.+ * network format is defined to be little endian+ * -------------------------------------------------------------------- */+void+vchi_writebuf_uint16(void *_ptr, uint16_t value)+{+	unsigned char *ptr = _ptr;+	ptr[0] = (value >> 0)  & 0xFF;+	ptr[1] = (value >> 8)  & 0xFF;+}++/***********************************************************+ * Name: vchi_service_use+ *+ * Arguments: const VCHI_SERVICE_HANDLE_T handle+ *+ * Description: Routine to increment refcount on a service+ *+ * Returns: void+ *+ ***********************************************************/+int32_t vchi_service_use(const VCHI_SERVICE_HANDLE_T handle)+{+	int32_t ret = -1;+	SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;+	if (service)+		ret = vchiq_status_to_vchi(vchiq_use_service(service->handle));+	return ret;+}+EXPORT_SYMBOL(vchi_service_use);++/***********************************************************+ * Name: vchi_service_release+ *+ * Arguments: const VCHI_SERVICE_HANDLE_T handle+ *+ * Description: Routine to decrement refcount on a service+ *+ * Returns: void+ *+ ***********************************************************/+int32_t vchi_service_release(const VCHI_SERVICE_HANDLE_T handle)+{+	int32_t ret = -1;+	SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;+	if (service)+		ret = vchiq_status_to_vchi(+			vchiq_release_service(service->handle));+	return ret;+}+EXPORT_SYMBOL(vchi_service_release);diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,151 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#include "vchiq_util.h"++static inline int is_pow2(int i)+{+	return i && !(i & (i - 1));+}++int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size)+{+	WARN_ON(!is_pow2(size));++	queue->size = size;+	queue->read = 0;+	queue->write = 0;++	sema_init(&queue->pop, 0);+	sema_init(&queue->push, 0);++	queue->storage = kzalloc(size * sizeof(VCHIQ_HEADER_T *), GFP_KERNEL);+	if (queue->storage == NULL) {+		vchiu_queue_delete(queue);+		return 0;+	}+	return 1;+}++void vchiu_queue_delete(VCHIU_QUEUE_T *queue)+{+	if (queue->storage != NULL)+		kfree(queue->storage);+}++int vchiu_queue_is_empty(VCHIU_QUEUE_T *queue)+{+	return queue->read == queue->write;+}++int vchiu_queue_is_full(VCHIU_QUEUE_T *queue)+{+	return queue->write == queue->read + queue->size;+}++void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header)+{+	while (queue->write == queue->read + queue->size) {+		if (down_interruptible(&queue->pop) != 0) {+			flush_signals(current);+		}+	}++	/*+	 * Write to queue->storage must be visible after read from+	 * queue->read+	 */+	smp_mb();++	queue->storage[queue->write & (queue->size - 1)] = header;++	/*+	 * Write to queue->storage must be visible before write to+	 * queue->write+	 */+	smp_wmb();++	queue->write++;++	up(&queue->push);+}++VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue)+{+	while (queue->write == queue->read) {+		if (down_interruptible(&queue->push) != 0) {+			flush_signals(current);+		}+	}++	up(&queue->push); // We haven't removed anything from the queue.++	/*+	 * Read from queue->storage must be visible after read from+	 * queue->write+	 */+	smp_rmb();++	return queue->storage[queue->read & (queue->size - 1)];+}++VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue)+{+	VCHIQ_HEADER_T *header;++	while (queue->write == queue->read) {+		if (down_interruptible(&queue->push) != 0) {+			flush_signals(current);+		}+	}++	/*+	 * Read from queue->storage must be visible after read from+	 * queue->write+	 */+	smp_rmb();++	header = queue->storage[queue->read & (queue->size - 1)];++	/*+	 * Read from queue->storage must be visible before write to+	 * queue->read+	 */+	smp_mb();++	queue->read++;++	up(&queue->pop);++	return header;+}diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,81 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef VCHIQ_UTIL_H+#define VCHIQ_UTIL_H++#include <linux/types.h>+#include <linux/semaphore.h>+#include <linux/mutex.h>+#include <linux/bitops.h>+#include <linux/kthread.h>+#include <linux/wait.h>+#include <linux/vmalloc.h>+#include <linux/jiffies.h>+#include <linux/delay.h>+#include <linux/string.h>+#include <linux/types.h>+#include <linux/interrupt.h>+#include <linux/random.h>+#include <linux/sched.h>+#include <linux/ctype.h>+#include <linux/uaccess.h>+#include <linux/time.h>  /* for time_t */+#include <linux/slab.h>+#include <linux/vmalloc.h>++#include "vchiq_if.h"++typedef struct {+	int size;+	int read;+	int write;++	struct semaphore pop;+	struct semaphore push;++	VCHIQ_HEADER_T **storage;+} VCHIU_QUEUE_T;++extern int  vchiu_queue_init(VCHIU_QUEUE_T *queue, int size);+extern void vchiu_queue_delete(VCHIU_QUEUE_T *queue);++extern int vchiu_queue_is_empty(VCHIU_QUEUE_T *queue);+extern int vchiu_queue_is_full(VCHIU_QUEUE_T *queue);++extern void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header);++extern VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue);+extern VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue);++#endifdiff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c--- linux-3.11.10.orig/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,59 @@+/**+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") version 2, as published by the Free+ * Software Foundation.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */+#include "vchiq_build_info.h"+#include <linux/broadcom/vc_debug_sym.h>++VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_hostname, "dc4-arm-01" );+VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_version, "9245b4c35b99b3870e1f7dc598c5692b3c66a6f0 (tainted)" );+VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_time,    __TIME__ );+VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_date,    __DATE__ );++const char *vchiq_get_build_hostname( void )+{+   return vchiq_build_hostname;+}++const char *vchiq_get_build_version( void )+{+   return vchiq_build_version;+}++const char *vchiq_get_build_date( void )+{+   return vchiq_build_date;+}++const char *vchiq_get_build_time( void )+{+   return vchiq_build_time;+}diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/Kconfig linux-3.11.10/drivers/misc/vc04_services/Kconfig--- linux-3.11.10.orig/drivers/misc/vc04_services/Kconfig	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/Kconfig	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,9 @@+config BCM2708_VCHIQ+	tristate "Videocore VCHIQ"+	depends on MACH_BCM2708+	default y+	help+		Kernel to VideoCore communication interface for the+		BCM2708 family of products.+		Defaults to Y when the Broadcom Videocore services+		are included in the build, N otherwise.diff -Nur linux-3.11.10.orig/drivers/misc/vc04_services/Makefile linux-3.11.10/drivers/misc/vc04_services/Makefile--- linux-3.11.10.orig/drivers/misc/vc04_services/Makefile	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/misc/vc04_services/Makefile	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,17 @@+ifeq ($(CONFIG_MACH_BCM2708),y)++obj-$(CONFIG_BCM2708_VCHIQ)	+= vchiq.o++vchiq-objs := \+   interface/vchiq_arm/vchiq_core.o  \+   interface/vchiq_arm/vchiq_arm.o \+   interface/vchiq_arm/vchiq_kern_lib.o \+   interface/vchiq_arm/vchiq_2835_arm.o \+   interface/vchiq_arm/vchiq_proc.o \+   interface/vchiq_arm/vchiq_shim.o \+   interface/vchiq_arm/vchiq_util.o \+   interface/vchiq_arm/vchiq_connected.o \++EXTRA_CFLAGS += -DVCOS_VERIFY_BKPTS=1 -Idrivers/misc/vc04_services -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000++endifdiff -Nur linux-3.11.10.orig/drivers/mmc/card/block.c linux-3.11.10/drivers/mmc/card/block.c--- linux-3.11.10.orig/drivers/mmc/card/block.c	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/mmc/card/block.c	2014-02-07 19:57:28.000000000 +0100@@ -1322,7 +1322,7 @@ 			brq->data.blocks = 1; 	} -	if (brq->data.blocks > 1 || do_rel_wr) {+	if (brq->data.blocks > 1 || do_rel_wr || card->host->caps2 & MMC_CAP2_FORCE_MULTIBLOCK) { 		/* SPI multiblock writes terminate using a special 		 * token, not a STOP_TRANSMISSION request. 		 */diff -Nur linux-3.11.10.orig/drivers/mmc/core/sd.c linux-3.11.10/drivers/mmc/core/sd.c--- linux-3.11.10.orig/drivers/mmc/core/sd.c	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/mmc/core/sd.c	2014-02-07 19:57:28.000000000 +0100@@ -13,6 +13,8 @@ #include <linux/err.h> #include <linux/slab.h> #include <linux/stat.h>+#include <linux/jiffies.h>+#include <linux/nmi.h>  #include <linux/mmc/host.h> #include <linux/mmc/card.h>@@ -58,6 +60,15 @@ 		__res & __mask;						\ 	}) +// timeout for tries+static const unsigned long retry_timeout_ms= 10*1000;++// try at least 10 times, even if timeout is reached+static const int retry_min_tries= 10;++// delay between tries+static const unsigned long retry_delay_ms= 10;+ /*  * Given the decoded CSD structure, decode the raw CID to our CID structure.  */@@ -210,12 +221,62 @@ }  /*- * Fetch and process SD Status register.+ * Fetch and process SD Configuration Register.+ */+static int mmc_read_scr(struct mmc_card *card)+{+	unsigned long timeout_at;+	int err, tries;++	timeout_at= jiffies + msecs_to_jiffies( retry_timeout_ms );+	tries= 		0;++	while( tries < retry_min_tries || time_before( jiffies, timeout_at ) )+	{+		unsigned long delay_at;+		tries++;++		err = mmc_app_send_scr(card, card->raw_scr);+		if( !err )+			break; // success!!!++		touch_nmi_watchdog();	  // we are still alive!++		// delay+		delay_at= jiffies + msecs_to_jiffies( retry_delay_ms );+		while( time_before( jiffies, delay_at ) )+		{+			mdelay( 1 );+			touch_nmi_watchdog();	  // we are still alive!+		}+	}++	if( err)+	{+		pr_err("%s: failed to read SD Configuration register (SCR) after %d tries during %lu ms, error %d\n", mmc_hostname(card->host), tries, retry_timeout_ms, err );+		return err;+	}++	if( tries > 1 )+	{+		pr_info("%s: could read SD Configuration register (SCR) at the %dth attempt\n", mmc_hostname(card->host), tries );+	}++	err = mmc_decode_scr(card);+	if (err)+		return err;++	return err;+}++/*+ * Fetch and process SD Status Register.  */ static int mmc_read_ssr(struct mmc_card *card) {+	unsigned long timeout_at; 	unsigned int au, es, et, eo;-	int err, i;+	int err, i, tries; 	u32 *ssr;  	if (!(card->csd.cmdclass & CCC_APP_SPEC)) {@@ -228,14 +289,40 @@ 	if (!ssr) 		return -ENOMEM; -	err = mmc_app_sd_status(card, ssr);-	if (err) {-		pr_warning("%s: problem reading SD Status "-			"register.\n", mmc_hostname(card->host));-		err = 0;+	timeout_at= jiffies + msecs_to_jiffies( retry_timeout_ms );+	tries= 		0;++	while( tries < retry_min_tries || time_before( jiffies, timeout_at ) )+	{+		unsigned long delay_at;+		tries++;++		err= mmc_app_sd_status(card, ssr);+		if( !err )+			break; // sucess!!!++		touch_nmi_watchdog();	  // we are still alive!++		// delay+		delay_at= jiffies + msecs_to_jiffies( retry_delay_ms );+		while( time_before( jiffies, delay_at ) )+		{+			mdelay( 1 );+			touch_nmi_watchdog();	  // we are still alive!+		}+	}++	if( err)+	{+		pr_err("%s: failed to read SD Status register (SSR) after %d tries during %lu ms, error %d\n", mmc_hostname(card->host), tries, retry_timeout_ms, err ); 		goto out; 	} +	if( tries > 1 )+	{+		pr_info("%s: read SD Status register (SSR) after %d attempts\n", mmc_hostname(card->host), tries );+	}+ 	for (i = 0; i < 16; i++) 		ssr[i] = be32_to_cpu(ssr[i]); @@ -813,14 +900,10 @@  	if (!reinit) { 		/*-		 * Fetch SCR from card.+		 * Fetch and decode SD Configuration register. 		 */-		err = mmc_app_send_scr(card, card->raw_scr);-		if (err)-			return err;--		err = mmc_decode_scr(card);-		if (err)+		err = mmc_read_scr(card);+		if( err ) 			return err;  		/*diff -Nur linux-3.11.10.orig/drivers/mmc/host/Kconfig linux-3.11.10/drivers/mmc/host/Kconfig--- linux-3.11.10.orig/drivers/mmc/host/Kconfig	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/mmc/host/Kconfig	2014-02-07 19:57:28.000000000 +0100@@ -260,6 +260,27 @@  	  If you have a controller with this interface, say Y or M here. +config MMC_SDHCI_BCM2708+	tristate "SDHCI support on BCM2708"+	depends on MMC_SDHCI && MACH_BCM2708+	select MMC_SDHCI_IO_ACCESSORS+	help+	  This selects the Secure Digital Host Controller Interface (SDHCI)+	  often referrered to as the eMMC block.++	  If you have a controller with this interface, say Y or M here.++	  If unsure, say N.++config MMC_SDHCI_BCM2708_DMA+	bool "DMA support on BCM2708 Arasan controller"+	depends on MMC_SDHCI_BCM2708+	help+	Enable DMA support on the Arasan SDHCI controller in Broadcom 2708+	  based chips.++	  If unsure, say N.+ config MMC_SDHCI_BCM2835 	tristate "SDHCI platform support for the BCM2835 SD/MMC Controller" 	depends on ARCH_BCM2835diff -Nur linux-3.11.10.orig/drivers/mmc/host/Makefile linux-3.11.10/drivers/mmc/host/Makefile--- linux-3.11.10.orig/drivers/mmc/host/Makefile	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/mmc/host/Makefile	2014-02-07 19:57:28.000000000 +0100@@ -15,6 +15,7 @@ obj-$(CONFIG_MMC_SDHCI_S3C)	+= sdhci-s3c.o obj-$(CONFIG_MMC_SDHCI_SIRF)   	+= sdhci-sirf.o obj-$(CONFIG_MMC_SDHCI_SPEAR)	+= sdhci-spear.o+obj-$(CONFIG_MMC_SDHCI_BCM2708)	+= sdhci-bcm2708.o obj-$(CONFIG_MMC_WBSD)		+= wbsd.o obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o obj-$(CONFIG_MMC_OMAP)		+= omap.odiff -Nur linux-3.11.10.orig/drivers/mmc/host/sdhci-bcm2708.c linux-3.11.10/drivers/mmc/host/sdhci-bcm2708.c--- linux-3.11.10.orig/drivers/mmc/host/sdhci-bcm2708.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/mmc/host/sdhci-bcm2708.c	2014-02-07 19:57:28.000000000 +0100@@ -0,0 +1,1420 @@+/*+ * sdhci-bcm2708.c Support for SDHCI device on BCM2708+ * Copyright (c) 2010 Broadcom+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License version 2 as+ * published by the Free Software Foundation.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.+ */++/* Supports:+ * SDHCI platform device - Arasan SD controller in BCM2708+ *+ * Inspired by sdhci-pci.c, by Pierre Ossman+ */++#include <linux/delay.h>+#include <linux/highmem.h>+#include <linux/platform_device.h>+#include <linux/module.h>+#include <linux/mmc/mmc.h>+#include <linux/mmc/host.h>+#include <linux/mmc/sd.h>++#include <linux/io.h>+#include <linux/dma-mapping.h>+#include <mach/dma.h>++#include "sdhci.h"++/*****************************************************************************\+ *									     *+ * Configuration							     *+ *									     *+\*****************************************************************************/++#define DRIVER_NAME "bcm2708_sdhci"++/* for the time being insist on DMA mode - PIO seems not to work */+#ifndef CONFIG_MMC_SDHCI_BCM2708_DMA+#warning Non-DMA (PIO) version of this driver currently unavailable+#endif+#undef CONFIG_MMC_SDHCI_BCM2708_DMA+#define CONFIG_MMC_SDHCI_BCM2708_DMA y++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA+/* #define CHECK_DMA_USE */+#endif+//#define LOG_REGISTERS++#define USE_SCHED_TIME+#define USE_SPACED_WRITES_2CLK 1  /* space consecutive register writes */+#define USE_SOFTWARE_TIMEOUTS 1   /* not hardware timeouts */+#define SOFTWARE_ERASE_TIMEOUT_SEC 30++#define SDHCI_BCM_DMA_CHAN 4   /* this default is normally overriden */+#define SDHCI_BCM_DMA_WAITS 0  /* delays slowing DMA transfers: 0-31 */+/* We are worried that SD card DMA use may be blocking the AXI bus for others */++/*! TODO: obtain these from the physical address */+#define DMA_SDHCI_BASE	 0x7e300000  /* EMMC register block on Videocore */+#define DMA_SDHCI_BUFFER (DMA_SDHCI_BASE + SDHCI_BUFFER)++#define BCM2708_SDHCI_SLEEP_TIMEOUT 1000   /* msecs */++/* Mhz clock that the EMMC core is running at. Should match the platform clockman settings */+#define BCM2708_EMMC_CLOCK_FREQ 50000000++#define REG_EXRDFIFO_EN     0x80+#define REG_EXRDFIFO_CFG    0x84++int cycle_delay=2;++/*****************************************************************************\+ *									     *+ * Debug								     *+ *									     *+\*****************************************************************************/++++#define DBG(f, x...) \+	pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x)+//	printk(KERN_INFO DRIVER_NAME " [%s()]: " f, __func__,## x)//GRAYG+++/*****************************************************************************\+ *									     *+ * High Precision Time							     *+ *									     *+\*****************************************************************************/++#ifdef USE_SCHED_TIME++#include <mach/frc.h>++typedef unsigned long hptime_t;++#define FMT_HPT "lu"++static inline hptime_t hptime(void)+{+	return frc_clock_ticks32();+}++#define HPTIME_CLK_NS 1000ul++#else++typedef unsigned long hptime_t;++#define FMT_HPT "lu"++static inline hptime_t hptime(void)+{+	return jiffies;+}++#define HPTIME_CLK_NS (1000000000ul/HZ)++#endif++static inline unsigned long int since_ns(hptime_t t)+{+	return (unsigned long)((hptime() - t) * HPTIME_CLK_NS);+}++static bool allow_highspeed = 1;+static int emmc_clock_freq = BCM2708_EMMC_CLOCK_FREQ;+static bool sync_after_dma = 1;+static bool missing_status = 1;+static bool spurious_crc_acmd51 = 0;+bool enable_llm = 1;+bool extra_messages = 0;++#if 0+static void hptime_test(void)+{+	hptime_t now;+	hptime_t later;++	now = hptime();+	msleep(10);+	later = hptime();++	printk(KERN_INFO DRIVER_NAME": 10ms = %"FMT_HPT" clks "+	       "(from %"FMT_HPT" to %"FMT_HPT") = %luns\n",+	       later-now, now, later,+	       (unsigned long)(HPTIME_CLK_NS * (later - now)));++	now = hptime();+	msleep(1000);+	later = hptime();++	printk(KERN_INFO DRIVER_NAME": 1s = %"FMT_HPT" clks "+	       "(from %"FMT_HPT" to %"FMT_HPT") = %luns\n",+	       later-now, now, later,+	       (unsigned long)(HPTIME_CLK_NS * (later - now)));+}+#endif++/*****************************************************************************\+ *									     *+ * SDHCI core callbacks							     *+ *									     *+\*****************************************************************************/+++#ifdef CHECK_DMA_USE+/*#define CHECK_DMA_REG_USE*/+#endif++#ifdef CHECK_DMA_REG_USE+/* we don't expect anything to be using these registers during a+   DMA (except the IRQ status) - so check */+static void check_dma_reg_use(struct sdhci_host *host, int reg);+#else+#define check_dma_reg_use(host, reg)+#endif+++static inline u32 sdhci_bcm2708_raw_readl(struct sdhci_host *host, int reg)+{+	return readl(host->ioaddr + reg);+}++u32 sdhci_bcm2708_readl(struct sdhci_host *host, int reg)+{+	u32 l = sdhci_bcm2708_raw_readl(host, reg);++#ifdef LOG_REGISTERS+	printk(KERN_ERR "%s: readl from 0x%02x, value 0x%08x\n",+	       mmc_hostname(host->mmc), reg, l);+#endif+	check_dma_reg_use(host, reg);++	return l;+}++u16 sdhci_bcm2708_readw(struct sdhci_host *host, int reg)+{+	u32 l = sdhci_bcm2708_raw_readl(host, reg & ~3);+	u32 w = l >> (reg << 3 & 0x18) & 0xffff;++#ifdef LOG_REGISTERS+	printk(KERN_ERR "%s: readw from 0x%02x, value 0x%04x\n",+	       mmc_hostname(host->mmc), reg, w);+#endif+	check_dma_reg_use(host, reg);++	return (u16)w;+}++u8 sdhci_bcm2708_readb(struct sdhci_host *host, int reg)+{+	u32 l = sdhci_bcm2708_raw_readl(host, reg & ~3);+	u32 b = l >> (reg << 3 & 0x18) & 0xff;++#ifdef LOG_REGISTERS+	printk(KERN_ERR "%s: readb from 0x%02x, value 0x%02x\n",+	       mmc_hostname(host->mmc), reg, b);+#endif+	check_dma_reg_use(host, reg);++	return (u8)b;+}+++static void sdhci_bcm2708_raw_writel(struct sdhci_host *host, u32 val, int reg)+{+	u32 ier;++#if USE_SPACED_WRITES_2CLK+	static bool timeout_disabled = false;+	unsigned int ns_2clk = 0;++	/* The Arasan has a bugette whereby it may lose the content of+	 * successive writes to registers that are within two SD-card clock+	 * cycles of each other (a clock domain crossing problem).+	 * It seems, however, that the data register does not have this problem.+	 * (Which is just as well - otherwise we'd have to nobble the DMA engine+	 * too)+	 */+	if (reg != SDHCI_BUFFER && host->clock != 0) {+		/* host->clock is the clock freq in Hz */+		static hptime_t last_write_hpt;+		hptime_t now = hptime();+		ns_2clk = cycle_delay*1000000/(host->clock/1000);++		if (now == last_write_hpt || now == last_write_hpt+1) {+			 /* we can't guarantee any significant time has+			  * passed - we'll have to wait anyway ! */+			ndelay(ns_2clk);+		} else+		{+			/* we must have waited at least this many ns: */+			unsigned int ns_wait = HPTIME_CLK_NS *+					       (last_write_hpt - now - 1);+			if (ns_wait < ns_2clk)+				ndelay(ns_2clk - ns_wait);+		}+		last_write_hpt = now;+	}+#if USE_SOFTWARE_TIMEOUTS+	/* The Arasan is clocked for timeouts using the SD clock which is too+	 * fast for ERASE commands and causes issues. So we disable timeouts+	 * for ERASE */+	if (host->cmd != NULL && host->cmd->opcode == MMC_ERASE &&+            reg == (SDHCI_COMMAND & ~3)) {+		mod_timer(&host->timer,+                          jiffies + SOFTWARE_ERASE_TIMEOUT_SEC * HZ);+		ier = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE);+		ier &= ~SDHCI_INT_DATA_TIMEOUT;+		writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE);+		timeout_disabled = true;+		ndelay(ns_2clk);+	} else if (timeout_disabled) {+		ier = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE);+		ier |= SDHCI_INT_DATA_TIMEOUT;+		writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE);+		timeout_disabled = false;+		ndelay(ns_2clk);+	}+#endif+	writel(val, host->ioaddr + reg);+#else+	void __iomem * regaddr = host->ioaddr + reg;++	writel(val, regaddr);++	if (reg != SDHCI_BUFFER && reg != SDHCI_INT_STATUS && host->clock != 0)+	{+		int timeout = 100000;+		while (val != readl(regaddr) && --timeout > 0)+		   continue;++		if (timeout <= 0)+			printk(KERN_ERR "%s: writing 0x%X to reg 0x%X "+			       "always gives 0x%X\n",+			       mmc_hostname(host->mmc),+			       val, reg, readl(regaddr));+		BUG_ON(timeout <= 0);+	}+#endif+}+++void sdhci_bcm2708_writel(struct sdhci_host *host, u32 val, int reg)+{+#ifdef LOG_REGISTERS+	printk(KERN_ERR "%s: writel to 0x%02x, value 0x%08x\n",+	       mmc_hostname(host->mmc), reg, val);+#endif+	check_dma_reg_use(host, reg);++	sdhci_bcm2708_raw_writel(host, val, reg);+}++void sdhci_bcm2708_writew(struct sdhci_host *host, u16 val, int reg)+{+	static u32 shadow = 0;++	u32 p = reg == SDHCI_COMMAND ? shadow :+		       sdhci_bcm2708_raw_readl(host, reg & ~3);+	u32 s = reg << 3 & 0x18;+	u32 l = val << s;+	u32 m = 0xffff << s;++#ifdef LOG_REGISTERS+	printk(KERN_ERR "%s: writew to 0x%02x, value 0x%04x\n",+	       mmc_hostname(host->mmc), reg, val);+#endif++	if (reg == SDHCI_TRANSFER_MODE)+		shadow = (p & ~m) | l;+	else {+		check_dma_reg_use(host, reg);+		sdhci_bcm2708_raw_writel(host, (p & ~m) | l, reg & ~3);+	}+}++void sdhci_bcm2708_writeb(struct sdhci_host *host, u8 val, int reg)+{+	u32 p = sdhci_bcm2708_raw_readl(host, reg & ~3);+	u32 s = reg << 3 & 0x18;+	u32 l = val << s;+	u32 m = 0xff << s;++#ifdef LOG_REGISTERS+	printk(KERN_ERR "%s: writeb to 0x%02x, value 0x%02x\n",+	       mmc_hostname(host->mmc), reg, val);+#endif++       check_dma_reg_use(host, reg);+       sdhci_bcm2708_raw_writel(host, (p & ~m) | l, reg & ~3);+}++static unsigned int sdhci_bcm2708_get_max_clock(struct sdhci_host *host)+{+	return emmc_clock_freq;+}++/*****************************************************************************\+ *									     *+ * DMA Operation							     *+ *									     *+\*****************************************************************************/++struct sdhci_bcm2708_priv {+	int			dma_chan;+	int			dma_irq;+	void __iomem	       *dma_chan_base;+	struct bcm2708_dma_cb  *cb_base;   /* DMA control blocks */+	dma_addr_t		cb_handle;+	/* tracking scatter gather progress */+	unsigned		sg_ix;	   /* scatter gather list index */+	unsigned		sg_done;   /* bytes in current sg_ix done */+#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA+	unsigned char		dma_wanted;  /* DMA transfer requested */+	unsigned char		dma_waits;   /* wait states in DMAs */+#ifdef CHECK_DMA_USE+	unsigned char		dmas_pending; /* no of unfinished DMAs */+	hptime_t		when_started;+	hptime_t		when_reset;+	hptime_t		when_stopped;+#endif+#endif+	/* signalling the end of a transfer */+	void		      (*complete)(struct sdhci_host *);+};++#define SDHCI_HOST_PRIV(host) \+	(struct sdhci_bcm2708_priv *)((struct sdhci_host *)(host)+1)++++#ifdef CHECK_DMA_REG_USE+static void check_dma_reg_use(struct sdhci_host *host, int reg)+{+	struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host);+	if (host_priv->dma_wanted && reg != SDHCI_INT_STATUS) {+		printk(KERN_INFO"%s: accessing register 0x%x during DMA\n",+		       mmc_hostname(host->mmc), reg);+	}+}+#endif++++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA++static void sdhci_clear_set_irqgen(struct sdhci_host *host, u32 clear, u32 set)+{+	u32 ier;++	ier = sdhci_bcm2708_raw_readl(host, SDHCI_SIGNAL_ENABLE);+	ier &= ~clear;+	ier |= set;+	/* change which requests generate IRQs - makes no difference to+	   the content of SDHCI_INT_STATUS, or the need to acknowledge IRQs */+	sdhci_bcm2708_raw_writel(host, ier, SDHCI_SIGNAL_ENABLE);+}++static void sdhci_signal_irqs(struct sdhci_host *host, u32 irqs)+{+	sdhci_clear_set_irqgen(host, 0, irqs);+}++static void sdhci_unsignal_irqs(struct sdhci_host *host, u32 irqs)+{+	sdhci_clear_set_irqgen(host, irqs, 0);+}++++static void schci_bcm2708_cb_read(struct sdhci_bcm2708_priv *host,+				  int ix,+				  dma_addr_t dma_addr, unsigned len,+				  int /*bool*/ is_last)+{+	struct bcm2708_dma_cb *cb = &host->cb_base[ix];+        unsigned char dmawaits = host->dma_waits;++	cb->info   = BCM2708_DMA_PER_MAP(BCM2708_DMA_DREQ_EMMC) |+		     BCM2708_DMA_WAITS(dmawaits) |+		     BCM2708_DMA_S_DREQ	 |+		     BCM2708_DMA_D_WIDTH |+		     BCM2708_DMA_D_INC;+	cb->src	   = DMA_SDHCI_BUFFER;	/* DATA register DMA address */+	cb->dst	   = dma_addr;+	cb->length = len;+	cb->stride = 0;++	if (is_last) {+		cb->info |= BCM2708_DMA_INT_EN |+		     BCM2708_DMA_WAIT_RESP;+		cb->next = 0;+	} else+		cb->next = host->cb_handle ++			   (ix+1)*sizeof(struct bcm2708_dma_cb);++	cb->pad[0] = 0;+	cb->pad[1] = 0;+}++static void schci_bcm2708_cb_write(struct sdhci_bcm2708_priv *host,+				   int ix,+				   dma_addr_t dma_addr, unsigned len,+				   int /*bool*/ is_last)+{+	struct bcm2708_dma_cb *cb = &host->cb_base[ix];+        unsigned char dmawaits = host->dma_waits;++	/* We can make arbitrarily large writes as long as we specify DREQ to+	   pace the delivery of bytes to the Arasan hardware */+	cb->info   = BCM2708_DMA_PER_MAP(BCM2708_DMA_DREQ_EMMC) |+		     BCM2708_DMA_WAITS(dmawaits) |+		     BCM2708_DMA_D_DREQ	 |+		     BCM2708_DMA_S_WIDTH |+		     BCM2708_DMA_S_INC;+	cb->src	   = dma_addr;+	cb->dst	   = DMA_SDHCI_BUFFER;	/* DATA register DMA address */+	cb->length = len;+	cb->stride = 0;++	if (is_last) {+		cb->info |= BCM2708_DMA_INT_EN |+		     BCM2708_DMA_WAIT_RESP;+		cb->next = 0;+	} else+		cb->next = host->cb_handle ++			   (ix+1)*sizeof(struct bcm2708_dma_cb);++	cb->pad[0] = 0;+	cb->pad[1] = 0;+}+++static void schci_bcm2708_dma_go(struct sdhci_host *host)+{+	struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host);+	void __iomem *dma_chan_base = host_priv->dma_chan_base;++	BUG_ON(host_priv->dma_wanted);+#ifdef CHECK_DMA_USE+	if (host_priv->dma_wanted)+		printk(KERN_ERR "%s: DMA already in progress - "+		       "now %"FMT_HPT", last started %lu "+		       "reset %lu stopped %lu\n",+		       mmc_hostname(host->mmc),+		       hptime(), since_ns(host_priv->when_started),+		       since_ns(host_priv->when_reset),+		       since_ns(host_priv->when_stopped));+	else if (host_priv->dmas_pending > 0)+		printk(KERN_INFO "%s: note - new DMA when %d reset DMAs "+		       "already in progress - "+		       "now %"FMT_HPT", started %lu reset %lu stopped %lu\n",+		       mmc_hostname(host->mmc),+		       host_priv->dmas_pending,+		       hptime(), since_ns(host_priv->when_started),+		       since_ns(host_priv->when_reset),+		       since_ns(host_priv->when_stopped));+	host_priv->dmas_pending += 1;+	host_priv->when_started = hptime();+#endif+	host_priv->dma_wanted = 1;+	DBG("PDMA go - base %p handle %08X\n", dma_chan_base,+	    host_priv->cb_handle);+	bcm_dma_start(dma_chan_base, host_priv->cb_handle);+}+++static void+sdhci_platdma_read(struct sdhci_host *host, dma_addr_t dma_addr, size_t len)+{+	struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host);++	DBG("PDMA to read %d bytes\n", len);+	host_priv->sg_done += len;+	schci_bcm2708_cb_read(host_priv, 0, dma_addr, len, 1/*TRUE*/);+	schci_bcm2708_dma_go(host);+}+++static void+sdhci_platdma_write(struct sdhci_host *host, dma_addr_t dma_addr, size_t len)+{+	struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host);++	DBG("PDMA to write %d bytes\n", len);+	//BUG_ON(0 != (len & 0x1ff));++	host_priv->sg_done += len;+	schci_bcm2708_cb_write(host_priv, 0, dma_addr, len, 1/*TRUE*/);+	schci_bcm2708_dma_go(host);+}++/*! space is avaiable to receive into or data is available to write+  Platform DMA exported function+*/+void+sdhci_bcm2708_platdma_avail(struct sdhci_host *host, unsigned int *ref_intmask,+			    void(*completion_callback)(struct sdhci_host *host))+{+	struct mmc_data *data = host->data;+	struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host);+	int sg_ix;+	size_t bytes;+	dma_addr_t addr;++	BUG_ON(NULL == data);+	BUG_ON(0 == data->blksz);++	host_priv->complete = completion_callback;++	sg_ix = host_priv->sg_ix;+	BUG_ON(sg_ix >= data->sg_len);++	/* we can DMA blocks larger than blksz - it may hang the DMA+	   channel but we are its only user */+	bytes = sg_dma_len(&data->sg[sg_ix]) - host_priv->sg_done;+	addr = sg_dma_address(&data->sg[sg_ix]) + host_priv->sg_done;++	if (bytes > 0) {+		/* We're going to poll for read/write available state until+		   we finish this DMA+		*/++		if (data->flags & MMC_DATA_READ) {+			if (*ref_intmask & SDHCI_INT_DATA_AVAIL)  {+				sdhci_unsignal_irqs(host, SDHCI_INT_DATA_AVAIL |+						    SDHCI_INT_SPACE_AVAIL);+				sdhci_platdma_read(host, addr, bytes);+			}+		} else {+			if (*ref_intmask & SDHCI_INT_SPACE_AVAIL) {+				sdhci_unsignal_irqs(host, SDHCI_INT_DATA_AVAIL |+						    SDHCI_INT_SPACE_AVAIL);+				sdhci_platdma_write(host, addr, bytes);+			}+		}+	}+	/* else:+	   we have run out of bytes that need transferring (e.g. we may be in+	   the middle of the last DMA transfer), or+	   it is also possible that we've been called when another IRQ is+	   signalled, even though we've turned off signalling of our own IRQ */++	*ref_intmask &= ~SDHCI_INT_DATA_END;+	/* don't let the main sdhci driver act on this .. we'll deal with it+	   when we respond to the DMA - if one is currently in progress */+}++/* is it possible to DMA the given mmc_data structure?+   Platform DMA exported function+*/+int /*bool*/+sdhci_bcm2708_platdma_dmaable(struct sdhci_host *host, struct mmc_data *data)+{+	struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host);+	int ok = bcm_sg_suitable_for_dma(data->sg, data->sg_len);++	if (!ok)+		DBG("Reverting to PIO - bad cache alignment\n");++	else {+		host_priv->sg_ix = 0;	 /* first SG index */+		host_priv->sg_done = 0;	 /* no bytes done */+	}++	return ok;+}++#include <mach/arm_control.h> //GRAYG+/*! the current SD transacton has been abandonned+  We need to tidy up if we were in the middle of a DMA+  Platform DMA exported function+*/+void+sdhci_bcm2708_platdma_reset(struct sdhci_host *host, struct mmc_data *data)+{+	struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host);+//	unsigned long flags;++	BUG_ON(NULL == host);++//	spin_lock_irqsave(&host->lock, flags);++	if (host_priv->dma_wanted) {+		if (NULL == data) {+			printk(KERN_ERR "%s: ongoing DMA reset - no data!\n",+			       mmc_hostname(host->mmc));+			BUG_ON(NULL == data);+		} else {+			struct scatterlist *sg;+			int sg_len;+			int sg_todo;+			int rc;+			unsigned long cs;++			sg = data->sg;+			sg_len = data->sg_len;+			sg_todo = sg_dma_len(&sg[host_priv->sg_ix]);++			cs = readl(host_priv->dma_chan_base + BCM2708_DMA_CS);++			if (!(BCM2708_DMA_ACTIVE & cs))+			{+				if (extra_messages)+					printk(KERN_INFO "%s: missed completion of "+				       "cmd %d DMA (%d/%d [%d]/[%d]) - "+				       "ignoring it\n",+				       mmc_hostname(host->mmc),+				       host->last_cmdop,+				       host_priv->sg_done, sg_todo,+				       host_priv->sg_ix+1, sg_len);+			}+			else+				printk(KERN_INFO "%s: resetting ongoing cmd %d"+				       "DMA before %d/%d [%d]/[%d] complete\n",+				       mmc_hostname(host->mmc),+				       host->last_cmdop,+				       host_priv->sg_done, sg_todo,+				       host_priv->sg_ix+1, sg_len);+#ifdef CHECK_DMA_USE+			printk(KERN_INFO "%s: now %"FMT_HPT" started %lu "+			       "last reset %lu last stopped %lu\n",+			       mmc_hostname(host->mmc),+			       hptime(), since_ns(host_priv->when_started),+			       since_ns(host_priv->when_reset),+			       since_ns(host_priv->when_stopped));+			{	unsigned long info, debug;+				void __iomem *base;+				unsigned long pend0, pend1, pend2;++				base = host_priv->dma_chan_base;+				cs = readl(base + BCM2708_DMA_CS);+				info = readl(base + BCM2708_DMA_INFO);+				debug = readl(base + BCM2708_DMA_DEBUG);+				printk(KERN_INFO "%s: DMA%d CS=%08lX TI=%08lX "+				       "DEBUG=%08lX\n",+				       mmc_hostname(host->mmc),+                                       host_priv->dma_chan,+				       cs, info, debug);+				pend0 = readl(__io_address(ARM_IRQ_PEND0));+				pend1 = readl(__io_address(ARM_IRQ_PEND1));+				pend2 = readl(__io_address(ARM_IRQ_PEND2));++				printk(KERN_INFO "%s: PEND0=%08lX "+				       "PEND1=%08lX PEND2=%08lX\n",+				       mmc_hostname(host->mmc),+				       pend0, pend1, pend2);++				//gintsts = readl(__io_address(GINTSTS));+				//gintmsk = readl(__io_address(GINTMSK));+				//printk(KERN_INFO "%s: USB GINTSTS=%08lX"+				//	 "GINTMSK=%08lX\n",+				//	 mmc_hostname(host->mmc), gintsts, gintmsk);+			}+#endif+			rc = bcm_dma_abort(host_priv->dma_chan_base);+			BUG_ON(rc != 0);+		}+		host_priv->dma_wanted = 0;+#ifdef CHECK_DMA_USE+		host_priv->when_reset = hptime();+#endif+	}++//	spin_unlock_irqrestore(&host->lock, flags);+}+++static void sdhci_bcm2708_dma_complete_irq(struct sdhci_host *host,+					   u32 dma_cs)+{+	struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host);+	struct mmc_data *data;+	struct scatterlist *sg;+	int sg_len;+	int sg_ix;+	int sg_todo;+//	unsigned long flags;++	BUG_ON(NULL == host);++//	spin_lock_irqsave(&host->lock, flags);+	data = host->data;++#ifdef CHECK_DMA_USE+	if (host_priv->dmas_pending <= 0)+		DBG("on completion no DMA in progress - "+		    "now %"FMT_HPT" started %lu reset %lu stopped %lu\n",+		    hptime(), since_ns(host_priv->when_started),+		    since_ns(host_priv->when_reset),+		    since_ns(host_priv->when_stopped));+	else if (host_priv->dmas_pending > 1)+		DBG("still %d DMA in progress after completion - "+		    "now %"FMT_HPT" started %lu reset %lu stopped %lu\n",+		    host_priv->dmas_pending - 1,+		    hptime(), since_ns(host_priv->when_started),+		    since_ns(host_priv->when_reset),+		    since_ns(host_priv->when_stopped));+	BUG_ON(host_priv->dmas_pending <= 0);+	host_priv->dmas_pending -= 1;+	host_priv->when_stopped = hptime();+#endif+	host_priv->dma_wanted = 0;++	if (NULL == data) {+		DBG("PDMA unused completion - status 0x%X\n", dma_cs);+//		spin_unlock_irqrestore(&host->lock, flags);+		return;+	}+	sg = data->sg;+	sg_len = data->sg_len;+	sg_todo = sg_dma_len(&sg[host_priv->sg_ix]);++	DBG("PDMA complete %d/%d [%d]/[%d]..\n",+	    host_priv->sg_done, sg_todo,+	    host_priv->sg_ix+1, sg_len);++	BUG_ON(host_priv->sg_done > sg_todo);++	if (host_priv->sg_done >= sg_todo) {+		host_priv->sg_ix++;+		host_priv->sg_done = 0;+	}++	sg_ix = host_priv->sg_ix;+	if (sg_ix < sg_len) {+		u32 irq_mask;+		/* Set off next DMA if we've got the capacity */++		if (data->flags & MMC_DATA_READ)+			irq_mask = SDHCI_INT_DATA_AVAIL;+		else+			irq_mask = SDHCI_INT_SPACE_AVAIL;++		/* We have to use the interrupt status register on the BCM2708+		   rather than the SDHCI_PRESENT_STATE register because latency+		   in the glue logic means that the information retrieved from+		   the latter is not always up-to-date w.r.t the DMA engine -+		   it may not indicate that a read or a write is ready yet */+		if (sdhci_bcm2708_raw_readl(host, SDHCI_INT_STATUS) &+		    irq_mask) {+			size_t bytes = sg_dma_len(&sg[sg_ix]) -+				       host_priv->sg_done;+			dma_addr_t addr = sg_dma_address(&data->sg[sg_ix]) ++					  host_priv->sg_done;++			/* acknowledge interrupt */+			sdhci_bcm2708_raw_writel(host, irq_mask,+						 SDHCI_INT_STATUS);++			BUG_ON(0 == bytes);++			if (data->flags & MMC_DATA_READ)+				sdhci_platdma_read(host, addr, bytes);+			else+				sdhci_platdma_write(host, addr, bytes);+		} else {+			DBG("PDMA - wait avail\n");+			/* may generate an IRQ if already present */+			sdhci_signal_irqs(host, SDHCI_INT_DATA_AVAIL |+						SDHCI_INT_SPACE_AVAIL);+		}+	} else {+		if (sync_after_dma) {+			/* On the Arasan controller the stop command (which will be+			   scheduled after this completes) does not seem to work+			   properly if we allow it to be issued when we are+			   transferring data to/from the SD card.+			   We get CRC and DEND errors unless we wait for+			   the SD controller to finish reading/writing to the card. */+			u32 state_mask;+			int timeout=3*1000*1000;++			DBG("PDMA over - sync card\n");+			if (data->flags & MMC_DATA_READ)+				state_mask = SDHCI_DOING_READ;+			else+				state_mask = SDHCI_DOING_WRITE;++			while (0 != (sdhci_bcm2708_raw_readl(host, SDHCI_PRESENT_STATE)+				& state_mask) && --timeout > 0)+			{+				udelay(1);+				continue;+			}+			if (timeout <= 0)+				printk(KERN_ERR"%s: final %s to SD card still "+				       "running\n",+				       mmc_hostname(host->mmc),+				       data->flags & MMC_DATA_READ? "read": "write");+		}+		if (host_priv->complete) {+			(*host_priv->complete)(host);+			DBG("PDMA %s complete\n",+			    data->flags & MMC_DATA_READ?"read":"write");+			sdhci_signal_irqs(host, SDHCI_INT_DATA_AVAIL |+						SDHCI_INT_SPACE_AVAIL);+		}+	}+//	spin_unlock_irqrestore(&host->lock, flags);+}++static irqreturn_t sdhci_bcm2708_dma_irq(int irq, void *dev_id)+{+	irqreturn_t result = IRQ_NONE;+	struct sdhci_host *host = dev_id;+	struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host);+	u32 dma_cs; /* control and status register */++	BUG_ON(NULL == dev_id);+	BUG_ON(NULL == host_priv->dma_chan_base);++	sdhci_spin_lock(host);++	dma_cs = readl(host_priv->dma_chan_base + BCM2708_DMA_CS);++	if (dma_cs & BCM2708_DMA_ERR) {+		unsigned long debug;+		debug = readl(host_priv->dma_chan_base ++			      BCM2708_DMA_DEBUG);+		printk(KERN_ERR "%s: DMA error - CS %lX DEBUG %lX\n",+		       mmc_hostname(host->mmc), (unsigned long)dma_cs,+		       (unsigned long)debug);+		/* reset error */+		writel(debug, host_priv->dma_chan_base ++		       BCM2708_DMA_DEBUG);+	}+	if (dma_cs & BCM2708_DMA_INT) {+		/* acknowledge interrupt */+		writel(BCM2708_DMA_INT,+		       host_priv->dma_chan_base + BCM2708_DMA_CS);++		dsb(); /* ARM data synchronization (push) operation */++		if (!host_priv->dma_wanted) {+			/* ignore this interrupt - it was reset */+			if (extra_messages)+				printk(KERN_INFO "%s: DMA IRQ %X ignored - "+			       "results were reset\n",+			       mmc_hostname(host->mmc), dma_cs);+#ifdef CHECK_DMA_USE+			printk(KERN_INFO "%s: now %"FMT_HPT+			       " started %lu reset %lu stopped %lu\n",+			       mmc_hostname(host->mmc), hptime(),+			       since_ns(host_priv->when_started),+			       since_ns(host_priv->when_reset),+			       since_ns(host_priv->when_stopped));+			host_priv->dmas_pending--;+#endif+		} else+			sdhci_bcm2708_dma_complete_irq(host, dma_cs);++		result = IRQ_HANDLED;+	}+	sdhci_spin_unlock(host);++	return result;+}+#endif /* CONFIG_MMC_SDHCI_BCM2708_DMA */+++/***************************************************************************** \+ *									     *+ * Device Attributes							     *+ *									     *+\*****************************************************************************/+++/**+ * Show the DMA-using status+ */+static ssize_t attr_dma_show(struct device *_dev,+			     struct device_attribute *attr, char *buf)+{+	struct sdhci_host *host = (struct sdhci_host *)dev_get_drvdata(_dev);++	if (host) {+		int use_dma = (host->flags & SDHCI_USE_PLATDMA? 1:0);+		return sprintf(buf, "%d\n", use_dma);+	} else+		return -EINVAL;+}++/**+ * Set the DMA-using status+ */+static ssize_t attr_dma_store(struct device *_dev,+			      struct device_attribute *attr,+			      const char *buf, size_t count)+{+	struct sdhci_host *host = (struct sdhci_host *)dev_get_drvdata(_dev);++	if (host) {+#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA+		int on = simple_strtol(buf, NULL, 0);+		if (on) {+			host->flags |= SDHCI_USE_PLATDMA;+			sdhci_bcm2708_writel(host, 1, REG_EXRDFIFO_EN);+			printk(KERN_INFO "%s: DMA enabled\n",+			       mmc_hostname(host->mmc));+		} else {+			host->flags &= ~(SDHCI_USE_PLATDMA | SDHCI_REQ_USE_DMA);+			sdhci_bcm2708_writel(host, 0, REG_EXRDFIFO_EN);+			printk(KERN_INFO "%s: DMA disabled\n",+			       mmc_hostname(host->mmc));+		}+#endif+		return count;+	} else+		return -EINVAL;+}++static DEVICE_ATTR(use_dma, S_IRUGO | S_IWUGO, attr_dma_show, attr_dma_store);+++/**+ * Show the DMA wait states used+ */+static ssize_t attr_dmawait_show(struct device *_dev,+			         struct device_attribute *attr, char *buf)+{+	struct sdhci_host *host = (struct sdhci_host *)dev_get_drvdata(_dev);++	if (host) {+		struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host);+		int dmawait = host_priv->dma_waits;+		return sprintf(buf, "%d\n", dmawait);+	} else+		return -EINVAL;+}++/**+ * Set the DMA wait state used+ */+static ssize_t attr_dmawait_store(struct device *_dev,+			          struct device_attribute *attr,+			          const char *buf, size_t count)+{+	struct sdhci_host *host = (struct sdhci_host *)dev_get_drvdata(_dev);++	if (host) {+#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA+		struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host);+		int dma_waits = simple_strtol(buf, NULL, 0);+		if (dma_waits >= 0 && dma_waits < 32)+                        host_priv->dma_waits = dma_waits;+		else+			printk(KERN_ERR "%s: illegal dma_waits value - %d",+			       mmc_hostname(host->mmc), dma_waits);+#endif+		return count;+	} else+		return -EINVAL;+}++static DEVICE_ATTR(dma_wait, S_IRUGO | S_IWUGO,+                   attr_dmawait_show, attr_dmawait_store);+++/**+ * Show the DMA-using status+ */+static ssize_t attr_status_show(struct device *_dev,+				struct device_attribute *attr, char *buf)+{+	struct sdhci_host *host = (struct sdhci_host *)dev_get_drvdata(_dev);++	if (host) {+		struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host);+		return sprintf(buf,+			       "present: yes\n"+			       "power: %s\n"+			       "clock: %u Hz\n"+#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA+			       "dma: %s (%d waits)\n",+#else+			       "dma: unconfigured\n",+#endif+			       "always on",+			       host->clock+#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA+			       , (host->flags & SDHCI_USE_PLATDMA)? "on": "off"+                               , host_priv->dma_waits+#endif+			       );+	} else+		return -EINVAL;+}++static DEVICE_ATTR(status, S_IRUGO, attr_status_show, NULL);++/***************************************************************************** \+ *									     *+ * Power Management							     *+ *									     *+\*****************************************************************************/+++#ifdef CONFIG_PM+static int sdhci_bcm2708_suspend(struct platform_device *dev, pm_message_t state)+{+	struct sdhci_host *host = (struct sdhci_host *)+				  platform_get_drvdata(dev);+	int ret = 0;++	if (host->mmc) {+		ret = mmc_suspend_host(host->mmc);+	}++	return ret;+}++static int sdhci_bcm2708_resume(struct platform_device *dev)+{+	struct sdhci_host *host = (struct sdhci_host *)+				  platform_get_drvdata(dev);+	int ret = 0;++	if (host->mmc) {+		ret = mmc_resume_host(host->mmc);+	}++	return ret;+}+#endif+++/*****************************************************************************\+ *                                                                           *+ * Device quirk functions. Implemented as local ops because the flags        *+ * field is out of space with newer kernels. This implementation can be      *+ * back ported to older kernels as well.                                     *+\****************************************************************************/+static unsigned int sdhci_bcm2708_quirk_extra_ints(struct sdhci_host *host)+{+        return 1;+}++static unsigned int sdhci_bcm2708_quirk_spurious_crc_acmd51(struct sdhci_host *host)+{+        return 1;+}++static unsigned int sdhci_bcm2708_quirk_voltage_broken(struct sdhci_host *host)+{+        return 1;+}++static unsigned int sdhci_bcm2708_uhs_broken(struct sdhci_host *host)+{+        return 1;+}++static unsigned int sdhci_bcm2708_missing_status(struct sdhci_host *host)+{+	return 1;+}++/***************************************************************************** \+ *									     *+ * Device ops								     *+ *									     *+\*****************************************************************************/++static struct sdhci_ops sdhci_bcm2708_ops = {+#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS+	.read_l = sdhci_bcm2708_readl,+	.read_w = sdhci_bcm2708_readw,+	.read_b = sdhci_bcm2708_readb,+	.write_l = sdhci_bcm2708_writel,+	.write_w = sdhci_bcm2708_writew,+	.write_b = sdhci_bcm2708_writeb,+#else+#error The BCM2708 SDHCI driver needs CONFIG_MMC_SDHCI_IO_ACCESSORS to be set+#endif+	.get_max_clock = sdhci_bcm2708_get_max_clock,++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA+	// Platform DMA operations+	.pdma_able  = sdhci_bcm2708_platdma_dmaable,+	.pdma_avail = sdhci_bcm2708_platdma_avail,+	.pdma_reset = sdhci_bcm2708_platdma_reset,+#endif+	.extra_ints = sdhci_bcm2708_quirk_extra_ints,+	.voltage_broken = sdhci_bcm2708_quirk_voltage_broken,+	.uhs_broken = sdhci_bcm2708_uhs_broken,+};++/*****************************************************************************\+ *									     *+ * Device probing/removal						     *+ *									     *+\*****************************************************************************/++static int sdhci_bcm2708_probe(struct platform_device *pdev)+{+	struct sdhci_host *host;+	struct resource *iomem;+	struct sdhci_bcm2708_priv *host_priv;+	int ret;++	BUG_ON(pdev == NULL);++	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);+	if (!iomem) {+		ret = -ENOMEM;+		goto err;+	}++	if (resource_size(iomem) != 0x100)+		dev_err(&pdev->dev, "Invalid iomem size. You may "+			"experience problems.\n");++	if (pdev->dev.parent)+		host = sdhci_alloc_host(pdev->dev.parent,+					sizeof(struct sdhci_bcm2708_priv));+	else+		host = sdhci_alloc_host(&pdev->dev,+					sizeof(struct sdhci_bcm2708_priv));++	if (IS_ERR(host)) {+		ret = PTR_ERR(host);+		goto err;+	}+	if (missing_status) {+		sdhci_bcm2708_ops.missing_status = sdhci_bcm2708_missing_status;+	}++	if( spurious_crc_acmd51 ) {+		sdhci_bcm2708_ops.spurious_crc_acmd51 = sdhci_bcm2708_quirk_spurious_crc_acmd51;+	}+++	printk("sdhci: %s low-latency mode\n",enable_llm?"Enable":"Disable");++	host->hw_name = "BCM2708_Arasan";+	host->ops = &sdhci_bcm2708_ops;+	host->irq = platform_get_irq(pdev, 0);+	host->second_irq = 0;++	host->quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |+		       SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |+		       SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |+               SDHCI_QUIRK_MISSING_CAPS |+               SDHCI_QUIRK_NO_HISPD_BIT |+               (sync_after_dma ? 0:SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12);+++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA+	host->flags = SDHCI_USE_PLATDMA;+#endif++	if (!request_mem_region(iomem->start, resource_size(iomem),+				mmc_hostname(host->mmc))) {+		dev_err(&pdev->dev, "cannot request region\n");+		ret = -EBUSY;+		goto err_request;+	}++	host->ioaddr = ioremap(iomem->start, resource_size(iomem));+	if (!host->ioaddr) {+		dev_err(&pdev->dev, "failed to remap registers\n");+		ret = -ENOMEM;+		goto err_remap;+	}++	host_priv = SDHCI_HOST_PRIV(host);++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA+	host_priv->dma_wanted = 0;+#ifdef CHECK_DMA_USE+	host_priv->dmas_pending = 0;+	host_priv->when_started = 0;+	host_priv->when_reset = 0;+	host_priv->when_stopped = 0;+#endif+	host_priv->sg_ix = 0;+	host_priv->sg_done = 0;+	host_priv->complete = NULL;+	host_priv->dma_waits = SDHCI_BCM_DMA_WAITS;++	host_priv->cb_base = dma_alloc_writecombine(&pdev->dev, SZ_4K,+						    &host_priv->cb_handle,+						    GFP_KERNEL);+	if (!host_priv->cb_base) {+		dev_err(&pdev->dev, "cannot allocate DMA CBs\n");+		ret = -ENOMEM;+		goto err_alloc_cb;+	}++	ret = bcm_dma_chan_alloc(BCM_DMA_FEATURE_FAST,+				 &host_priv->dma_chan_base,+				 &host_priv->dma_irq);+	if (ret < 0) {+		dev_err(&pdev->dev, "couldn't allocate a DMA channel\n");+		goto err_add_dma;+	}+	host_priv->dma_chan = ret;++	ret = request_irq(host_priv->dma_irq, sdhci_bcm2708_dma_irq,0,//IRQF_SHARED,+			  DRIVER_NAME " (dma)", host);+	if (ret) {+		dev_err(&pdev->dev, "cannot set DMA IRQ\n");+		goto err_add_dma_irq;+	}+	host->second_irq = host_priv->dma_irq;+	DBG("DMA CBs %p handle %08X DMA%d %p DMA IRQ %d\n",+	    host_priv->cb_base, (unsigned)host_priv->cb_handle,+	    host_priv->dma_chan, host_priv->dma_chan_base,+	    host_priv->dma_irq);++    if (allow_highspeed)+        host->mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;++    /* single block writes cause data loss with some SD cards! */+    host->mmc->caps2 |= MMC_CAP2_FORCE_MULTIBLOCK;+#endif++	ret = sdhci_add_host(host);+	if (ret)+		goto err_add_host;++	platform_set_drvdata(pdev, host);+	ret = device_create_file(&pdev->dev, &dev_attr_use_dma);+	ret = device_create_file(&pdev->dev, &dev_attr_dma_wait);+	ret = device_create_file(&pdev->dev, &dev_attr_status);++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA+	/* enable extension fifo for paced DMA transfers */+	sdhci_bcm2708_writel(host, 1, REG_EXRDFIFO_EN);+	sdhci_bcm2708_writel(host, 4, REG_EXRDFIFO_CFG);+#endif++	printk(KERN_INFO "%s: BCM2708 SDHC host at 0x%08llx DMA %d IRQ %d\n",+	       mmc_hostname(host->mmc), (unsigned long long)iomem->start,+	       host_priv->dma_chan, host_priv->dma_irq);++	return 0;++err_add_host:+#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA+	free_irq(host_priv->dma_irq, host);+err_add_dma_irq:+	bcm_dma_chan_free(host_priv->dma_chan);+err_add_dma:+	dma_free_writecombine(&pdev->dev, SZ_4K, host_priv->cb_base,+			      host_priv->cb_handle);+err_alloc_cb:+#endif+	iounmap(host->ioaddr);+err_remap:+	release_mem_region(iomem->start, resource_size(iomem));+err_request:+	sdhci_free_host(host);+err:+	dev_err(&pdev->dev, "probe failed, err %d\n", ret);+	return ret;+}++static int sdhci_bcm2708_remove(struct platform_device *pdev)+{+	struct sdhci_host *host = platform_get_drvdata(pdev);+	struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);+	struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host);+	int dead;+	u32 scratch;++	dead = 0;+	scratch = sdhci_bcm2708_readl(host, SDHCI_INT_STATUS);+	if (scratch == (u32)-1)+		dead = 1;++	device_remove_file(&pdev->dev, &dev_attr_status);+	device_remove_file(&pdev->dev, &dev_attr_dma_wait);+	device_remove_file(&pdev->dev, &dev_attr_use_dma);++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA+	free_irq(host_priv->dma_irq, host);+	dma_free_writecombine(&pdev->dev, SZ_4K, host_priv->cb_base,+			      host_priv->cb_handle);+#endif+	sdhci_remove_host(host, dead);+	iounmap(host->ioaddr);+	release_mem_region(iomem->start, resource_size(iomem));+	sdhci_free_host(host);+	platform_set_drvdata(pdev, NULL);++	return 0;+}++static struct platform_driver sdhci_bcm2708_driver = {+	.driver = {+		.name	= DRIVER_NAME,+		.owner	= THIS_MODULE,+	},+	.probe		= sdhci_bcm2708_probe,+	.remove		= sdhci_bcm2708_remove,++#ifdef CONFIG_PM+	.suspend = sdhci_bcm2708_suspend,+	.resume = sdhci_bcm2708_resume,+#endif++};++/*****************************************************************************\+ *									     *+ * Driver init/exit							     *+ *									     *+\*****************************************************************************/++static int __init sdhci_drv_init(void)+{+	return platform_driver_register(&sdhci_bcm2708_driver);+}++static void __exit sdhci_drv_exit(void)+{+	platform_driver_unregister(&sdhci_bcm2708_driver);+}++module_init(sdhci_drv_init);+module_exit(sdhci_drv_exit);++module_param(allow_highspeed, bool, 0444);+module_param(emmc_clock_freq, int, 0444);+module_param(sync_after_dma, bool, 0444);+module_param(missing_status, bool, 0444);+module_param(spurious_crc_acmd51, bool, 0444);+module_param(enable_llm, bool, 0444);+module_param(cycle_delay, int, 0444);+module_param(extra_messages, bool, 0444);++MODULE_DESCRIPTION("Secure Digital Host Controller Interface platform driver");+MODULE_AUTHOR("Broadcom <info@broadcom.com>");+MODULE_LICENSE("GPL v2");+MODULE_ALIAS("platform:"DRIVER_NAME);++MODULE_PARM_DESC(allow_highspeed, "Allow high speed transfers modes");+MODULE_PARM_DESC(emmc_clock_freq, "Specify the speed of emmc clock");+MODULE_PARM_DESC(sync_after_dma, "Block in driver until dma complete");+MODULE_PARM_DESC(missing_status, "Use the missing status quirk");+MODULE_PARM_DESC(spurious_crc_acmd51, "Use the spurious crc quirk for reading SCR (ACMD51)");+MODULE_PARM_DESC(enable_llm, "Enable low-latency mode");+MODULE_PARM_DESC(extra_messages, "Enable more sdcard warning messages");++diff -Nur linux-3.11.10.orig/drivers/mmc/host/sdhci.c linux-3.11.10/drivers/mmc/host/sdhci.c--- linux-3.11.10.orig/drivers/mmc/host/sdhci.c	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/mmc/host/sdhci.c	2014-02-07 19:57:28.000000000 +0100@@ -28,6 +28,7 @@ #include <linux/mmc/mmc.h> #include <linux/mmc/host.h> #include <linux/mmc/card.h>+#include <linux/mmc/sd.h> #include <linux/mmc/slot-gpio.h>  #include "sdhci.h"@@ -131,6 +132,91 @@  * Low level functions                                                       *  *                                                                           * \*****************************************************************************/+extern bool enable_llm;+static int sdhci_locked=0;+void sdhci_spin_lock(struct sdhci_host *host)+{+	spin_lock(&host->lock);+#ifdef CONFIG_PREEMPT+	if(enable_llm)+	{+		disable_irq_nosync(host->irq);+		if(host->second_irq)+			disable_irq_nosync(host->second_irq);+		local_irq_enable();+	}+#endif+}++void sdhci_spin_unlock(struct sdhci_host *host)+{+#ifdef CONFIG_PREEMPT+	if(enable_llm)+	{+		local_irq_disable();+		if(host->second_irq)+			enable_irq(host->second_irq);+		enable_irq(host->irq);+	}+#endif+	spin_unlock(&host->lock);+}++void sdhci_spin_lock_irqsave(struct sdhci_host *host,unsigned long *flags)+{+#ifdef CONFIG_PREEMPT+	if(enable_llm)+	{+		while(sdhci_locked)+		{+			preempt_schedule();+		}+		spin_lock_irqsave(&host->lock,*flags);+		disable_irq(host->irq);+		if(host->second_irq)+			disable_irq(host->second_irq);+		local_irq_enable();+	}+	else+#endif+		spin_lock_irqsave(&host->lock,*flags);+}++void sdhci_spin_unlock_irqrestore(struct sdhci_host *host,unsigned long flags)+{+#ifdef CONFIG_PREEMPT+	if(enable_llm)+	{+		local_irq_disable();+		if(host->second_irq)+			enable_irq(host->second_irq);+		enable_irq(host->irq);+	}+#endif+	spin_unlock_irqrestore(&host->lock,flags);+}++static void sdhci_spin_enable_schedule(struct sdhci_host *host)+{+#ifdef CONFIG_PREEMPT+	if(enable_llm)+	{+		sdhci_locked = 1;+		preempt_enable();+	}+#endif+}++static void sdhci_spin_disable_schedule(struct sdhci_host *host)+{+#ifdef CONFIG_PREEMPT+	if(enable_llm)+	{+		preempt_disable();+		sdhci_locked = 0;+	}+#endif+}  static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set) {@@ -300,7 +386,7 @@ 	struct sdhci_host *host = container_of(led, struct sdhci_host, led); 	unsigned long flags; -	spin_lock_irqsave(&host->lock, flags);+	sdhci_spin_lock_irqsave(host, &flags);  	if (host->runtime_suspended) 		goto out;@@ -310,7 +396,7 @@ 	else 		sdhci_activate_led(host); out:-	spin_unlock_irqrestore(&host->lock, flags);+	sdhci_spin_unlock_irqrestore(host, flags); } #endif @@ -327,7 +413,7 @@ 	u32 uninitialized_var(scratch); 	u8 *buf; -	DBG("PIO reading\n");+	DBG("PIO reading %db\n", host->data->blksz);  	blksize = host->data->blksz; 	chunk = 0;@@ -372,7 +458,7 @@ 	u32 scratch; 	u8 *buf; -	DBG("PIO writing\n");+	DBG("PIO writing %db\n", host->data->blksz);  	blksize = host->data->blksz; 	chunk = 0;@@ -411,19 +497,28 @@ 	local_irq_restore(flags); } -static void sdhci_transfer_pio(struct sdhci_host *host)+static void sdhci_transfer_pio(struct sdhci_host *host, u32 intstate) { 	u32 mask;+	u32 state = 0;+	u32 intmask;+	int available;  	BUG_ON(!host->data);  	if (host->blocks == 0) 		return; -	if (host->data->flags & MMC_DATA_READ)+	if (host->data->flags & MMC_DATA_READ) { 		mask = SDHCI_DATA_AVAILABLE;-	else+		intmask = SDHCI_INT_DATA_AVAIL;+	} else { 		mask = SDHCI_SPACE_AVAILABLE;+		intmask = SDHCI_INT_SPACE_AVAIL;+	}++	/* initially we can see whether we can procede using intstate */+	available = (intstate & intmask);  	/* 	 * Some controllers (JMicron JMB38x) mess up the buffer bits@@ -434,7 +529,7 @@ 		(host->data->blocks == 1)) 		mask = ~0; -	while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {+	while (available) { 		if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY) 			udelay(100); @@ -446,9 +541,11 @@ 		host->blocks--; 		if (host->blocks == 0) 			break;+		state = sdhci_readl(host, SDHCI_PRESENT_STATE);+		available = state & mask; 	} -	DBG("PIO transfer complete.\n");+	DBG("PIO transfer complete - %d blocks left.\n", host->blocks); }  static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags)@@ -721,7 +818,9 @@ 	u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; 	u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; -	if (host->flags & SDHCI_REQ_USE_DMA)+	/* platform DMA will begin on receipt of PIO irqs */+	if ((host->flags & SDHCI_REQ_USE_DMA) &&+	    !(host->flags & SDHCI_USE_PLATDMA)) 		sdhci_clear_set_irqs(host, pio_irqs, dma_irqs); 	else 		sdhci_clear_set_irqs(host, dma_irqs, pio_irqs);@@ -753,44 +852,25 @@ 	host->data_early = 0; 	host->data->bytes_xfered = 0; -	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))+	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA | SDHCI_USE_PLATDMA)) 		host->flags |= SDHCI_REQ_USE_DMA;  	/* 	 * FIXME: This doesn't account for merging when mapping the 	 * scatterlist. 	 */-	if (host->flags & SDHCI_REQ_USE_DMA) {-		int broken, i;-		struct scatterlist *sg;--		broken = 0;-		if (host->flags & SDHCI_USE_ADMA) {-			if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE)-				broken = 1;-		} else {-			if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE)-				broken = 1;-		}--		if (unlikely(broken)) {-			for_each_sg(data->sg, sg, data->sg_len, i) {-				if (sg->length & 0x3) {-					DBG("Reverting to PIO because of "-						"transfer size (%d)\n",-						sg->length);-					host->flags &= ~SDHCI_REQ_USE_DMA;-					break;-				}-			}-		}-	}  	/* 	 * The assumption here being that alignment is the same after 	 * translation to device address space. 	 */-	if (host->flags & SDHCI_REQ_USE_DMA) {+	if ((host->flags & (SDHCI_REQ_USE_DMA | SDHCI_USE_PLATDMA)) ==+	    (SDHCI_REQ_USE_DMA | SDHCI_USE_PLATDMA)) {++		if (! sdhci_platdma_dmaable(host, data))+			host->flags &= ~SDHCI_REQ_USE_DMA;++	} else if (host->flags & SDHCI_REQ_USE_DMA) { 		int broken, i; 		struct scatterlist *sg; @@ -849,7 +929,8 @@ 				 */ 				WARN_ON(1); 				host->flags &= ~SDHCI_REQ_USE_DMA;-			} else {+			} else+			if (!(host->flags & SDHCI_USE_PLATDMA)) { 				WARN_ON(sg_cnt != 1); 				sdhci_writel(host, sg_dma_address(data->sg), 					SDHCI_DMA_ADDRESS);@@ -865,11 +946,13 @@ 	if (host->version >= SDHCI_SPEC_200) { 		ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 		ctrl &= ~SDHCI_CTRL_DMA_MASK;+		if (! (host->flags & SDHCI_USE_PLATDMA)) { 		if ((host->flags & SDHCI_REQ_USE_DMA) && 			(host->flags & SDHCI_USE_ADMA)) 			ctrl |= SDHCI_CTRL_ADMA32; 		else 			ctrl |= SDHCI_CTRL_SDMA;+		} 		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 	} @@ -921,7 +1004,8 @@  	if (data->flags & MMC_DATA_READ) 		mode |= SDHCI_TRNS_READ;-	if (host->flags & SDHCI_REQ_USE_DMA)+	if ((host->flags & SDHCI_REQ_USE_DMA) &&+	    !(host->flags & SDHCI_USE_PLATDMA)) 		mode |= SDHCI_TRNS_DMA;  	sdhci_writew(host, mode, SDHCI_TRANSFER_MODE);@@ -937,13 +1021,16 @@ 	host->data = NULL;  	if (host->flags & SDHCI_REQ_USE_DMA) {-		if (host->flags & SDHCI_USE_ADMA)-			sdhci_adma_table_post(host, data);-		else {+		/* we may have to abandon an ongoing platform DMA */+		if (host->flags & SDHCI_USE_PLATDMA)+			sdhci_platdma_reset(host, data);++		if (host->flags & (SDHCI_USE_PLATDMA | SDHCI_USE_SDMA)) { 			dma_unmap_sg(mmc_dev(host->mmc), data->sg, 				data->sg_len, (data->flags & MMC_DATA_READ) ? 					DMA_FROM_DEVICE : DMA_TO_DEVICE);-		}+		} else if (host->flags & SDHCI_USE_ADMA)+                        sdhci_adma_table_post(host, data); 	}  	/*@@ -996,6 +1083,12 @@ 	if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY)) 		mask |= SDHCI_DATA_INHIBIT; +	if(host->ops->missing_status && (cmd->opcode == MMC_SEND_STATUS)) {+		timeout = 5000; // Really obscenely large delay to send the status, due to bug in controller+				// which might cause the STATUS command to get stuck when a data operation is in flow+		mask |= SDHCI_DATA_INHIBIT;+	}+ 	/* We shouldn't wait for data inihibit for stop commands, even 	   though they might use busy signaling */ 	if (host->mrq->data && (cmd == host->mrq->data->stop))@@ -1011,12 +1104,20 @@ 			return; 		} 		timeout--;+		sdhci_spin_enable_schedule(host); 		mdelay(1);+		sdhci_spin_disable_schedule(host); 	}+	DBG("send cmd %d - wait 0x%X irq 0x%x\n", cmd->opcode, mask,+	    sdhci_readl(host, SDHCI_INT_STATUS));  	mod_timer(&host->timer, jiffies + 10 * HZ);  	host->cmd = cmd;+	if (host->last_cmdop == MMC_APP_CMD)+		host->last_cmdop = -cmd->opcode;+	else+		host->last_cmdop = cmd->opcode;  	sdhci_prepare_data(host, cmd); @@ -1232,7 +1333,9 @@ 			return; 		} 		timeout--;+		sdhci_spin_enable_schedule(host); 		mdelay(1);+		sdhci_spin_disable_schedule(host); 	}  	clk |= SDHCI_CLOCK_CARD_EN;@@ -1333,7 +1436,7 @@  	sdhci_runtime_pm_get(host); -	spin_lock_irqsave(&host->lock, flags);+	sdhci_spin_lock_irqsave(host, &flags);  	WARN_ON(host->mrq != NULL); @@ -1391,9 +1494,9 @@ 					mmc->card->type == MMC_TYPE_MMC ? 					MMC_SEND_TUNING_BLOCK_HS200 : 					MMC_SEND_TUNING_BLOCK;-				spin_unlock_irqrestore(&host->lock, flags);+				sdhci_spin_unlock_irqrestore(host, flags); 				sdhci_execute_tuning(mmc, tuning_opcode);-				spin_lock_irqsave(&host->lock, flags);+				sdhci_spin_lock_irqsave(host, &flags);  				/* Restore original mmc_request structure */ 				host->mrq = mrq;@@ -1407,7 +1510,7 @@ 	}  	mmiowb();-	spin_unlock_irqrestore(&host->lock, flags);+	sdhci_spin_unlock_irqrestore(host, flags); }  static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)@@ -1416,10 +1519,10 @@ 	int vdd_bit = -1; 	u8 ctrl; -	spin_lock_irqsave(&host->lock, flags);+	sdhci_spin_lock_irqsave(host, &flags);  	if (host->flags & SDHCI_DEVICE_DEAD) {-		spin_unlock_irqrestore(&host->lock, flags);+		sdhci_spin_unlock_irqrestore(host, flags); 		if (host->vmmc && ios->power_mode == MMC_POWER_OFF) 			mmc_regulator_set_ocr(host->mmc, host->vmmc, 0); 		return;@@ -1446,9 +1549,9 @@ 		vdd_bit = sdhci_set_power(host, ios->vdd);  	if (host->vmmc && vdd_bit != -1) {-		spin_unlock_irqrestore(&host->lock, flags);+		sdhci_spin_unlock_irqrestore(host, flags); 		mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd_bit);-		spin_lock_irqsave(&host->lock, flags);+		sdhci_spin_lock_irqsave(host, &flags); 	}  	if (host->ops->platform_send_init_74_clocks)@@ -1487,7 +1590,7 @@ 	else 		ctrl &= ~SDHCI_CTRL_HISPD; -	if (host->version >= SDHCI_SPEC_300) {+	if (host->version >= SDHCI_SPEC_300 && !(host->ops->uhs_broken)) { 		u16 clk, ctrl_2;  		/* In case of UHS-I modes, set High Speed Enable */@@ -1585,7 +1688,7 @@ 		sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);  	mmiowb();-	spin_unlock_irqrestore(&host->lock, flags);+	sdhci_spin_unlock_irqrestore(host, flags); }  static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)@@ -1633,7 +1736,7 @@ 	unsigned long flags; 	int is_readonly; -	spin_lock_irqsave(&host->lock, flags);+	sdhci_spin_lock_irqsave(host, &flags);  	if (host->flags & SDHCI_DEVICE_DEAD) 		is_readonly = 0;@@ -1643,7 +1746,7 @@ 		is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE) 				& SDHCI_WRITE_PROTECT); -	spin_unlock_irqrestore(&host->lock, flags);+	sdhci_spin_unlock_irqrestore(host, flags);  	/* This quirk needs to be replaced by a callback-function later */ 	return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ?@@ -1716,9 +1819,9 @@ 	struct sdhci_host *host = mmc_priv(mmc); 	unsigned long flags; -	spin_lock_irqsave(&host->lock, flags);+	sdhci_spin_lock_irqsave(host, &flags); 	sdhci_enable_sdio_irq_nolock(host, enable);-	spin_unlock_irqrestore(&host->lock, flags);+	sdhci_spin_unlock_irqrestore(host, flags); }  static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,@@ -2066,7 +2169,7 @@ 	if (host->ops->card_event) 		host->ops->card_event(host); -	spin_lock_irqsave(&host->lock, flags);+	sdhci_spin_lock_irqsave(host, &flags);  	/* Check host->mrq first in case we are runtime suspended */ 	if (host->mrq && !sdhci_do_get_cd(host)) {@@ -2082,7 +2185,7 @@ 		tasklet_schedule(&host->finish_tasklet); 	} -	spin_unlock_irqrestore(&host->lock, flags);+	sdhci_spin_unlock_irqrestore(host, flags); }  static const struct mmc_host_ops sdhci_ops = {@@ -2121,14 +2224,14 @@  	host = (struct sdhci_host*)param; -	spin_lock_irqsave(&host->lock, flags);+	sdhci_spin_lock_irqsave(host, &flags);          /*          * If this tasklet gets rescheduled while running, it will          * be run again afterwards but without any active request.          */ 	if (!host->mrq) {-		spin_unlock_irqrestore(&host->lock, flags);+		sdhci_spin_unlock_irqrestore(host, flags); 		return; 	} @@ -2166,7 +2269,7 @@ #endif  	mmiowb();-	spin_unlock_irqrestore(&host->lock, flags);+	sdhci_spin_unlock_irqrestore(host, flags);  	mmc_request_done(host->mmc, mrq); 	sdhci_runtime_pm_put(host);@@ -2179,11 +2282,11 @@  	host = (struct sdhci_host*)data; -	spin_lock_irqsave(&host->lock, flags);+	sdhci_spin_lock_irqsave(host, &flags);  	if (host->mrq) { 		pr_err("%s: Timeout waiting for hardware "-			"interrupt.\n", mmc_hostname(host->mmc));+			"interrupt - cmd%d.\n", mmc_hostname(host->mmc), host->last_cmdop); 		sdhci_dumpregs(host);  		if (host->data) {@@ -2200,7 +2303,7 @@ 	}  	mmiowb();-	spin_unlock_irqrestore(&host->lock, flags);+	sdhci_spin_unlock_irqrestore(host, flags); }  static void sdhci_tuning_timer(unsigned long data)@@ -2210,11 +2313,11 @@  	host = (struct sdhci_host *)data; -	spin_lock_irqsave(&host->lock, flags);+	sdhci_spin_lock_irqsave(host, &flags);  	host->flags |= SDHCI_NEEDS_RETUNING; -	spin_unlock_irqrestore(&host->lock, flags);+	sdhci_spin_unlock_irqrestore(host, flags); }  /*****************************************************************************\@@ -2228,10 +2331,13 @@ 	BUG_ON(intmask == 0);  	if (!host->cmd) {+		if (!(host->ops->extra_ints)) { 		pr_err("%s: Got command interrupt 0x%08x even " 			"though no command operation was in progress.\n", 			mmc_hostname(host->mmc), (unsigned)intmask); 		sdhci_dumpregs(host);+		} else+			DBG("cmd irq 0x%08x cmd complete\n", (unsigned)intmask); 		return; 	} @@ -2301,6 +2407,19 @@ static void sdhci_show_adma_error(struct sdhci_host *host) { } #endif +static void sdhci_data_end(struct sdhci_host *host)+{+	if (host->cmd) {+		/*+		 * Data managed to finish before the+		 * command completed. Make sure we do+		 * things in the proper order.+		 */+		host->data_early = 1;+	} else+		sdhci_finish_data(host);+}+ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) { 	u32 command;@@ -2330,23 +2449,39 @@ 			} 		} +		if (!(host->ops->extra_ints)) { 		pr_err("%s: Got data interrupt 0x%08x even " 			"though no data operation was in progress.\n", 			mmc_hostname(host->mmc), (unsigned)intmask); 		sdhci_dumpregs(host);+		} else+			DBG("data irq 0x%08x but no data\n", (unsigned)intmask);  		return; 	}  	if (intmask & SDHCI_INT_DATA_TIMEOUT) 		host->data->error = -ETIMEDOUT;-	else if (intmask & SDHCI_INT_DATA_END_BIT)+	else if (intmask & SDHCI_INT_DATA_END_BIT) {+		DBG("end error in cmd %d\n", host->last_cmdop);+		if (host->ops->spurious_crc_acmd51 &&+		    host->last_cmdop == -SD_APP_SEND_SCR) {+			DBG("ignoring spurious data_end_bit error\n");+			intmask = SDHCI_INT_DATA_AVAIL|SDHCI_INT_DATA_END;+		} else 		host->data->error = -EILSEQ;-	else if ((intmask & SDHCI_INT_DATA_CRC) &&+	} else if ((intmask & SDHCI_INT_DATA_CRC) && 		SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))-			!= MMC_BUS_TEST_R)+			!= MMC_BUS_TEST_R) {+		DBG("crc error in cmd %d\n", host->last_cmdop);+		if (host->ops->spurious_crc_acmd51 &&+				host->last_cmdop == -SD_APP_SEND_SCR) {+			DBG("ignoring spurious data_crc_bit error\n");+			intmask = SDHCI_INT_DATA_AVAIL|SDHCI_INT_DATA_END;+		} else { 		host->data->error = -EILSEQ;-	else if (intmask & SDHCI_INT_ADMA_ERROR) {+		}+	} else if (intmask & SDHCI_INT_ADMA_ERROR) { 		pr_err("%s: ADMA error\n", mmc_hostname(host->mmc)); 		sdhci_show_adma_error(host); 		host->data->error = -EIO;@@ -2354,11 +2489,18 @@ 			host->ops->adma_workaround(host, intmask); 	} -	if (host->data->error)+	if (host->data->error) {+		DBG("finish request early on error %d\n", host->data->error); 		sdhci_finish_data(host);-	else {-		if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))-			sdhci_transfer_pio(host);+	} else {+		if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) {+			if (host->flags & SDHCI_REQ_USE_DMA) {+				/* possible only in PLATDMA mode */+				sdhci_platdma_avail(host, &intmask,+						&sdhci_data_end);+			} else+				sdhci_transfer_pio(host, intmask);+		}  		/* 		 * We currently don't do anything fancy with DMA@@ -2387,18 +2529,8 @@ 			sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS); 		} -		if (intmask & SDHCI_INT_DATA_END) {-			if (host->cmd) {-				/*-				 * Data managed to finish before the-				 * command completed. Make sure we do-				 * things in the proper order.-				 */-				host->data_early = 1;-			} else {-				sdhci_finish_data(host);-			}-		}+		if (intmask & SDHCI_INT_DATA_END)+			sdhci_data_end(host); 	} } @@ -2409,10 +2541,10 @@ 	u32 intmask, unexpected = 0; 	int cardint = 0, max_loops = 16; -	spin_lock(&host->lock);+	sdhci_spin_lock(host);  	if (host->runtime_suspended) {-		spin_unlock(&host->lock);+		sdhci_spin_unlock(host); 		pr_warning("%s: got irq while runtime suspended\n", 		       mmc_hostname(host->mmc)); 		return IRQ_HANDLED;@@ -2454,6 +2586,22 @@ 		tasklet_schedule(&host->card_tasklet); 	} +	if (intmask & SDHCI_INT_ERROR_MASK & ~SDHCI_INT_ERROR)+		DBG("controller reports error 0x%x -"+				"%s%s%s%s%s%s%s%s%s%s",+				intmask,+				intmask & SDHCI_INT_TIMEOUT? " timeout": "",+				intmask & SDHCI_INT_CRC     ? " crc": "",+				intmask & SDHCI_INT_END_BIT? " endbit": "",+				intmask & SDHCI_INT_INDEX? " index": "",+				intmask & SDHCI_INT_DATA_TIMEOUT? " data_timeout": "",+				intmask & SDHCI_INT_DATA_CRC? " data_crc": "",+				intmask & SDHCI_INT_DATA_END_BIT? " data_endbit": "",+				intmask & SDHCI_INT_BUS_POWER? " buspower": "",+				intmask & SDHCI_INT_ACMD12ERR? " acmd12": "",+				intmask & SDHCI_INT_ADMA_ERROR? " adma": ""+		   );+ 	if (intmask & SDHCI_INT_CMD_MASK) { 		sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, 			SDHCI_INT_STATUS);@@ -2468,7 +2616,13 @@  	intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); -	intmask &= ~SDHCI_INT_ERROR;+	if (intmask & SDHCI_INT_ERROR_MASK) {+		/* collect any uncovered errors */+		sdhci_writel(host, intmask & SDHCI_INT_ERROR_MASK,+				SDHCI_INT_STATUS);+	}++	intmask &= ~SDHCI_INT_ERROR_MASK;  	if (intmask & SDHCI_INT_BUS_POWER) { 		pr_err("%s: Card is consuming too much power!\n",@@ -2494,7 +2648,7 @@ 	if (intmask && --max_loops) 		goto again; out:-	spin_unlock(&host->lock);+	sdhci_spin_unlock(host);  	if (unexpected) { 		pr_err("%s: Unexpected interrupt 0x%08x.\n",@@ -2588,7 +2742,8 @@ { 	int ret; -	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {+	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA |+			   SDHCI_USE_PLATDMA)) { 		if (host->ops->enable_dma) 			host->ops->enable_dma(host); 	}@@ -2671,15 +2826,15 @@ 		host->flags &= ~SDHCI_NEEDS_RETUNING; 	} -	spin_lock_irqsave(&host->lock, flags);+	sdhci_spin_lock_irqsave(host, &flags); 	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);-	spin_unlock_irqrestore(&host->lock, flags);+	sdhci_spin_unlock_irqrestore(host, flags);  	synchronize_irq(host->irq); -	spin_lock_irqsave(&host->lock, flags);+	sdhci_spin_lock_irqsave(host, &flags); 	host->runtime_suspended = true;-	spin_unlock_irqrestore(&host->lock, flags);+	sdhci_spin_unlock_irqrestore(host, flags);  	return ret; }@@ -2705,16 +2860,16 @@ 	sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios); 	if ((host_flags & SDHCI_PV_ENABLED) && 		!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) {-		spin_lock_irqsave(&host->lock, flags);+		sdhci_spin_lock_irqsave(host, &flags); 		sdhci_enable_preset_value(host, true);-		spin_unlock_irqrestore(&host->lock, flags);+		sdhci_spin_unlock_irqrestore(host, flags); 	}  	/* Set the re-tuning expiration flag */ 	if (host->flags & SDHCI_USING_RETUNING_TIMER) 		host->flags |= SDHCI_NEEDS_RETUNING; -	spin_lock_irqsave(&host->lock, flags);+	sdhci_spin_lock_irqsave(host, &flags);  	host->runtime_suspended = false; @@ -2725,7 +2880,7 @@ 	/* Enable Card Detection */ 	sdhci_enable_card_detection(host); -	spin_unlock_irqrestore(&host->lock, flags);+	sdhci_spin_unlock_irqrestore(host, flags);  	return ret; }@@ -2820,14 +2975,16 @@ 		host->flags &= ~SDHCI_USE_ADMA; 	} -	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {+	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA |+			   SDHCI_USE_PLATDMA)) { 		if (host->ops->enable_dma) { 			if (host->ops->enable_dma(host)) { 				pr_warning("%s: No suitable DMA " 					"available. Falling back to PIO.\n", 					mmc_hostname(mmc)); 				host->flags &=-					~(SDHCI_USE_SDMA | SDHCI_USE_ADMA);+					~(SDHCI_USE_SDMA | SDHCI_USE_ADMA |+					  SDHCI_USE_PLATDMA); 			} 		} 	}@@ -3119,6 +3276,12 @@ 				   SDHCI_MAX_CURRENT_MULTIPLIER; 	} +	if(host->ops->voltage_broken) {+		ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34;+		// Cannot support UHS modes if we are stuck at 3.3V;+		mmc->caps &= ~(MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50);+	}+ 	mmc->ocr_avail = ocr_avail; 	mmc->ocr_avail_sdio = ocr_avail; 	if (host->ocr_avail_sdio)@@ -3213,7 +3376,7 @@ 		host->tuning_timer.function = sdhci_tuning_timer; 	} -	ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,+	ret = request_irq(host->irq, sdhci_irq, 0,//IRQF_SHARED, 		mmc_hostname(mmc), host); 	if (ret) { 		pr_err("%s: Failed to request IRQ %d: %d\n",@@ -3249,6 +3412,7 @@  	pr_info("%s: SDHCI controller on %s [%s] using %s\n", 		mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)),+		(host->flags & SDHCI_USE_PLATDMA) ? "platform's DMA" : 		(host->flags & SDHCI_USE_ADMA) ? "ADMA" : 		(host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"); @@ -3276,7 +3440,7 @@ 	unsigned long flags;  	if (dead) {-		spin_lock_irqsave(&host->lock, flags);+		sdhci_spin_lock_irqsave(host, &flags);  		host->flags |= SDHCI_DEVICE_DEAD; @@ -3288,7 +3452,7 @@ 			tasklet_schedule(&host->finish_tasklet); 		} -		spin_unlock_irqrestore(&host->lock, flags);+		sdhci_spin_unlock_irqrestore(host, flags); 	}  	sdhci_disable_card_detection(host);diff -Nur linux-3.11.10.orig/drivers/mmc/host/sdhci.h linux-3.11.10/drivers/mmc/host/sdhci.h--- linux-3.11.10.orig/drivers/mmc/host/sdhci.h	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/mmc/host/sdhci.h	2014-02-07 19:57:28.000000000 +0100@@ -289,6 +289,20 @@ 	void	(*platform_reset_enter)(struct sdhci_host *host, u8 mask); 	void	(*platform_reset_exit)(struct sdhci_host *host, u8 mask); 	int	(*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);++	int             (*pdma_able)(struct sdhci_host *host,+				     struct mmc_data *data);+	void            (*pdma_avail)(struct sdhci_host *host,+				      unsigned int *ref_intmask,+				      void(*complete)(struct sdhci_host *));+	void            (*pdma_reset)(struct sdhci_host *host,+				      struct mmc_data *data);+	unsigned int 	(*extra_ints)(struct sdhci_host *host);+	unsigned int	(*spurious_crc_acmd51)(struct sdhci_host *host);+	unsigned int	(*voltage_broken)(struct sdhci_host *host);+	unsigned int	(*uhs_broken)(struct sdhci_host *host);+	unsigned int	(*missing_status)(struct sdhci_host *host);+ 	void	(*hw_reset)(struct sdhci_host *host); 	void	(*platform_suspend)(struct sdhci_host *host); 	void	(*platform_resume)(struct sdhci_host *host);@@ -400,9 +414,38 @@ extern void sdhci_enable_irq_wakeups(struct sdhci_host *host); #endif +static inline int /*bool*/+sdhci_platdma_dmaable(struct sdhci_host *host, struct mmc_data *data)+{+	if (host->ops->pdma_able)+		return host->ops->pdma_able(host, data);+	else+		return 1;+}+static inline void+sdhci_platdma_avail(struct sdhci_host *host, unsigned int *ref_intmask,+		void(*completion_callback)(struct sdhci_host *))+{+	if (host->ops->pdma_avail)+		host->ops->pdma_avail(host, ref_intmask, completion_callback);+}++static inline void+sdhci_platdma_reset(struct sdhci_host *host, struct mmc_data *data)+{+	if (host->ops->pdma_reset)+		host->ops->pdma_reset(host, data);+}+ #ifdef CONFIG_PM_RUNTIME extern int sdhci_runtime_suspend_host(struct sdhci_host *host); extern int sdhci_runtime_resume_host(struct sdhci_host *host); #endif +extern void sdhci_spin_lock_irqsave(struct sdhci_host *host,unsigned long *flags);+extern void sdhci_spin_unlock_irqrestore(struct sdhci_host *host,unsigned long flags);+extern void sdhci_spin_lock(struct sdhci_host *host);+extern void sdhci_spin_unlock(struct sdhci_host *host);++ #endif /* __SDHCI_HW_H */diff -Nur linux-3.11.10.orig/drivers/net/usb/smsc95xx.c linux-3.11.10/drivers/net/usb/smsc95xx.c--- linux-3.11.10.orig/drivers/net/usb/smsc95xx.c	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/net/usb/smsc95xx.c	2014-02-07 19:57:28.000000000 +0100@@ -61,6 +61,7 @@ #define SUSPEND_SUSPEND3		(0x08) #define SUSPEND_ALLMODES		(SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \ 					 SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3)+#define MAC_ADDR_LEN                    (6)  struct smsc95xx_priv { 	u32 mac_cr;@@ -76,6 +77,10 @@ module_param(turbo_mode, bool, 0644); MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); +static char *macaddr = ":";+module_param(macaddr, charp, 0);+MODULE_PARM_DESC(macaddr, "MAC address");+ static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, 					    u32 *data, int in_pm) {@@ -765,8 +770,59 @@ 	return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); } +/* Check the macaddr module parameter for a MAC address */+static int smsc95xx_is_macaddr_param(struct usbnet *dev, u8 *dev_mac)+{+       int i, j, got_num, num;+       u8 mtbl[MAC_ADDR_LEN];++       if (macaddr[0] == ':')+               return 0;++       i = 0;+       j = 0;+       num = 0;+       got_num = 0;+       while (j < MAC_ADDR_LEN) {+               if (macaddr[i] && macaddr[i] != ':') {+                       got_num++;+                       if ('0' <= macaddr[i] && macaddr[i] <= '9')+                               num = num * 16 + macaddr[i] - '0';+                       else if ('A' <= macaddr[i] && macaddr[i] <= 'F')+                               num = num * 16 + 10 + macaddr[i] - 'A';+                       else if ('a' <= macaddr[i] && macaddr[i] <= 'f')+                               num = num * 16 + 10 + macaddr[i] - 'a';+                       else+                               break;+                       i++;+               } else if (got_num == 2) {+                       mtbl[j++] = (u8) num;+                       num = 0;+                       got_num = 0;+                       i++;+               } else {+                       break;+               }+       }++       if (j == MAC_ADDR_LEN) {+               netif_dbg(dev, ifup, dev->net, "Overriding MAC address with: "+               "%02x:%02x:%02x:%02x:%02x:%02x\n", mtbl[0], mtbl[1], mtbl[2],+                                               mtbl[3], mtbl[4], mtbl[5]);+               for (i = 0; i < MAC_ADDR_LEN; i++)+                       dev_mac[i] = mtbl[i];+               return 1;+       } else {+               return 0;+       }+}+ static void smsc95xx_init_mac_address(struct usbnet *dev) {+       /* Check module parameters */+       if (smsc95xx_is_macaddr_param(dev, dev->net->dev_addr))+               return;+ 	/* try reading mac address from EEPROM */ 	if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, 			dev->net->dev_addr) == 0) {diff -Nur linux-3.11.10.orig/drivers/net/wireless/ath/ath9k/hif_usb.c linux-3.11.10/drivers/net/wireless/ath/ath9k/hif_usb.c--- linux-3.11.10.orig/drivers/net/wireless/ath/ath9k/hif_usb.c	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/net/wireless/ath/ath9k/hif_usb.c	2014-02-07 19:57:28.000000000 +0100@@ -37,9 +37,11 @@ 	{ USB_DEVICE(0x13D3, 0x3350) }, /* Azurewave */ 	{ USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ 	{ USB_DEVICE(0x040D, 0x3801) }, /* VIA */+	{ USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */ 	{ USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */ 	{ USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */ 	{ USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */+	{ USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */  	{ USB_DEVICE(0x0cf3, 0x7015), 	  .driver_info = AR9287_USB },  /* Atheros */diff -Nur linux-3.11.10.orig/drivers/net/wireless/rt2x00/rt2800.h linux-3.11.10/drivers/net/wireless/rt2x00/rt2800.h--- linux-3.11.10.orig/drivers/net/wireless/rt2x00/rt2800.h	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/net/wireless/rt2x00/rt2800.h	2014-02-07 19:57:28.000000000 +0100@@ -70,6 +70,7 @@ #define RF3322				0x000c #define RF3053				0x000d #define RF5592				0x000f+#define RF3070				0x3070 #define RF3290				0x3290 #define RF5360				0x5360 #define RF5370				0x5370diff -Nur linux-3.11.10.orig/drivers/net/wireless/rt2x00/rt2800lib.c linux-3.11.10/drivers/net/wireless/rt2x00/rt2800lib.c--- linux-3.11.10.orig/drivers/net/wireless/rt2x00/rt2800lib.c	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/net/wireless/rt2x00/rt2800lib.c	2014-02-07 19:57:28.000000000 +0100@@ -2599,6 +2599,7 @@ 		break; 	case RF5360: 	case RF5370:+	case RF3070: 	case RF5372: 	case RF5390: 	case RF5392:@@ -2615,6 +2616,7 @@ 	    rt2x00_rf(rt2x00dev, RF3322) || 	    rt2x00_rf(rt2x00dev, RF5360) || 	    rt2x00_rf(rt2x00dev, RF5370) ||+	    rt2x00_rf(rt2x00dev, RF3070) || 	    rt2x00_rf(rt2x00dev, RF5372) || 	    rt2x00_rf(rt2x00dev, RF5390) || 	    rt2x00_rf(rt2x00dev, RF5392)) {@@ -3229,6 +3231,7 @@ 	case RF3290: 	case RF5360: 	case RF5370:+	case RF3070: 	case RF5372: 	case RF5390: 	case RF5392:@@ -5747,6 +5750,7 @@ 	case RF3322: 	case RF5360: 	case RF5370:+	case RF3070: 	case RF5372: 	case RF5390: 	case RF5392:@@ -6202,6 +6206,7 @@ 		   rt2x00_rf(rt2x00dev, RF3322) || 		   rt2x00_rf(rt2x00dev, RF5360) || 		   rt2x00_rf(rt2x00dev, RF5370) ||+		   rt2x00_rf(rt2x00dev, RF3070) || 		   rt2x00_rf(rt2x00dev, RF5372) || 		   rt2x00_rf(rt2x00dev, RF5390) || 		   rt2x00_rf(rt2x00dev, RF5392)) {@@ -6304,6 +6309,7 @@ 	case RF3290: 	case RF5360: 	case RF5370:+	case RF3070: 	case RF5372: 	case RF5390: 	case RF5392:diff -Nur linux-3.11.10.orig/drivers/net/wireless/rt2x00/rt2800lib.c.orig linux-3.11.10/drivers/net/wireless/rt2x00/rt2800lib.c.orig--- linux-3.11.10.orig/drivers/net/wireless/rt2x00/rt2800lib.c.orig	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/net/wireless/rt2x00/rt2800lib.c.orig	2013-11-29 19:42:37.000000000 +0100@@ -0,0 +1,6652 @@+/*+	Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>+	Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com>+	Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>+	Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com>++	Based on the original rt2800pci.c and rt2800usb.c.+	  Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>+	  Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>+	  Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>+	  Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>+	  Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>+	  Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>+	  <http://rt2x00.serialmonkey.com>++	This program is free software; you can redistribute it and/or modify+	it under the terms of the GNU General Public License as published by+	the Free Software Foundation; either version 2 of the License, or+	(at your option) any later version.++	This program is distributed in the hope that it will be useful,+	but WITHOUT ANY WARRANTY; without even the implied warranty of+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+	GNU General Public License for more details.++	You should have received a copy of the GNU General Public License+	along with this program; if not, write to the+	Free Software Foundation, Inc.,+	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.+ */++/*+	Module: rt2800lib+	Abstract: rt2800 generic device routines.+ */++#include <linux/crc-ccitt.h>+#include <linux/kernel.h>+#include <linux/module.h>+#include <linux/slab.h>++#include "rt2x00.h"+#include "rt2800lib.h"+#include "rt2800.h"++/*+ * Register access.+ * All access to the CSR registers will go through the methods+ * rt2800_register_read and rt2800_register_write.+ * BBP and RF register require indirect register access,+ * and use the CSR registers BBPCSR and RFCSR to achieve this.+ * These indirect registers work with busy bits,+ * and we will try maximal REGISTER_BUSY_COUNT times to access+ * the register while taking a REGISTER_BUSY_DELAY us delay+ * between each attampt. When the busy bit is still set at that time,+ * the access attempt is considered to have failed,+ * and we will print an error.+ * The _lock versions must be used if you already hold the csr_mutex+ */+#define WAIT_FOR_BBP(__dev, __reg) \+	rt2800_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg))+#define WAIT_FOR_RFCSR(__dev, __reg) \+	rt2800_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg))+#define WAIT_FOR_RF(__dev, __reg) \+	rt2800_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg))+#define WAIT_FOR_MCU(__dev, __reg) \+	rt2800_regbusy_read((__dev), H2M_MAILBOX_CSR, \+			    H2M_MAILBOX_CSR_OWNER, (__reg))++static inline bool rt2800_is_305x_soc(struct rt2x00_dev *rt2x00dev)+{+	/* check for rt2872 on SoC */+	if (!rt2x00_is_soc(rt2x00dev) ||+	    !rt2x00_rt(rt2x00dev, RT2872))+		return false;++	/* we know for sure that these rf chipsets are used on rt305x boards */+	if (rt2x00_rf(rt2x00dev, RF3020) ||+	    rt2x00_rf(rt2x00dev, RF3021) ||+	    rt2x00_rf(rt2x00dev, RF3022))+		return true;++	rt2x00_warn(rt2x00dev, "Unknown RF chipset on rt305x\n");+	return false;+}++static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,+			     const unsigned int word, const u8 value)+{+	u32 reg;++	mutex_lock(&rt2x00dev->csr_mutex);++	/*+	 * Wait until the BBP becomes available, afterwards we+	 * can safely write the new data into the register.+	 */+	if (WAIT_FOR_BBP(rt2x00dev, ®)) {+		reg = 0;+		rt2x00_set_field32(®, BBP_CSR_CFG_VALUE, value);+		rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word);+		rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1);+		rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0);+		rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1);++		rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);+	}++	mutex_unlock(&rt2x00dev->csr_mutex);+}++static void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev,+			    const unsigned int word, u8 *value)+{+	u32 reg;++	mutex_lock(&rt2x00dev->csr_mutex);++	/*+	 * Wait until the BBP becomes available, afterwards we+	 * can safely write the read request into the register.+	 * After the data has been written, we wait until hardware+	 * returns the correct value, if at any time the register+	 * doesn't become available in time, reg will be 0xffffffff+	 * which means we return 0xff to the caller.+	 */+	if (WAIT_FOR_BBP(rt2x00dev, ®)) {+		reg = 0;+		rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word);+		rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1);+		rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1);+		rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1);++		rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);++		WAIT_FOR_BBP(rt2x00dev, ®);+	}++	*value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE);++	mutex_unlock(&rt2x00dev->csr_mutex);+}++static void rt2800_rfcsr_write(struct rt2x00_dev *rt2x00dev,+			       const unsigned int word, const u8 value)+{+	u32 reg;++	mutex_lock(&rt2x00dev->csr_mutex);++	/*+	 * Wait until the RFCSR becomes available, afterwards we+	 * can safely write the new data into the register.+	 */+	if (WAIT_FOR_RFCSR(rt2x00dev, ®)) {+		reg = 0;+		rt2x00_set_field32(®, RF_CSR_CFG_DATA, value);+		rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word);+		rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 1);+		rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1);++		rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg);+	}++	mutex_unlock(&rt2x00dev->csr_mutex);+}++static void rt2800_rfcsr_read(struct rt2x00_dev *rt2x00dev,+			      const unsigned int word, u8 *value)+{+	u32 reg;++	mutex_lock(&rt2x00dev->csr_mutex);++	/*+	 * Wait until the RFCSR becomes available, afterwards we+	 * can safely write the read request into the register.+	 * After the data has been written, we wait until hardware+	 * returns the correct value, if at any time the register+	 * doesn't become available in time, reg will be 0xffffffff+	 * which means we return 0xff to the caller.+	 */+	if (WAIT_FOR_RFCSR(rt2x00dev, ®)) {+		reg = 0;+		rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word);+		rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 0);+		rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1);++		rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg);++		WAIT_FOR_RFCSR(rt2x00dev, ®);+	}++	*value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA);++	mutex_unlock(&rt2x00dev->csr_mutex);+}++static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev,+			    const unsigned int word, const u32 value)+{+	u32 reg;++	mutex_lock(&rt2x00dev->csr_mutex);++	/*+	 * Wait until the RF becomes available, afterwards we+	 * can safely write the new data into the register.+	 */+	if (WAIT_FOR_RF(rt2x00dev, ®)) {+		reg = 0;+		rt2x00_set_field32(®, RF_CSR_CFG0_REG_VALUE_BW, value);+		rt2x00_set_field32(®, RF_CSR_CFG0_STANDBYMODE, 0);+		rt2x00_set_field32(®, RF_CSR_CFG0_SEL, 0);+		rt2x00_set_field32(®, RF_CSR_CFG0_BUSY, 1);++		rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG0, reg);+		rt2x00_rf_write(rt2x00dev, word, value);+	}++	mutex_unlock(&rt2x00dev->csr_mutex);+}++static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev)+{+	u32 reg;+	int i, count;++	rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®);+	if (rt2x00_get_field32(reg, WLAN_EN))+		return 0;++	rt2x00_set_field32(®, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff);+	rt2x00_set_field32(®, FRC_WL_ANT_SET, 1);+	rt2x00_set_field32(®, WLAN_CLK_EN, 0);+	rt2x00_set_field32(®, WLAN_EN, 1);+	rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);++	udelay(REGISTER_BUSY_DELAY);++	count = 0;+	do {+		/*+		 * Check PLL_LD & XTAL_RDY.+		 */+		for (i = 0; i < REGISTER_BUSY_COUNT; i++) {+			rt2800_register_read(rt2x00dev, CMB_CTRL, ®);+			if (rt2x00_get_field32(reg, PLL_LD) &&+			    rt2x00_get_field32(reg, XTAL_RDY))+				break;+			udelay(REGISTER_BUSY_DELAY);+		}++		if (i >= REGISTER_BUSY_COUNT) {++			if (count >= 10)+				return -EIO;++			rt2800_register_write(rt2x00dev, 0x58, 0x018);+			udelay(REGISTER_BUSY_DELAY);+			rt2800_register_write(rt2x00dev, 0x58, 0x418);+			udelay(REGISTER_BUSY_DELAY);+			rt2800_register_write(rt2x00dev, 0x58, 0x618);+			udelay(REGISTER_BUSY_DELAY);+			count++;+		} else {+			count = 0;+		}++		rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®);+		rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 0);+		rt2x00_set_field32(®, WLAN_CLK_EN, 1);+		rt2x00_set_field32(®, WLAN_RESET, 1);+		rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);+		udelay(10);+		rt2x00_set_field32(®, WLAN_RESET, 0);+		rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);+		udelay(10);+		rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, 0x7fffffff);+	} while (count != 0);++	return 0;+}++void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,+			const u8 command, const u8 token,+			const u8 arg0, const u8 arg1)+{+	u32 reg;++	/*+	 * SOC devices don't support MCU requests.+	 */+	if (rt2x00_is_soc(rt2x00dev))+		return;++	mutex_lock(&rt2x00dev->csr_mutex);++	/*+	 * Wait until the MCU becomes available, afterwards we+	 * can safely write the new data into the register.+	 */+	if (WAIT_FOR_MCU(rt2x00dev, ®)) {+		rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1);+		rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token);+		rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0);+		rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1);+		rt2800_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg);++		reg = 0;+		rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command);+		rt2800_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg);+	}++	mutex_unlock(&rt2x00dev->csr_mutex);+}+EXPORT_SYMBOL_GPL(rt2800_mcu_request);++int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev)+{+	unsigned int i = 0;+	u32 reg;++	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {+		rt2800_register_read(rt2x00dev, MAC_CSR0, ®);+		if (reg && reg != ~0)+			return 0;+		msleep(1);+	}++	rt2x00_err(rt2x00dev, "Unstable hardware\n");+	return -EBUSY;+}+EXPORT_SYMBOL_GPL(rt2800_wait_csr_ready);++int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)+{+	unsigned int i;+	u32 reg;++	/*+	 * Some devices are really slow to respond here. Wait a whole second+	 * before timing out.+	 */+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {+		rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®);+		if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&+		    !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY))+			return 0;++		msleep(10);+	}++	rt2x00_err(rt2x00dev, "WPDMA TX/RX busy [0x%08x]\n", reg);+	return -EACCES;+}+EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready);++void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev)+{+	u32 reg;++	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®);+	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);+	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);+	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);+	rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);+	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);+	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);+}+EXPORT_SYMBOL_GPL(rt2800_disable_wpdma);++static bool rt2800_check_firmware_crc(const u8 *data, const size_t len)+{+	u16 fw_crc;+	u16 crc;++	/*+	 * The last 2 bytes in the firmware array are the crc checksum itself,+	 * this means that we should never pass those 2 bytes to the crc+	 * algorithm.+	 */+	fw_crc = (data[len - 2] << 8 | data[len - 1]);++	/*+	 * Use the crc ccitt algorithm.+	 * This will return the same value as the legacy driver which+	 * used bit ordering reversion on the both the firmware bytes+	 * before input input as well as on the final output.+	 * Obviously using crc ccitt directly is much more efficient.+	 */+	crc = crc_ccitt(~0, data, len - 2);++	/*+	 * There is a small difference between the crc-itu-t + bitrev and+	 * the crc-ccitt crc calculation. In the latter method the 2 bytes+	 * will be swapped, use swab16 to convert the crc to the correct+	 * value.+	 */+	crc = swab16(crc);++	return fw_crc == crc;+}++int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,+			  const u8 *data, const size_t len)+{+	size_t offset = 0;+	size_t fw_len;+	bool multiple;++	/*+	 * PCI(e) & SOC devices require firmware with a length+	 * of 8kb. USB devices require firmware files with a length+	 * of 4kb. Certain USB chipsets however require different firmware,+	 * which Ralink only provides attached to the original firmware+	 * file. Thus for USB devices, firmware files have a length+	 * which is a multiple of 4kb. The firmware for rt3290 chip also+	 * have a length which is a multiple of 4kb.+	 */+	if (rt2x00_is_usb(rt2x00dev) || rt2x00_rt(rt2x00dev, RT3290))+		fw_len = 4096;+	else+		fw_len = 8192;++	multiple = true;+	/*+	 * Validate the firmware length+	 */+	if (len != fw_len && (!multiple || (len % fw_len) != 0))+		return FW_BAD_LENGTH;++	/*+	 * Check if the chipset requires one of the upper parts+	 * of the firmware.+	 */+	if (rt2x00_is_usb(rt2x00dev) &&+	    !rt2x00_rt(rt2x00dev, RT2860) &&+	    !rt2x00_rt(rt2x00dev, RT2872) &&+	    !rt2x00_rt(rt2x00dev, RT3070) &&+	    ((len / fw_len) == 1))+		return FW_BAD_VERSION;++	/*+	 * 8kb firmware files must be checked as if it were+	 * 2 separate firmware files.+	 */+	while (offset < len) {+		if (!rt2800_check_firmware_crc(data + offset, fw_len))+			return FW_BAD_CRC;++		offset += fw_len;+	}++	return FW_OK;+}+EXPORT_SYMBOL_GPL(rt2800_check_firmware);++int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,+			 const u8 *data, const size_t len)+{+	unsigned int i;+	u32 reg;+	int retval;++	if (rt2x00_rt(rt2x00dev, RT3290)) {+		retval = rt2800_enable_wlan_rt3290(rt2x00dev);+		if (retval)+			return -EBUSY;+	}++	/*+	 * If driver doesn't wake up firmware here,+	 * rt2800_load_firmware will hang forever when interface is up again.+	 */+	rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000);++	/*+	 * Wait for stable hardware.+	 */+	if (rt2800_wait_csr_ready(rt2x00dev))+		return -EBUSY;++	if (rt2x00_is_pci(rt2x00dev)) {+		if (rt2x00_rt(rt2x00dev, RT3290) ||+		    rt2x00_rt(rt2x00dev, RT3572) ||+		    rt2x00_rt(rt2x00dev, RT5390) ||+		    rt2x00_rt(rt2x00dev, RT5392)) {+			rt2800_register_read(rt2x00dev, AUX_CTRL, ®);+			rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1);+			rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1);+			rt2800_register_write(rt2x00dev, AUX_CTRL, reg);+		}+		rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002);+	}++	rt2800_disable_wpdma(rt2x00dev);++	/*+	 * Write firmware to the device.+	 */+	rt2800_drv_write_firmware(rt2x00dev, data, len);++	/*+	 * Wait for device to stabilize.+	 */+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {+		rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®);+		if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY))+			break;+		msleep(1);+	}++	if (i == REGISTER_BUSY_COUNT) {+		rt2x00_err(rt2x00dev, "PBF system register not ready\n");+		return -EBUSY;+	}++	/*+	 * Disable DMA, will be reenabled later when enabling+	 * the radio.+	 */+	rt2800_disable_wpdma(rt2x00dev);++	/*+	 * Initialize firmware.+	 */+	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);+	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);+	if (rt2x00_is_usb(rt2x00dev)) {+		rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);+		rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);+	}+	msleep(1);++	return 0;+}+EXPORT_SYMBOL_GPL(rt2800_load_firmware);++void rt2800_write_tx_data(struct queue_entry *entry,+			  struct txentry_desc *txdesc)+{+	__le32 *txwi = rt2800_drv_get_txwi(entry);+	u32 word;+	int i;++	/*+	 * Initialize TX Info descriptor+	 */+	rt2x00_desc_read(txwi, 0, &word);+	rt2x00_set_field32(&word, TXWI_W0_FRAG,+			   test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));+	rt2x00_set_field32(&word, TXWI_W0_MIMO_PS,+			   test_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags));+	rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0);+	rt2x00_set_field32(&word, TXWI_W0_TS,+			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));+	rt2x00_set_field32(&word, TXWI_W0_AMPDU,+			   test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags));+	rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY,+			   txdesc->u.ht.mpdu_density);+	rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->u.ht.txop);+	rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->u.ht.mcs);+	rt2x00_set_field32(&word, TXWI_W0_BW,+			   test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags));+	rt2x00_set_field32(&word, TXWI_W0_SHORT_GI,+			   test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags));+	rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->u.ht.stbc);+	rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode);+	rt2x00_desc_write(txwi, 0, word);++	rt2x00_desc_read(txwi, 1, &word);+	rt2x00_set_field32(&word, TXWI_W1_ACK,+			   test_bit(ENTRY_TXD_ACK, &txdesc->flags));+	rt2x00_set_field32(&word, TXWI_W1_NSEQ,+			   test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));+	rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->u.ht.ba_size);+	rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,+			   test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?+			   txdesc->key_idx : txdesc->u.ht.wcid);+	rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,+			   txdesc->length);+	rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid);+	rt2x00_set_field32(&word, TXWI_W1_PACKETID_ENTRY, (entry->entry_idx % 3) + 1);+	rt2x00_desc_write(txwi, 1, word);++	/*+	 * Always write 0 to IV/EIV fields (word 2 and 3), hardware will insert+	 * the IV from the IVEIV register when TXD_W3_WIV is set to 0.+	 * When TXD_W3_WIV is set to 1 it will use the IV data+	 * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which+	 * crypto entry in the registers should be used to encrypt the frame.+	 *+	 * Nulify all remaining words as well, we don't know how to program them.+	 */+	for (i = 2; i < entry->queue->winfo_size / sizeof(__le32); i++)+		_rt2x00_desc_write(txwi, i, 0);+}+EXPORT_SYMBOL_GPL(rt2800_write_tx_data);++static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)+{+	s8 rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0);+	s8 rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1);+	s8 rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2);+	u16 eeprom;+	u8 offset0;+	u8 offset1;+	u8 offset2;++	if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {+		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom);+		offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0);+		offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1);+		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);+		offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_OFFSET2);+	} else {+		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom);+		offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET0);+		offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET1);+		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);+		offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_OFFSET2);+	}++	/*+	 * Convert the value from the descriptor into the RSSI value+	 * If the value in the descriptor is 0, it is considered invalid+	 * and the default (extremely low) rssi value is assumed+	 */+	rssi0 = (rssi0) ? (-12 - offset0 - rt2x00dev->lna_gain - rssi0) : -128;+	rssi1 = (rssi1) ? (-12 - offset1 - rt2x00dev->lna_gain - rssi1) : -128;+	rssi2 = (rssi2) ? (-12 - offset2 - rt2x00dev->lna_gain - rssi2) : -128;++	/*+	 * mac80211 only accepts a single RSSI value. Calculating the+	 * average doesn't deliver a fair answer either since -60:-60 would+	 * be considered equally good as -50:-70 while the second is the one+	 * which gives less energy...+	 */+	rssi0 = max(rssi0, rssi1);+	return (int)max(rssi0, rssi2);+}++void rt2800_process_rxwi(struct queue_entry *entry,+			 struct rxdone_entry_desc *rxdesc)+{+	__le32 *rxwi = (__le32 *) entry->skb->data;+	u32 word;++	rt2x00_desc_read(rxwi, 0, &word);++	rxdesc->cipher = rt2x00_get_field32(word, RXWI_W0_UDF);+	rxdesc->size = rt2x00_get_field32(word, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);++	rt2x00_desc_read(rxwi, 1, &word);++	if (rt2x00_get_field32(word, RXWI_W1_SHORT_GI))+		rxdesc->flags |= RX_FLAG_SHORT_GI;++	if (rt2x00_get_field32(word, RXWI_W1_BW))+		rxdesc->flags |= RX_FLAG_40MHZ;++	/*+	 * Detect RX rate, always use MCS as signal type.+	 */+	rxdesc->dev_flags |= RXDONE_SIGNAL_MCS;+	rxdesc->signal = rt2x00_get_field32(word, RXWI_W1_MCS);+	rxdesc->rate_mode = rt2x00_get_field32(word, RXWI_W1_PHYMODE);++	/*+	 * Mask of 0x8 bit to remove the short preamble flag.+	 */+	if (rxdesc->rate_mode == RATE_MODE_CCK)+		rxdesc->signal &= ~0x8;++	rt2x00_desc_read(rxwi, 2, &word);++	/*+	 * Convert descriptor AGC value to RSSI value.+	 */+	rxdesc->rssi = rt2800_agc_to_rssi(entry->queue->rt2x00dev, word);+	/*+	 * Remove RXWI descriptor from start of the buffer.+	 */+	skb_pull(entry->skb, entry->queue->winfo_size);+}+EXPORT_SYMBOL_GPL(rt2800_process_rxwi);++void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)+{+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);+	struct txdone_entry_desc txdesc;+	u32 word;+	u16 mcs, real_mcs;+	int aggr, ampdu;++	/*+	 * Obtain the status about this packet.+	 */+	txdesc.flags = 0;+	rt2x00_desc_read(txwi, 0, &word);++	mcs = rt2x00_get_field32(word, TXWI_W0_MCS);+	ampdu = rt2x00_get_field32(word, TXWI_W0_AMPDU);++	real_mcs = rt2x00_get_field32(status, TX_STA_FIFO_MCS);+	aggr = rt2x00_get_field32(status, TX_STA_FIFO_TX_AGGRE);++	/*+	 * If a frame was meant to be sent as a single non-aggregated MPDU+	 * but ended up in an aggregate the used tx rate doesn't correlate+	 * with the one specified in the TXWI as the whole aggregate is sent+	 * with the same rate.+	 *+	 * For example: two frames are sent to rt2x00, the first one sets+	 * AMPDU=1 and requests MCS7 whereas the second frame sets AMDPU=0+	 * and requests MCS15. If the hw aggregates both frames into one+	 * AMDPU the tx status for both frames will contain MCS7 although+	 * the frame was sent successfully.+	 *+	 * Hence, replace the requested rate with the real tx rate to not+	 * confuse the rate control algortihm by providing clearly wrong+	 * data.+	 */+	if (unlikely(aggr == 1 && ampdu == 0 && real_mcs != mcs)) {+		skbdesc->tx_rate_idx = real_mcs;+		mcs = real_mcs;+	}++	if (aggr == 1 || ampdu == 1)+		__set_bit(TXDONE_AMPDU, &txdesc.flags);++	/*+	 * Ralink has a retry mechanism using a global fallback+	 * table. We setup this fallback table to try the immediate+	 * lower rate for all rates. In the TX_STA_FIFO, the MCS field+	 * always contains the MCS used for the last transmission, be+	 * it successful or not.+	 */+	if (rt2x00_get_field32(status, TX_STA_FIFO_TX_SUCCESS)) {+		/*+		 * Transmission succeeded. The number of retries is+		 * mcs - real_mcs+		 */+		__set_bit(TXDONE_SUCCESS, &txdesc.flags);+		txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0);+	} else {+		/*+		 * Transmission failed. The number of retries is+		 * always 7 in this case (for a total number of 8+		 * frames sent).+		 */+		__set_bit(TXDONE_FAILURE, &txdesc.flags);+		txdesc.retry = rt2x00dev->long_retry;+	}++	/*+	 * the frame was retried at least once+	 * -> hw used fallback rates+	 */+	if (txdesc.retry)+		__set_bit(TXDONE_FALLBACK, &txdesc.flags);++	rt2x00lib_txdone(entry, &txdesc);+}+EXPORT_SYMBOL_GPL(rt2800_txdone_entry);++void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)+{+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);+	unsigned int beacon_base;+	unsigned int padding_len;+	u32 orig_reg, reg;+	const int txwi_desc_size = entry->queue->winfo_size;++	/*+	 * Disable beaconing while we are reloading the beacon data,+	 * otherwise we might be sending out invalid data.+	 */+	rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®);+	orig_reg = reg;+	rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0);+	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);++	/*+	 * Add space for the TXWI in front of the skb.+	 */+	memset(skb_push(entry->skb, txwi_desc_size), 0, txwi_desc_size);++	/*+	 * Register descriptor details in skb frame descriptor.+	 */+	skbdesc->flags |= SKBDESC_DESC_IN_SKB;+	skbdesc->desc = entry->skb->data;+	skbdesc->desc_len = txwi_desc_size;++	/*+	 * Add the TXWI for the beacon to the skb.+	 */+	rt2800_write_tx_data(entry, txdesc);++	/*+	 * Dump beacon to userspace through debugfs.+	 */+	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);++	/*+	 * Write entire beacon with TXWI and padding to register.+	 */+	padding_len = roundup(entry->skb->len, 4) - entry->skb->len;+	if (padding_len && skb_pad(entry->skb, padding_len)) {+		rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n");+		/* skb freed by skb_pad() on failure */+		entry->skb = NULL;+		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);+		return;+	}++	beacon_base = HW_BEACON_OFFSET(entry->entry_idx);+	rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,+				   entry->skb->len + padding_len);++	/*+	 * Enable beaconing again.+	 */+	rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1);+	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);++	/*+	 * Clean up beacon skb.+	 */+	dev_kfree_skb_any(entry->skb);+	entry->skb = NULL;+}+EXPORT_SYMBOL_GPL(rt2800_write_beacon);++static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,+						unsigned int beacon_base)+{+	int i;+	const int txwi_desc_size = rt2x00dev->bcn->winfo_size;++	/*+	 * For the Beacon base registers we only need to clear+	 * the whole TXWI which (when set to 0) will invalidate+	 * the entire beacon.+	 */+	for (i = 0; i < txwi_desc_size; i += sizeof(__le32))+		rt2800_register_write(rt2x00dev, beacon_base + i, 0);+}++void rt2800_clear_beacon(struct queue_entry *entry)+{+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;+	u32 reg;++	/*+	 * Disable beaconing while we are reloading the beacon data,+	 * otherwise we might be sending out invalid data.+	 */+	rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®);+	rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0);+	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);++	/*+	 * Clear beacon.+	 */+	rt2800_clear_beacon_register(rt2x00dev,+				     HW_BEACON_OFFSET(entry->entry_idx));++	/*+	 * Enabled beaconing again.+	 */+	rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1);+	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);+}+EXPORT_SYMBOL_GPL(rt2800_clear_beacon);++#ifdef CONFIG_RT2X00_LIB_DEBUGFS+const struct rt2x00debug rt2800_rt2x00debug = {+	.owner	= THIS_MODULE,+	.csr	= {+		.read		= rt2800_register_read,+		.write		= rt2800_register_write,+		.flags		= RT2X00DEBUGFS_OFFSET,+		.word_base	= CSR_REG_BASE,+		.word_size	= sizeof(u32),+		.word_count	= CSR_REG_SIZE / sizeof(u32),+	},+	.eeprom	= {+		.read		= rt2x00_eeprom_read,+		.write		= rt2x00_eeprom_write,+		.word_base	= EEPROM_BASE,+		.word_size	= sizeof(u16),+		.word_count	= EEPROM_SIZE / sizeof(u16),+	},+	.bbp	= {+		.read		= rt2800_bbp_read,+		.write		= rt2800_bbp_write,+		.word_base	= BBP_BASE,+		.word_size	= sizeof(u8),+		.word_count	= BBP_SIZE / sizeof(u8),+	},+	.rf	= {+		.read		= rt2x00_rf_read,+		.write		= rt2800_rf_write,+		.word_base	= RF_BASE,+		.word_size	= sizeof(u32),+		.word_count	= RF_SIZE / sizeof(u32),+	},+	.rfcsr	= {+		.read		= rt2800_rfcsr_read,+		.write		= rt2800_rfcsr_write,+		.word_base	= RFCSR_BASE,+		.word_size	= sizeof(u8),+		.word_count	= RFCSR_SIZE / sizeof(u8),+	},+};+EXPORT_SYMBOL_GPL(rt2800_rt2x00debug);+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */++int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)+{+	u32 reg;++	if (rt2x00_rt(rt2x00dev, RT3290)) {+		rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®);+		return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0);+	} else {+		rt2800_register_read(rt2x00dev, GPIO_CTRL, ®);+		return rt2x00_get_field32(reg, GPIO_CTRL_VAL2);+	}+}+EXPORT_SYMBOL_GPL(rt2800_rfkill_poll);++#ifdef CONFIG_RT2X00_LIB_LEDS+static void rt2800_brightness_set(struct led_classdev *led_cdev,+				  enum led_brightness brightness)+{+	struct rt2x00_led *led =+	    container_of(led_cdev, struct rt2x00_led, led_dev);+	unsigned int enabled = brightness != LED_OFF;+	unsigned int bg_mode =+	    (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);+	unsigned int polarity =+		rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,+				   EEPROM_FREQ_LED_POLARITY);+	unsigned int ledmode =+		rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,+				   EEPROM_FREQ_LED_MODE);+	u32 reg;++	/* Check for SoC (SOC devices don't support MCU requests) */+	if (rt2x00_is_soc(led->rt2x00dev)) {+		rt2800_register_read(led->rt2x00dev, LED_CFG, ®);++		/* Set LED Polarity */+		rt2x00_set_field32(®, LED_CFG_LED_POLAR, polarity);++		/* Set LED Mode */+		if (led->type == LED_TYPE_RADIO) {+			rt2x00_set_field32(®, LED_CFG_G_LED_MODE,+					   enabled ? 3 : 0);+		} else if (led->type == LED_TYPE_ASSOC) {+			rt2x00_set_field32(®, LED_CFG_Y_LED_MODE,+					   enabled ? 3 : 0);+		} else if (led->type == LED_TYPE_QUALITY) {+			rt2x00_set_field32(®, LED_CFG_R_LED_MODE,+					   enabled ? 3 : 0);+		}++		rt2800_register_write(led->rt2x00dev, LED_CFG, reg);++	} else {+		if (led->type == LED_TYPE_RADIO) {+			rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,+					      enabled ? 0x20 : 0);+		} else if (led->type == LED_TYPE_ASSOC) {+			rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,+					      enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20);+		} else if (led->type == LED_TYPE_QUALITY) {+			/*+			 * The brightness is divided into 6 levels (0 - 5),+			 * The specs tell us the following levels:+			 *	0, 1 ,3, 7, 15, 31+			 * to determine the level in a simple way we can simply+			 * work with bitshifting:+			 *	(1 << level) - 1+			 */+			rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,+					      (1 << brightness / (LED_FULL / 6)) - 1,+					      polarity);+		}+	}+}++static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,+		     struct rt2x00_led *led, enum led_type type)+{+	led->rt2x00dev = rt2x00dev;+	led->type = type;+	led->led_dev.brightness_set = rt2800_brightness_set;+	led->flags = LED_INITIALIZED;+}+#endif /* CONFIG_RT2X00_LIB_LEDS */++/*+ * Configuration handlers.+ */+static void rt2800_config_wcid(struct rt2x00_dev *rt2x00dev,+			       const u8 *address,+			       int wcid)+{+	struct mac_wcid_entry wcid_entry;+	u32 offset;++	offset = MAC_WCID_ENTRY(wcid);++	memset(&wcid_entry, 0xff, sizeof(wcid_entry));+	if (address)+		memcpy(wcid_entry.mac, address, ETH_ALEN);++	rt2800_register_multiwrite(rt2x00dev, offset,+				      &wcid_entry, sizeof(wcid_entry));+}++static void rt2800_delete_wcid_attr(struct rt2x00_dev *rt2x00dev, int wcid)+{+	u32 offset;+	offset = MAC_WCID_ATTR_ENTRY(wcid);+	rt2800_register_write(rt2x00dev, offset, 0);+}++static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,+					   int wcid, u32 bssidx)+{+	u32 offset = MAC_WCID_ATTR_ENTRY(wcid);+	u32 reg;++	/*+	 * The BSS Idx numbers is split in a main value of 3 bits,+	 * and a extended field for adding one additional bit to the value.+	 */+	rt2800_register_read(rt2x00dev, offset, ®);+	rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7));+	rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,+			   (bssidx & 0x8) >> 3);+	rt2800_register_write(rt2x00dev, offset, reg);+}++static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,+					   struct rt2x00lib_crypto *crypto,+					   struct ieee80211_key_conf *key)+{+	struct mac_iveiv_entry iveiv_entry;+	u32 offset;+	u32 reg;++	offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx);++	if (crypto->cmd == SET_KEY) {+		rt2800_register_read(rt2x00dev, offset, ®);+		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB,+				   !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE));+		/*+		 * Both the cipher as the BSS Idx numbers are split in a main+		 * value of 3 bits, and a extended field for adding one additional+		 * bit to the value.+		 */+		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER,+				   (crypto->cipher & 0x7));+		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER_EXT,+				   (crypto->cipher & 0x8) >> 3);+		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher);+		rt2800_register_write(rt2x00dev, offset, reg);+	} else {+		/* Delete the cipher without touching the bssidx */+		rt2800_register_read(rt2x00dev, offset, ®);+		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, 0);+		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, 0);+		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER_EXT, 0);+		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0);+		rt2800_register_write(rt2x00dev, offset, reg);+	}++	offset = MAC_IVEIV_ENTRY(key->hw_key_idx);++	memset(&iveiv_entry, 0, sizeof(iveiv_entry));+	if ((crypto->cipher == CIPHER_TKIP) ||+	    (crypto->cipher == CIPHER_TKIP_NO_MIC) ||+	    (crypto->cipher == CIPHER_AES))+		iveiv_entry.iv[3] |= 0x20;+	iveiv_entry.iv[3] |= key->keyidx << 6;+	rt2800_register_multiwrite(rt2x00dev, offset,+				      &iveiv_entry, sizeof(iveiv_entry));+}++int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,+			     struct rt2x00lib_crypto *crypto,+			     struct ieee80211_key_conf *key)+{+	struct hw_key_entry key_entry;+	struct rt2x00_field32 field;+	u32 offset;+	u32 reg;++	if (crypto->cmd == SET_KEY) {+		key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx;++		memcpy(key_entry.key, crypto->key,+		       sizeof(key_entry.key));+		memcpy(key_entry.tx_mic, crypto->tx_mic,+		       sizeof(key_entry.tx_mic));+		memcpy(key_entry.rx_mic, crypto->rx_mic,+		       sizeof(key_entry.rx_mic));++		offset = SHARED_KEY_ENTRY(key->hw_key_idx);+		rt2800_register_multiwrite(rt2x00dev, offset,+					      &key_entry, sizeof(key_entry));+	}++	/*+	 * The cipher types are stored over multiple registers+	 * starting with SHARED_KEY_MODE_BASE each word will have+	 * 32 bits and contains the cipher types for 2 bssidx each.+	 * Using the correct defines correctly will cause overhead,+	 * so just calculate the correct offset.+	 */+	field.bit_offset = 4 * (key->hw_key_idx % 8);+	field.bit_mask = 0x7 << field.bit_offset;++	offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8);++	rt2800_register_read(rt2x00dev, offset, ®);+	rt2x00_set_field32(®, field,+			   (crypto->cmd == SET_KEY) * crypto->cipher);+	rt2800_register_write(rt2x00dev, offset, reg);++	/*+	 * Update WCID information+	 */+	rt2800_config_wcid(rt2x00dev, crypto->address, key->hw_key_idx);+	rt2800_config_wcid_attr_bssidx(rt2x00dev, key->hw_key_idx,+				       crypto->bssidx);+	rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);++	return 0;+}+EXPORT_SYMBOL_GPL(rt2800_config_shared_key);++static inline int rt2800_find_wcid(struct rt2x00_dev *rt2x00dev)+{+	struct mac_wcid_entry wcid_entry;+	int idx;+	u32 offset;++	/*+	 * Search for the first free WCID entry and return the corresponding+	 * index.+	 *+	 * Make sure the WCID starts _after_ the last possible shared key+	 * entry (>32).+	 *+	 * Since parts of the pairwise key table might be shared with+	 * the beacon frame buffers 6 & 7 we should only write into the+	 * first 222 entries.+	 */+	for (idx = 33; idx <= 222; idx++) {+		offset = MAC_WCID_ENTRY(idx);+		rt2800_register_multiread(rt2x00dev, offset, &wcid_entry,+					  sizeof(wcid_entry));+		if (is_broadcast_ether_addr(wcid_entry.mac))+			return idx;+	}++	/*+	 * Use -1 to indicate that we don't have any more space in the WCID+	 * table.+	 */+	return -1;+}++int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,+			       struct rt2x00lib_crypto *crypto,+			       struct ieee80211_key_conf *key)+{+	struct hw_key_entry key_entry;+	u32 offset;++	if (crypto->cmd == SET_KEY) {+		/*+		 * Allow key configuration only for STAs that are+		 * known by the hw.+		 */+		if (crypto->wcid < 0)+			return -ENOSPC;+		key->hw_key_idx = crypto->wcid;++		memcpy(key_entry.key, crypto->key,+		       sizeof(key_entry.key));+		memcpy(key_entry.tx_mic, crypto->tx_mic,+		       sizeof(key_entry.tx_mic));+		memcpy(key_entry.rx_mic, crypto->rx_mic,+		       sizeof(key_entry.rx_mic));++		offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx);+		rt2800_register_multiwrite(rt2x00dev, offset,+					      &key_entry, sizeof(key_entry));+	}++	/*+	 * Update WCID information+	 */+	rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);++	return 0;+}+EXPORT_SYMBOL_GPL(rt2800_config_pairwise_key);++int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,+		   struct ieee80211_sta *sta)+{+	int wcid;+	struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);++	/*+	 * Find next free WCID.+	 */+	wcid = rt2800_find_wcid(rt2x00dev);++	/*+	 * Store selected wcid even if it is invalid so that we can+	 * later decide if the STA is uploaded into the hw.+	 */+	sta_priv->wcid = wcid;++	/*+	 * No space left in the device, however, we can still communicate+	 * with the STA -> No error.+	 */+	if (wcid < 0)+		return 0;++	/*+	 * Clean up WCID attributes and write STA address to the device.+	 */+	rt2800_delete_wcid_attr(rt2x00dev, wcid);+	rt2800_config_wcid(rt2x00dev, sta->addr, wcid);+	rt2800_config_wcid_attr_bssidx(rt2x00dev, wcid,+				       rt2x00lib_get_bssidx(rt2x00dev, vif));+	return 0;+}+EXPORT_SYMBOL_GPL(rt2800_sta_add);++int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid)+{+	/*+	 * Remove WCID entry, no need to clean the attributes as they will+	 * get renewed when the WCID is reused.+	 */+	rt2800_config_wcid(rt2x00dev, NULL, wcid);++	return 0;+}+EXPORT_SYMBOL_GPL(rt2800_sta_remove);++void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,+			  const unsigned int filter_flags)+{+	u32 reg;++	/*+	 * Start configuration steps.+	 * Note that the version error will always be dropped+	 * and broadcast frames will always be accepted since+	 * there is no filter for it at this time.+	 */+	rt2800_register_read(rt2x00dev, RX_FILTER_CFG, ®);+	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CRC_ERROR,+			   !(filter_flags & FIF_FCSFAIL));+	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PHY_ERROR,+			   !(filter_flags & FIF_PLCPFAIL));+	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME,+			   !(filter_flags & FIF_PROMISC_IN_BSS));+	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0);+	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_VER_ERROR, 1);+	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_MULTICAST,+			   !(filter_flags & FIF_ALLMULTI));+	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BROADCAST, 0);+	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_DUPLICATE, 1);+	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END_ACK,+			   !(filter_flags & FIF_CONTROL));+	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END,+			   !(filter_flags & FIF_CONTROL));+	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_ACK,+			   !(filter_flags & FIF_CONTROL));+	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CTS,+			   !(filter_flags & FIF_CONTROL));+	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_RTS,+			   !(filter_flags & FIF_CONTROL));+	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL,+			   !(filter_flags & FIF_PSPOLL));+	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 0);+	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR,+			   !(filter_flags & FIF_CONTROL));+	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL,+			   !(filter_flags & FIF_CONTROL));+	rt2800_register_write(rt2x00dev, RX_FILTER_CFG, reg);+}+EXPORT_SYMBOL_GPL(rt2800_config_filter);++void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,+			struct rt2x00intf_conf *conf, const unsigned int flags)+{+	u32 reg;+	bool update_bssid = false;++	if (flags & CONFIG_UPDATE_TYPE) {+		/*+		 * Enable synchronisation.+		 */+		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®);+		rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync);+		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);++		if (conf->sync == TSF_SYNC_AP_NONE) {+			/*+			 * Tune beacon queue transmit parameters for AP mode+			 */+			rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, ®);+			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_CWMIN, 0);+			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_AIFSN, 1);+			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);+			rt2x00_set_field32(®, TBTT_SYNC_CFG_TBTT_ADJUST, 0);+			rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);+		} else {+			rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, ®);+			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_CWMIN, 4);+			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_AIFSN, 2);+			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);+			rt2x00_set_field32(®, TBTT_SYNC_CFG_TBTT_ADJUST, 16);+			rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);+		}+	}++	if (flags & CONFIG_UPDATE_MAC) {+		if (flags & CONFIG_UPDATE_TYPE &&+		    conf->sync == TSF_SYNC_AP_NONE) {+			/*+			 * The BSSID register has to be set to our own mac+			 * address in AP mode.+			 */+			memcpy(conf->bssid, conf->mac, sizeof(conf->mac));+			update_bssid = true;+		}++		if (!is_zero_ether_addr((const u8 *)conf->mac)) {+			reg = le32_to_cpu(conf->mac[1]);+			rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff);+			conf->mac[1] = cpu_to_le32(reg);+		}++		rt2800_register_multiwrite(rt2x00dev, MAC_ADDR_DW0,+					      conf->mac, sizeof(conf->mac));+	}++	if ((flags & CONFIG_UPDATE_BSSID) || update_bssid) {+		if (!is_zero_ether_addr((const u8 *)conf->bssid)) {+			reg = le32_to_cpu(conf->bssid[1]);+			rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 3);+			rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 7);+			conf->bssid[1] = cpu_to_le32(reg);+		}++		rt2800_register_multiwrite(rt2x00dev, MAC_BSSID_DW0,+					      conf->bssid, sizeof(conf->bssid));+	}+}+EXPORT_SYMBOL_GPL(rt2800_config_intf);++static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev,+				    struct rt2x00lib_erp *erp)+{+	bool any_sta_nongf = !!(erp->ht_opmode &+				IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);+	u8 protection = erp->ht_opmode & IEEE80211_HT_OP_MODE_PROTECTION;+	u8 mm20_mode, mm40_mode, gf20_mode, gf40_mode;+	u16 mm20_rate, mm40_rate, gf20_rate, gf40_rate;+	u32 reg;++	/* default protection rate for HT20: OFDM 24M */+	mm20_rate = gf20_rate = 0x4004;++	/* default protection rate for HT40: duplicate OFDM 24M */+	mm40_rate = gf40_rate = 0x4084;++	switch (protection) {+	case IEEE80211_HT_OP_MODE_PROTECTION_NONE:+		/*+		 * All STAs in this BSS are HT20/40 but there might be+		 * STAs not supporting greenfield mode.+		 * => Disable protection for HT transmissions.+		 */+		mm20_mode = mm40_mode = gf20_mode = gf40_mode = 0;++		break;+	case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:+		/*+		 * All STAs in this BSS are HT20 or HT20/40 but there+		 * might be STAs not supporting greenfield mode.+		 * => Protect all HT40 transmissions.+		 */+		mm20_mode = gf20_mode = 0;+		mm40_mode = gf40_mode = 2;++		break;+	case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:+		/*+		 * Nonmember protection:+		 * According to 802.11n we _should_ protect all+		 * HT transmissions (but we don't have to).+		 *+		 * But if cts_protection is enabled we _shall_ protect+		 * all HT transmissions using a CCK rate.+		 *+		 * And if any station is non GF we _shall_ protect+		 * GF transmissions.+		 *+		 * We decide to protect everything+		 * -> fall through to mixed mode.+		 */+	case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:+		/*+		 * Legacy STAs are present+		 * => Protect all HT transmissions.+		 */+		mm20_mode = mm40_mode = gf20_mode = gf40_mode = 2;++		/*+		 * If erp protection is needed we have to protect HT+		 * transmissions with CCK 11M long preamble.+		 */+		if (erp->cts_protection) {+			/* don't duplicate RTS/CTS in CCK mode */+			mm20_rate = mm40_rate = 0x0003;+			gf20_rate = gf40_rate = 0x0003;+		}+		break;+	}++	/* check for STAs not supporting greenfield mode */+	if (any_sta_nongf)+		gf20_mode = gf40_mode = 2;++	/* Update HT protection config */+	rt2800_register_read(rt2x00dev, MM20_PROT_CFG, ®);+	rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_RATE, mm20_rate);+	rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_CTRL, mm20_mode);+	rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);++	rt2800_register_read(rt2x00dev, MM40_PROT_CFG, ®);+	rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, mm40_rate);+	rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, mm40_mode);+	rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);++	rt2800_register_read(rt2x00dev, GF20_PROT_CFG, ®);+	rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_RATE, gf20_rate);+	rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_CTRL, gf20_mode);+	rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);++	rt2800_register_read(rt2x00dev, GF40_PROT_CFG, ®);+	rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_RATE, gf40_rate);+	rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_CTRL, gf40_mode);+	rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);+}++void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,+		       u32 changed)+{+	u32 reg;++	if (changed & BSS_CHANGED_ERP_PREAMBLE) {+		rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, ®);+		rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY,+				   !!erp->short_preamble);+		rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE,+				   !!erp->short_preamble);+		rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);+	}++	if (changed & BSS_CHANGED_ERP_CTS_PROT) {+		rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®);+		rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL,+				   erp->cts_protection ? 2 : 0);+		rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);+	}++	if (changed & BSS_CHANGED_BASIC_RATES) {+		rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE,+					 erp->basic_rates);+		rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);+	}++	if (changed & BSS_CHANGED_ERP_SLOT) {+		rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®);+		rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME,+				   erp->slot_time);+		rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);++		rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, ®);+		rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs);+		rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);+	}++	if (changed & BSS_CHANGED_BEACON_INT) {+		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®);+		rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL,+				   erp->beacon_int * 16);+		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);+	}++	if (changed & BSS_CHANGED_HT)+		rt2800_config_ht_opmode(rt2x00dev, erp);+}+EXPORT_SYMBOL_GPL(rt2800_config_erp);++static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev)+{+	u32 reg;+	u16 eeprom;+	u8 led_ctrl, led_g_mode, led_r_mode;++	rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®);+	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {+		rt2x00_set_field32(®, GPIO_SWITCH_0, 1);+		rt2x00_set_field32(®, GPIO_SWITCH_1, 1);+	} else {+		rt2x00_set_field32(®, GPIO_SWITCH_0, 0);+		rt2x00_set_field32(®, GPIO_SWITCH_1, 0);+	}+	rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);++	rt2800_register_read(rt2x00dev, LED_CFG, ®);+	led_g_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 3 : 0;+	led_r_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 0 : 3;+	if (led_g_mode != rt2x00_get_field32(reg, LED_CFG_G_LED_MODE) ||+	    led_r_mode != rt2x00_get_field32(reg, LED_CFG_R_LED_MODE)) {+		rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);+		led_ctrl = rt2x00_get_field16(eeprom, EEPROM_FREQ_LED_MODE);+		if (led_ctrl == 0 || led_ctrl > 0x40) {+			rt2x00_set_field32(®, LED_CFG_G_LED_MODE, led_g_mode);+			rt2x00_set_field32(®, LED_CFG_R_LED_MODE, led_r_mode);+			rt2800_register_write(rt2x00dev, LED_CFG, reg);+		} else {+			rt2800_mcu_request(rt2x00dev, MCU_BAND_SELECT, 0xff,+					   (led_g_mode << 2) | led_r_mode, 1);+		}+	}+}++static void rt2800_set_ant_diversity(struct rt2x00_dev *rt2x00dev,+				     enum antenna ant)+{+	u32 reg;+	u8 eesk_pin = (ant == ANTENNA_A) ? 1 : 0;+	u8 gpio_bit3 = (ant == ANTENNA_A) ? 0 : 1;++	if (rt2x00_is_pci(rt2x00dev)) {+		rt2800_register_read(rt2x00dev, E2PROM_CSR, ®);+		rt2x00_set_field32(®, E2PROM_CSR_DATA_CLOCK, eesk_pin);+		rt2800_register_write(rt2x00dev, E2PROM_CSR, reg);+	} else if (rt2x00_is_usb(rt2x00dev))+		rt2800_mcu_request(rt2x00dev, MCU_ANT_SELECT, 0xff,+				   eesk_pin, 0);++	rt2800_register_read(rt2x00dev, GPIO_CTRL, ®);+	rt2x00_set_field32(®, GPIO_CTRL_DIR3, 0);+	rt2x00_set_field32(®, GPIO_CTRL_VAL3, gpio_bit3);+	rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);+}++void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)+{+	u8 r1;+	u8 r3;+	u16 eeprom;++	rt2800_bbp_read(rt2x00dev, 1, &r1);+	rt2800_bbp_read(rt2x00dev, 3, &r3);++	if (rt2x00_rt(rt2x00dev, RT3572) &&+	    test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags))+		rt2800_config_3572bt_ant(rt2x00dev);++	/*+	 * Configure the TX antenna.+	 */+	switch (ant->tx_chain_num) {+	case 1:+		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);+		break;+	case 2:+		if (rt2x00_rt(rt2x00dev, RT3572) &&+		    test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags))+			rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 1);+		else+			rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);+		break;+	case 3:+		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);+		break;+	}++	/*+	 * Configure the RX antenna.+	 */+	switch (ant->rx_chain_num) {+	case 1:+		if (rt2x00_rt(rt2x00dev, RT3070) ||+		    rt2x00_rt(rt2x00dev, RT3090) ||+		    rt2x00_rt(rt2x00dev, RT3352) ||+		    rt2x00_rt(rt2x00dev, RT3390)) {+			rt2x00_eeprom_read(rt2x00dev,+					   EEPROM_NIC_CONF1, &eeprom);+			if (rt2x00_get_field16(eeprom,+						EEPROM_NIC_CONF1_ANT_DIVERSITY))+				rt2800_set_ant_diversity(rt2x00dev,+						rt2x00dev->default_ant.rx);+		}+		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);+		break;+	case 2:+		if (rt2x00_rt(rt2x00dev, RT3572) &&+		    test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) {+			rt2x00_set_field8(&r3, BBP3_RX_ADC, 1);+			rt2x00_set_field8(&r3, BBP3_RX_ANTENNA,+				rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);+			rt2800_set_ant_diversity(rt2x00dev, ANTENNA_B);+		} else {+			rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1);+		}+		break;+	case 3:+		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2);+		break;+	}++	rt2800_bbp_write(rt2x00dev, 3, r3);+	rt2800_bbp_write(rt2x00dev, 1, r1);+}+EXPORT_SYMBOL_GPL(rt2800_config_ant);++static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev,+				   struct rt2x00lib_conf *libconf)+{+	u16 eeprom;+	short lna_gain;++	if (libconf->rf.channel <= 14) {+		rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);+		lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG);+	} else if (libconf->rf.channel <= 64) {+		rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);+		lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);+	} else if (libconf->rf.channel <= 128) {+		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);+		lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1);+	} else {+		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);+		lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2);+	}++	rt2x00dev->lna_gain = lna_gain;+}++static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev,+					 struct ieee80211_conf *conf,+					 struct rf_channel *rf,+					 struct channel_info *info)+{+	rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);++	if (rt2x00dev->default_ant.tx_chain_num == 1)+		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1);++	if (rt2x00dev->default_ant.rx_chain_num == 1) {+		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1);+		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);+	} else if (rt2x00dev->default_ant.rx_chain_num == 2)+		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);++	if (rf->channel > 14) {+		/*+		 * When TX power is below 0, we should increase it by 7 to+		 * make it a positive value (Minimum value is -7).+		 * However this means that values between 0 and 7 have+		 * double meaning, and we should set a 7DBm boost flag.+		 */+		rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST,+				   (info->default_power1 >= 0));++		if (info->default_power1 < 0)+			info->default_power1 += 7;++		rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, info->default_power1);++		rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST,+				   (info->default_power2 >= 0));++		if (info->default_power2 < 0)+			info->default_power2 += 7;++		rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, info->default_power2);+	} else {+		rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, info->default_power1);+		rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, info->default_power2);+	}++	rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf));++	rt2800_rf_write(rt2x00dev, 1, rf->rf1);+	rt2800_rf_write(rt2x00dev, 2, rf->rf2);+	rt2800_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);+	rt2800_rf_write(rt2x00dev, 4, rf->rf4);++	udelay(200);++	rt2800_rf_write(rt2x00dev, 1, rf->rf1);+	rt2800_rf_write(rt2x00dev, 2, rf->rf2);+	rt2800_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);+	rt2800_rf_write(rt2x00dev, 4, rf->rf4);++	udelay(200);++	rt2800_rf_write(rt2x00dev, 1, rf->rf1);+	rt2800_rf_write(rt2x00dev, 2, rf->rf2);+	rt2800_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);+	rt2800_rf_write(rt2x00dev, 4, rf->rf4);+}++static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,+					 struct ieee80211_conf *conf,+					 struct rf_channel *rf,+					 struct channel_info *info)+{+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;+	u8 rfcsr, calib_tx, calib_rx;++	rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);++	rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR3_K, rf->rf3);+	rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2);+	rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, info->default_power1);+	rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->default_power2);+	rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);+	rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD,+			  rt2x00dev->default_ant.rx_chain_num <= 1);+	rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD,+			  rt2x00dev->default_ant.rx_chain_num <= 2);+	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);+	rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD,+			  rt2x00dev->default_ant.tx_chain_num <= 1);+	rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD,+			  rt2x00dev->default_ant.tx_chain_num <= 2);+	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);+	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);+	msleep(1);+	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);+	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);+	rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);++	if (rt2x00_rt(rt2x00dev, RT3390)) {+		calib_tx = conf_is_ht40(conf) ? 0x68 : 0x4f;+		calib_rx = conf_is_ht40(conf) ? 0x6f : 0x4f;+	} else {+		if (conf_is_ht40(conf)) {+			calib_tx = drv_data->calibration_bw40;+			calib_rx = drv_data->calibration_bw40;+		} else {+			calib_tx = drv_data->calibration_bw20;+			calib_rx = drv_data->calibration_bw20;+		}+	}++	rt2800_rfcsr_read(rt2x00dev, 24, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR24_TX_CALIB, calib_tx);+	rt2800_rfcsr_write(rt2x00dev, 24, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR31_RX_CALIB, calib_rx);+	rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);+	rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);+	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);+	msleep(1);+	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);+	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);+}++static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,+					 struct ieee80211_conf *conf,+					 struct rf_channel *rf,+					 struct channel_info *info)+{+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;+	u8 rfcsr;+	u32 reg;++	if (rf->channel <= 14) {+		rt2800_bbp_write(rt2x00dev, 25, drv_data->bbp25);+		rt2800_bbp_write(rt2x00dev, 26, drv_data->bbp26);+	} else {+		rt2800_bbp_write(rt2x00dev, 25, 0x09);+		rt2800_bbp_write(rt2x00dev, 26, 0xff);+	}++	rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);+	rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3);++	rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2);+	if (rf->channel <= 14)+		rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 2);+	else+		rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 1);+	rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 5, &rfcsr);+	if (rf->channel <= 14)+		rt2x00_set_field8(&rfcsr, RFCSR5_R1, 1);+	else+		rt2x00_set_field8(&rfcsr, RFCSR5_R1, 2);+	rt2800_rfcsr_write(rt2x00dev, 5, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);+	if (rf->channel <= 14) {+		rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 3);+		rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,+				  info->default_power1);+	} else {+		rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 7);+		rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,+				(info->default_power1 & 0x3) |+				((info->default_power1 & 0xC) << 1));+	}+	rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);+	if (rf->channel <= 14) {+		rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 3);+		rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,+				  info->default_power2);+	} else {+		rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 7);+		rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,+				(info->default_power2 & 0x3) |+				((info->default_power2 & 0xC) << 1));+	}+	rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);+	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);+	rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);+	rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);+	rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);+	rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);+	if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) {+		if (rf->channel <= 14) {+			rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);+			rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);+		}+		rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);+		rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);+	} else {+		switch (rt2x00dev->default_ant.tx_chain_num) {+		case 1:+			rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);+		case 2:+			rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);+			break;+		}++		switch (rt2x00dev->default_ant.rx_chain_num) {+		case 1:+			rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);+		case 2:+			rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);+			break;+		}+	}+	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);+	rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);++	if (conf_is_ht40(conf)) {+		rt2800_rfcsr_write(rt2x00dev, 24, drv_data->calibration_bw40);+		rt2800_rfcsr_write(rt2x00dev, 31, drv_data->calibration_bw40);+	} else {+		rt2800_rfcsr_write(rt2x00dev, 24, drv_data->calibration_bw20);+		rt2800_rfcsr_write(rt2x00dev, 31, drv_data->calibration_bw20);+	}++	if (rf->channel <= 14) {+		rt2800_rfcsr_write(rt2x00dev, 7, 0xd8);+		rt2800_rfcsr_write(rt2x00dev, 9, 0xc3);+		rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);+		rt2800_rfcsr_write(rt2x00dev, 11, 0xb9);+		rt2800_rfcsr_write(rt2x00dev, 15, 0x53);+		rfcsr = 0x4c;+		rt2x00_set_field8(&rfcsr, RFCSR16_TXMIXER_GAIN,+				  drv_data->txmixer_gain_24g);+		rt2800_rfcsr_write(rt2x00dev, 16, rfcsr);+		rt2800_rfcsr_write(rt2x00dev, 17, 0x23);+		rt2800_rfcsr_write(rt2x00dev, 19, 0x93);+		rt2800_rfcsr_write(rt2x00dev, 20, 0xb3);+		rt2800_rfcsr_write(rt2x00dev, 25, 0x15);+		rt2800_rfcsr_write(rt2x00dev, 26, 0x85);+		rt2800_rfcsr_write(rt2x00dev, 27, 0x00);+		rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);+	} else {+		rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);+		rt2x00_set_field8(&rfcsr, RFCSR7_BIT2, 1);+		rt2x00_set_field8(&rfcsr, RFCSR7_BIT3, 0);+		rt2x00_set_field8(&rfcsr, RFCSR7_BIT4, 1);+		rt2x00_set_field8(&rfcsr, RFCSR7_BITS67, 0);+		rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);+		rt2800_rfcsr_write(rt2x00dev, 9, 0xc0);+		rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);+		rt2800_rfcsr_write(rt2x00dev, 11, 0x00);+		rt2800_rfcsr_write(rt2x00dev, 15, 0x43);+		rfcsr = 0x7a;+		rt2x00_set_field8(&rfcsr, RFCSR16_TXMIXER_GAIN,+				  drv_data->txmixer_gain_5g);+		rt2800_rfcsr_write(rt2x00dev, 16, rfcsr);+		rt2800_rfcsr_write(rt2x00dev, 17, 0x23);+		if (rf->channel <= 64) {+			rt2800_rfcsr_write(rt2x00dev, 19, 0xb7);+			rt2800_rfcsr_write(rt2x00dev, 20, 0xf6);+			rt2800_rfcsr_write(rt2x00dev, 25, 0x3d);+		} else if (rf->channel <= 128) {+			rt2800_rfcsr_write(rt2x00dev, 19, 0x74);+			rt2800_rfcsr_write(rt2x00dev, 20, 0xf4);+			rt2800_rfcsr_write(rt2x00dev, 25, 0x01);+		} else {+			rt2800_rfcsr_write(rt2x00dev, 19, 0x72);+			rt2800_rfcsr_write(rt2x00dev, 20, 0xf3);+			rt2800_rfcsr_write(rt2x00dev, 25, 0x01);+		}+		rt2800_rfcsr_write(rt2x00dev, 26, 0x87);+		rt2800_rfcsr_write(rt2x00dev, 27, 0x01);+		rt2800_rfcsr_write(rt2x00dev, 29, 0x9f);+	}++	rt2800_register_read(rt2x00dev, GPIO_CTRL, ®);+	rt2x00_set_field32(®, GPIO_CTRL_DIR7, 0);+	if (rf->channel <= 14)+		rt2x00_set_field32(®, GPIO_CTRL_VAL7, 1);+	else+		rt2x00_set_field32(®, GPIO_CTRL_VAL7, 0);+	rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);++	rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);+	rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);+}++#define POWER_BOUND		0x27+#define POWER_BOUND_5G		0x2b+#define FREQ_OFFSET_BOUND	0x5f++static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev)+{+	u8 rfcsr;++	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);+	if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND)+		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND);+	else+		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);+	rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);+}++static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,+					 struct ieee80211_conf *conf,+					 struct rf_channel *rf,+					 struct channel_info *info)+{+	u8 rfcsr;++	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);+	rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);+	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);+	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);+	if (info->default_power1 > POWER_BOUND)+		rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND);+	else+		rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);+	rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);++	rt2800_adjust_freq_offset(rt2x00dev);++	if (rf->channel <= 14) {+		if (rf->channel == 6)+			rt2800_bbp_write(rt2x00dev, 68, 0x0c);+		else+			rt2800_bbp_write(rt2x00dev, 68, 0x0b);++		if (rf->channel >= 1 && rf->channel <= 6)+			rt2800_bbp_write(rt2x00dev, 59, 0x0f);+		else if (rf->channel >= 7 && rf->channel <= 11)+			rt2800_bbp_write(rt2x00dev, 59, 0x0e);+		else if (rf->channel >= 12 && rf->channel <= 14)+			rt2800_bbp_write(rt2x00dev, 59, 0x0d);+	}+}++static void rt2800_config_channel_rf3322(struct rt2x00_dev *rt2x00dev,+					 struct ieee80211_conf *conf,+					 struct rf_channel *rf,+					 struct channel_info *info)+{+	u8 rfcsr;++	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);+	rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);++	rt2800_rfcsr_write(rt2x00dev, 11, 0x42);+	rt2800_rfcsr_write(rt2x00dev, 12, 0x1c);+	rt2800_rfcsr_write(rt2x00dev, 13, 0x00);++	if (info->default_power1 > POWER_BOUND)+		rt2800_rfcsr_write(rt2x00dev, 47, POWER_BOUND);+	else+		rt2800_rfcsr_write(rt2x00dev, 47, info->default_power1);++	if (info->default_power2 > POWER_BOUND)+		rt2800_rfcsr_write(rt2x00dev, 48, POWER_BOUND);+	else+		rt2800_rfcsr_write(rt2x00dev, 48, info->default_power2);++	rt2800_adjust_freq_offset(rt2x00dev);++	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);+	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);++	if ( rt2x00dev->default_ant.tx_chain_num == 2 )+		rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);+	else+		rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);++	if ( rt2x00dev->default_ant.rx_chain_num == 2 )+		rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);+	else+		rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);++	rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);+	rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);++	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);++	rt2800_rfcsr_write(rt2x00dev, 31, 80);+}++static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,+					 struct ieee80211_conf *conf,+					 struct rf_channel *rf,+					 struct channel_info *info)+{+	u8 rfcsr;++	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);+	rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);+	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);+	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);+	if (info->default_power1 > POWER_BOUND)+		rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND);+	else+		rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);+	rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);++	if (rt2x00_rt(rt2x00dev, RT5392)) {+		rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);+		if (info->default_power1 > POWER_BOUND)+			rt2x00_set_field8(&rfcsr, RFCSR50_TX, POWER_BOUND);+		else+			rt2x00_set_field8(&rfcsr, RFCSR50_TX,+					  info->default_power2);+		rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);+	}++	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);+	if (rt2x00_rt(rt2x00dev, RT5392)) {+		rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);+		rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);+	}+	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);+	rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);+	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);+	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);+	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);++	rt2800_adjust_freq_offset(rt2x00dev);++	if (rf->channel <= 14) {+		int idx = rf->channel-1;++		if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) {+			if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {+				/* r55/r59 value array of channel 1~14 */+				static const char r55_bt_rev[] = {0x83, 0x83,+					0x83, 0x73, 0x73, 0x63, 0x53, 0x53,+					0x53, 0x43, 0x43, 0x43, 0x43, 0x43};+				static const char r59_bt_rev[] = {0x0e, 0x0e,+					0x0e, 0x0e, 0x0e, 0x0b, 0x0a, 0x09,+					0x07, 0x07, 0x07, 0x07, 0x07, 0x07};++				rt2800_rfcsr_write(rt2x00dev, 55,+						   r55_bt_rev[idx]);+				rt2800_rfcsr_write(rt2x00dev, 59,+						   r59_bt_rev[idx]);+			} else {+				static const char r59_bt[] = {0x8b, 0x8b, 0x8b,+					0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x89,+					0x88, 0x88, 0x86, 0x85, 0x84};++				rt2800_rfcsr_write(rt2x00dev, 59, r59_bt[idx]);+			}+		} else {+			if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {+				static const char r55_nonbt_rev[] = {0x23, 0x23,+					0x23, 0x23, 0x13, 0x13, 0x03, 0x03,+					0x03, 0x03, 0x03, 0x03, 0x03, 0x03};+				static const char r59_nonbt_rev[] = {0x07, 0x07,+					0x07, 0x07, 0x07, 0x07, 0x07, 0x07,+					0x07, 0x07, 0x06, 0x05, 0x04, 0x04};++				rt2800_rfcsr_write(rt2x00dev, 55,+						   r55_nonbt_rev[idx]);+				rt2800_rfcsr_write(rt2x00dev, 59,+						   r59_nonbt_rev[idx]);+			} else if (rt2x00_rt(rt2x00dev, RT5390) ||+				   rt2x00_rt(rt2x00dev, RT5392)) {+				static const char r59_non_bt[] = {0x8f, 0x8f,+					0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d,+					0x8a, 0x88, 0x88, 0x87, 0x87, 0x86};++				rt2800_rfcsr_write(rt2x00dev, 59,+						   r59_non_bt[idx]);+			}+		}+	}+}++static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,+					 struct ieee80211_conf *conf,+					 struct rf_channel *rf,+					 struct channel_info *info)+{+	u8 rfcsr, ep_reg;+	u32 reg;+	int power_bound;++	/* TODO */+	const bool is_11b = false;+	const bool is_type_ep = false;++	rt2800_register_read(rt2x00dev, LDO_CFG0, ®);+	rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL,+			   (rf->channel > 14 || conf_is_ht40(conf)) ? 5 : 0);+	rt2800_register_write(rt2x00dev, LDO_CFG0, reg);++	/* Order of values on rf_channel entry: N, K, mod, R */+	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1 & 0xff);++	rt2800_rfcsr_read(rt2x00dev,  9, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR9_K, rf->rf2 & 0xf);+	rt2x00_set_field8(&rfcsr, RFCSR9_N, (rf->rf1 & 0x100) >> 8);+	rt2x00_set_field8(&rfcsr, RFCSR9_MOD, ((rf->rf3 - 8) & 0x4) >> 2);+	rt2800_rfcsr_write(rt2x00dev, 9, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf4 - 1);+	rt2x00_set_field8(&rfcsr, RFCSR11_MOD, (rf->rf3 - 8) & 0x3);+	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);++	if (rf->channel <= 14) {+		rt2800_rfcsr_write(rt2x00dev, 10, 0x90);+		/* FIXME: RF11 owerwrite ? */+		rt2800_rfcsr_write(rt2x00dev, 11, 0x4A);+		rt2800_rfcsr_write(rt2x00dev, 12, 0x52);+		rt2800_rfcsr_write(rt2x00dev, 13, 0x42);+		rt2800_rfcsr_write(rt2x00dev, 22, 0x40);+		rt2800_rfcsr_write(rt2x00dev, 24, 0x4A);+		rt2800_rfcsr_write(rt2x00dev, 25, 0x80);+		rt2800_rfcsr_write(rt2x00dev, 27, 0x42);+		rt2800_rfcsr_write(rt2x00dev, 36, 0x80);+		rt2800_rfcsr_write(rt2x00dev, 37, 0x08);+		rt2800_rfcsr_write(rt2x00dev, 38, 0x89);+		rt2800_rfcsr_write(rt2x00dev, 39, 0x1B);+		rt2800_rfcsr_write(rt2x00dev, 40, 0x0D);+		rt2800_rfcsr_write(rt2x00dev, 41, 0x9B);+		rt2800_rfcsr_write(rt2x00dev, 42, 0xD5);+		rt2800_rfcsr_write(rt2x00dev, 43, 0x72);+		rt2800_rfcsr_write(rt2x00dev, 44, 0x0E);+		rt2800_rfcsr_write(rt2x00dev, 45, 0xA2);+		rt2800_rfcsr_write(rt2x00dev, 46, 0x6B);+		rt2800_rfcsr_write(rt2x00dev, 48, 0x10);+		rt2800_rfcsr_write(rt2x00dev, 51, 0x3E);+		rt2800_rfcsr_write(rt2x00dev, 52, 0x48);+		rt2800_rfcsr_write(rt2x00dev, 54, 0x38);+		rt2800_rfcsr_write(rt2x00dev, 56, 0xA1);+		rt2800_rfcsr_write(rt2x00dev, 57, 0x00);+		rt2800_rfcsr_write(rt2x00dev, 58, 0x39);+		rt2800_rfcsr_write(rt2x00dev, 60, 0x45);+		rt2800_rfcsr_write(rt2x00dev, 61, 0x91);+		rt2800_rfcsr_write(rt2x00dev, 62, 0x39);++		/* TODO RF27 <- tssi */++		rfcsr = rf->channel <= 10 ? 0x07 : 0x06;+		rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);+		rt2800_rfcsr_write(rt2x00dev, 59, rfcsr);++		if (is_11b) {+			/* CCK */+			rt2800_rfcsr_write(rt2x00dev, 31, 0xF8);+			rt2800_rfcsr_write(rt2x00dev, 32, 0xC0);+			if (is_type_ep)+				rt2800_rfcsr_write(rt2x00dev, 55, 0x06);+			else+				rt2800_rfcsr_write(rt2x00dev, 55, 0x47);+		} else {+			/* OFDM */+			if (is_type_ep)+				rt2800_rfcsr_write(rt2x00dev, 55, 0x03);+			else+				rt2800_rfcsr_write(rt2x00dev, 55, 0x43);+		}++		power_bound = POWER_BOUND;+		ep_reg = 0x2;+	} else {+		rt2800_rfcsr_write(rt2x00dev, 10, 0x97);+		/* FIMXE: RF11 overwrite */+		rt2800_rfcsr_write(rt2x00dev, 11, 0x40);+		rt2800_rfcsr_write(rt2x00dev, 25, 0xBF);+		rt2800_rfcsr_write(rt2x00dev, 27, 0x42);+		rt2800_rfcsr_write(rt2x00dev, 36, 0x00);+		rt2800_rfcsr_write(rt2x00dev, 37, 0x04);+		rt2800_rfcsr_write(rt2x00dev, 38, 0x85);+		rt2800_rfcsr_write(rt2x00dev, 40, 0x42);+		rt2800_rfcsr_write(rt2x00dev, 41, 0xBB);+		rt2800_rfcsr_write(rt2x00dev, 42, 0xD7);+		rt2800_rfcsr_write(rt2x00dev, 45, 0x41);+		rt2800_rfcsr_write(rt2x00dev, 48, 0x00);+		rt2800_rfcsr_write(rt2x00dev, 57, 0x77);+		rt2800_rfcsr_write(rt2x00dev, 60, 0x05);+		rt2800_rfcsr_write(rt2x00dev, 61, 0x01);++		/* TODO RF27 <- tssi */++		if (rf->channel >= 36 && rf->channel <= 64) {++			rt2800_rfcsr_write(rt2x00dev, 12, 0x2E);+			rt2800_rfcsr_write(rt2x00dev, 13, 0x22);+			rt2800_rfcsr_write(rt2x00dev, 22, 0x60);+			rt2800_rfcsr_write(rt2x00dev, 23, 0x7F);+			if (rf->channel <= 50)+				rt2800_rfcsr_write(rt2x00dev, 24, 0x09);+			else if (rf->channel >= 52)+				rt2800_rfcsr_write(rt2x00dev, 24, 0x07);+			rt2800_rfcsr_write(rt2x00dev, 39, 0x1C);+			rt2800_rfcsr_write(rt2x00dev, 43, 0x5B);+			rt2800_rfcsr_write(rt2x00dev, 44, 0X40);+			rt2800_rfcsr_write(rt2x00dev, 46, 0X00);+			rt2800_rfcsr_write(rt2x00dev, 51, 0xFE);+			rt2800_rfcsr_write(rt2x00dev, 52, 0x0C);+			rt2800_rfcsr_write(rt2x00dev, 54, 0xF8);+			if (rf->channel <= 50) {+				rt2800_rfcsr_write(rt2x00dev, 55, 0x06),+				rt2800_rfcsr_write(rt2x00dev, 56, 0xD3);+			} else if (rf->channel >= 52) {+				rt2800_rfcsr_write(rt2x00dev, 55, 0x04);+				rt2800_rfcsr_write(rt2x00dev, 56, 0xBB);+			}++			rt2800_rfcsr_write(rt2x00dev, 58, 0x15);+			rt2800_rfcsr_write(rt2x00dev, 59, 0x7F);+			rt2800_rfcsr_write(rt2x00dev, 62, 0x15);++		} else if (rf->channel >= 100 && rf->channel <= 165) {++			rt2800_rfcsr_write(rt2x00dev, 12, 0x0E);+			rt2800_rfcsr_write(rt2x00dev, 13, 0x42);+			rt2800_rfcsr_write(rt2x00dev, 22, 0x40);+			if (rf->channel <= 153) {+				rt2800_rfcsr_write(rt2x00dev, 23, 0x3C);+				rt2800_rfcsr_write(rt2x00dev, 24, 0x06);+			} else if (rf->channel >= 155) {+				rt2800_rfcsr_write(rt2x00dev, 23, 0x38);+				rt2800_rfcsr_write(rt2x00dev, 24, 0x05);+			}+			if (rf->channel <= 138) {+				rt2800_rfcsr_write(rt2x00dev, 39, 0x1A);+				rt2800_rfcsr_write(rt2x00dev, 43, 0x3B);+				rt2800_rfcsr_write(rt2x00dev, 44, 0x20);+				rt2800_rfcsr_write(rt2x00dev, 46, 0x18);+			} else if (rf->channel >= 140) {+				rt2800_rfcsr_write(rt2x00dev, 39, 0x18);+				rt2800_rfcsr_write(rt2x00dev, 43, 0x1B);+				rt2800_rfcsr_write(rt2x00dev, 44, 0x10);+				rt2800_rfcsr_write(rt2x00dev, 46, 0X08);+			}+			if (rf->channel <= 124)+				rt2800_rfcsr_write(rt2x00dev, 51, 0xFC);+			else if (rf->channel >= 126)+				rt2800_rfcsr_write(rt2x00dev, 51, 0xEC);+			if (rf->channel <= 138)+				rt2800_rfcsr_write(rt2x00dev, 52, 0x06);+			else if (rf->channel >= 140)+				rt2800_rfcsr_write(rt2x00dev, 52, 0x06);+			rt2800_rfcsr_write(rt2x00dev, 54, 0xEB);+			if (rf->channel <= 138)+				rt2800_rfcsr_write(rt2x00dev, 55, 0x01);+			else if (rf->channel >= 140)+				rt2800_rfcsr_write(rt2x00dev, 55, 0x00);+			if (rf->channel <= 128)+				rt2800_rfcsr_write(rt2x00dev, 56, 0xBB);+			else if (rf->channel >= 130)+				rt2800_rfcsr_write(rt2x00dev, 56, 0xAB);+			if (rf->channel <= 116)+				rt2800_rfcsr_write(rt2x00dev, 58, 0x1D);+			else if (rf->channel >= 118)+				rt2800_rfcsr_write(rt2x00dev, 58, 0x15);+			if (rf->channel <= 138)+				rt2800_rfcsr_write(rt2x00dev, 59, 0x3F);+			else if (rf->channel >= 140)+				rt2800_rfcsr_write(rt2x00dev, 59, 0x7C);+			if (rf->channel <= 116)+				rt2800_rfcsr_write(rt2x00dev, 62, 0x1D);+			else if (rf->channel >= 118)+				rt2800_rfcsr_write(rt2x00dev, 62, 0x15);+		}++		power_bound = POWER_BOUND_5G;+		ep_reg = 0x3;+	}++	rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);+	if (info->default_power1 > power_bound)+		rt2x00_set_field8(&rfcsr, RFCSR49_TX, power_bound);+	else+		rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);+	if (is_type_ep)+		rt2x00_set_field8(&rfcsr, RFCSR49_EP, ep_reg);+	rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);+	if (info->default_power2 > power_bound)+		rt2x00_set_field8(&rfcsr, RFCSR50_TX, power_bound);+	else+		rt2x00_set_field8(&rfcsr, RFCSR50_TX, info->default_power2);+	if (is_type_ep)+		rt2x00_set_field8(&rfcsr, RFCSR50_EP, ep_reg);+	rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);+	rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);++	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD,+			  rt2x00dev->default_ant.tx_chain_num >= 1);+	rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD,+			  rt2x00dev->default_ant.tx_chain_num == 2);+	rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);++	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD,+			  rt2x00dev->default_ant.rx_chain_num >= 1);+	rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD,+			  rt2x00dev->default_ant.rx_chain_num == 2);+	rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);++	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);+	rt2800_rfcsr_write(rt2x00dev, 6, 0xe4);++	if (conf_is_ht40(conf))+		rt2800_rfcsr_write(rt2x00dev, 30, 0x16);+	else+		rt2800_rfcsr_write(rt2x00dev, 30, 0x10);++	if (!is_11b) {+		rt2800_rfcsr_write(rt2x00dev, 31, 0x80);+		rt2800_rfcsr_write(rt2x00dev, 32, 0x80);+	}++	/* TODO proper frequency adjustment */+	rt2800_adjust_freq_offset(rt2x00dev);++	/* TODO merge with others */+	rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);+	rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);++	/* BBP settings */+	rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);+	rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);+	rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);++	rt2800_bbp_write(rt2x00dev, 79, (rf->channel <= 14) ? 0x1C : 0x18);+	rt2800_bbp_write(rt2x00dev, 80, (rf->channel <= 14) ? 0x0E : 0x08);+	rt2800_bbp_write(rt2x00dev, 81, (rf->channel <= 14) ? 0x3A : 0x38);+	rt2800_bbp_write(rt2x00dev, 82, (rf->channel <= 14) ? 0x62 : 0x92);++	/* GLRT band configuration */+	rt2800_bbp_write(rt2x00dev, 195, 128);+	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0xE0 : 0xF0);+	rt2800_bbp_write(rt2x00dev, 195, 129);+	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x1F : 0x1E);+	rt2800_bbp_write(rt2x00dev, 195, 130);+	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x38 : 0x28);+	rt2800_bbp_write(rt2x00dev, 195, 131);+	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x32 : 0x20);+	rt2800_bbp_write(rt2x00dev, 195, 133);+	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x28 : 0x7F);+	rt2800_bbp_write(rt2x00dev, 195, 124);+	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x19 : 0x7F);+}++static void rt2800_bbp_write_with_rx_chain(struct rt2x00_dev *rt2x00dev,+					   const unsigned int word,+					   const u8 value)+{+	u8 chain, reg;++	for (chain = 0; chain < rt2x00dev->default_ant.rx_chain_num; chain++) {+		rt2800_bbp_read(rt2x00dev, 27, ®);+		rt2x00_set_field8(®,  BBP27_RX_CHAIN_SEL, chain);+		rt2800_bbp_write(rt2x00dev, 27, reg);++		rt2800_bbp_write(rt2x00dev, word, value);+	}+}++static void rt2800_iq_calibrate(struct rt2x00_dev *rt2x00dev, int channel)+{+	u8 cal;++	/* TX0 IQ Gain */+	rt2800_bbp_write(rt2x00dev, 158, 0x2c);+	if (channel <= 14)+		cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_GAIN_CAL_TX0_2G);+	else if (channel >= 36 && channel <= 64)+		cal = rt2x00_eeprom_byte(rt2x00dev,+					 EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5G);+	else if (channel >= 100 && channel <= 138)+		cal = rt2x00_eeprom_byte(rt2x00dev,+					 EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5G);+	else if (channel >= 140 && channel <= 165)+		cal = rt2x00_eeprom_byte(rt2x00dev,+					 EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5G);+	else+		cal = 0;+	rt2800_bbp_write(rt2x00dev, 159, cal);++	/* TX0 IQ Phase */+	rt2800_bbp_write(rt2x00dev, 158, 0x2d);+	if (channel <= 14)+		cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_PHASE_CAL_TX0_2G);+	else if (channel >= 36 && channel <= 64)+		cal = rt2x00_eeprom_byte(rt2x00dev,+					 EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5G);+	else if (channel >= 100 && channel <= 138)+		cal = rt2x00_eeprom_byte(rt2x00dev,+					 EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5G);+	else if (channel >= 140 && channel <= 165)+		cal = rt2x00_eeprom_byte(rt2x00dev,+					 EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5G);+	else+		cal = 0;+	rt2800_bbp_write(rt2x00dev, 159, cal);++	/* TX1 IQ Gain */+	rt2800_bbp_write(rt2x00dev, 158, 0x4a);+	if (channel <= 14)+		cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_GAIN_CAL_TX1_2G);+	else if (channel >= 36 && channel <= 64)+		cal = rt2x00_eeprom_byte(rt2x00dev,+					 EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5G);+	else if (channel >= 100 && channel <= 138)+		cal = rt2x00_eeprom_byte(rt2x00dev,+					 EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5G);+	else if (channel >= 140 && channel <= 165)+		cal = rt2x00_eeprom_byte(rt2x00dev,+					 EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5G);+	else+		cal = 0;+	rt2800_bbp_write(rt2x00dev, 159, cal);++	/* TX1 IQ Phase */+	rt2800_bbp_write(rt2x00dev, 158, 0x4b);+	if (channel <= 14)+		cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_PHASE_CAL_TX1_2G);+	else if (channel >= 36 && channel <= 64)+		cal = rt2x00_eeprom_byte(rt2x00dev,+					 EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5G);+	else if (channel >= 100 && channel <= 138)+		cal = rt2x00_eeprom_byte(rt2x00dev,+					 EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5G);+	else if (channel >= 140 && channel <= 165)+		cal = rt2x00_eeprom_byte(rt2x00dev,+					 EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5G);+	else+		cal = 0;+	rt2800_bbp_write(rt2x00dev, 159, cal);++	/* FIXME: possible RX0, RX1 callibration ? */++	/* RF IQ compensation control */+	rt2800_bbp_write(rt2x00dev, 158, 0x04);+	cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_RF_IQ_COMPENSATION_CONTROL);+	rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0);++	/* RF IQ imbalance compensation control */+	rt2800_bbp_write(rt2x00dev, 158, 0x03);+	cal = rt2x00_eeprom_byte(rt2x00dev,+				 EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CONTROL);+	rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0);+}++static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,+				  struct ieee80211_conf *conf,+				  struct rf_channel *rf,+				  struct channel_info *info)+{+	u32 reg;+	unsigned int tx_pin;+	u8 bbp, rfcsr;++	if (rf->channel <= 14) {+		info->default_power1 = TXPOWER_G_TO_DEV(info->default_power1);+		info->default_power2 = TXPOWER_G_TO_DEV(info->default_power2);+	} else {+		info->default_power1 = TXPOWER_A_TO_DEV(info->default_power1);+		info->default_power2 = TXPOWER_A_TO_DEV(info->default_power2);+	}++	switch (rt2x00dev->chip.rf) {+	case RF2020:+	case RF3020:+	case RF3021:+	case RF3022:+	case RF3320:+		rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info);+		break;+	case RF3052:+		rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info);+		break;+	case RF3290:+		rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);+		break;+	case RF3322:+		rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);+		break;+	case RF5360:+	case RF5370:+	case RF5372:+	case RF5390:+	case RF5392:+		rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);+		break;+	case RF5592:+		rt2800_config_channel_rf55xx(rt2x00dev, conf, rf, info);+		break;+	default:+		rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);+	}++	if (rt2x00_rf(rt2x00dev, RF3290) ||+	    rt2x00_rf(rt2x00dev, RF3322) ||+	    rt2x00_rf(rt2x00dev, RF5360) ||+	    rt2x00_rf(rt2x00dev, RF5370) ||+	    rt2x00_rf(rt2x00dev, RF5372) ||+	    rt2x00_rf(rt2x00dev, RF5390) ||+	    rt2x00_rf(rt2x00dev, RF5392)) {+		rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);+		rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);+		rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);+		rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);++		rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);+		rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);+		rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);+	}++	/*+	 * Change BBP settings+	 */+	if (rt2x00_rt(rt2x00dev, RT3352)) {+		rt2800_bbp_write(rt2x00dev, 27, 0x0);+		rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);+		rt2800_bbp_write(rt2x00dev, 27, 0x20);+		rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);+	} else {+		rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);+		rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);+		rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);+		rt2800_bbp_write(rt2x00dev, 86, 0);+	}++	if (rf->channel <= 14) {+		if (!rt2x00_rt(rt2x00dev, RT5390) &&+		    !rt2x00_rt(rt2x00dev, RT5392)) {+			if (test_bit(CAPABILITY_EXTERNAL_LNA_BG,+				     &rt2x00dev->cap_flags)) {+				rt2800_bbp_write(rt2x00dev, 82, 0x62);+				rt2800_bbp_write(rt2x00dev, 75, 0x46);+			} else {+				rt2800_bbp_write(rt2x00dev, 82, 0x84);+				rt2800_bbp_write(rt2x00dev, 75, 0x50);+			}+		}+	} else {+		if (rt2x00_rt(rt2x00dev, RT3572))+			rt2800_bbp_write(rt2x00dev, 82, 0x94);+		else+			rt2800_bbp_write(rt2x00dev, 82, 0xf2);++		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))+			rt2800_bbp_write(rt2x00dev, 75, 0x46);+		else+			rt2800_bbp_write(rt2x00dev, 75, 0x50);+	}++	rt2800_register_read(rt2x00dev, TX_BAND_CFG, ®);+	rt2x00_set_field32(®, TX_BAND_CFG_HT40_MINUS, conf_is_ht40_minus(conf));+	rt2x00_set_field32(®, TX_BAND_CFG_A, rf->channel > 14);+	rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14);+	rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg);++	if (rt2x00_rt(rt2x00dev, RT3572))+		rt2800_rfcsr_write(rt2x00dev, 8, 0);++	tx_pin = 0;++	switch (rt2x00dev->default_ant.tx_chain_num) {+	case 3:+		/* Turn on tertiary PAs */+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A2_EN,+				   rf->channel > 14);+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G2_EN,+				   rf->channel <= 14);+		/* fall-through */+	case 2:+		/* Turn on secondary PAs */+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN,+				   rf->channel > 14);+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN,+				   rf->channel <= 14);+		/* fall-through */+	case 1:+		/* Turn on primary PAs */+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN,+				   rf->channel > 14);+		if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags))+			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1);+		else+			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN,+					   rf->channel <= 14);+		break;+	}++	switch (rt2x00dev->default_ant.rx_chain_num) {+	case 3:+		/* Turn on tertiary LNAs */+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN, 1);+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN, 1);+		/* fall-through */+	case 2:+		/* Turn on secondary LNAs */+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1);+		/* fall-through */+	case 1:+		/* Turn on primary LNAs */+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1);+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);+		break;+	}++	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);+	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1);++	rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);++	if (rt2x00_rt(rt2x00dev, RT3572))+		rt2800_rfcsr_write(rt2x00dev, 8, 0x80);++	if (rt2x00_rt(rt2x00dev, RT5592)) {+		rt2800_bbp_write(rt2x00dev, 195, 141);+		rt2800_bbp_write(rt2x00dev, 196, conf_is_ht40(conf) ? 0x10 : 0x1a);++		/* AGC init */+		reg = (rf->channel <= 14 ? 0x1c : 0x24) + 2 * rt2x00dev->lna_gain;+		rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);++		rt2800_iq_calibrate(rt2x00dev, rf->channel);+	}++	rt2800_bbp_read(rt2x00dev, 4, &bbp);+	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));+	rt2800_bbp_write(rt2x00dev, 4, bbp);++	rt2800_bbp_read(rt2x00dev, 3, &bbp);+	rt2x00_set_field8(&bbp, BBP3_HT40_MINUS, conf_is_ht40_minus(conf));+	rt2800_bbp_write(rt2x00dev, 3, bbp);++	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {+		if (conf_is_ht40(conf)) {+			rt2800_bbp_write(rt2x00dev, 69, 0x1a);+			rt2800_bbp_write(rt2x00dev, 70, 0x0a);+			rt2800_bbp_write(rt2x00dev, 73, 0x16);+		} else {+			rt2800_bbp_write(rt2x00dev, 69, 0x16);+			rt2800_bbp_write(rt2x00dev, 70, 0x08);+			rt2800_bbp_write(rt2x00dev, 73, 0x11);+		}+	}++	msleep(1);++	/*+	 * Clear channel statistic counters+	 */+	rt2800_register_read(rt2x00dev, CH_IDLE_STA, ®);+	rt2800_register_read(rt2x00dev, CH_BUSY_STA, ®);+	rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, ®);++	/*+	 * Clear update flag+	 */+	if (rt2x00_rt(rt2x00dev, RT3352)) {+		rt2800_bbp_read(rt2x00dev, 49, &bbp);+		rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0);+		rt2800_bbp_write(rt2x00dev, 49, bbp);+	}+}++static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)+{+	u8 tssi_bounds[9];+	u8 current_tssi;+	u16 eeprom;+	u8 step;+	int i;++	/*+	 * First check if temperature compensation is supported.+	 */+	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);+	if (!rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC))+		return 0;++	/*+	 * Read TSSI boundaries for temperature compensation from+	 * the EEPROM.+	 *+	 * Array idx               0    1    2    3    4    5    6    7    8+	 * Matching Delta value   -4   -3   -2   -1    0   +1   +2   +3   +4+	 * Example TSSI bounds  0xF0 0xD0 0xB5 0xA0 0x88 0x45 0x25 0x15 0x00+	 */+	if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {+		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom);+		tssi_bounds[0] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_BG1_MINUS4);+		tssi_bounds[1] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_BG1_MINUS3);++		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom);+		tssi_bounds[2] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_BG2_MINUS2);+		tssi_bounds[3] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_BG2_MINUS1);++		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom);+		tssi_bounds[4] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_BG3_REF);+		tssi_bounds[5] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_BG3_PLUS1);++		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom);+		tssi_bounds[6] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_BG4_PLUS2);+		tssi_bounds[7] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_BG4_PLUS3);++		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom);+		tssi_bounds[8] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_BG5_PLUS4);++		step = rt2x00_get_field16(eeprom,+					  EEPROM_TSSI_BOUND_BG5_AGC_STEP);+	} else {+		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom);+		tssi_bounds[0] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_A1_MINUS4);+		tssi_bounds[1] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_A1_MINUS3);++		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom);+		tssi_bounds[2] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_A2_MINUS2);+		tssi_bounds[3] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_A2_MINUS1);++		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom);+		tssi_bounds[4] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_A3_REF);+		tssi_bounds[5] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_A3_PLUS1);++		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom);+		tssi_bounds[6] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_A4_PLUS2);+		tssi_bounds[7] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_A4_PLUS3);++		rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom);+		tssi_bounds[8] = rt2x00_get_field16(eeprom,+					EEPROM_TSSI_BOUND_A5_PLUS4);++		step = rt2x00_get_field16(eeprom,+					  EEPROM_TSSI_BOUND_A5_AGC_STEP);+	}++	/*+	 * Check if temperature compensation is supported.+	 */+	if (tssi_bounds[4] == 0xff || step == 0xff)+		return 0;++	/*+	 * Read current TSSI (BBP 49).+	 */+	rt2800_bbp_read(rt2x00dev, 49, ¤t_tssi);++	/*+	 * Compare TSSI value (BBP49) with the compensation boundaries+	 * from the EEPROM and increase or decrease tx power.+	 */+	for (i = 0; i <= 3; i++) {+		if (current_tssi > tssi_bounds[i])+			break;+	}++	if (i == 4) {+		for (i = 8; i >= 5; i--) {+			if (current_tssi < tssi_bounds[i])+				break;+		}+	}++	return (i - 4) * step;+}++static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev,+				      enum ieee80211_band band)+{+	u16 eeprom;+	u8 comp_en;+	u8 comp_type;+	int comp_value = 0;++	rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom);++	/*+	 * HT40 compensation not required.+	 */+	if (eeprom == 0xffff ||+	    !test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))+		return 0;++	if (band == IEEE80211_BAND_2GHZ) {+		comp_en = rt2x00_get_field16(eeprom,+				 EEPROM_TXPOWER_DELTA_ENABLE_2G);+		if (comp_en) {+			comp_type = rt2x00_get_field16(eeprom,+					   EEPROM_TXPOWER_DELTA_TYPE_2G);+			comp_value = rt2x00_get_field16(eeprom,+					    EEPROM_TXPOWER_DELTA_VALUE_2G);+			if (!comp_type)+				comp_value = -comp_value;+		}+	} else {+		comp_en = rt2x00_get_field16(eeprom,+				 EEPROM_TXPOWER_DELTA_ENABLE_5G);+		if (comp_en) {+			comp_type = rt2x00_get_field16(eeprom,+					   EEPROM_TXPOWER_DELTA_TYPE_5G);+			comp_value = rt2x00_get_field16(eeprom,+					    EEPROM_TXPOWER_DELTA_VALUE_5G);+			if (!comp_type)+				comp_value = -comp_value;+		}+	}++	return comp_value;+}++static int rt2800_get_txpower_reg_delta(struct rt2x00_dev *rt2x00dev,+					int power_level, int max_power)+{+	int delta;++	if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags))+		return 0;++	/*+	 * XXX: We don't know the maximum transmit power of our hardware since+	 * the EEPROM doesn't expose it. We only know that we are calibrated+	 * to 100% tx power.+	 *+	 * Hence, we assume the regulatory limit that cfg80211 calulated for+	 * the current channel is our maximum and if we are requested to lower+	 * the value we just reduce our tx power accordingly.+	 */+	delta = power_level - max_power;+	return min(delta, 0);+}++static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,+				   enum ieee80211_band band, int power_level,+				   u8 txpower, int delta)+{+	u16 eeprom;+	u8 criterion;+	u8 eirp_txpower;+	u8 eirp_txpower_criterion;+	u8 reg_limit;++	if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) {+		/*+		 * Check if eirp txpower exceed txpower_limit.+		 * We use OFDM 6M as criterion and its eirp txpower+		 * is stored at EEPROM_EIRP_MAX_TX_POWER.+		 * .11b data rate need add additional 4dbm+		 * when calculating eirp txpower.+		 */+		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + 1,+				   &eeprom);+		criterion = rt2x00_get_field16(eeprom,+					       EEPROM_TXPOWER_BYRATE_RATE0);++		rt2x00_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER,+				   &eeprom);++		if (band == IEEE80211_BAND_2GHZ)+			eirp_txpower_criterion = rt2x00_get_field16(eeprom,+						 EEPROM_EIRP_MAX_TX_POWER_2GHZ);+		else+			eirp_txpower_criterion = rt2x00_get_field16(eeprom,+						 EEPROM_EIRP_MAX_TX_POWER_5GHZ);++		eirp_txpower = eirp_txpower_criterion + (txpower - criterion) ++			       (is_rate_b ? 4 : 0) + delta;++		reg_limit = (eirp_txpower > power_level) ?+					(eirp_txpower - power_level) : 0;+	} else+		reg_limit = 0;++	txpower = max(0, txpower + delta - reg_limit);+	return min_t(u8, txpower, 0xc);+}++/*+ * We configure transmit power using MAC TX_PWR_CFG_{0,...,N} registers and+ * BBP R1 register. TX_PWR_CFG_X allow to configure per rate TX power values,+ * 4 bits for each rate (tune from 0 to 15 dBm). BBP_R1 controls transmit power+ * for all rates, but allow to set only 4 discrete values: -12, -6, 0 and 6 dBm.+ * Reference per rate transmit power values are located in the EEPROM at+ * EEPROM_TXPOWER_BYRATE offset. We adjust them and BBP R1 settings according to+ * current conditions (i.e. band, bandwidth, temperature, user settings).+ */+static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,+				  struct ieee80211_channel *chan,+				  int power_level)+{+	u8 txpower, r1;+	u16 eeprom;+	u32 reg, offset;+	int i, is_rate_b, delta, power_ctrl;+	enum ieee80211_band band = chan->band;++	/*+	 * Calculate HT40 compensation. For 40MHz we need to add or subtract+	 * value read from EEPROM (different for 2GHz and for 5GHz).+	 */+	delta = rt2800_get_txpower_bw_comp(rt2x00dev, band);++	/*+	 * Calculate temperature compensation. Depends on measurement of current+	 * TSSI (Transmitter Signal Strength Indication) we know TX power (due+	 * to temperature or maybe other factors) is smaller or bigger than+	 * expected. We adjust it, based on TSSI reference and boundaries values+	 * provided in EEPROM.+	 */+	delta += rt2800_get_gain_calibration_delta(rt2x00dev);++	/*+	 * Decrease power according to user settings, on devices with unknown+	 * maximum tx power. For other devices we take user power_level into+	 * consideration on rt2800_compensate_txpower().+	 */+	delta += rt2800_get_txpower_reg_delta(rt2x00dev, power_level,+					      chan->max_power);++	/*+	 * BBP_R1 controls TX power for all rates, it allow to set the following+	 * gains -12, -6, 0, +6 dBm by setting values 2, 1, 0, 3 respectively.+	 *+	 * TODO: we do not use +6 dBm option to do not increase power beyond+	 * regulatory limit, however this could be utilized for devices with+	 * CAPABILITY_POWER_LIMIT.+	 *+	 * TODO: add different temperature compensation code for RT3290 & RT5390+	 * to allow to use BBP_R1 for those chips.+	 */+	if (!rt2x00_rt(rt2x00dev, RT3290) &&+	    !rt2x00_rt(rt2x00dev, RT5390)) {+		rt2800_bbp_read(rt2x00dev, 1, &r1);+		if (delta <= -12) {+			power_ctrl = 2;+			delta += 12;+		} else if (delta <= -6) {+			power_ctrl = 1;+			delta += 6;+		} else {+			power_ctrl = 0;+		}+		rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl);+		rt2800_bbp_write(rt2x00dev, 1, r1);+	}++	offset = TX_PWR_CFG_0;++	for (i = 0; i < EEPROM_TXPOWER_BYRATE_SIZE; i += 2) {+		/* just to be safe */+		if (offset > TX_PWR_CFG_4)+			break;++		rt2800_register_read(rt2x00dev, offset, ®);++		/* read the next four txpower values */+		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i,+				   &eeprom);++		is_rate_b = i ? 0 : 1;+		/*+		 * TX_PWR_CFG_0: 1MBS, TX_PWR_CFG_1: 24MBS,+		 * TX_PWR_CFG_2: MCS4, TX_PWR_CFG_3: MCS12,+		 * TX_PWR_CFG_4: unknown+		 */+		txpower = rt2x00_get_field16(eeprom,+					     EEPROM_TXPOWER_BYRATE_RATE0);+		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,+					     power_level, txpower, delta);+		rt2x00_set_field32(®, TX_PWR_CFG_RATE0, txpower);++		/*+		 * TX_PWR_CFG_0: 2MBS, TX_PWR_CFG_1: 36MBS,+		 * TX_PWR_CFG_2: MCS5, TX_PWR_CFG_3: MCS13,+		 * TX_PWR_CFG_4: unknown+		 */+		txpower = rt2x00_get_field16(eeprom,+					     EEPROM_TXPOWER_BYRATE_RATE1);+		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,+					     power_level, txpower, delta);+		rt2x00_set_field32(®, TX_PWR_CFG_RATE1, txpower);++		/*+		 * TX_PWR_CFG_0: 5.5MBS, TX_PWR_CFG_1: 48MBS,+		 * TX_PWR_CFG_2: MCS6,  TX_PWR_CFG_3: MCS14,+		 * TX_PWR_CFG_4: unknown+		 */+		txpower = rt2x00_get_field16(eeprom,+					     EEPROM_TXPOWER_BYRATE_RATE2);+		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,+					     power_level, txpower, delta);+		rt2x00_set_field32(®, TX_PWR_CFG_RATE2, txpower);++		/*+		 * TX_PWR_CFG_0: 11MBS, TX_PWR_CFG_1: 54MBS,+		 * TX_PWR_CFG_2: MCS7,  TX_PWR_CFG_3: MCS15,+		 * TX_PWR_CFG_4: unknown+		 */+		txpower = rt2x00_get_field16(eeprom,+					     EEPROM_TXPOWER_BYRATE_RATE3);+		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,+					     power_level, txpower, delta);+		rt2x00_set_field32(®, TX_PWR_CFG_RATE3, txpower);++		/* read the next four txpower values */+		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i + 1,+				   &eeprom);++		is_rate_b = 0;+		/*+		 * TX_PWR_CFG_0: 6MBS, TX_PWR_CFG_1: MCS0,+		 * TX_PWR_CFG_2: MCS8, TX_PWR_CFG_3: unknown,+		 * TX_PWR_CFG_4: unknown+		 */+		txpower = rt2x00_get_field16(eeprom,+					     EEPROM_TXPOWER_BYRATE_RATE0);+		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,+					     power_level, txpower, delta);+		rt2x00_set_field32(®, TX_PWR_CFG_RATE4, txpower);++		/*+		 * TX_PWR_CFG_0: 9MBS, TX_PWR_CFG_1: MCS1,+		 * TX_PWR_CFG_2: MCS9, TX_PWR_CFG_3: unknown,+		 * TX_PWR_CFG_4: unknown+		 */+		txpower = rt2x00_get_field16(eeprom,+					     EEPROM_TXPOWER_BYRATE_RATE1);+		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,+					     power_level, txpower, delta);+		rt2x00_set_field32(®, TX_PWR_CFG_RATE5, txpower);++		/*+		 * TX_PWR_CFG_0: 12MBS, TX_PWR_CFG_1: MCS2,+		 * TX_PWR_CFG_2: MCS10, TX_PWR_CFG_3: unknown,+		 * TX_PWR_CFG_4: unknown+		 */+		txpower = rt2x00_get_field16(eeprom,+					     EEPROM_TXPOWER_BYRATE_RATE2);+		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,+					     power_level, txpower, delta);+		rt2x00_set_field32(®, TX_PWR_CFG_RATE6, txpower);++		/*+		 * TX_PWR_CFG_0: 18MBS, TX_PWR_CFG_1: MCS3,+		 * TX_PWR_CFG_2: MCS11, TX_PWR_CFG_3: unknown,+		 * TX_PWR_CFG_4: unknown+		 */+		txpower = rt2x00_get_field16(eeprom,+					     EEPROM_TXPOWER_BYRATE_RATE3);+		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,+					     power_level, txpower, delta);+		rt2x00_set_field32(®, TX_PWR_CFG_RATE7, txpower);++		rt2800_register_write(rt2x00dev, offset, reg);++		/* next TX_PWR_CFG register */+		offset += 4;+	}+}++void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev)+{+	rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.chandef.chan,+			      rt2x00dev->tx_power);+}+EXPORT_SYMBOL_GPL(rt2800_gain_calibration);++void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)+{+	u32	tx_pin;+	u8	rfcsr;++	/*+	 * A voltage-controlled oscillator(VCO) is an electronic oscillator+	 * designed to be controlled in oscillation frequency by a voltage+	 * input. Maybe the temperature will affect the frequency of+	 * oscillation to be shifted. The VCO calibration will be called+	 * periodically to adjust the frequency to be precision.+	*/++	rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin);+	tx_pin &= TX_PIN_CFG_PA_PE_DISABLE;+	rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);++	switch (rt2x00dev->chip.rf) {+	case RF2020:+	case RF3020:+	case RF3021:+	case RF3022:+	case RF3320:+	case RF3052:+		rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);+		rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);+		rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);+		break;+	case RF3290:+	case RF5360:+	case RF5370:+	case RF5372:+	case RF5390:+	case RF5392:+		rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);+		rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);+		rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);+		break;+	default:+		return;+	}++	mdelay(1);++	rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin);+	if (rt2x00dev->rf_channel <= 14) {+		switch (rt2x00dev->default_ant.tx_chain_num) {+		case 3:+			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G2_EN, 1);+			/* fall through */+		case 2:+			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1);+			/* fall through */+		case 1:+		default:+			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1);+			break;+		}+	} else {+		switch (rt2x00dev->default_ant.tx_chain_num) {+		case 3:+			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A2_EN, 1);+			/* fall through */+		case 2:+			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1);+			/* fall through */+		case 1:+		default:+			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, 1);+			break;+		}+	}+	rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);++}+EXPORT_SYMBOL_GPL(rt2800_vco_calibration);++static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev,+				      struct rt2x00lib_conf *libconf)+{+	u32 reg;++	rt2800_register_read(rt2x00dev, TX_RTY_CFG, ®);+	rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT,+			   libconf->conf->short_frame_max_tx_count);+	rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT,+			   libconf->conf->long_frame_max_tx_count);+	rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg);+}++static void rt2800_config_ps(struct rt2x00_dev *rt2x00dev,+			     struct rt2x00lib_conf *libconf)+{+	enum dev_state state =+	    (libconf->conf->flags & IEEE80211_CONF_PS) ?+		STATE_SLEEP : STATE_AWAKE;+	u32 reg;++	if (state == STATE_SLEEP) {+		rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0);++		rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®);+		rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5);+		rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE,+				   libconf->conf->listen_interval - 1);+		rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 1);+		rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);++		rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);+	} else {+		rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®);+		rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);+		rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);+		rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 0);+		rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);++		rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);+	}+}++void rt2800_config(struct rt2x00_dev *rt2x00dev,+		   struct rt2x00lib_conf *libconf,+		   const unsigned int flags)+{+	/* Always recalculate LNA gain before changing configuration */+	rt2800_config_lna_gain(rt2x00dev, libconf);++	if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {+		rt2800_config_channel(rt2x00dev, libconf->conf,+				      &libconf->rf, &libconf->channel);+		rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan,+				      libconf->conf->power_level);+	}+	if (flags & IEEE80211_CONF_CHANGE_POWER)+		rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan,+				      libconf->conf->power_level);+	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)+		rt2800_config_retry_limit(rt2x00dev, libconf);+	if (flags & IEEE80211_CONF_CHANGE_PS)+		rt2800_config_ps(rt2x00dev, libconf);+}+EXPORT_SYMBOL_GPL(rt2800_config);++/*+ * Link tuning+ */+void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual)+{+	u32 reg;++	/*+	 * Update FCS error count from register.+	 */+	rt2800_register_read(rt2x00dev, RX_STA_CNT0, ®);+	qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR);+}+EXPORT_SYMBOL_GPL(rt2800_link_stats);++static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)+{+	u8 vgc;++	if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {+		if (rt2x00_rt(rt2x00dev, RT3070) ||+		    rt2x00_rt(rt2x00dev, RT3071) ||+		    rt2x00_rt(rt2x00dev, RT3090) ||+		    rt2x00_rt(rt2x00dev, RT3290) ||+		    rt2x00_rt(rt2x00dev, RT3390) ||+		    rt2x00_rt(rt2x00dev, RT3572) ||+		    rt2x00_rt(rt2x00dev, RT5390) ||+		    rt2x00_rt(rt2x00dev, RT5392) ||+		    rt2x00_rt(rt2x00dev, RT5592))+			vgc = 0x1c + (2 * rt2x00dev->lna_gain);+		else+			vgc = 0x2e + rt2x00dev->lna_gain;+	} else { /* 5GHZ band */+		if (rt2x00_rt(rt2x00dev, RT3572))+			vgc = 0x22 + (rt2x00dev->lna_gain * 5) / 3;+		else if (rt2x00_rt(rt2x00dev, RT5592))+			vgc = 0x24 + (2 * rt2x00dev->lna_gain);+		else {+			if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))+				vgc = 0x32 + (rt2x00dev->lna_gain * 5) / 3;+			else+				vgc = 0x3a + (rt2x00dev->lna_gain * 5) / 3;+		}+	}++	return vgc;+}++static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev,+				  struct link_qual *qual, u8 vgc_level)+{+	if (qual->vgc_level != vgc_level) {+		if (rt2x00_rt(rt2x00dev, RT5592)) {+			rt2800_bbp_write(rt2x00dev, 83, qual->rssi > -65 ? 0x4a : 0x7a);+			rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, vgc_level);+		} else+			rt2800_bbp_write(rt2x00dev, 66, vgc_level);+		qual->vgc_level = vgc_level;+		qual->vgc_level_reg = vgc_level;+	}+}++void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual)+{+	rt2800_set_vgc(rt2x00dev, qual, rt2800_get_default_vgc(rt2x00dev));+}+EXPORT_SYMBOL_GPL(rt2800_reset_tuner);++void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,+		       const u32 count)+{+	u8 vgc;++	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C))+		return;+	/*+	 * When RSSI is better then -80 increase VGC level with 0x10, except+	 * for rt5592 chip.+	 */++	vgc = rt2800_get_default_vgc(rt2x00dev);++	if (rt2x00_rt(rt2x00dev, RT5592)) {+		if (qual->rssi > -65)+			vgc += 0x20;+	} else {+		if (qual->rssi > -80)+			vgc += 0x10;+	}++	rt2800_set_vgc(rt2x00dev, qual, vgc);+}+EXPORT_SYMBOL_GPL(rt2800_link_tuner);++/*+ * Initialization functions.+ */+static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)+{+	u32 reg;+	u16 eeprom;+	unsigned int i;+	int ret;++	rt2800_disable_wpdma(rt2x00dev);++	ret = rt2800_drv_init_registers(rt2x00dev);+	if (ret)+		return ret;++	rt2800_register_read(rt2x00dev, BCN_OFFSET0, ®);+	rt2x00_set_field32(®, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */+	rt2x00_set_field32(®, BCN_OFFSET0_BCN1, 0xe8); /* 0x3a00 */+	rt2x00_set_field32(®, BCN_OFFSET0_BCN2, 0xf0); /* 0x3c00 */+	rt2x00_set_field32(®, BCN_OFFSET0_BCN3, 0xf8); /* 0x3e00 */+	rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg);++	rt2800_register_read(rt2x00dev, BCN_OFFSET1, ®);+	rt2x00_set_field32(®, BCN_OFFSET1_BCN4, 0xc8); /* 0x3200 */+	rt2x00_set_field32(®, BCN_OFFSET1_BCN5, 0xd0); /* 0x3400 */+	rt2x00_set_field32(®, BCN_OFFSET1_BCN6, 0x77); /* 0x1dc0 */+	rt2x00_set_field32(®, BCN_OFFSET1_BCN7, 0x6f); /* 0x1bc0 */+	rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg);++	rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);+	rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);++	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);++	rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®);+	rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, 1600);+	rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0);+	rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, 0);+	rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0);+	rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0);+	rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0);+	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);++	rt2800_config_filter(rt2x00dev, FIF_ALLMULTI);++	rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®);+	rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, 9);+	rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);+	rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);++	if (rt2x00_rt(rt2x00dev, RT3290)) {+		rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®);+		if (rt2x00_get_field32(reg, WLAN_EN) == 1) {+			rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 1);+			rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);+		}++		rt2800_register_read(rt2x00dev, CMB_CTRL, ®);+		if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) {+			rt2x00_set_field32(®, LDO0_EN, 1);+			rt2x00_set_field32(®, LDO_BGSEL, 3);+			rt2800_register_write(rt2x00dev, CMB_CTRL, reg);+		}++		rt2800_register_read(rt2x00dev, OSC_CTRL, ®);+		rt2x00_set_field32(®, OSC_ROSC_EN, 1);+		rt2x00_set_field32(®, OSC_CAL_REQ, 1);+		rt2x00_set_field32(®, OSC_REF_CYCLE, 0x27);+		rt2800_register_write(rt2x00dev, OSC_CTRL, reg);++		rt2800_register_read(rt2x00dev, COEX_CFG0, ®);+		rt2x00_set_field32(®, COEX_CFG_ANT, 0x5e);+		rt2800_register_write(rt2x00dev, COEX_CFG0, reg);++		rt2800_register_read(rt2x00dev, COEX_CFG2, ®);+		rt2x00_set_field32(®, BT_COEX_CFG1, 0x00);+		rt2x00_set_field32(®, BT_COEX_CFG0, 0x17);+		rt2x00_set_field32(®, WL_COEX_CFG1, 0x93);+		rt2x00_set_field32(®, WL_COEX_CFG0, 0x7f);+		rt2800_register_write(rt2x00dev, COEX_CFG2, reg);++		rt2800_register_read(rt2x00dev, PLL_CTRL, ®);+		rt2x00_set_field32(®, PLL_CONTROL, 1);+		rt2800_register_write(rt2x00dev, PLL_CTRL, reg);+	}++	if (rt2x00_rt(rt2x00dev, RT3071) ||+	    rt2x00_rt(rt2x00dev, RT3090) ||+	    rt2x00_rt(rt2x00dev, RT3290) ||+	    rt2x00_rt(rt2x00dev, RT3390)) {++		if (rt2x00_rt(rt2x00dev, RT3290))+			rt2800_register_write(rt2x00dev, TX_SW_CFG0,+					      0x00000404);+		else+			rt2800_register_write(rt2x00dev, TX_SW_CFG0,+					      0x00000400);++		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);+		if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||+		    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||+		    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {+			rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);+			if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))+				rt2800_register_write(rt2x00dev, TX_SW_CFG2,+						      0x0000002c);+			else+				rt2800_register_write(rt2x00dev, TX_SW_CFG2,+						      0x0000000f);+		} else {+			rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);+		}+	} else if (rt2x00_rt(rt2x00dev, RT3070)) {+		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);++		if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {+			rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);+			rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000002c);+		} else {+			rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);+			rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);+		}+	} else if (rt2800_is_305x_soc(rt2x00dev)) {+		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);+		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);+		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030);+	} else if (rt2x00_rt(rt2x00dev, RT3352)) {+		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);+		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);+		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);+	} else if (rt2x00_rt(rt2x00dev, RT3572)) {+		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);+		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);+	} else if (rt2x00_rt(rt2x00dev, RT5390) ||+		   rt2x00_rt(rt2x00dev, RT5392) ||+		   rt2x00_rt(rt2x00dev, RT5592)) {+		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);+		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);+		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);+	} else {+		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);+		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);+	}++	rt2800_register_read(rt2x00dev, TX_LINK_CFG, ®);+	rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32);+	rt2x00_set_field32(®, TX_LINK_CFG_MFB_ENABLE, 0);+	rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0);+	rt2x00_set_field32(®, TX_LINK_CFG_TX_MRQ_EN, 0);+	rt2x00_set_field32(®, TX_LINK_CFG_TX_RDG_EN, 0);+	rt2x00_set_field32(®, TX_LINK_CFG_TX_CF_ACK_EN, 1);+	rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB, 0);+	rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFS, 0);+	rt2800_register_write(rt2x00dev, TX_LINK_CFG, reg);++	rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®);+	rt2x00_set_field32(®, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9);+	rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 32);+	rt2x00_set_field32(®, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10);+	rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);++	rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®);+	rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);+	if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) ||+	    rt2x00_rt(rt2x00dev, RT2883) ||+	    rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E))+		rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2);+	else+		rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1);+	rt2x00_set_field32(®, MAX_LEN_CFG_MIN_PSDU, 0);+	rt2x00_set_field32(®, MAX_LEN_CFG_MIN_MPDU, 0);+	rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg);++	rt2800_register_read(rt2x00dev, LED_CFG, ®);+	rt2x00_set_field32(®, LED_CFG_ON_PERIOD, 70);+	rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, 30);+	rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3);+	rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3);+	rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 3);+	rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3);+	rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1);+	rt2800_register_write(rt2x00dev, LED_CFG, reg);++	rt2800_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f);++	rt2800_register_read(rt2x00dev, TX_RTY_CFG, ®);+	rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT, 15);+	rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, 31);+	rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000);+	rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0);+	rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0);+	rt2x00_set_field32(®, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1);+	rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg);++	rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, ®);+	rt2x00_set_field32(®, AUTO_RSP_CFG_AUTORESPONDER, 1);+	rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, 1);+	rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MMODE, 0);+	rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MREF, 0);+	rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, 1);+	rt2x00_set_field32(®, AUTO_RSP_CFG_DUAL_CTS_EN, 0);+	rt2x00_set_field32(®, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0);+	rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);++	rt2800_register_read(rt2x00dev, CCK_PROT_CFG, ®);+	rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_RATE, 3);+	rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_CTRL, 0);+	rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_NAV_SHORT, 1);+	rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1);+	rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1);+	rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1);+	rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 0);+	rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1);+	rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 0);+	rt2x00_set_field32(®, CCK_PROT_CFG_RTS_TH_EN, 1);+	rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg);++	rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®);+	rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_RATE, 3);+	rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, 0);+	rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_NAV_SHORT, 1);+	rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1);+	rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1);+	rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1);+	rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 0);+	rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1);+	rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 0);+	rt2x00_set_field32(®, OFDM_PROT_CFG_RTS_TH_EN, 1);+	rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);++	rt2800_register_read(rt2x00dev, MM20_PROT_CFG, ®);+	rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_RATE, 0x4004);+	rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_CTRL, 0);+	rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_NAV_SHORT, 1);+	rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1);+	rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);+	rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1);+	rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0);+	rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1);+	rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0);+	rt2x00_set_field32(®, MM20_PROT_CFG_RTS_TH_EN, 0);+	rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);++	rt2800_register_read(rt2x00dev, MM40_PROT_CFG, ®);+	rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, 0x4084);+	rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, 0);+	rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_NAV_SHORT, 1);+	rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1);+	rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);+	rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1);+	rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1);+	rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1);+	rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1);+	rt2x00_set_field32(®, MM40_PROT_CFG_RTS_TH_EN, 0);+	rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);++	rt2800_register_read(rt2x00dev, GF20_PROT_CFG, ®);+	rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_RATE, 0x4004);+	rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_CTRL, 0);+	rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_NAV_SHORT, 1);+	rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1);+	rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);+	rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1);+	rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0);+	rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1);+	rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0);+	rt2x00_set_field32(®, GF20_PROT_CFG_RTS_TH_EN, 0);+	rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);++	rt2800_register_read(rt2x00dev, GF40_PROT_CFG, ®);+	rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_RATE, 0x4084);+	rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_CTRL, 0);+	rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_NAV_SHORT, 1);+	rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1);+	rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);+	rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1);+	rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1);+	rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1);+	rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1);+	rt2x00_set_field32(®, GF40_PROT_CFG_RTS_TH_EN, 0);+	rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);++	if (rt2x00_is_usb(rt2x00dev)) {+		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);++		rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®);+		rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);+		rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);+		rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);+		rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);+		rt2x00_set_field32(®, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 3);+		rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 0);+		rt2x00_set_field32(®, WPDMA_GLO_CFG_BIG_ENDIAN, 0);+		rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_HDR_SCATTER, 0);+		rt2x00_set_field32(®, WPDMA_GLO_CFG_HDR_SEG_LEN, 0);+		rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);+	}++	/*+	 * The legacy driver also sets TXOP_CTRL_CFG_RESERVED_TRUN_EN to 1+	 * although it is reserved.+	 */+	rt2800_register_read(rt2x00dev, TXOP_CTRL_CFG, ®);+	rt2x00_set_field32(®, TXOP_CTRL_CFG_TIMEOUT_TRUN_EN, 1);+	rt2x00_set_field32(®, TXOP_CTRL_CFG_AC_TRUN_EN, 1);+	rt2x00_set_field32(®, TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN, 1);+	rt2x00_set_field32(®, TXOP_CTRL_CFG_USER_MODE_TRUN_EN, 1);+	rt2x00_set_field32(®, TXOP_CTRL_CFG_MIMO_PS_TRUN_EN, 1);+	rt2x00_set_field32(®, TXOP_CTRL_CFG_RESERVED_TRUN_EN, 1);+	rt2x00_set_field32(®, TXOP_CTRL_CFG_LSIG_TXOP_EN, 0);+	rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CCA_EN, 0);+	rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CCA_DLY, 88);+	rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CWMIN, 0);+	rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg);++	reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;+	rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);++	rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®);+	rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32);+	rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES,+			   IEEE80211_MAX_RTS_THRESHOLD);+	rt2x00_set_field32(®, TX_RTS_CFG_RTS_FBK_EN, 0);+	rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg);++	rt2800_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca);++	/*+	 * Usually the CCK SIFS time should be set to 10 and the OFDM SIFS+	 * time should be set to 16. However, the original Ralink driver uses+	 * 16 for both and indeed using a value of 10 for CCK SIFS results in+	 * connection problems with 11g + CTS protection. Hence, use the same+	 * defaults as the Ralink driver: 16 for both, CCK and OFDM SIFS.+	 */+	rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, ®);+	rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, 16);+	rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, 16);+	rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4);+	rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, 314);+	rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1);+	rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);++	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);++	/*+	 * ASIC will keep garbage value after boot, clear encryption keys.+	 */+	for (i = 0; i < 4; i++)+		rt2800_register_write(rt2x00dev,+					 SHARED_KEY_MODE_ENTRY(i), 0);++	for (i = 0; i < 256; i++) {+		rt2800_config_wcid(rt2x00dev, NULL, i);+		rt2800_delete_wcid_attr(rt2x00dev, i);+		rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);+	}++	/*+	 * Clear all beacons+	 */+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE0);+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE1);+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE2);+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE3);+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE4);+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE5);+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE6);+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE7);++	if (rt2x00_is_usb(rt2x00dev)) {+		rt2800_register_read(rt2x00dev, US_CYC_CNT, ®);+		rt2x00_set_field32(®, US_CYC_CNT_CLOCK_CYCLE, 30);+		rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);+	} else if (rt2x00_is_pcie(rt2x00dev)) {+		rt2800_register_read(rt2x00dev, US_CYC_CNT, ®);+		rt2x00_set_field32(®, US_CYC_CNT_CLOCK_CYCLE, 125);+		rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);+	}++	rt2800_register_read(rt2x00dev, HT_FBK_CFG0, ®);+	rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS0FBK, 0);+	rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS1FBK, 0);+	rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS2FBK, 1);+	rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS3FBK, 2);+	rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS4FBK, 3);+	rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS5FBK, 4);+	rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS6FBK, 5);+	rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS7FBK, 6);+	rt2800_register_write(rt2x00dev, HT_FBK_CFG0, reg);++	rt2800_register_read(rt2x00dev, HT_FBK_CFG1, ®);+	rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS8FBK, 8);+	rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS9FBK, 8);+	rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS10FBK, 9);+	rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS11FBK, 10);+	rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS12FBK, 11);+	rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS13FBK, 12);+	rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS14FBK, 13);+	rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS15FBK, 14);+	rt2800_register_write(rt2x00dev, HT_FBK_CFG1, reg);++	rt2800_register_read(rt2x00dev, LG_FBK_CFG0, ®);+	rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS0FBK, 8);+	rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS1FBK, 8);+	rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS2FBK, 9);+	rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS3FBK, 10);+	rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS4FBK, 11);+	rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS5FBK, 12);+	rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS6FBK, 13);+	rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS7FBK, 14);+	rt2800_register_write(rt2x00dev, LG_FBK_CFG0, reg);++	rt2800_register_read(rt2x00dev, LG_FBK_CFG1, ®);+	rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS0FBK, 0);+	rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS1FBK, 0);+	rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS2FBK, 1);+	rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS3FBK, 2);+	rt2800_register_write(rt2x00dev, LG_FBK_CFG1, reg);++	/*+	 * Do not force the BA window size, we use the TXWI to set it+	 */+	rt2800_register_read(rt2x00dev, AMPDU_BA_WINSIZE, ®);+	rt2x00_set_field32(®, AMPDU_BA_WINSIZE_FORCE_WINSIZE_ENABLE, 0);+	rt2x00_set_field32(®, AMPDU_BA_WINSIZE_FORCE_WINSIZE, 0);+	rt2800_register_write(rt2x00dev, AMPDU_BA_WINSIZE, reg);++	/*+	 * We must clear the error counters.+	 * These registers are cleared on read,+	 * so we may pass a useless variable to store the value.+	 */+	rt2800_register_read(rt2x00dev, RX_STA_CNT0, ®);+	rt2800_register_read(rt2x00dev, RX_STA_CNT1, ®);+	rt2800_register_read(rt2x00dev, RX_STA_CNT2, ®);+	rt2800_register_read(rt2x00dev, TX_STA_CNT0, ®);+	rt2800_register_read(rt2x00dev, TX_STA_CNT1, ®);+	rt2800_register_read(rt2x00dev, TX_STA_CNT2, ®);++	/*+	 * Setup leadtime for pre tbtt interrupt to 6ms+	 */+	rt2800_register_read(rt2x00dev, INT_TIMER_CFG, ®);+	rt2x00_set_field32(®, INT_TIMER_CFG_PRE_TBTT_TIMER, 6 << 4);+	rt2800_register_write(rt2x00dev, INT_TIMER_CFG, reg);++	/*+	 * Set up channel statistics timer+	 */+	rt2800_register_read(rt2x00dev, CH_TIME_CFG, ®);+	rt2x00_set_field32(®, CH_TIME_CFG_EIFS_BUSY, 1);+	rt2x00_set_field32(®, CH_TIME_CFG_NAV_BUSY, 1);+	rt2x00_set_field32(®, CH_TIME_CFG_RX_BUSY, 1);+	rt2x00_set_field32(®, CH_TIME_CFG_TX_BUSY, 1);+	rt2x00_set_field32(®, CH_TIME_CFG_TMR_EN, 1);+	rt2800_register_write(rt2x00dev, CH_TIME_CFG, reg);++	return 0;+}++static int rt2800_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev)+{+	unsigned int i;+	u32 reg;++	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {+		rt2800_register_read(rt2x00dev, MAC_STATUS_CFG, ®);+		if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY))+			return 0;++		udelay(REGISTER_BUSY_DELAY);+	}++	rt2x00_err(rt2x00dev, "BBP/RF register access failed, aborting\n");+	return -EACCES;+}++static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)+{+	unsigned int i;+	u8 value;++	/*+	 * BBP was enabled after firmware was loaded,+	 * but we need to reactivate it now.+	 */+	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);+	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);+	msleep(1);++	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {+		rt2800_bbp_read(rt2x00dev, 0, &value);+		if ((value != 0xff) && (value != 0x00))+			return 0;+		udelay(REGISTER_BUSY_DELAY);+	}++	rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");+	return -EACCES;+}++static void rt2800_bbp4_mac_if_ctrl(struct rt2x00_dev *rt2x00dev)+{+	u8 value;++	rt2800_bbp_read(rt2x00dev, 4, &value);+	rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);+	rt2800_bbp_write(rt2x00dev, 4, value);+}++static void rt2800_init_freq_calibration(struct rt2x00_dev *rt2x00dev)+{+	rt2800_bbp_write(rt2x00dev, 142, 1);+	rt2800_bbp_write(rt2x00dev, 143, 57);+}++static void rt2800_init_bbp_5592_glrt(struct rt2x00_dev *rt2x00dev)+{+	const u8 glrt_table[] = {+		0xE0, 0x1F, 0X38, 0x32, 0x08, 0x28, 0x19, 0x0A, 0xFF, 0x00, /* 128 ~ 137 */+		0x16, 0x10, 0x10, 0x0B, 0x36, 0x2C, 0x26, 0x24, 0x42, 0x36, /* 138 ~ 147 */+		0x30, 0x2D, 0x4C, 0x46, 0x3D, 0x40, 0x3E, 0x42, 0x3D, 0x40, /* 148 ~ 157 */+		0X3C, 0x34, 0x2C, 0x2F, 0x3C, 0x35, 0x2E, 0x2A, 0x49, 0x41, /* 158 ~ 167 */+		0x36, 0x31, 0x30, 0x30, 0x0E, 0x0D, 0x28, 0x21, 0x1C, 0x16, /* 168 ~ 177 */+		0x50, 0x4A, 0x43, 0x40, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, /* 178 ~ 187 */+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 188 ~ 197 */+		0x00, 0x00, 0x7D, 0x14, 0x32, 0x2C, 0x36, 0x4C, 0x43, 0x2C, /* 198 ~ 207 */+		0x2E, 0x36, 0x30, 0x6E,					    /* 208 ~ 211 */+	};+	int i;++	for (i = 0; i < ARRAY_SIZE(glrt_table); i++) {+		rt2800_bbp_write(rt2x00dev, 195, 128 + i);+		rt2800_bbp_write(rt2x00dev, 196, glrt_table[i]);+	}+};++static void rt2800_init_bbp_early(struct rt2x00_dev *rt2x00dev)+{+	rt2800_bbp_write(rt2x00dev, 65, 0x2C);+	rt2800_bbp_write(rt2x00dev, 66, 0x38);+	rt2800_bbp_write(rt2x00dev, 68, 0x0B);+	rt2800_bbp_write(rt2x00dev, 69, 0x12);+	rt2800_bbp_write(rt2x00dev, 70, 0x0a);+	rt2800_bbp_write(rt2x00dev, 73, 0x10);+	rt2800_bbp_write(rt2x00dev, 81, 0x37);+	rt2800_bbp_write(rt2x00dev, 82, 0x62);+	rt2800_bbp_write(rt2x00dev, 83, 0x6A);+	rt2800_bbp_write(rt2x00dev, 84, 0x99);+	rt2800_bbp_write(rt2x00dev, 86, 0x00);+	rt2800_bbp_write(rt2x00dev, 91, 0x04);+	rt2800_bbp_write(rt2x00dev, 92, 0x00);+	rt2800_bbp_write(rt2x00dev, 103, 0x00);+	rt2800_bbp_write(rt2x00dev, 105, 0x05);+	rt2800_bbp_write(rt2x00dev, 106, 0x35);+}++static void rt2800_disable_unused_dac_adc(struct rt2x00_dev *rt2x00dev)+{+	u16 eeprom;+	u8 value;++	rt2800_bbp_read(rt2x00dev, 138, &value);+	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);+	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)+		value |= 0x20;+	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)+		value &= ~0x02;+	rt2800_bbp_write(rt2x00dev, 138, value);+}++static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev)+{+	rt2800_bbp_write(rt2x00dev, 31, 0x08);++	rt2800_bbp_write(rt2x00dev, 65, 0x2c);+	rt2800_bbp_write(rt2x00dev, 66, 0x38);++	rt2800_bbp_write(rt2x00dev, 69, 0x12);+	rt2800_bbp_write(rt2x00dev, 73, 0x10);++	rt2800_bbp_write(rt2x00dev, 70, 0x0a);++	rt2800_bbp_write(rt2x00dev, 78, 0x0e);+	rt2800_bbp_write(rt2x00dev, 80, 0x08);++	rt2800_bbp_write(rt2x00dev, 82, 0x62);++	rt2800_bbp_write(rt2x00dev, 83, 0x6a);++	rt2800_bbp_write(rt2x00dev, 84, 0x99);++	rt2800_bbp_write(rt2x00dev, 86, 0x00);++	rt2800_bbp_write(rt2x00dev, 91, 0x04);++	rt2800_bbp_write(rt2x00dev, 92, 0x00);++	rt2800_bbp_write(rt2x00dev, 103, 0xc0);++	rt2800_bbp_write(rt2x00dev, 105, 0x01);++	rt2800_bbp_write(rt2x00dev, 106, 0x35);+}++static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev)+{+	rt2800_bbp_write(rt2x00dev, 65, 0x2c);+	rt2800_bbp_write(rt2x00dev, 66, 0x38);++	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {+		rt2800_bbp_write(rt2x00dev, 69, 0x16);+		rt2800_bbp_write(rt2x00dev, 73, 0x12);+	} else {+		rt2800_bbp_write(rt2x00dev, 69, 0x12);+		rt2800_bbp_write(rt2x00dev, 73, 0x10);+	}++	rt2800_bbp_write(rt2x00dev, 70, 0x0a);++	rt2800_bbp_write(rt2x00dev, 81, 0x37);++	rt2800_bbp_write(rt2x00dev, 82, 0x62);++	rt2800_bbp_write(rt2x00dev, 83, 0x6a);++	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D))+		rt2800_bbp_write(rt2x00dev, 84, 0x19);+	else+		rt2800_bbp_write(rt2x00dev, 84, 0x99);++	rt2800_bbp_write(rt2x00dev, 86, 0x00);++	rt2800_bbp_write(rt2x00dev, 91, 0x04);++	rt2800_bbp_write(rt2x00dev, 92, 0x00);++	rt2800_bbp_write(rt2x00dev, 103, 0x00);++	rt2800_bbp_write(rt2x00dev, 105, 0x05);++	rt2800_bbp_write(rt2x00dev, 106, 0x35);+}++static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev)+{+	rt2800_bbp_write(rt2x00dev, 65, 0x2c);+	rt2800_bbp_write(rt2x00dev, 66, 0x38);++	rt2800_bbp_write(rt2x00dev, 69, 0x12);+	rt2800_bbp_write(rt2x00dev, 73, 0x10);++	rt2800_bbp_write(rt2x00dev, 70, 0x0a);++	rt2800_bbp_write(rt2x00dev, 79, 0x13);+	rt2800_bbp_write(rt2x00dev, 80, 0x05);+	rt2800_bbp_write(rt2x00dev, 81, 0x33);++	rt2800_bbp_write(rt2x00dev, 82, 0x62);++	rt2800_bbp_write(rt2x00dev, 83, 0x6a);++	rt2800_bbp_write(rt2x00dev, 84, 0x99);++	rt2800_bbp_write(rt2x00dev, 86, 0x00);++	rt2800_bbp_write(rt2x00dev, 91, 0x04);++	rt2800_bbp_write(rt2x00dev, 92, 0x00);++	if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) ||+	    rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) ||+	    rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E))+		rt2800_bbp_write(rt2x00dev, 103, 0xc0);+	else+		rt2800_bbp_write(rt2x00dev, 103, 0x00);++	rt2800_bbp_write(rt2x00dev, 105, 0x05);++	rt2800_bbp_write(rt2x00dev, 106, 0x35);++	if (rt2x00_rt(rt2x00dev, RT3071) ||+	    rt2x00_rt(rt2x00dev, RT3090))+		rt2800_disable_unused_dac_adc(rt2x00dev);+}++static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev)+{+	u8 value;++	rt2800_bbp4_mac_if_ctrl(rt2x00dev);++	rt2800_bbp_write(rt2x00dev, 31, 0x08);++	rt2800_bbp_write(rt2x00dev, 65, 0x2c);+	rt2800_bbp_write(rt2x00dev, 66, 0x38);++	rt2800_bbp_write(rt2x00dev, 68, 0x0b);++	rt2800_bbp_write(rt2x00dev, 69, 0x12);+	rt2800_bbp_write(rt2x00dev, 73, 0x13);+	rt2800_bbp_write(rt2x00dev, 75, 0x46);+	rt2800_bbp_write(rt2x00dev, 76, 0x28);++	rt2800_bbp_write(rt2x00dev, 77, 0x58);++	rt2800_bbp_write(rt2x00dev, 70, 0x0a);++	rt2800_bbp_write(rt2x00dev, 74, 0x0b);+	rt2800_bbp_write(rt2x00dev, 79, 0x18);+	rt2800_bbp_write(rt2x00dev, 80, 0x09);+	rt2800_bbp_write(rt2x00dev, 81, 0x33);++	rt2800_bbp_write(rt2x00dev, 82, 0x62);++	rt2800_bbp_write(rt2x00dev, 83, 0x7a);++	rt2800_bbp_write(rt2x00dev, 84, 0x9a);++	rt2800_bbp_write(rt2x00dev, 86, 0x38);++	rt2800_bbp_write(rt2x00dev, 91, 0x04);++	rt2800_bbp_write(rt2x00dev, 92, 0x02);++	rt2800_bbp_write(rt2x00dev, 103, 0xc0);++	rt2800_bbp_write(rt2x00dev, 104, 0x92);++	rt2800_bbp_write(rt2x00dev, 105, 0x1c);++	rt2800_bbp_write(rt2x00dev, 106, 0x03);++	rt2800_bbp_write(rt2x00dev, 128, 0x12);++	rt2800_bbp_write(rt2x00dev, 67, 0x24);+	rt2800_bbp_write(rt2x00dev, 143, 0x04);+	rt2800_bbp_write(rt2x00dev, 142, 0x99);+	rt2800_bbp_write(rt2x00dev, 150, 0x30);+	rt2800_bbp_write(rt2x00dev, 151, 0x2e);+	rt2800_bbp_write(rt2x00dev, 152, 0x20);+	rt2800_bbp_write(rt2x00dev, 153, 0x34);+	rt2800_bbp_write(rt2x00dev, 154, 0x40);+	rt2800_bbp_write(rt2x00dev, 155, 0x3b);+	rt2800_bbp_write(rt2x00dev, 253, 0x04);++	rt2800_bbp_read(rt2x00dev, 47, &value);+	rt2x00_set_field8(&value, BBP47_TSSI_ADC6, 1);+	rt2800_bbp_write(rt2x00dev, 47, value);++	/* Use 5-bit ADC for Acquisition and 8-bit ADC for data */+	rt2800_bbp_read(rt2x00dev, 3, &value);+	rt2x00_set_field8(&value, BBP3_ADC_MODE_SWITCH, 1);+	rt2x00_set_field8(&value, BBP3_ADC_INIT_MODE, 1);+	rt2800_bbp_write(rt2x00dev, 3, value);+}++static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev)+{+	rt2800_bbp_write(rt2x00dev, 3, 0x00);+	rt2800_bbp_write(rt2x00dev, 4, 0x50);++	rt2800_bbp_write(rt2x00dev, 31, 0x08);++	rt2800_bbp_write(rt2x00dev, 47, 0x48);++	rt2800_bbp_write(rt2x00dev, 65, 0x2c);+	rt2800_bbp_write(rt2x00dev, 66, 0x38);++	rt2800_bbp_write(rt2x00dev, 68, 0x0b);++	rt2800_bbp_write(rt2x00dev, 69, 0x12);+	rt2800_bbp_write(rt2x00dev, 73, 0x13);+	rt2800_bbp_write(rt2x00dev, 75, 0x46);+	rt2800_bbp_write(rt2x00dev, 76, 0x28);++	rt2800_bbp_write(rt2x00dev, 77, 0x59);++	rt2800_bbp_write(rt2x00dev, 70, 0x0a);++	rt2800_bbp_write(rt2x00dev, 78, 0x0e);+	rt2800_bbp_write(rt2x00dev, 80, 0x08);+	rt2800_bbp_write(rt2x00dev, 81, 0x37);++	rt2800_bbp_write(rt2x00dev, 82, 0x62);++	rt2800_bbp_write(rt2x00dev, 83, 0x6a);++	rt2800_bbp_write(rt2x00dev, 84, 0x99);++	rt2800_bbp_write(rt2x00dev, 86, 0x38);++	rt2800_bbp_write(rt2x00dev, 88, 0x90);++	rt2800_bbp_write(rt2x00dev, 91, 0x04);++	rt2800_bbp_write(rt2x00dev, 92, 0x02);++	rt2800_bbp_write(rt2x00dev, 103, 0xc0);++	rt2800_bbp_write(rt2x00dev, 104, 0x92);++	rt2800_bbp_write(rt2x00dev, 105, 0x34);++	rt2800_bbp_write(rt2x00dev, 106, 0x05);++	rt2800_bbp_write(rt2x00dev, 120, 0x50);++	rt2800_bbp_write(rt2x00dev, 137, 0x0f);++	rt2800_bbp_write(rt2x00dev, 163, 0xbd);+	/* Set ITxBF timeout to 0x9c40=1000msec */+	rt2800_bbp_write(rt2x00dev, 179, 0x02);+	rt2800_bbp_write(rt2x00dev, 180, 0x00);+	rt2800_bbp_write(rt2x00dev, 182, 0x40);+	rt2800_bbp_write(rt2x00dev, 180, 0x01);+	rt2800_bbp_write(rt2x00dev, 182, 0x9c);+	rt2800_bbp_write(rt2x00dev, 179, 0x00);+	/* Reprogram the inband interface to put right values in RXWI */+	rt2800_bbp_write(rt2x00dev, 142, 0x04);+	rt2800_bbp_write(rt2x00dev, 143, 0x3b);+	rt2800_bbp_write(rt2x00dev, 142, 0x06);+	rt2800_bbp_write(rt2x00dev, 143, 0xa0);+	rt2800_bbp_write(rt2x00dev, 142, 0x07);+	rt2800_bbp_write(rt2x00dev, 143, 0xa1);+	rt2800_bbp_write(rt2x00dev, 142, 0x08);+	rt2800_bbp_write(rt2x00dev, 143, 0xa2);++	rt2800_bbp_write(rt2x00dev, 148, 0xc8);+}++static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev)+{+	rt2800_bbp_write(rt2x00dev, 65, 0x2c);+	rt2800_bbp_write(rt2x00dev, 66, 0x38);++	rt2800_bbp_write(rt2x00dev, 69, 0x12);+	rt2800_bbp_write(rt2x00dev, 73, 0x10);++	rt2800_bbp_write(rt2x00dev, 70, 0x0a);++	rt2800_bbp_write(rt2x00dev, 79, 0x13);+	rt2800_bbp_write(rt2x00dev, 80, 0x05);+	rt2800_bbp_write(rt2x00dev, 81, 0x33);++	rt2800_bbp_write(rt2x00dev, 82, 0x62);++	rt2800_bbp_write(rt2x00dev, 83, 0x6a);++	rt2800_bbp_write(rt2x00dev, 84, 0x99);++	rt2800_bbp_write(rt2x00dev, 86, 0x00);++	rt2800_bbp_write(rt2x00dev, 91, 0x04);++	rt2800_bbp_write(rt2x00dev, 92, 0x00);++	if (rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E))+		rt2800_bbp_write(rt2x00dev, 103, 0xc0);+	else+		rt2800_bbp_write(rt2x00dev, 103, 0x00);++	rt2800_bbp_write(rt2x00dev, 105, 0x05);++	rt2800_bbp_write(rt2x00dev, 106, 0x35);++	rt2800_disable_unused_dac_adc(rt2x00dev);+}++static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev)+{+	rt2800_bbp_write(rt2x00dev, 31, 0x08);++	rt2800_bbp_write(rt2x00dev, 65, 0x2c);+	rt2800_bbp_write(rt2x00dev, 66, 0x38);++	rt2800_bbp_write(rt2x00dev, 69, 0x12);+	rt2800_bbp_write(rt2x00dev, 73, 0x10);++	rt2800_bbp_write(rt2x00dev, 70, 0x0a);++	rt2800_bbp_write(rt2x00dev, 79, 0x13);+	rt2800_bbp_write(rt2x00dev, 80, 0x05);+	rt2800_bbp_write(rt2x00dev, 81, 0x33);++	rt2800_bbp_write(rt2x00dev, 82, 0x62);++	rt2800_bbp_write(rt2x00dev, 83, 0x6a);++	rt2800_bbp_write(rt2x00dev, 84, 0x99);++	rt2800_bbp_write(rt2x00dev, 86, 0x00);++	rt2800_bbp_write(rt2x00dev, 91, 0x04);++	rt2800_bbp_write(rt2x00dev, 92, 0x00);++	rt2800_bbp_write(rt2x00dev, 103, 0xc0);++	rt2800_bbp_write(rt2x00dev, 105, 0x05);++	rt2800_bbp_write(rt2x00dev, 106, 0x35);++	rt2800_disable_unused_dac_adc(rt2x00dev);+}++static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)+{+	int ant, div_mode;+	u16 eeprom;+	u8 value;++	rt2800_bbp4_mac_if_ctrl(rt2x00dev);++	rt2800_bbp_write(rt2x00dev, 31, 0x08);++	rt2800_bbp_write(rt2x00dev, 65, 0x2c);+	rt2800_bbp_write(rt2x00dev, 66, 0x38);++	rt2800_bbp_write(rt2x00dev, 68, 0x0b);++	rt2800_bbp_write(rt2x00dev, 69, 0x12);+	rt2800_bbp_write(rt2x00dev, 73, 0x13);+	rt2800_bbp_write(rt2x00dev, 75, 0x46);+	rt2800_bbp_write(rt2x00dev, 76, 0x28);++	rt2800_bbp_write(rt2x00dev, 77, 0x59);++	rt2800_bbp_write(rt2x00dev, 70, 0x0a);++	rt2800_bbp_write(rt2x00dev, 79, 0x13);+	rt2800_bbp_write(rt2x00dev, 80, 0x05);+	rt2800_bbp_write(rt2x00dev, 81, 0x33);++	rt2800_bbp_write(rt2x00dev, 82, 0x62);++	rt2800_bbp_write(rt2x00dev, 83, 0x7a);++	rt2800_bbp_write(rt2x00dev, 84, 0x9a);++	rt2800_bbp_write(rt2x00dev, 86, 0x38);++	if (rt2x00_rt(rt2x00dev, RT5392))+		rt2800_bbp_write(rt2x00dev, 88, 0x90);++	rt2800_bbp_write(rt2x00dev, 91, 0x04);++	rt2800_bbp_write(rt2x00dev, 92, 0x02);++	if (rt2x00_rt(rt2x00dev, RT5392)) {+		rt2800_bbp_write(rt2x00dev, 95, 0x9a);+		rt2800_bbp_write(rt2x00dev, 98, 0x12);+	}++	rt2800_bbp_write(rt2x00dev, 103, 0xc0);++	rt2800_bbp_write(rt2x00dev, 104, 0x92);++	rt2800_bbp_write(rt2x00dev, 105, 0x3c);++	if (rt2x00_rt(rt2x00dev, RT5390))+		rt2800_bbp_write(rt2x00dev, 106, 0x03);+	else if (rt2x00_rt(rt2x00dev, RT5392))+		rt2800_bbp_write(rt2x00dev, 106, 0x12);+	else+		WARN_ON(1);++	rt2800_bbp_write(rt2x00dev, 128, 0x12);++	if (rt2x00_rt(rt2x00dev, RT5392)) {+		rt2800_bbp_write(rt2x00dev, 134, 0xd0);+		rt2800_bbp_write(rt2x00dev, 135, 0xf6);+	}++	rt2800_disable_unused_dac_adc(rt2x00dev);++	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);+	div_mode = rt2x00_get_field16(eeprom,+				      EEPROM_NIC_CONF1_ANT_DIVERSITY);+	ant = (div_mode == 3) ? 1 : 0;++	/* check if this is a Bluetooth combo card */+	if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) {+		u32 reg;++		rt2800_register_read(rt2x00dev, GPIO_CTRL, ®);+		rt2x00_set_field32(®, GPIO_CTRL_DIR3, 0);+		rt2x00_set_field32(®, GPIO_CTRL_DIR6, 0);+		rt2x00_set_field32(®, GPIO_CTRL_VAL3, 0);+		rt2x00_set_field32(®, GPIO_CTRL_VAL6, 0);+		if (ant == 0)+			rt2x00_set_field32(®, GPIO_CTRL_VAL3, 1);+		else if (ant == 1)+			rt2x00_set_field32(®, GPIO_CTRL_VAL6, 1);+		rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);+	}++	/* This chip has hardware antenna diversity*/+	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390R)) {+		rt2800_bbp_write(rt2x00dev, 150, 0); /* Disable Antenna Software OFDM */+		rt2800_bbp_write(rt2x00dev, 151, 0); /* Disable Antenna Software CCK */+		rt2800_bbp_write(rt2x00dev, 154, 0); /* Clear previously selected antenna */+	}++	rt2800_bbp_read(rt2x00dev, 152, &value);+	if (ant == 0)+		rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1);+	else+		rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0);+	rt2800_bbp_write(rt2x00dev, 152, value);++	rt2800_init_freq_calibration(rt2x00dev);+}++static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev)+{+	int ant, div_mode;+	u16 eeprom;+	u8 value;++	rt2800_init_bbp_early(rt2x00dev);++	rt2800_bbp_read(rt2x00dev, 105, &value);+	rt2x00_set_field8(&value, BBP105_MLD,+			  rt2x00dev->default_ant.rx_chain_num == 2);+	rt2800_bbp_write(rt2x00dev, 105, value);++	rt2800_bbp4_mac_if_ctrl(rt2x00dev);++	rt2800_bbp_write(rt2x00dev, 20, 0x06);+	rt2800_bbp_write(rt2x00dev, 31, 0x08);+	rt2800_bbp_write(rt2x00dev, 65, 0x2C);+	rt2800_bbp_write(rt2x00dev, 68, 0xDD);+	rt2800_bbp_write(rt2x00dev, 69, 0x1A);+	rt2800_bbp_write(rt2x00dev, 70, 0x05);+	rt2800_bbp_write(rt2x00dev, 73, 0x13);+	rt2800_bbp_write(rt2x00dev, 74, 0x0F);+	rt2800_bbp_write(rt2x00dev, 75, 0x4F);+	rt2800_bbp_write(rt2x00dev, 76, 0x28);+	rt2800_bbp_write(rt2x00dev, 77, 0x59);+	rt2800_bbp_write(rt2x00dev, 84, 0x9A);+	rt2800_bbp_write(rt2x00dev, 86, 0x38);+	rt2800_bbp_write(rt2x00dev, 88, 0x90);+	rt2800_bbp_write(rt2x00dev, 91, 0x04);+	rt2800_bbp_write(rt2x00dev, 92, 0x02);+	rt2800_bbp_write(rt2x00dev, 95, 0x9a);+	rt2800_bbp_write(rt2x00dev, 98, 0x12);+	rt2800_bbp_write(rt2x00dev, 103, 0xC0);+	rt2800_bbp_write(rt2x00dev, 104, 0x92);+	/* FIXME BBP105 owerwrite */+	rt2800_bbp_write(rt2x00dev, 105, 0x3C);+	rt2800_bbp_write(rt2x00dev, 106, 0x35);+	rt2800_bbp_write(rt2x00dev, 128, 0x12);+	rt2800_bbp_write(rt2x00dev, 134, 0xD0);+	rt2800_bbp_write(rt2x00dev, 135, 0xF6);+	rt2800_bbp_write(rt2x00dev, 137, 0x0F);++	/* Initialize GLRT (Generalized Likehood Radio Test) */+	rt2800_init_bbp_5592_glrt(rt2x00dev);++	rt2800_bbp4_mac_if_ctrl(rt2x00dev);++	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);+	div_mode = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_ANT_DIVERSITY);+	ant = (div_mode == 3) ? 1 : 0;+	rt2800_bbp_read(rt2x00dev, 152, &value);+	if (ant == 0) {+		/* Main antenna */+		rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1);+	} else {+		/* Auxiliary antenna */+		rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0);+	}+	rt2800_bbp_write(rt2x00dev, 152, value);++	if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) {+		rt2800_bbp_read(rt2x00dev, 254, &value);+		rt2x00_set_field8(&value, BBP254_BIT7, 1);+		rt2800_bbp_write(rt2x00dev, 254, value);+	}++	rt2800_init_freq_calibration(rt2x00dev);++	rt2800_bbp_write(rt2x00dev, 84, 0x19);+	if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C))+		rt2800_bbp_write(rt2x00dev, 103, 0xc0);+}++static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)+{+	unsigned int i;+	u16 eeprom;+	u8 reg_id;+	u8 value;++	if (rt2800_is_305x_soc(rt2x00dev))+		rt2800_init_bbp_305x_soc(rt2x00dev);++	switch (rt2x00dev->chip.rt) {+	case RT2860:+	case RT2872:+	case RT2883:+		rt2800_init_bbp_28xx(rt2x00dev);+		break;+	case RT3070:+	case RT3071:+	case RT3090:+		rt2800_init_bbp_30xx(rt2x00dev);+		break;+	case RT3290:+		rt2800_init_bbp_3290(rt2x00dev);+		break;+	case RT3352:+		rt2800_init_bbp_3352(rt2x00dev);+		break;+	case RT3390:+		rt2800_init_bbp_3390(rt2x00dev);+		break;+	case RT3572:+		rt2800_init_bbp_3572(rt2x00dev);+		break;+	case RT5390:+	case RT5392:+		rt2800_init_bbp_53xx(rt2x00dev);+		break;+	case RT5592:+		rt2800_init_bbp_5592(rt2x00dev);+		return;+	}++	for (i = 0; i < EEPROM_BBP_SIZE; i++) {+		rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);++		if (eeprom != 0xffff && eeprom != 0x0000) {+			reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);+			value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);+			rt2800_bbp_write(rt2x00dev, reg_id, value);+		}+	}+}++static void rt2800_led_open_drain_enable(struct rt2x00_dev *rt2x00dev)+{+	u32 reg;++	rt2800_register_read(rt2x00dev, OPT_14_CSR, ®);+	rt2x00_set_field32(®, OPT_14_CSR_BIT0, 1);+	rt2800_register_write(rt2x00dev, OPT_14_CSR, reg);+}++static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, bool bw40,+				u8 filter_target)+{+	unsigned int i;+	u8 bbp;+	u8 rfcsr;+	u8 passband;+	u8 stopband;+	u8 overtuned = 0;+	u8 rfcsr24 = (bw40) ? 0x27 : 0x07;++	rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24);++	rt2800_bbp_read(rt2x00dev, 4, &bbp);+	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40);+	rt2800_bbp_write(rt2x00dev, 4, bbp);++	rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR31_RX_H20M, bw40);+	rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);++	rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1);+	rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);++	/*+	 * Set power & frequency of passband test tone+	 */+	rt2800_bbp_write(rt2x00dev, 24, 0);++	for (i = 0; i < 100; i++) {+		rt2800_bbp_write(rt2x00dev, 25, 0x90);+		msleep(1);++		rt2800_bbp_read(rt2x00dev, 55, &passband);+		if (passband)+			break;+	}++	/*+	 * Set power & frequency of stopband test tone+	 */+	rt2800_bbp_write(rt2x00dev, 24, 0x06);++	for (i = 0; i < 100; i++) {+		rt2800_bbp_write(rt2x00dev, 25, 0x90);+		msleep(1);++		rt2800_bbp_read(rt2x00dev, 55, &stopband);++		if ((passband - stopband) <= filter_target) {+			rfcsr24++;+			overtuned += ((passband - stopband) == filter_target);+		} else+			break;++		rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24);+	}++	rfcsr24 -= !!overtuned;++	rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24);+	return rfcsr24;+}++static void rt2800_rf_init_calibration(struct rt2x00_dev *rt2x00dev,+				       const unsigned int rf_reg)+{+	u8 rfcsr;++	rt2800_rfcsr_read(rt2x00dev, rf_reg, &rfcsr);+	rt2x00_set_field8(&rfcsr, FIELD8(0x80), 1);+	rt2800_rfcsr_write(rt2x00dev, rf_reg, rfcsr);+	msleep(1);+	rt2x00_set_field8(&rfcsr, FIELD8(0x80), 0);+	rt2800_rfcsr_write(rt2x00dev, rf_reg, rfcsr);+}++static void rt2800_rx_filter_calibration(struct rt2x00_dev *rt2x00dev)+{+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;+	u8 filter_tgt_bw20;+	u8 filter_tgt_bw40;+	u8 rfcsr, bbp;++	/*+	 * TODO: sync filter_tgt values with vendor driver+	 */+	if (rt2x00_rt(rt2x00dev, RT3070)) {+		filter_tgt_bw20 = 0x16;+		filter_tgt_bw40 = 0x19;+	} else {+		filter_tgt_bw20 = 0x13;+		filter_tgt_bw40 = 0x15;+	}++	drv_data->calibration_bw20 =+		rt2800_init_rx_filter(rt2x00dev, false, filter_tgt_bw20);+	drv_data->calibration_bw40 =+		rt2800_init_rx_filter(rt2x00dev, true, filter_tgt_bw40);++	/*+	 * Save BBP 25 & 26 values for later use in channel switching (for 3052)+	 */+	rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25);+	rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26);++	/*+	 * Set back to initial state+	 */+	rt2800_bbp_write(rt2x00dev, 24, 0);++	rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0);+	rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);++	/*+	 * Set BBP back to BW20+	 */+	rt2800_bbp_read(rt2x00dev, 4, &bbp);+	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);+	rt2800_bbp_write(rt2x00dev, 4, bbp);+}++static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev)+{+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;+	u8 min_gain, rfcsr, bbp;+	u16 eeprom;++	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);++	rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0);+	if (rt2x00_rt(rt2x00dev, RT3070) ||+	    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||+	    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||+	    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {+		if (!test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags))+			rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);+	}++	min_gain = rt2x00_rt(rt2x00dev, RT3070) ? 1 : 2;+	if (drv_data->txmixer_gain_24g >= min_gain) {+		rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN,+				  drv_data->txmixer_gain_24g);+	}++	rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);++	if (rt2x00_rt(rt2x00dev, RT3090)) {+		/*  Turn off unused DAC1 and ADC1 to reduce power consumption */+		rt2800_bbp_read(rt2x00dev, 138, &bbp);+		rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);+		if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)+			rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0);+		if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)+			rt2x00_set_field8(&bbp, BBP138_TX_DAC1, 1);+		rt2800_bbp_write(rt2x00dev, 138, bbp);+	}++	if (rt2x00_rt(rt2x00dev, RT3070)) {+		rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr);+		if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F))+			rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3);+		else+			rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0);+		rt2x00_set_field8(&rfcsr, RFCSR27_R2, 0);+		rt2x00_set_field8(&rfcsr, RFCSR27_R3, 0);+		rt2x00_set_field8(&rfcsr, RFCSR27_R4, 0);+		rt2800_rfcsr_write(rt2x00dev, 27, rfcsr);+	} else if (rt2x00_rt(rt2x00dev, RT3071) ||+		   rt2x00_rt(rt2x00dev, RT3090) ||+		   rt2x00_rt(rt2x00dev, RT3390)) {+		rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);+		rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);+		rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);+		rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);+		rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);+		rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);+		rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);++		rt2800_rfcsr_read(rt2x00dev, 15, &rfcsr);+		rt2x00_set_field8(&rfcsr, RFCSR15_TX_LO2_EN, 0);+		rt2800_rfcsr_write(rt2x00dev, 15, rfcsr);++		rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr);+		rt2x00_set_field8(&rfcsr, RFCSR20_RX_LO1_EN, 0);+		rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);++		rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr);+		rt2x00_set_field8(&rfcsr, RFCSR21_RX_LO2_EN, 0);+		rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);+	}+}++static void rt2800_normal_mode_setup_5xxx(struct rt2x00_dev *rt2x00dev)+{+	u8 reg;+	u16 eeprom;++	/*  Turn off unused DAC1 and ADC1 to reduce power consumption */+	rt2800_bbp_read(rt2x00dev, 138, ®);+	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);+	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)+		rt2x00_set_field8(®, BBP138_RX_ADC1, 0);+	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)+		rt2x00_set_field8(®, BBP138_TX_DAC1, 1);+	rt2800_bbp_write(rt2x00dev, 138, reg);++	rt2800_rfcsr_read(rt2x00dev, 38, ®);+	rt2x00_set_field8(®, RFCSR38_RX_LO1_EN, 0);+	rt2800_rfcsr_write(rt2x00dev, 38, reg);++	rt2800_rfcsr_read(rt2x00dev, 39, ®);+	rt2x00_set_field8(®, RFCSR39_RX_LO2_EN, 0);+	rt2800_rfcsr_write(rt2x00dev, 39, reg);++	rt2800_bbp4_mac_if_ctrl(rt2x00dev);++	rt2800_rfcsr_read(rt2x00dev, 30, ®);+	rt2x00_set_field8(®, RFCSR30_RX_VCM, 2);+	rt2800_rfcsr_write(rt2x00dev, 30, reg);+}++static void rt2800_init_rfcsr_305x_soc(struct rt2x00_dev *rt2x00dev)+{+	rt2800_rf_init_calibration(rt2x00dev, 30);++	rt2800_rfcsr_write(rt2x00dev, 0, 0x50);+	rt2800_rfcsr_write(rt2x00dev, 1, 0x01);+	rt2800_rfcsr_write(rt2x00dev, 2, 0xf7);+	rt2800_rfcsr_write(rt2x00dev, 3, 0x75);+	rt2800_rfcsr_write(rt2x00dev, 4, 0x40);+	rt2800_rfcsr_write(rt2x00dev, 5, 0x03);+	rt2800_rfcsr_write(rt2x00dev, 6, 0x02);+	rt2800_rfcsr_write(rt2x00dev, 7, 0x50);+	rt2800_rfcsr_write(rt2x00dev, 8, 0x39);+	rt2800_rfcsr_write(rt2x00dev, 9, 0x0f);+	rt2800_rfcsr_write(rt2x00dev, 10, 0x60);+	rt2800_rfcsr_write(rt2x00dev, 11, 0x21);+	rt2800_rfcsr_write(rt2x00dev, 12, 0x75);+	rt2800_rfcsr_write(rt2x00dev, 13, 0x75);+	rt2800_rfcsr_write(rt2x00dev, 14, 0x90);+	rt2800_rfcsr_write(rt2x00dev, 15, 0x58);+	rt2800_rfcsr_write(rt2x00dev, 16, 0xb3);+	rt2800_rfcsr_write(rt2x00dev, 17, 0x92);+	rt2800_rfcsr_write(rt2x00dev, 18, 0x2c);+	rt2800_rfcsr_write(rt2x00dev, 19, 0x02);+	rt2800_rfcsr_write(rt2x00dev, 20, 0xba);+	rt2800_rfcsr_write(rt2x00dev, 21, 0xdb);+	rt2800_rfcsr_write(rt2x00dev, 22, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 23, 0x31);+	rt2800_rfcsr_write(rt2x00dev, 24, 0x08);+	rt2800_rfcsr_write(rt2x00dev, 25, 0x01);+	rt2800_rfcsr_write(rt2x00dev, 26, 0x25);+	rt2800_rfcsr_write(rt2x00dev, 27, 0x23);+	rt2800_rfcsr_write(rt2x00dev, 28, 0x13);+	rt2800_rfcsr_write(rt2x00dev, 29, 0x83);+	rt2800_rfcsr_write(rt2x00dev, 30, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 31, 0x00);+}++static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev)+{+	u8 rfcsr;+	u16 eeprom;+	u32 reg;++	/* XXX vendor driver do this only for 3070 */+	rt2800_rf_init_calibration(rt2x00dev, 30);++	rt2800_rfcsr_write(rt2x00dev, 4, 0x40);+	rt2800_rfcsr_write(rt2x00dev, 5, 0x03);+	rt2800_rfcsr_write(rt2x00dev, 6, 0x02);+	rt2800_rfcsr_write(rt2x00dev, 7, 0x60);+	rt2800_rfcsr_write(rt2x00dev, 9, 0x0f);+	rt2800_rfcsr_write(rt2x00dev, 10, 0x41);+	rt2800_rfcsr_write(rt2x00dev, 11, 0x21);+	rt2800_rfcsr_write(rt2x00dev, 12, 0x7b);+	rt2800_rfcsr_write(rt2x00dev, 14, 0x90);+	rt2800_rfcsr_write(rt2x00dev, 15, 0x58);+	rt2800_rfcsr_write(rt2x00dev, 16, 0xb3);+	rt2800_rfcsr_write(rt2x00dev, 17, 0x92);+	rt2800_rfcsr_write(rt2x00dev, 18, 0x2c);+	rt2800_rfcsr_write(rt2x00dev, 19, 0x02);+	rt2800_rfcsr_write(rt2x00dev, 20, 0xba);+	rt2800_rfcsr_write(rt2x00dev, 21, 0xdb);+	rt2800_rfcsr_write(rt2x00dev, 24, 0x16);+	rt2800_rfcsr_write(rt2x00dev, 25, 0x01);+	rt2800_rfcsr_write(rt2x00dev, 29, 0x1f);++	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {+		rt2800_register_read(rt2x00dev, LDO_CFG0, ®);+		rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1);+		rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3);+		rt2800_register_write(rt2x00dev, LDO_CFG0, reg);+	} else if (rt2x00_rt(rt2x00dev, RT3071) ||+		   rt2x00_rt(rt2x00dev, RT3090)) {+		rt2800_rfcsr_write(rt2x00dev, 31, 0x14);++		rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);+		rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);+		rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);++		rt2800_register_read(rt2x00dev, LDO_CFG0, ®);+		rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1);+		if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||+		    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) {+			rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);+			if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))+				rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3);+			else+				rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0);+		}+		rt2800_register_write(rt2x00dev, LDO_CFG0, reg);++		rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®);+		rt2x00_set_field32(®, GPIO_SWITCH_5, 0);+		rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);+	}++	rt2800_rx_filter_calibration(rt2x00dev);++	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) ||+	    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||+	    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E))+		rt2800_rfcsr_write(rt2x00dev, 27, 0x03);++	rt2800_led_open_drain_enable(rt2x00dev);+	rt2800_normal_mode_setup_3xxx(rt2x00dev);+}++static void rt2800_init_rfcsr_3290(struct rt2x00_dev *rt2x00dev)+{+	u8 rfcsr;++	rt2800_rf_init_calibration(rt2x00dev, 2);++	rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);+	rt2800_rfcsr_write(rt2x00dev, 2, 0x80);+	rt2800_rfcsr_write(rt2x00dev, 3, 0x08);+	rt2800_rfcsr_write(rt2x00dev, 4, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);+	rt2800_rfcsr_write(rt2x00dev, 8, 0xf3);+	rt2800_rfcsr_write(rt2x00dev, 9, 0x02);+	rt2800_rfcsr_write(rt2x00dev, 10, 0x53);+	rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);+	rt2800_rfcsr_write(rt2x00dev, 12, 0x46);+	rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);+	rt2800_rfcsr_write(rt2x00dev, 18, 0x02);+	rt2800_rfcsr_write(rt2x00dev, 22, 0x20);+	rt2800_rfcsr_write(rt2x00dev, 25, 0x83);+	rt2800_rfcsr_write(rt2x00dev, 26, 0x82);+	rt2800_rfcsr_write(rt2x00dev, 27, 0x09);+	rt2800_rfcsr_write(rt2x00dev, 29, 0x10);+	rt2800_rfcsr_write(rt2x00dev, 30, 0x10);+	rt2800_rfcsr_write(rt2x00dev, 31, 0x80);+	rt2800_rfcsr_write(rt2x00dev, 32, 0x80);+	rt2800_rfcsr_write(rt2x00dev, 33, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 34, 0x05);+	rt2800_rfcsr_write(rt2x00dev, 35, 0x12);+	rt2800_rfcsr_write(rt2x00dev, 36, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 38, 0x85);+	rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);+	rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);+	rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);+	rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);+	rt2800_rfcsr_write(rt2x00dev, 43, 0x7b);+	rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);+	rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);+	rt2800_rfcsr_write(rt2x00dev, 46, 0x73);+	rt2800_rfcsr_write(rt2x00dev, 47, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 48, 0x10);+	rt2800_rfcsr_write(rt2x00dev, 49, 0x98);+	rt2800_rfcsr_write(rt2x00dev, 52, 0x38);+	rt2800_rfcsr_write(rt2x00dev, 53, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 54, 0x78);+	rt2800_rfcsr_write(rt2x00dev, 55, 0x43);+	rt2800_rfcsr_write(rt2x00dev, 56, 0x02);+	rt2800_rfcsr_write(rt2x00dev, 57, 0x80);+	rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);+	rt2800_rfcsr_write(rt2x00dev, 59, 0x09);+	rt2800_rfcsr_write(rt2x00dev, 60, 0x45);+	rt2800_rfcsr_write(rt2x00dev, 61, 0xc1);++	rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR29_RSSI_GAIN, 3);+	rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);++	rt2800_led_open_drain_enable(rt2x00dev);+	rt2800_normal_mode_setup_3xxx(rt2x00dev);+}++static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev)+{+	rt2800_rf_init_calibration(rt2x00dev, 30);++	rt2800_rfcsr_write(rt2x00dev, 0, 0xf0);+	rt2800_rfcsr_write(rt2x00dev, 1, 0x23);+	rt2800_rfcsr_write(rt2x00dev, 2, 0x50);+	rt2800_rfcsr_write(rt2x00dev, 3, 0x18);+	rt2800_rfcsr_write(rt2x00dev, 4, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 5, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 6, 0x33);+	rt2800_rfcsr_write(rt2x00dev, 7, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 8, 0xf1);+	rt2800_rfcsr_write(rt2x00dev, 9, 0x02);+	rt2800_rfcsr_write(rt2x00dev, 10, 0xd2);+	rt2800_rfcsr_write(rt2x00dev, 11, 0x42);+	rt2800_rfcsr_write(rt2x00dev, 12, 0x1c);+	rt2800_rfcsr_write(rt2x00dev, 13, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 14, 0x5a);+	rt2800_rfcsr_write(rt2x00dev, 15, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 16, 0x01);+	rt2800_rfcsr_write(rt2x00dev, 18, 0x45);+	rt2800_rfcsr_write(rt2x00dev, 19, 0x02);+	rt2800_rfcsr_write(rt2x00dev, 20, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 21, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 22, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 23, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 24, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 25, 0x80);+	rt2800_rfcsr_write(rt2x00dev, 26, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 27, 0x03);+	rt2800_rfcsr_write(rt2x00dev, 28, 0x03);+	rt2800_rfcsr_write(rt2x00dev, 29, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 30, 0x10);+	rt2800_rfcsr_write(rt2x00dev, 31, 0x80);+	rt2800_rfcsr_write(rt2x00dev, 32, 0x80);+	rt2800_rfcsr_write(rt2x00dev, 33, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 34, 0x01);+	rt2800_rfcsr_write(rt2x00dev, 35, 0x03);+	rt2800_rfcsr_write(rt2x00dev, 36, 0xbd);+	rt2800_rfcsr_write(rt2x00dev, 37, 0x3c);+	rt2800_rfcsr_write(rt2x00dev, 38, 0x5f);+	rt2800_rfcsr_write(rt2x00dev, 39, 0xc5);+	rt2800_rfcsr_write(rt2x00dev, 40, 0x33);+	rt2800_rfcsr_write(rt2x00dev, 41, 0x5b);+	rt2800_rfcsr_write(rt2x00dev, 42, 0x5b);+	rt2800_rfcsr_write(rt2x00dev, 43, 0xdb);+	rt2800_rfcsr_write(rt2x00dev, 44, 0xdb);+	rt2800_rfcsr_write(rt2x00dev, 45, 0xdb);+	rt2800_rfcsr_write(rt2x00dev, 46, 0xdd);+	rt2800_rfcsr_write(rt2x00dev, 47, 0x0d);+	rt2800_rfcsr_write(rt2x00dev, 48, 0x14);+	rt2800_rfcsr_write(rt2x00dev, 49, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 50, 0x2d);+	rt2800_rfcsr_write(rt2x00dev, 51, 0x7f);+	rt2800_rfcsr_write(rt2x00dev, 52, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 53, 0x52);+	rt2800_rfcsr_write(rt2x00dev, 54, 0x1b);+	rt2800_rfcsr_write(rt2x00dev, 55, 0x7f);+	rt2800_rfcsr_write(rt2x00dev, 56, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 57, 0x52);+	rt2800_rfcsr_write(rt2x00dev, 58, 0x1b);+	rt2800_rfcsr_write(rt2x00dev, 59, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 60, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 61, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 62, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 63, 0x00);++	rt2800_rx_filter_calibration(rt2x00dev);+	rt2800_led_open_drain_enable(rt2x00dev);+	rt2800_normal_mode_setup_3xxx(rt2x00dev);+}++static void rt2800_init_rfcsr_3390(struct rt2x00_dev *rt2x00dev)+{+	u32 reg;++	rt2800_rf_init_calibration(rt2x00dev, 30);++	rt2800_rfcsr_write(rt2x00dev, 0, 0xa0);+	rt2800_rfcsr_write(rt2x00dev, 1, 0xe1);+	rt2800_rfcsr_write(rt2x00dev, 2, 0xf1);+	rt2800_rfcsr_write(rt2x00dev, 3, 0x62);+	rt2800_rfcsr_write(rt2x00dev, 4, 0x40);+	rt2800_rfcsr_write(rt2x00dev, 5, 0x8b);+	rt2800_rfcsr_write(rt2x00dev, 6, 0x42);+	rt2800_rfcsr_write(rt2x00dev, 7, 0x34);+	rt2800_rfcsr_write(rt2x00dev, 8, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 9, 0xc0);+	rt2800_rfcsr_write(rt2x00dev, 10, 0x61);+	rt2800_rfcsr_write(rt2x00dev, 11, 0x21);+	rt2800_rfcsr_write(rt2x00dev, 12, 0x3b);+	rt2800_rfcsr_write(rt2x00dev, 13, 0xe0);+	rt2800_rfcsr_write(rt2x00dev, 14, 0x90);+	rt2800_rfcsr_write(rt2x00dev, 15, 0x53);+	rt2800_rfcsr_write(rt2x00dev, 16, 0xe0);+	rt2800_rfcsr_write(rt2x00dev, 17, 0x94);+	rt2800_rfcsr_write(rt2x00dev, 18, 0x5c);+	rt2800_rfcsr_write(rt2x00dev, 19, 0x4a);+	rt2800_rfcsr_write(rt2x00dev, 20, 0xb2);+	rt2800_rfcsr_write(rt2x00dev, 21, 0xf6);+	rt2800_rfcsr_write(rt2x00dev, 22, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 23, 0x14);+	rt2800_rfcsr_write(rt2x00dev, 24, 0x08);+	rt2800_rfcsr_write(rt2x00dev, 25, 0x3d);+	rt2800_rfcsr_write(rt2x00dev, 26, 0x85);+	rt2800_rfcsr_write(rt2x00dev, 27, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 28, 0x41);+	rt2800_rfcsr_write(rt2x00dev, 29, 0x8f);+	rt2800_rfcsr_write(rt2x00dev, 30, 0x20);+	rt2800_rfcsr_write(rt2x00dev, 31, 0x0f);++	rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®);+	rt2x00_set_field32(®, GPIO_SWITCH_5, 0);+	rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);++	rt2800_rx_filter_calibration(rt2x00dev);++	if (rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E))+		rt2800_rfcsr_write(rt2x00dev, 27, 0x03);++	rt2800_led_open_drain_enable(rt2x00dev);+	rt2800_normal_mode_setup_3xxx(rt2x00dev);+}++static void rt2800_init_rfcsr_3572(struct rt2x00_dev *rt2x00dev)+{+	u8 rfcsr;+	u32 reg;++	rt2800_rf_init_calibration(rt2x00dev, 30);++	rt2800_rfcsr_write(rt2x00dev, 0, 0x70);+	rt2800_rfcsr_write(rt2x00dev, 1, 0x81);+	rt2800_rfcsr_write(rt2x00dev, 2, 0xf1);+	rt2800_rfcsr_write(rt2x00dev, 3, 0x02);+	rt2800_rfcsr_write(rt2x00dev, 4, 0x4c);+	rt2800_rfcsr_write(rt2x00dev, 5, 0x05);+	rt2800_rfcsr_write(rt2x00dev, 6, 0x4a);+	rt2800_rfcsr_write(rt2x00dev, 7, 0xd8);+	rt2800_rfcsr_write(rt2x00dev, 9, 0xc3);+	rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);+	rt2800_rfcsr_write(rt2x00dev, 11, 0xb9);+	rt2800_rfcsr_write(rt2x00dev, 12, 0x70);+	rt2800_rfcsr_write(rt2x00dev, 13, 0x65);+	rt2800_rfcsr_write(rt2x00dev, 14, 0xa0);+	rt2800_rfcsr_write(rt2x00dev, 15, 0x53);+	rt2800_rfcsr_write(rt2x00dev, 16, 0x4c);+	rt2800_rfcsr_write(rt2x00dev, 17, 0x23);+	rt2800_rfcsr_write(rt2x00dev, 18, 0xac);+	rt2800_rfcsr_write(rt2x00dev, 19, 0x93);+	rt2800_rfcsr_write(rt2x00dev, 20, 0xb3);+	rt2800_rfcsr_write(rt2x00dev, 21, 0xd0);+	rt2800_rfcsr_write(rt2x00dev, 22, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 23, 0x3c);+	rt2800_rfcsr_write(rt2x00dev, 24, 0x16);+	rt2800_rfcsr_write(rt2x00dev, 25, 0x15);+	rt2800_rfcsr_write(rt2x00dev, 26, 0x85);+	rt2800_rfcsr_write(rt2x00dev, 27, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 28, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);+	rt2800_rfcsr_write(rt2x00dev, 30, 0x09);+	rt2800_rfcsr_write(rt2x00dev, 31, 0x10);++	rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);+	rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);+	rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);++	rt2800_register_read(rt2x00dev, LDO_CFG0, ®);+	rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3);+	rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1);+	rt2800_register_write(rt2x00dev, LDO_CFG0, reg);+	msleep(1);+	rt2800_register_read(rt2x00dev, LDO_CFG0, ®);+	rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0);+	rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1);+	rt2800_register_write(rt2x00dev, LDO_CFG0, reg);++	rt2800_rx_filter_calibration(rt2x00dev);+	rt2800_led_open_drain_enable(rt2x00dev);+	rt2800_normal_mode_setup_3xxx(rt2x00dev);+}++static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)+{+	rt2800_rf_init_calibration(rt2x00dev, 2);++	rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);+	rt2800_rfcsr_write(rt2x00dev, 2, 0x80);+	rt2800_rfcsr_write(rt2x00dev, 3, 0x88);+	rt2800_rfcsr_write(rt2x00dev, 5, 0x10);+	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))+		rt2800_rfcsr_write(rt2x00dev, 6, 0xe0);+	else+		rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);+	rt2800_rfcsr_write(rt2x00dev, 7, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 10, 0x53);+	rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);+	rt2800_rfcsr_write(rt2x00dev, 12, 0xc6);+	rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);+	rt2800_rfcsr_write(rt2x00dev, 14, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 15, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 16, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 18, 0x03);+	rt2800_rfcsr_write(rt2x00dev, 19, 0x00);++	rt2800_rfcsr_write(rt2x00dev, 20, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 21, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 22, 0x20);+	rt2800_rfcsr_write(rt2x00dev, 23, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 24, 0x00);+	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))+		rt2800_rfcsr_write(rt2x00dev, 25, 0x80);+	else+		rt2800_rfcsr_write(rt2x00dev, 25, 0xc0);+	rt2800_rfcsr_write(rt2x00dev, 26, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 27, 0x09);+	rt2800_rfcsr_write(rt2x00dev, 28, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 29, 0x10);++	rt2800_rfcsr_write(rt2x00dev, 30, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 31, 0x80);+	rt2800_rfcsr_write(rt2x00dev, 32, 0x80);+	rt2800_rfcsr_write(rt2x00dev, 33, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 34, 0x07);+	rt2800_rfcsr_write(rt2x00dev, 35, 0x12);+	rt2800_rfcsr_write(rt2x00dev, 36, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 37, 0x08);+	rt2800_rfcsr_write(rt2x00dev, 38, 0x85);+	rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);++	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))+		rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);+	else+		rt2800_rfcsr_write(rt2x00dev, 40, 0x4b);+	rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);+	rt2800_rfcsr_write(rt2x00dev, 42, 0xd2);+	rt2800_rfcsr_write(rt2x00dev, 43, 0x9a);+	rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);+	rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);+	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))+		rt2800_rfcsr_write(rt2x00dev, 46, 0x73);+	else+		rt2800_rfcsr_write(rt2x00dev, 46, 0x7b);+	rt2800_rfcsr_write(rt2x00dev, 47, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 48, 0x10);+	rt2800_rfcsr_write(rt2x00dev, 49, 0x94);++	rt2800_rfcsr_write(rt2x00dev, 52, 0x38);+	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))+		rt2800_rfcsr_write(rt2x00dev, 53, 0x00);+	else+		rt2800_rfcsr_write(rt2x00dev, 53, 0x84);+	rt2800_rfcsr_write(rt2x00dev, 54, 0x78);+	rt2800_rfcsr_write(rt2x00dev, 55, 0x44);+	rt2800_rfcsr_write(rt2x00dev, 56, 0x22);+	rt2800_rfcsr_write(rt2x00dev, 57, 0x80);+	rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);+	rt2800_rfcsr_write(rt2x00dev, 59, 0x63);++	rt2800_rfcsr_write(rt2x00dev, 60, 0x45);+	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))+		rt2800_rfcsr_write(rt2x00dev, 61, 0xd1);+	else+		rt2800_rfcsr_write(rt2x00dev, 61, 0xdd);+	rt2800_rfcsr_write(rt2x00dev, 62, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 63, 0x00);++	rt2800_normal_mode_setup_5xxx(rt2x00dev);++	rt2800_led_open_drain_enable(rt2x00dev);+}++static void rt2800_init_rfcsr_5392(struct rt2x00_dev *rt2x00dev)+{+	rt2800_rf_init_calibration(rt2x00dev, 2);++	rt2800_rfcsr_write(rt2x00dev, 1, 0x17);+	rt2800_rfcsr_write(rt2x00dev, 2, 0x80);+	rt2800_rfcsr_write(rt2x00dev, 3, 0x88);+	rt2800_rfcsr_write(rt2x00dev, 5, 0x10);+	rt2800_rfcsr_write(rt2x00dev, 6, 0xe0);+	rt2800_rfcsr_write(rt2x00dev, 7, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 10, 0x53);+	rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);+	rt2800_rfcsr_write(rt2x00dev, 12, 0x46);+	rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);+	rt2800_rfcsr_write(rt2x00dev, 14, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 15, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 16, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 18, 0x03);+	rt2800_rfcsr_write(rt2x00dev, 19, 0x4d);+	rt2800_rfcsr_write(rt2x00dev, 20, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 21, 0x8d);+	rt2800_rfcsr_write(rt2x00dev, 22, 0x20);+	rt2800_rfcsr_write(rt2x00dev, 23, 0x0b);+	rt2800_rfcsr_write(rt2x00dev, 24, 0x44);+	rt2800_rfcsr_write(rt2x00dev, 25, 0x80);+	rt2800_rfcsr_write(rt2x00dev, 26, 0x82);+	rt2800_rfcsr_write(rt2x00dev, 27, 0x09);+	rt2800_rfcsr_write(rt2x00dev, 28, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 29, 0x10);+	rt2800_rfcsr_write(rt2x00dev, 30, 0x10);+	rt2800_rfcsr_write(rt2x00dev, 31, 0x80);+	rt2800_rfcsr_write(rt2x00dev, 32, 0x20);+	rt2800_rfcsr_write(rt2x00dev, 33, 0xC0);+	rt2800_rfcsr_write(rt2x00dev, 34, 0x07);+	rt2800_rfcsr_write(rt2x00dev, 35, 0x12);+	rt2800_rfcsr_write(rt2x00dev, 36, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 37, 0x08);+	rt2800_rfcsr_write(rt2x00dev, 38, 0x89);+	rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);+	rt2800_rfcsr_write(rt2x00dev, 40, 0x0f);+	rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);+	rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);+	rt2800_rfcsr_write(rt2x00dev, 43, 0x9b);+	rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);+	rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);+	rt2800_rfcsr_write(rt2x00dev, 46, 0x73);+	rt2800_rfcsr_write(rt2x00dev, 47, 0x0c);+	rt2800_rfcsr_write(rt2x00dev, 48, 0x10);+	rt2800_rfcsr_write(rt2x00dev, 49, 0x94);+	rt2800_rfcsr_write(rt2x00dev, 50, 0x94);+	rt2800_rfcsr_write(rt2x00dev, 51, 0x3a);+	rt2800_rfcsr_write(rt2x00dev, 52, 0x48);+	rt2800_rfcsr_write(rt2x00dev, 53, 0x44);+	rt2800_rfcsr_write(rt2x00dev, 54, 0x38);+	rt2800_rfcsr_write(rt2x00dev, 55, 0x43);+	rt2800_rfcsr_write(rt2x00dev, 56, 0xa1);+	rt2800_rfcsr_write(rt2x00dev, 57, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 58, 0x39);+	rt2800_rfcsr_write(rt2x00dev, 59, 0x07);+	rt2800_rfcsr_write(rt2x00dev, 60, 0x45);+	rt2800_rfcsr_write(rt2x00dev, 61, 0x91);+	rt2800_rfcsr_write(rt2x00dev, 62, 0x39);+	rt2800_rfcsr_write(rt2x00dev, 63, 0x07);++	rt2800_normal_mode_setup_5xxx(rt2x00dev);++	rt2800_led_open_drain_enable(rt2x00dev);+}++static void rt2800_init_rfcsr_5592(struct rt2x00_dev *rt2x00dev)+{+	rt2800_rf_init_calibration(rt2x00dev, 30);++	rt2800_rfcsr_write(rt2x00dev, 1, 0x3F);+	rt2800_rfcsr_write(rt2x00dev, 3, 0x08);+	rt2800_rfcsr_write(rt2x00dev, 3, 0x08);+	rt2800_rfcsr_write(rt2x00dev, 5, 0x10);+	rt2800_rfcsr_write(rt2x00dev, 6, 0xE4);+	rt2800_rfcsr_write(rt2x00dev, 7, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 14, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 15, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 16, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 18, 0x03);+	rt2800_rfcsr_write(rt2x00dev, 19, 0x4D);+	rt2800_rfcsr_write(rt2x00dev, 20, 0x10);+	rt2800_rfcsr_write(rt2x00dev, 21, 0x8D);+	rt2800_rfcsr_write(rt2x00dev, 26, 0x82);+	rt2800_rfcsr_write(rt2x00dev, 28, 0x00);+	rt2800_rfcsr_write(rt2x00dev, 29, 0x10);+	rt2800_rfcsr_write(rt2x00dev, 33, 0xC0);+	rt2800_rfcsr_write(rt2x00dev, 34, 0x07);+	rt2800_rfcsr_write(rt2x00dev, 35, 0x12);+	rt2800_rfcsr_write(rt2x00dev, 47, 0x0C);+	rt2800_rfcsr_write(rt2x00dev, 53, 0x22);+	rt2800_rfcsr_write(rt2x00dev, 63, 0x07);++	rt2800_rfcsr_write(rt2x00dev, 2, 0x80);+	msleep(1);++	rt2800_adjust_freq_offset(rt2x00dev);++	/* Enable DC filter */+	if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C))+		rt2800_bbp_write(rt2x00dev, 103, 0xc0);++	rt2800_normal_mode_setup_5xxx(rt2x00dev);++	if (rt2x00_rt_rev_lt(rt2x00dev, RT5592, REV_RT5592C))+		rt2800_rfcsr_write(rt2x00dev, 27, 0x03);++	rt2800_led_open_drain_enable(rt2x00dev);+}++static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)+{+	if (rt2800_is_305x_soc(rt2x00dev)) {+		rt2800_init_rfcsr_305x_soc(rt2x00dev);+		return;+	}++	switch (rt2x00dev->chip.rt) {+	case RT3070:+	case RT3071:+	case RT3090:+		rt2800_init_rfcsr_30xx(rt2x00dev);+		break;+	case RT3290:+		rt2800_init_rfcsr_3290(rt2x00dev);+		break;+	case RT3352:+		rt2800_init_rfcsr_3352(rt2x00dev);+		break;+	case RT3390:+		rt2800_init_rfcsr_3390(rt2x00dev);+		break;+	case RT3572:+		rt2800_init_rfcsr_3572(rt2x00dev);+		break;+	case RT5390:+		rt2800_init_rfcsr_5390(rt2x00dev);+		break;+	case RT5392:+		rt2800_init_rfcsr_5392(rt2x00dev);+		break;+	case RT5592:+		rt2800_init_rfcsr_5592(rt2x00dev);+		break;+	}+}++int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)+{+	u32 reg;+	u16 word;++	/*+	 * Initialize all registers.+	 */+	if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) ||+		     rt2800_init_registers(rt2x00dev)))+		return -EIO;++	if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev)))+		return -EIO;++	/*+	 * Send signal to firmware during boot time.+	 */+	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);+	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);+	if (rt2x00_is_usb(rt2x00dev))+		rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);+	rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);+	msleep(1);++	if (unlikely(rt2800_wait_bbp_ready(rt2x00dev)))+		return -EIO;++	rt2800_init_bbp(rt2x00dev);+	rt2800_init_rfcsr(rt2x00dev);++	if (rt2x00_is_usb(rt2x00dev) &&+	    (rt2x00_rt(rt2x00dev, RT3070) ||+	     rt2x00_rt(rt2x00dev, RT3071) ||+	     rt2x00_rt(rt2x00dev, RT3572))) {+		udelay(200);+		rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0);+		udelay(10);+	}++	/*+	 * Enable RX.+	 */+	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®);+	rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1);+	rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0);+	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);++	udelay(50);++	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®);+	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1);+	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1);+	rt2x00_set_field32(®, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 2);+	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);+	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);++	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®);+	rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1);+	rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1);+	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);++	/*+	 * Initialize LED control+	 */+	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF, &word);+	rt2800_mcu_request(rt2x00dev, MCU_LED_AG_CONF, 0xff,+			   word & 0xff, (word >> 8) & 0xff);++	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF, &word);+	rt2800_mcu_request(rt2x00dev, MCU_LED_ACT_CONF, 0xff,+			   word & 0xff, (word >> 8) & 0xff);++	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY, &word);+	rt2800_mcu_request(rt2x00dev, MCU_LED_LED_POLARITY, 0xff,+			   word & 0xff, (word >> 8) & 0xff);++	return 0;+}+EXPORT_SYMBOL_GPL(rt2800_enable_radio);++void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev)+{+	u32 reg;++	rt2800_disable_wpdma(rt2x00dev);++	/* Wait for DMA, ignore error */+	rt2800_wait_wpdma_ready(rt2x00dev);++	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®);+	rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 0);+	rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0);+	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);+}+EXPORT_SYMBOL_GPL(rt2800_disable_radio);++int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)+{+	u32 reg;+	u16 efuse_ctrl_reg;++	if (rt2x00_rt(rt2x00dev, RT3290))+		efuse_ctrl_reg = EFUSE_CTRL_3290;+	else+		efuse_ctrl_reg = EFUSE_CTRL;++	rt2800_register_read(rt2x00dev, efuse_ctrl_reg, ®);+	return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);+}+EXPORT_SYMBOL_GPL(rt2800_efuse_detect);++static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)+{+	u32 reg;+	u16 efuse_ctrl_reg;+	u16 efuse_data0_reg;+	u16 efuse_data1_reg;+	u16 efuse_data2_reg;+	u16 efuse_data3_reg;++	if (rt2x00_rt(rt2x00dev, RT3290)) {+		efuse_ctrl_reg = EFUSE_CTRL_3290;+		efuse_data0_reg = EFUSE_DATA0_3290;+		efuse_data1_reg = EFUSE_DATA1_3290;+		efuse_data2_reg = EFUSE_DATA2_3290;+		efuse_data3_reg = EFUSE_DATA3_3290;+	} else {+		efuse_ctrl_reg = EFUSE_CTRL;+		efuse_data0_reg = EFUSE_DATA0;+		efuse_data1_reg = EFUSE_DATA1;+		efuse_data2_reg = EFUSE_DATA2;+		efuse_data3_reg = EFUSE_DATA3;+	}+	mutex_lock(&rt2x00dev->csr_mutex);++	rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, ®);+	rt2x00_set_field32(®, EFUSE_CTRL_ADDRESS_IN, i);+	rt2x00_set_field32(®, EFUSE_CTRL_MODE, 0);+	rt2x00_set_field32(®, EFUSE_CTRL_KICK, 1);+	rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg);++	/* Wait until the EEPROM has been loaded */+	rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, ®);+	/* Apparently the data is read from end to start */+	rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, ®);+	/* The returned value is in CPU order, but eeprom is le */+	*(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);+	rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, ®);+	*(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);+	rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, ®);+	*(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg);+	rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, ®);+	*(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);++	mutex_unlock(&rt2x00dev->csr_mutex);+}++int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)+{+	unsigned int i;++	for (i = 0; i < EEPROM_SIZE / sizeof(u16); i += 8)+		rt2800_efuse_read(rt2x00dev, i);++	return 0;+}+EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse);++static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)+{+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;+	u16 word;+	u8 *mac;+	u8 default_lna_gain;+	int retval;++	/*+	 * Read the EEPROM.+	 */+	retval = rt2800_read_eeprom(rt2x00dev);+	if (retval)+		return retval;++	/*+	 * Start validation of the data that has been read.+	 */+	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);+	if (!is_valid_ether_addr(mac)) {+		eth_random_addr(mac);+		rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);+	}++	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word);+	if (word == 0xffff) {+		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2);+		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1);+		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820);+		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);+		rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);+	} else if (rt2x00_rt(rt2x00dev, RT2860) ||+		   rt2x00_rt(rt2x00dev, RT2872)) {+		/*+		 * There is a max of 2 RX streams for RT28x0 series+		 */+		if (rt2x00_get_field16(word, EEPROM_NIC_CONF0_RXPATH) > 2)+			rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2);+		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);+	}++	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &word);+	if (word == 0xffff) {+		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_HW_RADIO, 0);+		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC, 0);+		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G, 0);+		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G, 0);+		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_CARDBUS_ACCEL, 0);+		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_SB_2G, 0);+		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_SB_5G, 0);+		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_WPS_PBC, 0);+		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_2G, 0);+		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_5G, 0);+		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BROADBAND_EXT_LNA, 0);+		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_ANT_DIVERSITY, 0);+		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_INTERNAL_TX_ALC, 0);+		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BT_COEXIST, 0);+		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_DAC_TEST, 0);+		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF1, word);+		rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);+	}++	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);+	if ((word & 0x00ff) == 0x00ff) {+		rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);+		rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);+		rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);+	}+	if ((word & 0xff00) == 0xff00) {+		rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,+				   LED_MODE_TXRX_ACTIVITY);+		rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0);+		rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);+		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_AG_CONF, 0x5555);+		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_ACT_CONF, 0x2221);+		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_POLARITY, 0xa9f8);+		rt2x00_eeprom_dbg(rt2x00dev, "Led Mode: 0x%04x\n", word);+	}++	/*+	 * During the LNA validation we are going to use+	 * lna0 as correct value. Note that EEPROM_LNA+	 * is never validated.+	 */+	rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word);+	default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0);++	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word);+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10)+		rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0);+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10)+		rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0);+	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word);++	rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word);+	if ((word & 0x00ff) != 0x00ff) {+		drv_data->txmixer_gain_24g =+			rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL);+	} else {+		drv_data->txmixer_gain_24g = 0;+	}++	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)+		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);+	if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 ||+	    rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff)+		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1,+				   default_lna_gain);+	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word);++	rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word);+	if ((word & 0x00ff) != 0x00ff) {+		drv_data->txmixer_gain_5g =+			rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL);+	} else {+		drv_data->txmixer_gain_5g = 0;+	}++	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10)+		rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0);+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10)+		rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0);+	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word);++	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)+		rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);+	if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 ||+	    rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff)+		rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2,+				   default_lna_gain);+	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);++	return 0;+}++static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)+{+	u16 value;+	u16 eeprom;+	u16 rf;++	/*+	 * Read EEPROM word for configuration.+	 */+	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);++	/*+	 * Identify RF chipset by EEPROM value+	 * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field+	 * RT53xx: defined in "EEPROM_CHIP_ID" field+	 */+	if (rt2x00_rt(rt2x00dev, RT3290) ||+	    rt2x00_rt(rt2x00dev, RT5390) ||+	    rt2x00_rt(rt2x00dev, RT5392))+		rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);+	else+		rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);++	switch (rf) {+	case RF2820:+	case RF2850:+	case RF2720:+	case RF2750:+	case RF3020:+	case RF2020:+	case RF3021:+	case RF3022:+	case RF3052:+	case RF3290:+	case RF3320:+	case RF3322:+	case RF5360:+	case RF5370:+	case RF5372:+	case RF5390:+	case RF5392:+	case RF5592:+		break;+	default:+		rt2x00_err(rt2x00dev, "Invalid RF chipset 0x%04x detected\n",+			   rf);+		return -ENODEV;+	}++	rt2x00_set_rf(rt2x00dev, rf);++	/*+	 * Identify default antenna configuration.+	 */+	rt2x00dev->default_ant.tx_chain_num =+	    rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH);+	rt2x00dev->default_ant.rx_chain_num =+	    rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH);++	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);++	if (rt2x00_rt(rt2x00dev, RT3070) ||+	    rt2x00_rt(rt2x00dev, RT3090) ||+	    rt2x00_rt(rt2x00dev, RT3352) ||+	    rt2x00_rt(rt2x00dev, RT3390)) {+		value = rt2x00_get_field16(eeprom,+				EEPROM_NIC_CONF1_ANT_DIVERSITY);+		switch (value) {+		case 0:+		case 1:+		case 2:+			rt2x00dev->default_ant.tx = ANTENNA_A;+			rt2x00dev->default_ant.rx = ANTENNA_A;+			break;+		case 3:+			rt2x00dev->default_ant.tx = ANTENNA_A;+			rt2x00dev->default_ant.rx = ANTENNA_B;+			break;+		}+	} else {+		rt2x00dev->default_ant.tx = ANTENNA_A;+		rt2x00dev->default_ant.rx = ANTENNA_A;+	}++	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390R)) {+		rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY; /* Unused */+		rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY; /* Unused */+	}++	/*+	 * Determine external LNA informations.+	 */+	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G))+		__set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);+	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G))+		__set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);++	/*+	 * Detect if this device has an hardware controlled radio.+	 */+	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_HW_RADIO))+		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);++	/*+	 * Detect if this device has Bluetooth co-existence.+	 */+	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST))+		__set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags);++	/*+	 * Read frequency offset and RF programming sequence.+	 */+	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);+	rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);++	/*+	 * Store led settings, for correct led behaviour.+	 */+#ifdef CONFIG_RT2X00_LIB_LEDS+	rt2800_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);+	rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);+	rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);++	rt2x00dev->led_mcu_reg = eeprom;+#endif /* CONFIG_RT2X00_LIB_LEDS */++	/*+	 * Check if support EIRP tx power limit feature.+	 */+	rt2x00_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, &eeprom);++	if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) <+					EIRP_MAX_TX_POWER_LIMIT)+		__set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags);++	return 0;+}++/*+ * RF value list for rt28xx+ * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750)+ */+static const struct rf_channel rf_vals[] = {+	{ 1,  0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b },+	{ 2,  0x18402ecc, 0x184c0786, 0x18168a55, 0x1800519f },+	{ 3,  0x18402ecc, 0x184c078a, 0x18168a55, 0x1800518b },+	{ 4,  0x18402ecc, 0x184c078a, 0x18168a55, 0x1800519f },+	{ 5,  0x18402ecc, 0x184c078e, 0x18168a55, 0x1800518b },+	{ 6,  0x18402ecc, 0x184c078e, 0x18168a55, 0x1800519f },+	{ 7,  0x18402ecc, 0x184c0792, 0x18168a55, 0x1800518b },+	{ 8,  0x18402ecc, 0x184c0792, 0x18168a55, 0x1800519f },+	{ 9,  0x18402ecc, 0x184c0796, 0x18168a55, 0x1800518b },+	{ 10, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800519f },+	{ 11, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800518b },+	{ 12, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800519f },+	{ 13, 0x18402ecc, 0x184c079e, 0x18168a55, 0x1800518b },+	{ 14, 0x18402ecc, 0x184c07a2, 0x18168a55, 0x18005193 },++	/* 802.11 UNI / HyperLan 2 */+	{ 36, 0x18402ecc, 0x184c099a, 0x18158a55, 0x180ed1a3 },+	{ 38, 0x18402ecc, 0x184c099e, 0x18158a55, 0x180ed193 },+	{ 40, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed183 },+	{ 44, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed1a3 },+	{ 46, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed18b },+	{ 48, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed19b },+	{ 52, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed193 },+	{ 54, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed1a3 },+	{ 56, 0x18402ec8, 0x184c068e, 0x18158a55, 0x180ed18b },+	{ 60, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed183 },+	{ 62, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed193 },+	{ 64, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed1a3 },++	/* 802.11 HyperLan 2 */+	{ 100, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed783 },+	{ 102, 0x18402ec8, 0x184c06b2, 0x18578a55, 0x180ed793 },+	{ 104, 0x18402ec8, 0x185c06b2, 0x18578a55, 0x180ed1a3 },+	{ 108, 0x18402ecc, 0x185c0a32, 0x18578a55, 0x180ed193 },+	{ 110, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed183 },+	{ 112, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed19b },+	{ 116, 0x18402ecc, 0x184c0a3a, 0x18178a55, 0x180ed1a3 },+	{ 118, 0x18402ecc, 0x184c0a3e, 0x18178a55, 0x180ed193 },+	{ 120, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed183 },+	{ 124, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed193 },+	{ 126, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed15b },+	{ 128, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed1a3 },+	{ 132, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed18b },+	{ 134, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed193 },+	{ 136, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed19b },+	{ 140, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed183 },++	/* 802.11 UNII */+	{ 149, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed1a7 },+	{ 151, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed187 },+	{ 153, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed18f },+	{ 157, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed19f },+	{ 159, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed1a7 },+	{ 161, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed187 },+	{ 165, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed197 },+	{ 167, 0x18402ec4, 0x184c03d2, 0x18179855, 0x1815531f },+	{ 169, 0x18402ec4, 0x184c03d2, 0x18179855, 0x18155327 },+	{ 171, 0x18402ec4, 0x184c03d6, 0x18179855, 0x18155307 },+	{ 173, 0x18402ec4, 0x184c03d6, 0x18179855, 0x1815530f },++	/* 802.11 Japan */+	{ 184, 0x15002ccc, 0x1500491e, 0x1509be55, 0x150c0a0b },+	{ 188, 0x15002ccc, 0x15004922, 0x1509be55, 0x150c0a13 },+	{ 192, 0x15002ccc, 0x15004926, 0x1509be55, 0x150c0a1b },+	{ 196, 0x15002ccc, 0x1500492a, 0x1509be55, 0x150c0a23 },+	{ 208, 0x15002ccc, 0x1500493a, 0x1509be55, 0x150c0a13 },+	{ 212, 0x15002ccc, 0x1500493e, 0x1509be55, 0x150c0a1b },+	{ 216, 0x15002ccc, 0x15004982, 0x1509be55, 0x150c0a23 },+};++/*+ * RF value list for rt3xxx+ * Supports: 2.4 GHz (all) & 5.2 GHz (RF3052)+ */+static const struct rf_channel rf_vals_3x[] = {+	{1,  241, 2, 2 },+	{2,  241, 2, 7 },+	{3,  242, 2, 2 },+	{4,  242, 2, 7 },+	{5,  243, 2, 2 },+	{6,  243, 2, 7 },+	{7,  244, 2, 2 },+	{8,  244, 2, 7 },+	{9,  245, 2, 2 },+	{10, 245, 2, 7 },+	{11, 246, 2, 2 },+	{12, 246, 2, 7 },+	{13, 247, 2, 2 },+	{14, 248, 2, 4 },++	/* 802.11 UNI / HyperLan 2 */+	{36, 0x56, 0, 4},+	{38, 0x56, 0, 6},+	{40, 0x56, 0, 8},+	{44, 0x57, 0, 0},+	{46, 0x57, 0, 2},+	{48, 0x57, 0, 4},+	{52, 0x57, 0, 8},+	{54, 0x57, 0, 10},+	{56, 0x58, 0, 0},+	{60, 0x58, 0, 4},+	{62, 0x58, 0, 6},+	{64, 0x58, 0, 8},++	/* 802.11 HyperLan 2 */+	{100, 0x5b, 0, 8},+	{102, 0x5b, 0, 10},+	{104, 0x5c, 0, 0},+	{108, 0x5c, 0, 4},+	{110, 0x5c, 0, 6},+	{112, 0x5c, 0, 8},+	{116, 0x5d, 0, 0},+	{118, 0x5d, 0, 2},+	{120, 0x5d, 0, 4},+	{124, 0x5d, 0, 8},+	{126, 0x5d, 0, 10},+	{128, 0x5e, 0, 0},+	{132, 0x5e, 0, 4},+	{134, 0x5e, 0, 6},+	{136, 0x5e, 0, 8},+	{140, 0x5f, 0, 0},++	/* 802.11 UNII */+	{149, 0x5f, 0, 9},+	{151, 0x5f, 0, 11},+	{153, 0x60, 0, 1},+	{157, 0x60, 0, 5},+	{159, 0x60, 0, 7},+	{161, 0x60, 0, 9},+	{165, 0x61, 0, 1},+	{167, 0x61, 0, 3},+	{169, 0x61, 0, 5},+	{171, 0x61, 0, 7},+	{173, 0x61, 0, 9},+};++static const struct rf_channel rf_vals_5592_xtal20[] = {+	/* Channel, N, K, mod, R */+	{1, 482, 4, 10, 3},+	{2, 483, 4, 10, 3},+	{3, 484, 4, 10, 3},+	{4, 485, 4, 10, 3},+	{5, 486, 4, 10, 3},+	{6, 487, 4, 10, 3},+	{7, 488, 4, 10, 3},+	{8, 489, 4, 10, 3},+	{9, 490, 4, 10, 3},+	{10, 491, 4, 10, 3},+	{11, 492, 4, 10, 3},+	{12, 493, 4, 10, 3},+	{13, 494, 4, 10, 3},+	{14, 496, 8, 10, 3},+	{36, 172, 8, 12, 1},+	{38, 173, 0, 12, 1},+	{40, 173, 4, 12, 1},+	{42, 173, 8, 12, 1},+	{44, 174, 0, 12, 1},+	{46, 174, 4, 12, 1},+	{48, 174, 8, 12, 1},+	{50, 175, 0, 12, 1},+	{52, 175, 4, 12, 1},+	{54, 175, 8, 12, 1},+	{56, 176, 0, 12, 1},+	{58, 176, 4, 12, 1},+	{60, 176, 8, 12, 1},+	{62, 177, 0, 12, 1},+	{64, 177, 4, 12, 1},+	{100, 183, 4, 12, 1},+	{102, 183, 8, 12, 1},+	{104, 184, 0, 12, 1},+	{106, 184, 4, 12, 1},+	{108, 184, 8, 12, 1},+	{110, 185, 0, 12, 1},+	{112, 185, 4, 12, 1},+	{114, 185, 8, 12, 1},+	{116, 186, 0, 12, 1},+	{118, 186, 4, 12, 1},+	{120, 186, 8, 12, 1},+	{122, 187, 0, 12, 1},+	{124, 187, 4, 12, 1},+	{126, 187, 8, 12, 1},+	{128, 188, 0, 12, 1},+	{130, 188, 4, 12, 1},+	{132, 188, 8, 12, 1},+	{134, 189, 0, 12, 1},+	{136, 189, 4, 12, 1},+	{138, 189, 8, 12, 1},+	{140, 190, 0, 12, 1},+	{149, 191, 6, 12, 1},+	{151, 191, 10, 12, 1},+	{153, 192, 2, 12, 1},+	{155, 192, 6, 12, 1},+	{157, 192, 10, 12, 1},+	{159, 193, 2, 12, 1},+	{161, 193, 6, 12, 1},+	{165, 194, 2, 12, 1},+	{184, 164, 0, 12, 1},+	{188, 164, 4, 12, 1},+	{192, 165, 8, 12, 1},+	{196, 166, 0, 12, 1},+};++static const struct rf_channel rf_vals_5592_xtal40[] = {+	/* Channel, N, K, mod, R */+	{1, 241, 2, 10, 3},+	{2, 241, 7, 10, 3},+	{3, 242, 2, 10, 3},+	{4, 242, 7, 10, 3},+	{5, 243, 2, 10, 3},+	{6, 243, 7, 10, 3},+	{7, 244, 2, 10, 3},+	{8, 244, 7, 10, 3},+	{9, 245, 2, 10, 3},+	{10, 245, 7, 10, 3},+	{11, 246, 2, 10, 3},+	{12, 246, 7, 10, 3},+	{13, 247, 2, 10, 3},+	{14, 248, 4, 10, 3},+	{36, 86, 4, 12, 1},+	{38, 86, 6, 12, 1},+	{40, 86, 8, 12, 1},+	{42, 86, 10, 12, 1},+	{44, 87, 0, 12, 1},+	{46, 87, 2, 12, 1},+	{48, 87, 4, 12, 1},+	{50, 87, 6, 12, 1},+	{52, 87, 8, 12, 1},+	{54, 87, 10, 12, 1},+	{56, 88, 0, 12, 1},+	{58, 88, 2, 12, 1},+	{60, 88, 4, 12, 1},+	{62, 88, 6, 12, 1},+	{64, 88, 8, 12, 1},+	{100, 91, 8, 12, 1},+	{102, 91, 10, 12, 1},+	{104, 92, 0, 12, 1},+	{106, 92, 2, 12, 1},+	{108, 92, 4, 12, 1},+	{110, 92, 6, 12, 1},+	{112, 92, 8, 12, 1},+	{114, 92, 10, 12, 1},+	{116, 93, 0, 12, 1},+	{118, 93, 2, 12, 1},+	{120, 93, 4, 12, 1},+	{122, 93, 6, 12, 1},+	{124, 93, 8, 12, 1},+	{126, 93, 10, 12, 1},+	{128, 94, 0, 12, 1},+	{130, 94, 2, 12, 1},+	{132, 94, 4, 12, 1},+	{134, 94, 6, 12, 1},+	{136, 94, 8, 12, 1},+	{138, 94, 10, 12, 1},+	{140, 95, 0, 12, 1},+	{149, 95, 9, 12, 1},+	{151, 95, 11, 12, 1},+	{153, 96, 1, 12, 1},+	{155, 96, 3, 12, 1},+	{157, 96, 5, 12, 1},+	{159, 96, 7, 12, 1},+	{161, 96, 9, 12, 1},+	{165, 97, 1, 12, 1},+	{184, 82, 0, 12, 1},+	{188, 82, 4, 12, 1},+	{192, 82, 8, 12, 1},+	{196, 83, 0, 12, 1},+};++static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)+{+	struct hw_mode_spec *spec = &rt2x00dev->spec;+	struct channel_info *info;+	char *default_power1;+	char *default_power2;+	unsigned int i;+	u16 eeprom;+	u32 reg;++	/*+	 * Disable powersaving as default on PCI devices.+	 */+	if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))+		rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;++	/*+	 * Initialize all hw fields.+	 */+	rt2x00dev->hw->flags =+	    IEEE80211_HW_SIGNAL_DBM |+	    IEEE80211_HW_SUPPORTS_PS |+	    IEEE80211_HW_PS_NULLFUNC_STACK |+	    IEEE80211_HW_AMPDU_AGGREGATION |+	    IEEE80211_HW_REPORTS_TX_ACK_STATUS |+	    IEEE80211_HW_SUPPORTS_HT_CCK_RATES;++	/*+	 * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices+	 * unless we are capable of sending the buffered frames out after the+	 * DTIM transmission using rt2x00lib_beacondone. This will send out+	 * multicast and broadcast traffic immediately instead of buffering it+	 * infinitly and thus dropping it after some time.+	 */+	if (!rt2x00_is_usb(rt2x00dev))+		rt2x00dev->hw->flags |=+			IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;++	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);+	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,+				rt2x00_eeprom_addr(rt2x00dev,+						   EEPROM_MAC_ADDR_0));++	/*+	 * As rt2800 has a global fallback table we cannot specify+	 * more then one tx rate per frame but since the hw will+	 * try several rates (based on the fallback table) we should+	 * initialize max_report_rates to the maximum number of rates+	 * we are going to try. Otherwise mac80211 will truncate our+	 * reported tx rates and the rc algortihm will end up with+	 * incorrect data.+	 */+	rt2x00dev->hw->max_rates = 1;+	rt2x00dev->hw->max_report_rates = 7;+	rt2x00dev->hw->max_rate_tries = 1;++	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);++	/*+	 * Initialize hw_mode information.+	 */+	spec->supported_bands = SUPPORT_BAND_2GHZ;+	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;++	if (rt2x00_rf(rt2x00dev, RF2820) ||+	    rt2x00_rf(rt2x00dev, RF2720)) {+		spec->num_channels = 14;+		spec->channels = rf_vals;+	} else if (rt2x00_rf(rt2x00dev, RF2850) ||+		   rt2x00_rf(rt2x00dev, RF2750)) {+		spec->supported_bands |= SUPPORT_BAND_5GHZ;+		spec->num_channels = ARRAY_SIZE(rf_vals);+		spec->channels = rf_vals;+	} else if (rt2x00_rf(rt2x00dev, RF3020) ||+		   rt2x00_rf(rt2x00dev, RF2020) ||+		   rt2x00_rf(rt2x00dev, RF3021) ||+		   rt2x00_rf(rt2x00dev, RF3022) ||+		   rt2x00_rf(rt2x00dev, RF3290) ||+		   rt2x00_rf(rt2x00dev, RF3320) ||+		   rt2x00_rf(rt2x00dev, RF3322) ||+		   rt2x00_rf(rt2x00dev, RF5360) ||+		   rt2x00_rf(rt2x00dev, RF5370) ||+		   rt2x00_rf(rt2x00dev, RF5372) ||+		   rt2x00_rf(rt2x00dev, RF5390) ||+		   rt2x00_rf(rt2x00dev, RF5392)) {+		spec->num_channels = 14;+		spec->channels = rf_vals_3x;+	} else if (rt2x00_rf(rt2x00dev, RF3052)) {+		spec->supported_bands |= SUPPORT_BAND_5GHZ;+		spec->num_channels = ARRAY_SIZE(rf_vals_3x);+		spec->channels = rf_vals_3x;+	} else if (rt2x00_rf(rt2x00dev, RF5592)) {+		spec->supported_bands |= SUPPORT_BAND_5GHZ;++		rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, ®);+		if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) {+			spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal40);+			spec->channels = rf_vals_5592_xtal40;+		} else {+			spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal20);+			spec->channels = rf_vals_5592_xtal20;+		}+	}++	if (WARN_ON_ONCE(!spec->channels))+		return -ENODEV;++	/*+	 * Initialize HT information.+	 */+	if (!rt2x00_rf(rt2x00dev, RF2020))+		spec->ht.ht_supported = true;+	else+		spec->ht.ht_supported = false;++	spec->ht.cap =+	    IEEE80211_HT_CAP_SUP_WIDTH_20_40 |+	    IEEE80211_HT_CAP_GRN_FLD |+	    IEEE80211_HT_CAP_SGI_20 |+	    IEEE80211_HT_CAP_SGI_40;++	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) >= 2)+		spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC;++	spec->ht.cap |=+	    rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) <<+		IEEE80211_HT_CAP_RX_STBC_SHIFT;++	spec->ht.ampdu_factor = 3;+	spec->ht.ampdu_density = 4;+	spec->ht.mcs.tx_params =+	    IEEE80211_HT_MCS_TX_DEFINED |+	    IEEE80211_HT_MCS_TX_RX_DIFF |+	    ((rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) - 1) <<+		IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);++	switch (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH)) {+	case 3:+		spec->ht.mcs.rx_mask[2] = 0xff;+	case 2:+		spec->ht.mcs.rx_mask[1] = 0xff;+	case 1:+		spec->ht.mcs.rx_mask[0] = 0xff;+		spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */+		break;+	}++	/*+	 * Create channel information array+	 */+	info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);+	if (!info)+		return -ENOMEM;++	spec->channels_info = info;++	default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);+	default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);++	for (i = 0; i < 14; i++) {+		info[i].default_power1 = default_power1[i];+		info[i].default_power2 = default_power2[i];+	}++	if (spec->num_channels > 14) {+		default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1);+		default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);++		for (i = 14; i < spec->num_channels; i++) {+			info[i].default_power1 = default_power1[i - 14];+			info[i].default_power2 = default_power2[i - 14];+		}+	}++	switch (rt2x00dev->chip.rf) {+	case RF2020:+	case RF3020:+	case RF3021:+	case RF3022:+	case RF3320:+	case RF3052:+	case RF3290:+	case RF5360:+	case RF5370:+	case RF5372:+	case RF5390:+	case RF5392:+		__set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags);+		break;+	}++	return 0;+}++static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev)+{+	u32 reg;+	u32 rt;+	u32 rev;++	if (rt2x00_rt(rt2x00dev, RT3290))+		rt2800_register_read(rt2x00dev, MAC_CSR0_3290, ®);+	else+		rt2800_register_read(rt2x00dev, MAC_CSR0, ®);++	rt = rt2x00_get_field32(reg, MAC_CSR0_CHIPSET);+	rev = rt2x00_get_field32(reg, MAC_CSR0_REVISION);++	switch (rt) {+	case RT2860:+	case RT2872:+	case RT2883:+	case RT3070:+	case RT3071:+	case RT3090:+	case RT3290:+	case RT3352:+	case RT3390:+	case RT3572:+	case RT5390:+	case RT5392:+	case RT5592:+		break;+	default:+		rt2x00_err(rt2x00dev, "Invalid RT chipset 0x%04x, rev %04x detected\n",+			   rt, rev);+		return -ENODEV;+	}++	rt2x00_set_rt(rt2x00dev, rt, rev);++	return 0;+}++int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)+{+	int retval;+	u32 reg;++	retval = rt2800_probe_rt(rt2x00dev);+	if (retval)+		return retval;++	/*+	 * Allocate eeprom data.+	 */+	retval = rt2800_validate_eeprom(rt2x00dev);+	if (retval)+		return retval;++	retval = rt2800_init_eeprom(rt2x00dev);+	if (retval)+		return retval;++	/*+	 * Enable rfkill polling by setting GPIO direction of the+	 * rfkill switch GPIO pin correctly.+	 */+	rt2800_register_read(rt2x00dev, GPIO_CTRL, ®);+	rt2x00_set_field32(®, GPIO_CTRL_DIR2, 1);+	rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);++	/*+	 * Initialize hw specifications.+	 */+	retval = rt2800_probe_hw_mode(rt2x00dev);+	if (retval)+		return retval;++	/*+	 * Set device capabilities.+	 */+	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);+	__set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);+	if (!rt2x00_is_usb(rt2x00dev))+		__set_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags);++	/*+	 * Set device requirements.+	 */+	if (!rt2x00_is_soc(rt2x00dev))+		__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);+	__set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags);+	__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);+	if (!rt2800_hwcrypt_disabled(rt2x00dev))+		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);+	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);+	__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);+	if (rt2x00_is_usb(rt2x00dev))+		__set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);+	else {+		__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);+		__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);+	}++	/*+	 * Set the rssi offset.+	 */+	rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;++	return 0;+}+EXPORT_SYMBOL_GPL(rt2800_probe_hw);++/*+ * IEEE80211 stack callback functions.+ */+void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32,+			 u16 *iv16)+{+	struct rt2x00_dev *rt2x00dev = hw->priv;+	struct mac_iveiv_entry iveiv_entry;+	u32 offset;++	offset = MAC_IVEIV_ENTRY(hw_key_idx);+	rt2800_register_multiread(rt2x00dev, offset,+				      &iveiv_entry, sizeof(iveiv_entry));++	memcpy(iv16, &iveiv_entry.iv[0], sizeof(*iv16));+	memcpy(iv32, &iveiv_entry.iv[4], sizeof(*iv32));+}+EXPORT_SYMBOL_GPL(rt2800_get_tkip_seq);++int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value)+{+	struct rt2x00_dev *rt2x00dev = hw->priv;+	u32 reg;+	bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD);++	rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®);+	rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, value);+	rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg);++	rt2800_register_read(rt2x00dev, CCK_PROT_CFG, ®);+	rt2x00_set_field32(®, CCK_PROT_CFG_RTS_TH_EN, enabled);+	rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg);++	rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®);+	rt2x00_set_field32(®, OFDM_PROT_CFG_RTS_TH_EN, enabled);+	rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);++	rt2800_register_read(rt2x00dev, MM20_PROT_CFG, ®);+	rt2x00_set_field32(®, MM20_PROT_CFG_RTS_TH_EN, enabled);+	rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);++	rt2800_register_read(rt2x00dev, MM40_PROT_CFG, ®);+	rt2x00_set_field32(®, MM40_PROT_CFG_RTS_TH_EN, enabled);+	rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);++	rt2800_register_read(rt2x00dev, GF20_PROT_CFG, ®);+	rt2x00_set_field32(®, GF20_PROT_CFG_RTS_TH_EN, enabled);+	rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);++	rt2800_register_read(rt2x00dev, GF40_PROT_CFG, ®);+	rt2x00_set_field32(®, GF40_PROT_CFG_RTS_TH_EN, enabled);+	rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);++	return 0;+}+EXPORT_SYMBOL_GPL(rt2800_set_rts_threshold);++int rt2800_conf_tx(struct ieee80211_hw *hw,+		   struct ieee80211_vif *vif, u16 queue_idx,+		   const struct ieee80211_tx_queue_params *params)+{+	struct rt2x00_dev *rt2x00dev = hw->priv;+	struct data_queue *queue;+	struct rt2x00_field32 field;+	int retval;+	u32 reg;+	u32 offset;++	/*+	 * First pass the configuration through rt2x00lib, that will+	 * update the queue settings and validate the input. After that+	 * we are free to update the registers based on the value+	 * in the queue parameter.+	 */+	retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);+	if (retval)+		return retval;++	/*+	 * We only need to perform additional register initialization+	 * for WMM queues/+	 */+	if (queue_idx >= 4)+		return 0;++	queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);++	/* Update WMM TXOP register */+	offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2)));+	field.bit_offset = (queue_idx & 1) * 16;+	field.bit_mask = 0xffff << field.bit_offset;++	rt2800_register_read(rt2x00dev, offset, ®);+	rt2x00_set_field32(®, field, queue->txop);+	rt2800_register_write(rt2x00dev, offset, reg);++	/* Update WMM registers */+	field.bit_offset = queue_idx * 4;+	field.bit_mask = 0xf << field.bit_offset;++	rt2800_register_read(rt2x00dev, WMM_AIFSN_CFG, ®);+	rt2x00_set_field32(®, field, queue->aifs);+	rt2800_register_write(rt2x00dev, WMM_AIFSN_CFG, reg);++	rt2800_register_read(rt2x00dev, WMM_CWMIN_CFG, ®);+	rt2x00_set_field32(®, field, queue->cw_min);+	rt2800_register_write(rt2x00dev, WMM_CWMIN_CFG, reg);++	rt2800_register_read(rt2x00dev, WMM_CWMAX_CFG, ®);+	rt2x00_set_field32(®, field, queue->cw_max);+	rt2800_register_write(rt2x00dev, WMM_CWMAX_CFG, reg);++	/* Update EDCA registers */+	offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx);++	rt2800_register_read(rt2x00dev, offset, ®);+	rt2x00_set_field32(®, EDCA_AC0_CFG_TX_OP, queue->txop);+	rt2x00_set_field32(®, EDCA_AC0_CFG_AIFSN, queue->aifs);+	rt2x00_set_field32(®, EDCA_AC0_CFG_CWMIN, queue->cw_min);+	rt2x00_set_field32(®, EDCA_AC0_CFG_CWMAX, queue->cw_max);+	rt2800_register_write(rt2x00dev, offset, reg);++	return 0;+}+EXPORT_SYMBOL_GPL(rt2800_conf_tx);++u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)+{+	struct rt2x00_dev *rt2x00dev = hw->priv;+	u64 tsf;+	u32 reg;++	rt2800_register_read(rt2x00dev, TSF_TIMER_DW1, ®);+	tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32;+	rt2800_register_read(rt2x00dev, TSF_TIMER_DW0, ®);+	tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD);++	return tsf;+}+EXPORT_SYMBOL_GPL(rt2800_get_tsf);++int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,+			enum ieee80211_ampdu_mlme_action action,+			struct ieee80211_sta *sta, u16 tid, u16 *ssn,+			u8 buf_size)+{+	struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv;+	int ret = 0;++	/*+	 * Don't allow aggregation for stations the hardware isn't aware+	 * of because tx status reports for frames to an unknown station+	 * always contain wcid=255 and thus we can't distinguish between+	 * multiple stations which leads to unwanted situations when the+	 * hw reorders frames due to aggregation.+	 */+	if (sta_priv->wcid < 0)+		return 1;++	switch (action) {+	case IEEE80211_AMPDU_RX_START:+	case IEEE80211_AMPDU_RX_STOP:+		/*+		 * The hw itself takes care of setting up BlockAck mechanisms.+		 * So, we only have to allow mac80211 to nagotiate a BlockAck+		 * agreement. Once that is done, the hw will BlockAck incoming+		 * AMPDUs without further setup.+		 */+		break;+	case IEEE80211_AMPDU_TX_START:+		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);+		break;+	case IEEE80211_AMPDU_TX_STOP_CONT:+	case IEEE80211_AMPDU_TX_STOP_FLUSH:+	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:+		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);+		break;+	case IEEE80211_AMPDU_TX_OPERATIONAL:+		break;+	default:+		rt2x00_warn((struct rt2x00_dev *)hw->priv,+			    "Unknown AMPDU action\n");+	}++	return ret;+}+EXPORT_SYMBOL_GPL(rt2800_ampdu_action);++int rt2800_get_survey(struct ieee80211_hw *hw, int idx,+		      struct survey_info *survey)+{+	struct rt2x00_dev *rt2x00dev = hw->priv;+	struct ieee80211_conf *conf = &hw->conf;+	u32 idle, busy, busy_ext;++	if (idx != 0)+		return -ENOENT;++	survey->channel = conf->chandef.chan;++	rt2800_register_read(rt2x00dev, CH_IDLE_STA, &idle);+	rt2800_register_read(rt2x00dev, CH_BUSY_STA, &busy);+	rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &busy_ext);++	if (idle || busy) {+		survey->filled = SURVEY_INFO_CHANNEL_TIME |+				 SURVEY_INFO_CHANNEL_TIME_BUSY |+				 SURVEY_INFO_CHANNEL_TIME_EXT_BUSY;++		survey->channel_time = (idle + busy) / 1000;+		survey->channel_time_busy = busy / 1000;+		survey->channel_time_ext_busy = busy_ext / 1000;+	}++	if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))+		survey->filled |= SURVEY_INFO_IN_USE;++	return 0;++}+EXPORT_SYMBOL_GPL(rt2800_get_survey);++MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz");+MODULE_VERSION(DRV_VERSION);+MODULE_DESCRIPTION("Ralink RT2800 library");+MODULE_LICENSE("GPL");diff -Nur linux-3.11.10.orig/drivers/spi/Kconfig linux-3.11.10/drivers/spi/Kconfig--- linux-3.11.10.orig/drivers/spi/Kconfig	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/spi/Kconfig	2014-02-07 19:57:29.000000000 +0100@@ -86,6 +86,14 @@ 	  is for the regular SPI controller. Slave mode operation is not also 	  not supported. +config SPI_BCM2708+	tristate "BCM2708 SPI controller driver (SPI0)"+	depends on MACH_BCM2708+	help+	  This selects a driver for the Broadcom BCM2708 SPI master (SPI0). This+	  driver is not compatible with the "Universal SPI Master" or the SPI slave+	  device.+ config SPI_BFIN5XX 	tristate "SPI controller driver for ADI Blackfin5xx" 	depends on BLACKFINdiff -Nur linux-3.11.10.orig/drivers/spi/Makefile linux-3.11.10/drivers/spi/Makefile--- linux-3.11.10.orig/drivers/spi/Makefile	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/spi/Makefile	2014-02-07 19:57:29.000000000 +0100@@ -17,6 +17,7 @@ obj-$(CONFIG_SPI_BCM2835)		+= spi-bcm2835.o obj-$(CONFIG_SPI_BCM63XX)		+= spi-bcm63xx.o obj-$(CONFIG_SPI_BFIN5XX)		+= spi-bfin5xx.o+obj-$(CONFIG_SPI_BCM2708)		+= spi-bcm2708.o obj-$(CONFIG_SPI_BFIN_SPORT)		+= spi-bfin-sport.o obj-$(CONFIG_SPI_BITBANG)		+= spi-bitbang.o obj-$(CONFIG_SPI_BUTTERFLY)		+= spi-butterfly.odiff -Nur linux-3.11.10.orig/drivers/spi/spi-bcm2708.c linux-3.11.10/drivers/spi/spi-bcm2708.c--- linux-3.11.10.orig/drivers/spi/spi-bcm2708.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/spi/spi-bcm2708.c	2014-02-07 19:57:29.000000000 +0100@@ -0,0 +1,626 @@+/*+ * Driver for Broadcom BCM2708 SPI Controllers+ *+ * Copyright (C) 2012 Chris Boot+ *+ * This driver is inspired by:+ * spi-ath79.c, Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>+ * spi-atmel.c, Copyright (C) 2006 Atmel Corporation+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.+ */++#include <linux/kernel.h>+#include <linux/module.h>+#include <linux/spinlock.h>+#include <linux/clk.h>+#include <linux/err.h>+#include <linux/platform_device.h>+#include <linux/io.h>+#include <linux/spi/spi.h>+#include <linux/interrupt.h>+#include <linux/delay.h>+#include <linux/log2.h>+#include <linux/sched.h>+#include <linux/wait.h>++/* SPI register offsets */+#define SPI_CS			0x00+#define SPI_FIFO		0x04+#define SPI_CLK			0x08+#define SPI_DLEN		0x0c+#define SPI_LTOH		0x10+#define SPI_DC			0x14++/* Bitfields in CS */+#define SPI_CS_LEN_LONG		0x02000000+#define SPI_CS_DMA_LEN		0x01000000+#define SPI_CS_CSPOL2		0x00800000+#define SPI_CS_CSPOL1		0x00400000+#define SPI_CS_CSPOL0		0x00200000+#define SPI_CS_RXF		0x00100000+#define SPI_CS_RXR		0x00080000+#define SPI_CS_TXD		0x00040000+#define SPI_CS_RXD		0x00020000+#define SPI_CS_DONE		0x00010000+#define SPI_CS_LEN		0x00002000+#define SPI_CS_REN		0x00001000+#define SPI_CS_ADCS		0x00000800+#define SPI_CS_INTR		0x00000400+#define SPI_CS_INTD		0x00000200+#define SPI_CS_DMAEN		0x00000100+#define SPI_CS_TA		0x00000080+#define SPI_CS_CSPOL		0x00000040+#define SPI_CS_CLEAR_RX		0x00000020+#define SPI_CS_CLEAR_TX		0x00000010+#define SPI_CS_CPOL		0x00000008+#define SPI_CS_CPHA		0x00000004+#define SPI_CS_CS_10		0x00000002+#define SPI_CS_CS_01		0x00000001++#define SPI_TIMEOUT_MS	150++#define DRV_NAME	"bcm2708_spi"++struct bcm2708_spi {+	spinlock_t lock;+	void __iomem *base;+	int irq;+	struct clk *clk;+	bool stopping;++	struct list_head queue;+	struct workqueue_struct *workq;+	struct work_struct work;+	struct completion done;++	const u8 *tx_buf;+	u8 *rx_buf;+	int len;+};++struct bcm2708_spi_state {+	u32 cs;+	u16 cdiv;+};++/*+ * This function sets the ALT mode on the SPI pins so that we can use them with+ * the SPI hardware.+ *+ * FIXME: This is a hack. Use pinmux / pinctrl.+ */+static void bcm2708_init_pinmode(void)+{+#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))+#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))++	int pin;+	u32 *gpio = ioremap(0x20200000, SZ_16K);++	/* SPI is on GPIO 7..11 */+	for (pin = 7; pin <= 11; pin++) {+		INP_GPIO(pin);		/* set mode to GPIO input first */+		SET_GPIO_ALT(pin, 0);	/* set mode to ALT 0 */+	}++	iounmap(gpio);++#undef INP_GPIO+#undef SET_GPIO_ALT+}++static inline u32 bcm2708_rd(struct bcm2708_spi *bs, unsigned reg)+{+	return readl(bs->base + reg);+}++static inline void bcm2708_wr(struct bcm2708_spi *bs, unsigned reg, u32 val)+{+	writel(val, bs->base + reg);+}++static inline void bcm2708_rd_fifo(struct bcm2708_spi *bs, int len)+{+	u8 byte;++	while (len--) {+		byte = bcm2708_rd(bs, SPI_FIFO);+		if (bs->rx_buf)+			*bs->rx_buf++ = byte;+	}+}++static inline void bcm2708_wr_fifo(struct bcm2708_spi *bs, int len)+{+	u8 byte;+	u16 val;++	if (len > bs->len)+		len = bs->len;++	if (unlikely(bcm2708_rd(bs, SPI_CS) & SPI_CS_LEN)) {+		/* LoSSI mode */+		if (unlikely(len % 2)) {+			printk(KERN_ERR"bcm2708_wr_fifo: length must be even, skipping.\n");+			bs->len = 0;+			return;+		}+		while (len) {+			if (bs->tx_buf) {+				val = *(const u16 *)bs->tx_buf;+				bs->tx_buf += 2;+			} else+				val = 0;+			bcm2708_wr(bs, SPI_FIFO, val);+			bs->len -= 2;+			len -= 2;+		}+		return;+	}++	while (len--) {+		byte = bs->tx_buf ? *bs->tx_buf++ : 0;+		bcm2708_wr(bs, SPI_FIFO, byte);+		bs->len--;+	}+}++static irqreturn_t bcm2708_spi_interrupt(int irq, void *dev_id)+{+	struct spi_master *master = dev_id;+	struct bcm2708_spi *bs = spi_master_get_devdata(master);+	u32 cs;++	spin_lock(&bs->lock);++	cs = bcm2708_rd(bs, SPI_CS);++	if (cs & SPI_CS_DONE) {+		if (bs->len) { /* first interrupt in a transfer */+			/* fill the TX fifo with up to 16 bytes */+			bcm2708_wr_fifo(bs, 16);+		} else { /* transfer complete */+			/* disable interrupts */+			cs &= ~(SPI_CS_INTR | SPI_CS_INTD);+			bcm2708_wr(bs, SPI_CS, cs);++			/* drain RX FIFO */+			while (cs & SPI_CS_RXD) {+				bcm2708_rd_fifo(bs, 1);+				cs = bcm2708_rd(bs, SPI_CS);+			}++			/* wake up our bh */+			complete(&bs->done);+		}+	} else if (cs & SPI_CS_RXR) {+		/* read 12 bytes of data */+		bcm2708_rd_fifo(bs, 12);++		/* write up to 12 bytes */+		bcm2708_wr_fifo(bs, 12);+	}++	spin_unlock(&bs->lock);++	return IRQ_HANDLED;+}++static int bcm2708_setup_state(struct spi_master *master,+		struct device *dev, struct bcm2708_spi_state *state,+		u32 hz, u8 csel, u8 mode, u8 bpw)+{+	struct bcm2708_spi *bs = spi_master_get_devdata(master);+	int cdiv;+	unsigned long bus_hz;+	u32 cs = 0;++	bus_hz = clk_get_rate(bs->clk);++	if (hz >= bus_hz) {+		cdiv = 2; /* bus_hz / 2 is as fast as we can go */+	} else if (hz) {+		cdiv = DIV_ROUND_UP(bus_hz, hz);++		/* CDIV must be a power of 2, so round up */+		cdiv = roundup_pow_of_two(cdiv);++		if (cdiv > 65536) {+			dev_dbg(dev,+				"setup: %d Hz too slow, cdiv %u; min %ld Hz\n",+				hz, cdiv, bus_hz / 65536);+			return -EINVAL;+		} else if (cdiv == 65536) {+			cdiv = 0;+		} else if (cdiv == 1) {+			cdiv = 2; /* 1 gets rounded down to 0; == 65536 */+		}+	} else {+		cdiv = 0;+	}++	switch (bpw) {+	case 8:+		break;+	case 9:+		/* Reading in LoSSI mode is a special case. See 'BCM2835 ARM Peripherals' datasheet */+		cs |= SPI_CS_LEN;+		break;+	default:+		dev_dbg(dev, "setup: invalid bits_per_word %u (must be 8 or 9)\n",+			bpw);+		return -EINVAL;+	}++	if (mode & SPI_CPOL)+		cs |= SPI_CS_CPOL;+	if (mode & SPI_CPHA)+		cs |= SPI_CS_CPHA;++	if (!(mode & SPI_NO_CS)) {+		if (mode & SPI_CS_HIGH) {+			cs |= SPI_CS_CSPOL;+			cs |= SPI_CS_CSPOL0 << csel;+		}++		cs |= csel;+	} else {+		cs |= SPI_CS_CS_10 | SPI_CS_CS_01;+	}++	if (state) {+		state->cs = cs;+		state->cdiv = cdiv;+		dev_dbg(dev, "setup: want %d Hz; "+			"bus_hz=%lu / cdiv=%u == %lu Hz; "+			"mode %u: cs 0x%08X\n",+			hz, bus_hz, cdiv, bus_hz/cdiv, mode, cs);+	}++	return 0;+}++static int bcm2708_process_transfer(struct bcm2708_spi *bs,+		struct spi_message *msg, struct spi_transfer *xfer)+{+	struct spi_device *spi = msg->spi;+	struct bcm2708_spi_state state, *stp;+	int ret;+	u32 cs;++	if (bs->stopping)+		return -ESHUTDOWN;++	if (xfer->bits_per_word || xfer->speed_hz) {+		ret = bcm2708_setup_state(spi->master, &spi->dev, &state,+			xfer->speed_hz ? xfer->speed_hz : spi->max_speed_hz,+			spi->chip_select, spi->mode,+			xfer->bits_per_word ? xfer->bits_per_word :+				spi->bits_per_word);+		if (ret)+			return ret;++		stp = &state;+	} else {+		stp = spi->controller_state;+	}++	INIT_COMPLETION(bs->done);+	bs->tx_buf = xfer->tx_buf;+	bs->rx_buf = xfer->rx_buf;+	bs->len = xfer->len;++	cs = stp->cs | SPI_CS_INTR | SPI_CS_INTD | SPI_CS_TA;++	bcm2708_wr(bs, SPI_CLK, stp->cdiv);+	bcm2708_wr(bs, SPI_CS, cs);++	ret = wait_for_completion_timeout(&bs->done,+			msecs_to_jiffies(SPI_TIMEOUT_MS));+	if (ret == 0) {+		dev_err(&spi->dev, "transfer timed out\n");+		return -ETIMEDOUT;+	}++	if (xfer->delay_usecs)+		udelay(xfer->delay_usecs);++	if (list_is_last(&xfer->transfer_list, &msg->transfers) ||+			xfer->cs_change) {+		/* clear TA and interrupt flags */+		bcm2708_wr(bs, SPI_CS, stp->cs);+	}++	msg->actual_length += (xfer->len - bs->len);++	return 0;+}++static void bcm2708_work(struct work_struct *work)+{+	struct bcm2708_spi *bs = container_of(work, struct bcm2708_spi, work);+	unsigned long flags;+	struct spi_message *msg;+	struct spi_transfer *xfer;+	int status = 0;++	spin_lock_irqsave(&bs->lock, flags);+	while (!list_empty(&bs->queue)) {+		msg = list_first_entry(&bs->queue, struct spi_message, queue);+		list_del_init(&msg->queue);+		spin_unlock_irqrestore(&bs->lock, flags);++		list_for_each_entry(xfer, &msg->transfers, transfer_list) {+			status = bcm2708_process_transfer(bs, msg, xfer);+			if (status)+				break;+		}++		msg->status = status;+		msg->complete(msg->context);++		spin_lock_irqsave(&bs->lock, flags);+	}+	spin_unlock_irqrestore(&bs->lock, flags);+}++static int bcm2708_spi_setup(struct spi_device *spi)+{+	struct bcm2708_spi *bs = spi_master_get_devdata(spi->master);+	struct bcm2708_spi_state *state;+	int ret;++	if (bs->stopping)+		return -ESHUTDOWN;++	if (!(spi->mode & SPI_NO_CS) &&+			(spi->chip_select > spi->master->num_chipselect)) {+		dev_dbg(&spi->dev,+			"setup: invalid chipselect %u (%u defined)\n",+			spi->chip_select, spi->master->num_chipselect);+		return -EINVAL;+	}++	state = spi->controller_state;+	if (!state) {+		state = kzalloc(sizeof(*state), GFP_KERNEL);+		if (!state)+			return -ENOMEM;++		spi->controller_state = state;+	}++	ret = bcm2708_setup_state(spi->master, &spi->dev, state,+		spi->max_speed_hz, spi->chip_select, spi->mode,+		spi->bits_per_word);+	if (ret < 0) {+		kfree(state);+		spi->controller_state = NULL;+                return ret;+	}++	dev_dbg(&spi->dev,+		"setup: cd %d: %d Hz, bpw %u, mode 0x%x -> CS=%08x CDIV=%04x\n",+		spi->chip_select, spi->max_speed_hz, spi->bits_per_word,+		spi->mode, state->cs, state->cdiv);++	return 0;+}++static int bcm2708_spi_transfer(struct spi_device *spi, struct spi_message *msg)+{+	struct bcm2708_spi *bs = spi_master_get_devdata(spi->master);+	struct spi_transfer *xfer;+	int ret;+	unsigned long flags;++	if (unlikely(list_empty(&msg->transfers)))+		return -EINVAL;++	if (bs->stopping)+		return -ESHUTDOWN;++	list_for_each_entry(xfer, &msg->transfers, transfer_list) {+		if (!(xfer->tx_buf || xfer->rx_buf) && xfer->len) {+			dev_dbg(&spi->dev, "missing rx or tx buf\n");+			return -EINVAL;+		}++		if (!xfer->bits_per_word || xfer->speed_hz)+			continue;++		ret = bcm2708_setup_state(spi->master, &spi->dev, NULL,+			xfer->speed_hz ? xfer->speed_hz : spi->max_speed_hz,+			spi->chip_select, spi->mode,+			xfer->bits_per_word ? xfer->bits_per_word :+				spi->bits_per_word);+		if (ret)+			return ret;+	}++	msg->status = -EINPROGRESS;+	msg->actual_length = 0;++	spin_lock_irqsave(&bs->lock, flags);+	list_add_tail(&msg->queue, &bs->queue);+	queue_work(bs->workq, &bs->work);+	spin_unlock_irqrestore(&bs->lock, flags);++	return 0;+}++static void bcm2708_spi_cleanup(struct spi_device *spi)+{+	if (spi->controller_state) {+		kfree(spi->controller_state);+		spi->controller_state = NULL;+	}+}++static int bcm2708_spi_probe(struct platform_device *pdev)+{+	struct resource *regs;+	int irq, err = -ENOMEM;+	struct clk *clk;+	struct spi_master *master;+	struct bcm2708_spi *bs;++	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);+	if (!regs) {+		dev_err(&pdev->dev, "could not get IO memory\n");+		return -ENXIO;+	}++	irq = platform_get_irq(pdev, 0);+	if (irq < 0) {+		dev_err(&pdev->dev, "could not get IRQ\n");+		return irq;+	}++	clk = clk_get(&pdev->dev, NULL);+	if (IS_ERR(clk)) {+		dev_err(&pdev->dev, "could not find clk: %ld\n", PTR_ERR(clk));+		return PTR_ERR(clk);+	}++	bcm2708_init_pinmode();++	master = spi_alloc_master(&pdev->dev, sizeof(*bs));+	if (!master) {+		dev_err(&pdev->dev, "spi_alloc_master() failed\n");+		goto out_clk_put;+	}++	/* the spi->mode bits understood by this driver: */+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;++	master->bus_num = pdev->id;+	master->num_chipselect = 3;+	master->setup = bcm2708_spi_setup;+	master->transfer = bcm2708_spi_transfer;+	master->cleanup = bcm2708_spi_cleanup;+	platform_set_drvdata(pdev, master);++	bs = spi_master_get_devdata(master);++	spin_lock_init(&bs->lock);+	INIT_LIST_HEAD(&bs->queue);+	init_completion(&bs->done);+	INIT_WORK(&bs->work, bcm2708_work);++	bs->base = ioremap(regs->start, resource_size(regs));+	if (!bs->base) {+		dev_err(&pdev->dev, "could not remap memory\n");+		goto out_master_put;+	}++	bs->workq = create_singlethread_workqueue(dev_name(&pdev->dev));+	if (!bs->workq) {+		dev_err(&pdev->dev, "could not create workqueue\n");+		goto out_iounmap;+	}++	bs->irq = irq;+	bs->clk = clk;+	bs->stopping = false;++	err = request_irq(irq, bcm2708_spi_interrupt, 0, dev_name(&pdev->dev),+			master);+	if (err) {+		dev_err(&pdev->dev, "could not request IRQ: %d\n", err);+		goto out_workqueue;+	}++	/* initialise the hardware */+	clk_enable(clk);+	bcm2708_wr(bs, SPI_CS, SPI_CS_REN | SPI_CS_CLEAR_RX | SPI_CS_CLEAR_TX);++	err = spi_register_master(master);+	if (err) {+		dev_err(&pdev->dev, "could not register SPI master: %d\n", err);+		goto out_free_irq;+	}++	dev_info(&pdev->dev, "SPI Controller at 0x%08lx (irq %d)\n",+		(unsigned long)regs->start, irq);++	return 0;++out_free_irq:+	free_irq(bs->irq, master);+out_workqueue:+	destroy_workqueue(bs->workq);+out_iounmap:+	iounmap(bs->base);+out_master_put:+	spi_master_put(master);+out_clk_put:+	clk_put(clk);+	return err;+}++static int bcm2708_spi_remove(struct platform_device *pdev)+{+	struct spi_master *master = platform_get_drvdata(pdev);+	struct bcm2708_spi *bs = spi_master_get_devdata(master);++	/* reset the hardware and block queue progress */+	spin_lock_irq(&bs->lock);+	bs->stopping = true;+	bcm2708_wr(bs, SPI_CS, SPI_CS_CLEAR_RX | SPI_CS_CLEAR_TX);+	spin_unlock_irq(&bs->lock);++	flush_work_sync(&bs->work);++	clk_disable(bs->clk);+	clk_put(bs->clk);+	free_irq(bs->irq, master);+	iounmap(bs->base);++	spi_unregister_master(master);++	return 0;+}++static struct platform_driver bcm2708_spi_driver = {+	.driver		= {+		.name	= DRV_NAME,+		.owner	= THIS_MODULE,+	},+	.probe		= bcm2708_spi_probe,+	.remove		= bcm2708_spi_remove,+};+++static int __init bcm2708_spi_init(void)+{+	return platform_driver_probe(&bcm2708_spi_driver, bcm2708_spi_probe);+}+module_init(bcm2708_spi_init);++static void __exit bcm2708_spi_exit(void)+{+	platform_driver_unregister(&bcm2708_spi_driver);+}+module_exit(bcm2708_spi_exit);+++//module_platform_driver(bcm2708_spi_driver);++MODULE_DESCRIPTION("SPI controller driver for Broadcom BCM2708");+MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");+MODULE_LICENSE("GPL v2");+MODULE_ALIAS("platform:" DRV_NAME);diff -Nur linux-3.11.10.orig/drivers/staging/media/lirc/Kconfig linux-3.11.10/drivers/staging/media/lirc/Kconfig--- linux-3.11.10.orig/drivers/staging/media/lirc/Kconfig	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/staging/media/lirc/Kconfig	2014-02-07 19:57:29.000000000 +0100@@ -38,6 +38,12 @@ 	help 	  Driver for Homebrew Parallel Port Receivers +config LIRC_RPI+	tristate "Homebrew GPIO Port Receiver/Transmitter for the RaspberryPi"+	depends on LIRC+	help+	  Driver for Homebrew GPIO Port Receiver/Transmitter for the RaspberryPi+ config LIRC_SASEM 	tristate "Sasem USB IR Remote" 	depends on LIRC && USBdiff -Nur linux-3.11.10.orig/drivers/staging/media/lirc/lirc_rpi.c linux-3.11.10/drivers/staging/media/lirc/lirc_rpi.c--- linux-3.11.10.orig/drivers/staging/media/lirc/lirc_rpi.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/staging/media/lirc/lirc_rpi.c	2014-02-07 19:57:29.000000000 +0100@@ -0,0 +1,692 @@+/*+ * lirc_rpi.c+ *+ * lirc_rpi - Device driver that records pulse- and pause-lengths+ *	      (space-lengths) (just like the lirc_serial driver does)+ *	      between GPIO interrupt events on the Raspberry Pi.+ *	      Lots of code has been taken from the lirc_serial module,+ *	      so I would like say thanks to the authors.+ *+ * Copyright (C) 2012 Aron Robert Szabo <aron@reon.hu>,+ *		      Michael Bishop <cleverca22@gmail.com>+ *  This program is free software; you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation; either version 2 of the License, or+ *  (at your option) any later version.+ *+ *  This program is distributed in the hope that it will be useful,+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ *  GNU General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program; if not, write to the Free Software+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+ */++#include <linux/module.h>+#include <linux/errno.h>+#include <linux/interrupt.h>+#include <linux/sched.h>+#include <linux/kernel.h>+#include <linux/time.h>+#include <linux/string.h>+#include <linux/delay.h>+#include <linux/platform_device.h>+#include <linux/irq.h>+#include <linux/spinlock.h>+#include <media/lirc.h>+#include <media/lirc_dev.h>+#include <linux/gpio.h>++#define LIRC_DRIVER_NAME "lirc_rpi"+#define RBUF_LEN 256+#define LIRC_TRANSMITTER_LATENCY 256++#ifndef MAX_UDELAY_MS+#define MAX_UDELAY_US 5000+#else+#define MAX_UDELAY_US (MAX_UDELAY_MS*1000)+#endif++#define dprintk(fmt, args...)					\+	do {							\+		if (debug)					\+			printk(KERN_DEBUG LIRC_DRIVER_NAME ": "	\+			       fmt, ## args);			\+	} while (0)++/* module parameters */++/* set the default GPIO input pin */+static int gpio_in_pin = 18;+/* set the default GPIO output pin */+static int gpio_out_pin = 17;+/* enable debugging messages */+static int debug;+/* -1 = auto, 0 = active high, 1 = active low */+static int sense = -1;+/* use softcarrier by default */+static int softcarrier = 1;+/* 0 = do not invert output, 1 = invert output */+static int invert = 0;++struct gpio_chip *gpiochip;+struct irq_chip *irqchip;+struct irq_data *irqdata;++/* forward declarations */+static long send_pulse(unsigned long length);+static void send_space(long length);+static void lirc_rpi_exit(void);++int valid_gpio_pins[] = { 0, 1, 4, 8, 7, 9, 10, 11, 14, 15, 17, 18, 21, 22, 23,+	24, 25 };++static struct platform_device *lirc_rpi_dev;+static struct timeval lasttv = { 0, 0 };+static struct lirc_buffer rbuf;+static spinlock_t lock;++/* initialized/set in init_timing_params() */+static unsigned int freq = 38000;+static unsigned int duty_cycle = 50;+static unsigned long period;+static unsigned long pulse_width;+static unsigned long space_width;++static void safe_udelay(unsigned long usecs)+{+	while (usecs > MAX_UDELAY_US) {+		udelay(MAX_UDELAY_US);+		usecs -= MAX_UDELAY_US;+	}+	udelay(usecs);+}++static int init_timing_params(unsigned int new_duty_cycle,+	unsigned int new_freq)+{+	/*+	 * period, pulse/space width are kept with 8 binary places -+	 * IE multiplied by 256.+	 */+	if (256 * 1000000L / new_freq * new_duty_cycle / 100 <=+	    LIRC_TRANSMITTER_LATENCY)+		return -EINVAL;+	if (256 * 1000000L / new_freq * (100 - new_duty_cycle) / 100 <=+	    LIRC_TRANSMITTER_LATENCY)+		return -EINVAL;+	duty_cycle = new_duty_cycle;+	freq = new_freq;+	period = 256 * 1000000L / freq;+	pulse_width = period * duty_cycle / 100;+	space_width = period - pulse_width;+	dprintk("in init_timing_params, freq=%d pulse=%ld, "+		"space=%ld\n", freq, pulse_width, space_width);+	return 0;+}++static long send_pulse_softcarrier(unsigned long length)+{+	int flag;+	unsigned long actual, target, d;++	length <<= 8;++	actual = 0; target = 0; flag = 0;+	while (actual < length) {+		if (flag) {+			gpiochip->set(gpiochip, gpio_out_pin, invert);+			target += space_width;+		} else {+			gpiochip->set(gpiochip, gpio_out_pin, !invert);+			target += pulse_width;+		}+		d = (target - actual -+		     LIRC_TRANSMITTER_LATENCY + 128) >> 8;+		/*+		 * Note - we've checked in ioctl that the pulse/space+		 * widths are big enough so that d is > 0+		 */+		udelay(d);+		actual += (d << 8) + LIRC_TRANSMITTER_LATENCY;+		flag = !flag;+	}+	return (actual-length) >> 8;+}++static long send_pulse(unsigned long length)+{+	if (length <= 0)+		return 0;++	if (softcarrier) {+		return send_pulse_softcarrier(length);+	} else {+		gpiochip->set(gpiochip, gpio_out_pin, !invert);+		safe_udelay(length);+		return 0;+	}+}++static void send_space(long length)+{+	gpiochip->set(gpiochip, gpio_out_pin, invert);+	if (length <= 0)+		return;+	safe_udelay(length);+}++static void rbwrite(int l)+{+	if (lirc_buffer_full(&rbuf)) {+		/* no new signals will be accepted */+		dprintk("Buffer overrun\n");+		return;+	}+	lirc_buffer_write(&rbuf, (void *)&l);+}++static void frbwrite(int l)+{+	/* simple noise filter */+	static int pulse, space;+	static unsigned int ptr;++	if (ptr > 0 && (l & PULSE_BIT)) {+		pulse += l & PULSE_MASK;+		if (pulse > 250) {+			rbwrite(space);+			rbwrite(pulse | PULSE_BIT);+			ptr = 0;+			pulse = 0;+		}+		return;+	}+	if (!(l & PULSE_BIT)) {+		if (ptr == 0) {+			if (l > 20000) {+				space = l;+				ptr++;+				return;+			}+		} else {+			if (l > 20000) {+				space += pulse;+				if (space > PULSE_MASK)+					space = PULSE_MASK;+				space += l;+				if (space > PULSE_MASK)+					space = PULSE_MASK;+				pulse = 0;+				return;+			}+			rbwrite(space);+			rbwrite(pulse | PULSE_BIT);+			ptr = 0;+			pulse = 0;+		}+	}+	rbwrite(l);+}++static irqreturn_t irq_handler(int i, void *blah, struct pt_regs *regs)+{+	struct timeval tv;+	long deltv;+	int data;+	int signal;++	/* use the GPIO signal level */+	signal = gpiochip->get(gpiochip, gpio_in_pin);++	/* unmask the irq */+	irqchip->irq_unmask(irqdata);++	if (sense != -1) {+		/* get current time */+		do_gettimeofday(&tv);++		/* calc time since last interrupt in microseconds */+		deltv = tv.tv_sec-lasttv.tv_sec;+		if (tv.tv_sec < lasttv.tv_sec ||+		    (tv.tv_sec == lasttv.tv_sec &&+		     tv.tv_usec < lasttv.tv_usec)) {+			printk(KERN_WARNING LIRC_DRIVER_NAME+			       ": AIEEEE: your clock just jumped backwards\n");+			printk(KERN_WARNING LIRC_DRIVER_NAME+			       ": %d %d %lx %lx %lx %lx\n", signal, sense,+			       tv.tv_sec, lasttv.tv_sec,+			       tv.tv_usec, lasttv.tv_usec);+			data = PULSE_MASK;+		} else if (deltv > 15) {+			data = PULSE_MASK; /* really long time */+			if (!(signal^sense)) {+				/* sanity check */+				printk(KERN_WARNING LIRC_DRIVER_NAME+				       ": AIEEEE: %d %d %lx %lx %lx %lx\n",+				       signal, sense, tv.tv_sec, lasttv.tv_sec,+				       tv.tv_usec, lasttv.tv_usec);+				/*+				 * detecting pulse while this+				 * MUST be a space!+				 */+				sense = sense ? 0 : 1;+			}+		} else {+			data = (int) (deltv*1000000 ++				      (tv.tv_usec - lasttv.tv_usec));+		}+		frbwrite(signal^sense ? data : (data|PULSE_BIT));+		lasttv = tv;+		wake_up_interruptible(&rbuf.wait_poll);+	}++	return IRQ_HANDLED;+}++static int is_right_chip(struct gpio_chip *chip, void *data)+{+	dprintk("is_right_chip %s %d\n", chip->label, strcmp(data, chip->label));++	if (strcmp(data, chip->label) == 0)+		return 1;+	return 0;+}++static int init_port(void)+{+	int i, nlow, nhigh, ret, irq;++	gpiochip = gpiochip_find("bcm2708_gpio", is_right_chip);++	if (!gpiochip)+		return -ENODEV;++	if (gpio_request(gpio_out_pin, LIRC_DRIVER_NAME " ir/out")) {+		printk(KERN_ALERT LIRC_DRIVER_NAME+		       ": cant claim gpio pin %d\n", gpio_out_pin);+		ret = -ENODEV;+		goto exit_init_port;+	}++	if (gpio_request(gpio_in_pin, LIRC_DRIVER_NAME " ir/in")) {+		printk(KERN_ALERT LIRC_DRIVER_NAME+		       ": cant claim gpio pin %d\n", gpio_in_pin);+		ret = -ENODEV;+		goto exit_gpio_free_out_pin;+	}++	gpiochip->direction_input(gpiochip, gpio_in_pin);+	gpiochip->direction_output(gpiochip, gpio_out_pin, 1);+	gpiochip->set(gpiochip, gpio_out_pin, invert);++	irq = gpiochip->to_irq(gpiochip, gpio_in_pin);+	dprintk("to_irq %d\n", irq);+	irqdata = irq_get_irq_data(irq);++	if (irqdata && irqdata->chip) {+		irqchip = irqdata->chip;+	} else {+		ret = -ENODEV;+		goto exit_gpio_free_in_pin;+	}++	/* if pin is high, then this must be an active low receiver. */+	if (sense == -1) {+		/* wait 1/2 sec for the power supply */+		msleep(500);++		/*+		 * probe 9 times every 0.04s, collect "votes" for+		 * active high/low+		 */+		nlow = 0;+		nhigh = 0;+		for (i = 0; i < 9; i++) {+			if (gpiochip->get(gpiochip, gpio_in_pin))+				nlow++;+			else+				nhigh++;+			msleep(40);+		}+		sense = (nlow >= nhigh ? 1 : 0);+		printk(KERN_INFO LIRC_DRIVER_NAME+		       ": auto-detected active %s receiver on GPIO pin %d\n",+		       sense ? "low" : "high", gpio_in_pin);+	} else {+		printk(KERN_INFO LIRC_DRIVER_NAME+		       ": manually using active %s receiver on GPIO pin %d\n",+		       sense ? "low" : "high", gpio_in_pin);+	}++	return 0;++	exit_gpio_free_in_pin:+	gpio_free(gpio_in_pin);++	exit_gpio_free_out_pin:+	gpio_free(gpio_out_pin);++	exit_init_port:+	return ret;+}++// called when the character device is opened+static int set_use_inc(void *data)+{+	int result;+	unsigned long flags;++	/* initialize timestamp */+	do_gettimeofday(&lasttv);++	result = request_irq(gpiochip->to_irq(gpiochip, gpio_in_pin),+			     (irq_handler_t) irq_handler, 0,+			     LIRC_DRIVER_NAME, (void*) 0);++	switch (result) {+	case -EBUSY:+		printk(KERN_ERR LIRC_DRIVER_NAME+		       ": IRQ %d is busy\n",+		       gpiochip->to_irq(gpiochip, gpio_in_pin));+		return -EBUSY;+	case -EINVAL:+		printk(KERN_ERR LIRC_DRIVER_NAME+		       ": Bad irq number or handler\n");+		return -EINVAL;+	default:+		dprintk("Interrupt %d obtained\n",+			gpiochip->to_irq(gpiochip, gpio_in_pin));+		break;+	};++	/* initialize pulse/space widths */+	init_timing_params(duty_cycle, freq);++	spin_lock_irqsave(&lock, flags);++	/* GPIO Pin Falling/Rising Edge Detect Enable */+	irqchip->irq_set_type(irqdata,+			      IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING);++	/* unmask the irq */+	irqchip->irq_unmask(irqdata);++	spin_unlock_irqrestore(&lock, flags);++	return 0;+}++static void set_use_dec(void *data)+{+	unsigned long flags;++	spin_lock_irqsave(&lock, flags);++	/* GPIO Pin Falling/Rising Edge Detect Disable */+	irqchip->irq_set_type(irqdata, 0);+	irqchip->irq_mask(irqdata);++	spin_unlock_irqrestore(&lock, flags);++	free_irq(gpiochip->to_irq(gpiochip, gpio_in_pin), (void *) 0);++	dprintk(KERN_INFO LIRC_DRIVER_NAME+		": freed IRQ %d\n", gpiochip->to_irq(gpiochip, gpio_in_pin));+}++static ssize_t lirc_write(struct file *file, const char *buf,+	size_t n, loff_t *ppos)+{+	int i, count;+	unsigned long flags;+	long delta = 0;+	int *wbuf;++	count = n / sizeof(int);+	if (n % sizeof(int) || count % 2 == 0)+		return -EINVAL;+	wbuf = memdup_user(buf, n);+	if (IS_ERR(wbuf))+		return PTR_ERR(wbuf);+	spin_lock_irqsave(&lock, flags);++	for (i = 0; i < count; i++) {+		if (i%2)+			send_space(wbuf[i] - delta);+		else+			delta = send_pulse(wbuf[i]);+	}+	gpiochip->set(gpiochip, gpio_out_pin, invert);++	spin_unlock_irqrestore(&lock, flags);+	kfree(wbuf);+	return n;+}++static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)+{+	int result;+	__u32 value;++	switch (cmd) {+	case LIRC_GET_SEND_MODE:+		return -ENOIOCTLCMD;+		break;++	case LIRC_SET_SEND_MODE:+		result = get_user(value, (__u32 *) arg);+		if (result)+			return result;+		/* only LIRC_MODE_PULSE supported */+		if (value != LIRC_MODE_PULSE)+			return -ENOSYS;+		break;++	case LIRC_GET_LENGTH:+		return -ENOSYS;+		break;++	case LIRC_SET_SEND_DUTY_CYCLE:+		dprintk("SET_SEND_DUTY_CYCLE\n");+		result = get_user(value, (__u32 *) arg);+		if (result)+			return result;+		if (value <= 0 || value > 100)+			return -EINVAL;+		return init_timing_params(value, freq);+		break;++	case LIRC_SET_SEND_CARRIER:+		dprintk("SET_SEND_CARRIER\n");+		result = get_user(value, (__u32 *) arg);+		if (result)+			return result;+		if (value > 500000 || value < 20000)+			return -EINVAL;+		return init_timing_params(duty_cycle, value);+		break;++	default:+		return lirc_dev_fop_ioctl(filep, cmd, arg);+	}+	return 0;+}++static const struct file_operations lirc_fops = {+	.owner		= THIS_MODULE,+	.write		= lirc_write,+	.unlocked_ioctl	= lirc_ioctl,+	.read		= lirc_dev_fop_read,+	.poll		= lirc_dev_fop_poll,+	.open		= lirc_dev_fop_open,+	.release	= lirc_dev_fop_close,+	.llseek		= no_llseek,+};++static struct lirc_driver driver = {+	.name		= LIRC_DRIVER_NAME,+	.minor		= -1,+	.code_length	= 1,+	.sample_rate	= 0,+	.data		= NULL,+	.add_to_buf	= NULL,+	.rbuf		= &rbuf,+	.set_use_inc	= set_use_inc,+	.set_use_dec	= set_use_dec,+	.fops		= &lirc_fops,+	.dev		= NULL,+	.owner		= THIS_MODULE,+};++static struct platform_driver lirc_rpi_driver = {+	.driver = {+		.name   = LIRC_DRIVER_NAME,+		.owner  = THIS_MODULE,+	},+};++static int __init lirc_rpi_init(void)+{+	int result;++	/* Init read buffer. */+	result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN);+	if (result < 0)+		return -ENOMEM;++	result = platform_driver_register(&lirc_rpi_driver);+	if (result) {+		printk(KERN_ERR LIRC_DRIVER_NAME+		       ": lirc register returned %d\n", result);+		goto exit_buffer_free;+	}++	lirc_rpi_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0);+	if (!lirc_rpi_dev) {+		result = -ENOMEM;+		goto exit_driver_unregister;+	}++	result = platform_device_add(lirc_rpi_dev);+	if (result)+		goto exit_device_put;++	return 0;++	exit_device_put:+	platform_device_put(lirc_rpi_dev);++	exit_driver_unregister:+	platform_driver_unregister(&lirc_rpi_driver);++	exit_buffer_free:+	lirc_buffer_free(&rbuf);++	return result;+}++static void lirc_rpi_exit(void)+{+	gpio_free(gpio_out_pin);+	gpio_free(gpio_in_pin);+	platform_device_unregister(lirc_rpi_dev);+	platform_driver_unregister(&lirc_rpi_driver);+	lirc_buffer_free(&rbuf);+}++static int __init lirc_rpi_init_module(void)+{+	int result, i;++	result = lirc_rpi_init();+	if (result)+		return result;++	/* check if the module received valid gpio pin numbers */+	result = 0;+	if (gpio_in_pin != gpio_out_pin) {+		for(i = 0; (i < ARRAY_SIZE(valid_gpio_pins)) && (result != 2); i++) {+			if (gpio_in_pin == valid_gpio_pins[i] ||+			   gpio_out_pin == valid_gpio_pins[i]) {+				result++;+			}+		}+	}++	if (result != 2) {+		result = -EINVAL;+		printk(KERN_ERR LIRC_DRIVER_NAME+		       ": invalid GPIO pin(s) specified!\n");+		goto exit_rpi;+	}++	driver.features = LIRC_CAN_SET_SEND_DUTY_CYCLE |+			  LIRC_CAN_SET_SEND_CARRIER |+			  LIRC_CAN_SEND_PULSE |+			  LIRC_CAN_REC_MODE2;++	driver.dev = &lirc_rpi_dev->dev;+	driver.minor = lirc_register_driver(&driver);++	if (driver.minor < 0) {+		printk(KERN_ERR LIRC_DRIVER_NAME+		       ": device registration failed with %d\n", result);+		result = -EIO;+		goto exit_rpi;+	}++	printk(KERN_INFO LIRC_DRIVER_NAME ": driver registered!\n");++	result = init_port();+	if (result < 0)+		goto exit_rpi;++	return 0;++	exit_rpi:+	lirc_rpi_exit();++	return result;+}++static void __exit lirc_rpi_exit_module(void)+{+	lirc_rpi_exit();++	lirc_unregister_driver(driver.minor);+	printk(KERN_INFO LIRC_DRIVER_NAME ": cleaned up module\n");+}++module_init(lirc_rpi_init_module);+module_exit(lirc_rpi_exit_module);++MODULE_DESCRIPTION("Infra-red receiver and blaster driver for Raspberry Pi GPIO.");+MODULE_AUTHOR("Aron Robert Szabo <aron@reon.hu>");+MODULE_AUTHOR("Michael Bishop <cleverca22@gmail.com>");+MODULE_LICENSE("GPL");++module_param(gpio_out_pin, int, S_IRUGO);+MODULE_PARM_DESC(gpio_out_pin, "GPIO output/transmitter pin number of the BCM"+		 " processor. Valid pin numbers are: 0, 1, 4, 8, 7, 9, 10, 11,"+		 " 14, 15, 17, 18, 21, 22, 23, 24, 25, default 17");++module_param(gpio_in_pin, int, S_IRUGO);+MODULE_PARM_DESC(gpio_in_pin, "GPIO input pin number of the BCM processor."+		 " Valid pin numbers are: 0, 1, 4, 8, 7, 9, 10, 11, 14, 15,"+		 " 17, 18, 21, 22, 23, 24, 25, default 18");++module_param(sense, bool, S_IRUGO);+MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit"+		 " (0 = active high, 1 = active low )");++module_param(softcarrier, bool, S_IRUGO);+MODULE_PARM_DESC(softcarrier, "Software carrier (0 = off, 1 = on, default on)");++module_param(invert, bool, S_IRUGO);+MODULE_PARM_DESC(invert, "Invert output (0 = off, 1 = on, default off");++module_param(debug, bool, S_IRUGO | S_IWUSR);+MODULE_PARM_DESC(debug, "Enable debugging messages");diff -Nur linux-3.11.10.orig/drivers/staging/media/lirc/Makefile linux-3.11.10/drivers/staging/media/lirc/Makefile--- linux-3.11.10.orig/drivers/staging/media/lirc/Makefile	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/staging/media/lirc/Makefile	2014-02-07 19:57:29.000000000 +0100@@ -7,6 +7,7 @@ obj-$(CONFIG_LIRC_IGORPLUGUSB)	+= lirc_igorplugusb.o obj-$(CONFIG_LIRC_IMON)		+= lirc_imon.o obj-$(CONFIG_LIRC_PARALLEL)	+= lirc_parallel.o+obj-$(CONFIG_LIRC_RPI)		+= lirc_rpi.o obj-$(CONFIG_LIRC_SASEM)	+= lirc_sasem.o obj-$(CONFIG_LIRC_SERIAL)	+= lirc_serial.o obj-$(CONFIG_LIRC_SIR)		+= lirc_sir.odiff -Nur linux-3.11.10.orig/drivers/thermal/bcm2835-thermal.c linux-3.11.10/drivers/thermal/bcm2835-thermal.c--- linux-3.11.10.orig/drivers/thermal/bcm2835-thermal.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/thermal/bcm2835-thermal.c	2014-02-07 19:57:29.000000000 +0100@@ -0,0 +1,184 @@+/*****************************************************************************+* Copyright 2011 Broadcom Corporation.  All rights reserved.+*+* Unless you and Broadcom execute a separate written software license+* agreement governing use of this software, this software is licensed to you+* under the terms of the GNU General Public License version 2, available at+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").+*+* Notwithstanding the above, under no circumstances may you combine this+* software in any way with any other Broadcom software provided under a+* license other than the GPL, without Broadcom's express prior written+* consent.+*****************************************************************************/++#include <linux/kernel.h>+#include <linux/module.h>+#include <linux/init.h>+#include <linux/platform_device.h>+#include <linux/slab.h>+#include <linux/sysfs.h>+#include <mach/vcio.h>+#include <linux/thermal.h>+++/* --- DEFINITIONS --- */+#define MODULE_NAME "bcm2835_thermal"++/*#define THERMAL_DEBUG_ENABLE*/++#ifdef THERMAL_DEBUG_ENABLE+#define print_debug(fmt,...) printk(KERN_INFO "%s:%s:%d: "fmt"\n", MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__)+#else+#define print_debug(fmt,...)+#endif+#define print_err(fmt,...) printk(KERN_ERR "%s:%s:%d: "fmt"\n", MODULE_NAME, __func__,__LINE__, ##__VA_ARGS__)++#define VC_TAG_GET_TEMP 0x00030006+#define VC_TAG_GET_MAX_TEMP 0x0003000A++typedef enum {+	TEMP,+	MAX_TEMP,+} temp_type;++/* --- STRUCTS --- */+/* tag part of the message */+struct vc_msg_tag {+	uint32_t tag_id;		/* the tag ID for the temperature */+	uint32_t buffer_size;	/* size of the buffer (should be 8) */+	uint32_t request_code;	/* identifies message as a request (should be 0) */+	uint32_t id;			/* extra ID field (should be 0) */+	uint32_t val;			/* returned value of the temperature */+};++/* message structure to be sent to videocore */+struct vc_msg {+	uint32_t msg_size;		/* simply, sizeof(struct vc_msg) */+	uint32_t request_code;		/* holds various information like the success and number of bytes returned (refer to mailboxes wiki) */+	struct vc_msg_tag tag;		/* the tag structure above to make */+	uint32_t end_tag;		/* an end identifier, should be set to NULL */+};++struct bcm2835_thermal_data {+	struct thermal_zone_device *thermal_dev;+	struct vc_msg msg;+};++/* --- GLOBALS --- */+static struct bcm2835_thermal_data bcm2835_data;++/* Thermal Device Operations */+static struct thermal_zone_device_ops ops;++/* --- FUNCTIONS --- */++static int bcm2835_get_temp_or_max(struct thermal_zone_device *thermal_dev, unsigned long *temp, unsigned tag_id)+{+	int result = -1, retry = 3;+	print_debug("IN");++	*temp = 0;+	while (result != 0 && retry-- > 0) {+		/* wipe all previous message data */+		memset(&bcm2835_data.msg, 0, sizeof bcm2835_data.msg);++		/* prepare message */+		bcm2835_data.msg.msg_size = sizeof bcm2835_data.msg;+		bcm2835_data.msg.tag.buffer_size = 8;+		bcm2835_data.msg.tag.tag_id = tag_id;++		/* send the message */+		result = bcm_mailbox_property(&bcm2835_data.msg, sizeof bcm2835_data.msg);+		print_debug("Got %stemperature as %u (%d,%x)\n", tag_id==VC_TAG_GET_MAX_TEMP ? "max ":"", (uint)bcm2835_data.msg.tag.val, result, bcm2835_data.msg.request_code);+		if (!(bcm2835_data.msg.request_code & 0x80000000))+			result = -1;+	}++	/* check if it was all ok and return the rate in milli degrees C */+	if (result == 0)+		*temp = (uint)bcm2835_data.msg.tag.val;+	else+		print_err("Failed to get temperature! (%x:%d)\n", tag_id, result);+	print_debug("OUT");+	return result;+}++static int bcm2835_get_temp(struct thermal_zone_device *thermal_dev, unsigned long *temp)+{+	return bcm2835_get_temp_or_max(thermal_dev, temp, VC_TAG_GET_TEMP);+}++static int bcm2835_get_max_temp(struct thermal_zone_device *thermal_dev, int trip_num, unsigned long *temp)+{+	return bcm2835_get_temp_or_max(thermal_dev, temp, VC_TAG_GET_MAX_TEMP);+}++static int bcm2835_get_trip_type(struct thermal_zone_device * thermal_dev, int trip_num, enum thermal_trip_type *trip_type)+{+	*trip_type = THERMAL_TRIP_HOT;+	return 0;+}+++static int bcm2835_get_mode(struct thermal_zone_device *thermal_dev, enum thermal_device_mode *dev_mode)+{+	*dev_mode = THERMAL_DEVICE_ENABLED;+	return 0;+}+++static int bcm2835_thermal_probe(struct platform_device *pdev)+{+	print_debug("IN");+	print_debug("THERMAL Driver has been probed!");++	/* check that the device isn't null!*/+	if(pdev == NULL)+	{+		print_debug("Platform device is empty!");+		return -ENODEV;+	}++	if(!(bcm2835_data.thermal_dev = thermal_zone_device_register("bcm2835_thermal",  1, 0, NULL, &ops, NULL, 0, 0)))+	{+		print_debug("Unable to register the thermal device!");+		return -EFAULT;+	}+	return 0;+}+++static int bcm2835_thermal_remove(struct platform_device *pdev)+{+	print_debug("IN");++	thermal_zone_device_unregister(bcm2835_data.thermal_dev);++	print_debug("OUT");++	return 0;+}++static struct thermal_zone_device_ops ops  = {+	.get_temp = bcm2835_get_temp,+	.get_trip_temp = bcm2835_get_max_temp,+	.get_trip_type = bcm2835_get_trip_type,+	.get_mode = bcm2835_get_mode,+};++/* Thermal Driver */+static struct platform_driver bcm2835_thermal_driver = {+	.probe = bcm2835_thermal_probe,+	.remove = bcm2835_thermal_remove,+	.driver = {+				.name = "bcm2835_thermal",+				.owner = THIS_MODULE,+			},+};++MODULE_LICENSE("GPL");+MODULE_AUTHOR("Dorian Peake");+MODULE_DESCRIPTION("Thermal driver for bcm2835 chip");++module_platform_driver(bcm2835_thermal_driver);diff -Nur linux-3.11.10.orig/drivers/thermal/Kconfig linux-3.11.10/drivers/thermal/Kconfig--- linux-3.11.10.orig/drivers/thermal/Kconfig	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/thermal/Kconfig	2014-02-07 19:57:29.000000000 +0100@@ -169,6 +169,12 @@ 	  enforce idle time which results in more package C-state residency. The 	  user interface is exposed via generic thermal framework. +config THERMAL_BCM2835+	tristate "BCM2835 Thermal Driver"+	help+	  This will enable temperature monitoring for the Broadcom BCM2835+	  chip. If built as a module, it will be called 'bcm2835-thermal'.+ config X86_PKG_TEMP_THERMAL 	tristate "X86 package temperature thermal driver" 	depends on X86_THERMAL_VECTORdiff -Nur linux-3.11.10.orig/drivers/thermal/Makefile linux-3.11.10/drivers/thermal/Makefile--- linux-3.11.10.orig/drivers/thermal/Makefile	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/thermal/Makefile	2014-02-07 19:57:29.000000000 +0100@@ -23,5 +23,6 @@ obj-$(CONFIG_ARMADA_THERMAL)	+= armada_thermal.o obj-$(CONFIG_DB8500_CPUFREQ_COOLING)	+= db8500_cpufreq_cooling.o obj-$(CONFIG_INTEL_POWERCLAMP)	+= intel_powerclamp.o+obj-$(CONFIG_THERMAL_BCM2835)	+= bcm2835-thermal.o obj-$(CONFIG_X86_PKG_TEMP_THERMAL)	+= x86_pkg_temp_thermal.o obj-$(CONFIG_TI_SOC_THERMAL)	+= ti-soc-thermal/diff -Nur linux-3.11.10.orig/drivers/tty/serial/amba-pl011.c linux-3.11.10/drivers/tty/serial/amba-pl011.c--- linux-3.11.10.orig/drivers/tty/serial/amba-pl011.c	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/tty/serial/amba-pl011.c	2014-02-07 19:57:29.000000000 +0100@@ -84,7 +84,7 @@  static unsigned int get_fifosize_arm(struct amba_device *dev) {-	return amba_rev(dev) < 3 ? 16 : 32;+	return 16; //TODO: fix: amba_rev(dev) < 3 ? 16 : 32; }  static struct vendor_data vendor_arm = {diff -Nur linux-3.11.10.orig/drivers/usb/core/generic.c linux-3.11.10/drivers/usb/core/generic.c--- linux-3.11.10.orig/drivers/usb/core/generic.c	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/usb/core/generic.c	2014-02-07 19:57:30.000000000 +0100@@ -152,6 +152,7 @@ 		dev_warn(&udev->dev, 			"no configuration chosen from %d choice%s\n", 			num_configs, plural(num_configs));+		dev_warn(&udev->dev, "No support over %dmA\n", udev->bus_mA); 	} 	return i; }diff -Nur linux-3.11.10.orig/drivers/usb/core/message.c linux-3.11.10/drivers/usb/core/message.c--- linux-3.11.10.orig/drivers/usb/core/message.c	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/usb/core/message.c	2014-02-07 19:57:30.000000000 +0100@@ -1875,6 +1875,85 @@ 	if (cp->string == NULL && 			!(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) 		cp->string = usb_cache_string(dev, cp->desc.iConfiguration);+/* Uncomment this define to enable the HS Electrical Test support */+#define DWC_HS_ELECT_TST 1+#ifdef DWC_HS_ELECT_TST+		/* Here we implement the HS Electrical Test support. The+		 * tester uses a vendor ID of 0x1A0A to indicate we should+		 * run a special test sequence. The product ID tells us+		 * which sequence to run. We invoke the test sequence by+		 * sending a non-standard SetFeature command to our root+		 * hub port. Our dwc_otg_hcd_hub_control() routine will+		 * recognize the command and perform the desired test+		 * sequence.+		 */+		if (dev->descriptor.idVendor == 0x1A0A) {+			/* HSOTG Electrical Test */+			dev_warn(&dev->dev, "VID from HSOTG Electrical Test Fixture\n");++			if (dev->bus && dev->bus->root_hub) {+				struct usb_device *hdev = dev->bus->root_hub;+				dev_warn(&dev->dev, "Got PID 0x%x\n", dev->descriptor.idProduct);++				switch (dev->descriptor.idProduct) {+				case 0x0101:	/* TEST_SE0_NAK */+					dev_warn(&dev->dev, "TEST_SE0_NAK\n");+					usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),+							USB_REQ_SET_FEATURE, USB_RT_PORT,+							USB_PORT_FEAT_TEST, 0x300, NULL, 0, HZ);+					break;++				case 0x0102:	/* TEST_J */+					dev_warn(&dev->dev, "TEST_J\n");+					usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),+							USB_REQ_SET_FEATURE, USB_RT_PORT,+							USB_PORT_FEAT_TEST, 0x100, NULL, 0, HZ);+					break;++				case 0x0103:	/* TEST_K */+					dev_warn(&dev->dev, "TEST_K\n");+					usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),+							USB_REQ_SET_FEATURE, USB_RT_PORT,+							USB_PORT_FEAT_TEST, 0x200, NULL, 0, HZ);+					break;++				case 0x0104:	/* TEST_PACKET */+					dev_warn(&dev->dev, "TEST_PACKET\n");+					usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),+							USB_REQ_SET_FEATURE, USB_RT_PORT,+							USB_PORT_FEAT_TEST, 0x400, NULL, 0, HZ);+					break;++				case 0x0105:	/* TEST_FORCE_ENABLE */+					dev_warn(&dev->dev, "TEST_FORCE_ENABLE\n");+					usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),+							USB_REQ_SET_FEATURE, USB_RT_PORT,+							USB_PORT_FEAT_TEST, 0x500, NULL, 0, HZ);+					break;++				case 0x0106:	/* HS_HOST_PORT_SUSPEND_RESUME */+					dev_warn(&dev->dev, "HS_HOST_PORT_SUSPEND_RESUME\n");+					usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),+							USB_REQ_SET_FEATURE, USB_RT_PORT,+							USB_PORT_FEAT_TEST, 0x600, NULL, 0, 40 * HZ);+					break;++				case 0x0107:	/* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */+					dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup\n");+					usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),+							USB_REQ_SET_FEATURE, USB_RT_PORT,+							USB_PORT_FEAT_TEST, 0x700, NULL, 0, 40 * HZ);+					break;++				case 0x0108:	/* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */+					dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute\n");+					usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),+							USB_REQ_SET_FEATURE, USB_RT_PORT,+							USB_PORT_FEAT_TEST, 0x800, NULL, 0, 40 * HZ);+				}+			}+		}+#endif /* DWC_HS_ELECT_TST */  	/* Now that the interfaces are installed, re-enable LPM. */ 	usb_unlocked_enable_lpm(dev);diff -Nur linux-3.11.10.orig/drivers/usb/core/otg_whitelist.h linux-3.11.10/drivers/usb/core/otg_whitelist.h--- linux-3.11.10.orig/drivers/usb/core/otg_whitelist.h	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/usb/core/otg_whitelist.h	2014-02-07 19:57:30.000000000 +0100@@ -19,33 +19,82 @@ static struct usb_device_id whitelist_table [] = {  /* hubs are optional in OTG, but very handy ... */+#define CERT_WITHOUT_HUBS+#if defined(CERT_WITHOUT_HUBS)+{ USB_DEVICE( 0x0000, 0x0000 ), }, /* Root HUB Only*/+#else { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), }, { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), },+{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 2), },+#endif  #ifdef	CONFIG_USB_PRINTER		/* ignoring nonstatic linkage! */ /* FIXME actually, printers are NOT supposed to use device classes;  * they're supposed to use interface classes...  */-{ USB_DEVICE_INFO(7, 1, 1) },-{ USB_DEVICE_INFO(7, 1, 2) },-{ USB_DEVICE_INFO(7, 1, 3) },+//{ USB_DEVICE_INFO(7, 1, 1) },+//{ USB_DEVICE_INFO(7, 1, 2) },+//{ USB_DEVICE_INFO(7, 1, 3) }, #endif  #ifdef	CONFIG_USB_NET_CDCETHER /* Linux-USB CDC Ethernet gadget */-{ USB_DEVICE(0x0525, 0xa4a1), },+//{ USB_DEVICE(0x0525, 0xa4a1), }, /* Linux-USB CDC Ethernet + RNDIS gadget */-{ USB_DEVICE(0x0525, 0xa4a2), },+//{ USB_DEVICE(0x0525, 0xa4a2), }, #endif  #if	defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE) /* gadget zero, for testing */-{ USB_DEVICE(0x0525, 0xa4a0), },+//{ USB_DEVICE(0x0525, 0xa4a0), }, #endif +/* OPT Tester */+{ USB_DEVICE( 0x1a0a, 0x0101 ), }, /* TEST_SE0_NAK */+{ USB_DEVICE( 0x1a0a, 0x0102 ), }, /* Test_J */+{ USB_DEVICE( 0x1a0a, 0x0103 ), }, /* Test_K */+{ USB_DEVICE( 0x1a0a, 0x0104 ), }, /* Test_PACKET */+{ USB_DEVICE( 0x1a0a, 0x0105 ), }, /* Test_FORCE_ENABLE */+{ USB_DEVICE( 0x1a0a, 0x0106 ), }, /* HS_PORT_SUSPEND_RESUME  */+{ USB_DEVICE( 0x1a0a, 0x0107 ), }, /* SINGLE_STEP_GET_DESCRIPTOR setup */+{ USB_DEVICE( 0x1a0a, 0x0108 ), }, /* SINGLE_STEP_GET_DESCRIPTOR execute */++/* Sony cameras */+{ USB_DEVICE_VER(0x054c,0x0010,0x0410, 0x0500), },++/* Memory Devices */+//{ USB_DEVICE( 0x0781, 0x5150 ), }, /* SanDisk */+//{ USB_DEVICE( 0x05DC, 0x0080 ), }, /* Lexar */+//{ USB_DEVICE( 0x4146, 0x9281 ), }, /* IOMEGA */+//{ USB_DEVICE( 0x067b, 0x2507 ), }, /* Hammer 20GB External HD  */+{ USB_DEVICE( 0x0EA0, 0x2168 ), }, /* Ours Technology Inc. (BUFFALO ClipDrive)*/+//{ USB_DEVICE( 0x0457, 0x0150 ), }, /* Silicon Integrated Systems Corp. */++/* HP Printers */+//{ USB_DEVICE( 0x03F0, 0x1102 ), }, /* HP Photosmart 245 */+//{ USB_DEVICE( 0x03F0, 0x1302 ), }, /* HP Photosmart 370 Series */++/* Speakers */+//{ USB_DEVICE( 0x0499, 0x3002 ), }, /* YAMAHA YST-MS35D USB Speakers */+//{ USB_DEVICE( 0x0672, 0x1041 ), }, /* Labtec USB Headset */+ { }	/* Terminating entry */ }; +static inline void report_errors(struct usb_device *dev)+{+	/* OTG MESSAGE: report errors here, customize to match your product */+	dev_info(&dev->dev, "device Vendor:%04x Product:%04x is not supported\n",+		 le16_to_cpu(dev->descriptor.idVendor),+		 le16_to_cpu(dev->descriptor.idProduct));+        if (USB_CLASS_HUB == dev->descriptor.bDeviceClass){+                dev_printk(KERN_CRIT, &dev->dev, "Unsupported Hub Topology\n");+        } else {+                dev_printk(KERN_CRIT, &dev->dev, "Attached Device is not Supported\n");+        }+}++ static int is_targeted(struct usb_device *dev) { 	struct usb_device_id	*id = whitelist_table;@@ -55,58 +104,83 @@ 		return 1;  	/* HNP test device is _never_ targeted (see OTG spec 6.6.6) */-	if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a &&-	     le16_to_cpu(dev->descriptor.idProduct) == 0xbadd))-		return 0;+	if (dev->descriptor.idVendor == 0x1a0a &&+            dev->descriptor.idProduct == 0xbadd) {+                return 0;+	} else if (!enable_whitelist) {+		return 1;+        } else { -	/* NOTE: can't use usb_match_id() since interface caches-	 * aren't set up yet. this is cut/paste from that code.-	 */-	for (id = whitelist_table; id->match_flags; id++) {-		if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&-		    id->idVendor != le16_to_cpu(dev->descriptor.idVendor))-			continue;--		if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&-		    id->idProduct != le16_to_cpu(dev->descriptor.idProduct))-			continue;--		/* No need to test id->bcdDevice_lo != 0, since 0 is never-		   greater than any unsigned number. */-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&-		    (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))-			continue;--		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&-		    (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))-			continue;--		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&-		    (id->bDeviceClass != dev->descriptor.bDeviceClass))-			continue;--		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&-		    (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))-			continue;--		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&-		    (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))-			continue;+#ifdef DEBUG+                dev_dbg(&dev->dev, "device V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n",+                        dev->descriptor.idVendor,+                        dev->descriptor.idProduct,+                        dev->descriptor.bDeviceClass,+                        dev->descriptor.bDeviceSubClass,+                        dev->descriptor.bDeviceProtocol);+#endif  		return 1;+		/* NOTE: can't use usb_match_id() since interface caches+		 * aren't set up yet. this is cut/paste from that code.+		 */+		for (id = whitelist_table; id->match_flags; id++) {+#ifdef DEBUG+			dev_dbg(&dev->dev,+				"ID: V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n",+				id->idVendor,+				id->idProduct,+				id->bDeviceClass,+				id->bDeviceSubClass,+				id->bDeviceProtocol);+#endif++			if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&+			    id->idVendor != le16_to_cpu(dev->descriptor.idVendor))+				continue;++			if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&+			    id->idProduct != le16_to_cpu(dev->descriptor.idProduct))+				continue;++			/* No need to test id->bcdDevice_lo != 0, since 0 is never+			   greater than any unsigned number. */+			if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&+			    (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))+				continue;++			if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&+			    (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))+				continue;++			if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&+			    (id->bDeviceClass != dev->descriptor.bDeviceClass))+				continue;++			if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&+			    (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))+				continue;++			if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&+			    (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))+				continue;++			return 1;+		} 	}  	/* add other match criteria here ... */ --	/* OTG MESSAGE: report errors here, customize to match your product */-	dev_err(&dev->dev, "device v%04x p%04x is not supported\n",-		le16_to_cpu(dev->descriptor.idVendor),-		le16_to_cpu(dev->descriptor.idProduct)); #ifdef	CONFIG_USB_OTG_WHITELIST+	report_errors(dev); 	return 0; #else-	return 1;+	if (enable_whitelist) {+		report_errors(dev);+		return 0;+	} else {+		return 1;+	} #endif } diff -Nur linux-3.11.10.orig/drivers/usb/gadget/file_storage.c linux-3.11.10/drivers/usb/gadget/file_storage.c--- linux-3.11.10.orig/drivers/usb/gadget/file_storage.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/gadget/file_storage.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,3676 @@+/*+ * file_storage.c -- File-backed USB Storage Gadget, for USB development+ *+ * Copyright (C) 2003-2008 Alan Stern+ * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") as published by the Free Software+ * Foundation, either version 2 of that License or (at your option) any+ * later version.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */+++/*+ * The File-backed Storage Gadget acts as a USB Mass Storage device,+ * appearing to the host as a disk drive or as a CD-ROM drive.  In addition+ * to providing an example of a genuinely useful gadget driver for a USB+ * device, it also illustrates a technique of double-buffering for increased+ * throughput.  Last but not least, it gives an easy way to probe the+ * behavior of the Mass Storage drivers in a USB host.+ *+ * Backing storage is provided by a regular file or a block device, specified+ * by the "file" module parameter.  Access can be limited to read-only by+ * setting the optional "ro" module parameter.  (For CD-ROM emulation,+ * access is always read-only.)  The gadget will indicate that it has+ * removable media if the optional "removable" module parameter is set.+ *+ * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),+ * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected+ * by the optional "transport" module parameter.  It also supports the+ * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),+ * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by+ * the optional "protocol" module parameter.  In addition, the default+ * Vendor ID, Product ID, release number and serial number can be overridden.+ *+ * There is support for multiple logical units (LUNs), each of which has+ * its own backing file.  The number of LUNs can be set using the optional+ * "luns" module parameter (anywhere from 1 to 8), and the corresponding+ * files are specified using comma-separated lists for "file" and "ro".+ * The default number of LUNs is taken from the number of "file" elements;+ * it is 1 if "file" is not given.  If "removable" is not set then a backing+ * file must be specified for each LUN.  If it is set, then an unspecified+ * or empty backing filename means the LUN's medium is not loaded.  Ideally+ * each LUN would be settable independently as a disk drive or a CD-ROM+ * drive, but currently all LUNs have to be the same type.  The CD-ROM+ * emulation includes a single data track and no audio tracks; hence there+ * need be only one backing file per LUN.+ *+ * Requirements are modest; only a bulk-in and a bulk-out endpoint are+ * needed (an interrupt-out endpoint is also needed for CBI).  The memory+ * requirement amounts to two 16K buffers, size configurable by a parameter.+ * Support is included for both full-speed and high-speed operation.+ *+ * Note that the driver is slightly non-portable in that it assumes a+ * single memory/DMA buffer will be useable for bulk-in, bulk-out, and+ * interrupt-in endpoints.  With most device controllers this isn't an+ * issue, but there may be some with hardware restrictions that prevent+ * a buffer from being used by more than one endpoint.+ *+ * Module options:+ *+ *	file=filename[,filename...]+ *				Required if "removable" is not set, names of+ *					the files or block devices used for+ *					backing storage+ *	serial=HHHH...		Required serial number (string of hex chars)+ *	ro=b[,b...]		Default false, booleans for read-only access+ *	removable		Default false, boolean for removable media+ *	luns=N			Default N = number of filenames, number of+ *					LUNs to support+ *	nofua=b[,b...]		Default false, booleans for ignore FUA flag+ *					in SCSI WRITE(10,12) commands+ *	stall			Default determined according to the type of+ *					USB device controller (usually true),+ *					boolean to permit the driver to halt+ *					bulk endpoints+ *	cdrom			Default false, boolean for whether to emulate+ *					a CD-ROM drive+ *	transport=XXX		Default BBB, transport name (CB, CBI, or BBB)+ *	protocol=YYY		Default SCSI, protocol name (RBC, 8020 or+ *					ATAPI, QIC, UFI, 8070, or SCSI;+ *					also 1 - 6)+ *	vendor=0xVVVV		Default 0x0525 (NetChip), USB Vendor ID+ *	product=0xPPPP		Default 0xa4a5 (FSG), USB Product ID+ *	release=0xRRRR		Override the USB release number (bcdDevice)+ *	buflen=N		Default N=16384, buffer size used (will be+ *					rounded down to a multiple of+ *					PAGE_CACHE_SIZE)+ *+ * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro",+ * "removable", "luns", "nofua", "stall", and "cdrom" options are available;+ * default values are used for everything else.+ *+ * The pathnames of the backing files and the ro settings are available in+ * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of+ * the gadget's sysfs directory.  If the "removable" option is set, writing to+ * these files will simulate ejecting/loading the medium (writing an empty+ * line means eject) and adjusting a write-enable tab.  Changes to the ro+ * setting are not allowed when the medium is loaded or if CD-ROM emulation+ * is being used.+ *+ * This gadget driver is heavily based on "Gadget Zero" by David Brownell.+ * The driver's SCSI command interface was based on the "Information+ * technology - Small Computer System Interface - 2" document from+ * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at+ * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>.  The single exception+ * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the+ * "Universal Serial Bus Mass Storage Class UFI Command Specification"+ * document, Revision 1.0, December 14, 1998, available at+ * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.+ */+++/*+ *				Driver Design+ *+ * The FSG driver is fairly straightforward.  There is a main kernel+ * thread that handles most of the work.  Interrupt routines field+ * callbacks from the controller driver: bulk- and interrupt-request+ * completion notifications, endpoint-0 events, and disconnect events.+ * Completion events are passed to the main thread by wakeup calls.  Many+ * ep0 requests are handled at interrupt time, but SetInterface,+ * SetConfiguration, and device reset requests are forwarded to the+ * thread in the form of "exceptions" using SIGUSR1 signals (since they+ * should interrupt any ongoing file I/O operations).+ *+ * The thread's main routine implements the standard command/data/status+ * parts of a SCSI interaction.  It and its subroutines are full of tests+ * for pending signals/exceptions -- all this polling is necessary since+ * the kernel has no setjmp/longjmp equivalents.  (Maybe this is an+ * indication that the driver really wants to be running in userspace.)+ * An important point is that so long as the thread is alive it keeps an+ * open reference to the backing file.  This will prevent unmounting+ * the backing file's underlying filesystem and could cause problems+ * during system shutdown, for example.  To prevent such problems, the+ * thread catches INT, TERM, and KILL signals and converts them into+ * an EXIT exception.+ *+ * In normal operation the main thread is started during the gadget's+ * fsg_bind() callback and stopped during fsg_unbind().  But it can also+ * exit when it receives a signal, and there's no point leaving the+ * gadget running when the thread is dead.  So just before the thread+ * exits, it deregisters the gadget driver.  This makes things a little+ * tricky: The driver is deregistered at two places, and the exiting+ * thread can indirectly call fsg_unbind() which in turn can tell the+ * thread to exit.  The first problem is resolved through the use of the+ * REGISTERED atomic bitflag; the driver will only be deregistered once.+ * The second problem is resolved by having fsg_unbind() check+ * fsg->state; it won't try to stop the thread if the state is already+ * FSG_STATE_TERMINATED.+ *+ * To provide maximum throughput, the driver uses a circular pipeline of+ * buffer heads (struct fsg_buffhd).  In principle the pipeline can be+ * arbitrarily long; in practice the benefits don't justify having more+ * than 2 stages (i.e., double buffering).  But it helps to think of the+ * pipeline as being a long one.  Each buffer head contains a bulk-in and+ * a bulk-out request pointer (since the buffer can be used for both+ * output and input -- directions always are given from the host's+ * point of view) as well as a pointer to the buffer and various state+ * variables.+ *+ * Use of the pipeline follows a simple protocol.  There is a variable+ * (fsg->next_buffhd_to_fill) that points to the next buffer head to use.+ * At any time that buffer head may still be in use from an earlier+ * request, so each buffer head has a state variable indicating whether+ * it is EMPTY, FULL, or BUSY.  Typical use involves waiting for the+ * buffer head to be EMPTY, filling the buffer either by file I/O or by+ * USB I/O (during which the buffer head is BUSY), and marking the buffer+ * head FULL when the I/O is complete.  Then the buffer will be emptied+ * (again possibly by USB I/O, during which it is marked BUSY) and+ * finally marked EMPTY again (possibly by a completion routine).+ *+ * A module parameter tells the driver to avoid stalling the bulk+ * endpoints wherever the transport specification allows.  This is+ * necessary for some UDCs like the SuperH, which cannot reliably clear a+ * halt on a bulk endpoint.  However, under certain circumstances the+ * Bulk-only specification requires a stall.  In such cases the driver+ * will halt the endpoint and set a flag indicating that it should clear+ * the halt in software during the next device reset.  Hopefully this+ * will permit everything to work correctly.  Furthermore, although the+ * specification allows the bulk-out endpoint to halt when the host sends+ * too much data, implementing this would cause an unavoidable race.+ * The driver will always use the "no-stall" approach for OUT transfers.+ *+ * One subtle point concerns sending status-stage responses for ep0+ * requests.  Some of these requests, such as device reset, can involve+ * interrupting an ongoing file I/O operation, which might take an+ * arbitrarily long time.  During that delay the host might give up on+ * the original ep0 request and issue a new one.  When that happens the+ * driver should not notify the host about completion of the original+ * request, as the host will no longer be waiting for it.  So the driver+ * assigns to each ep0 request a unique tag, and it keeps track of the+ * tag value of the request associated with a long-running exception+ * (device-reset, interface-change, or configuration-change).  When the+ * exception handler is finished, the status-stage response is submitted+ * only if the current ep0 request tag is equal to the exception request+ * tag.  Thus only the most recently received ep0 request will get a+ * status-stage response.+ *+ * Warning: This driver source file is too long.  It ought to be split up+ * into a header file plus about 3 separate .c files, to handle the details+ * of the Gadget, USB Mass Storage, and SCSI protocols.+ */+++/* #define VERBOSE_DEBUG */+/* #define DUMP_MSGS */+++#include <linux/blkdev.h>+#include <linux/completion.h>+#include <linux/dcache.h>+#include <linux/delay.h>+#include <linux/device.h>+#include <linux/fcntl.h>+#include <linux/file.h>+#include <linux/fs.h>+#include <linux/kref.h>+#include <linux/kthread.h>+#include <linux/limits.h>+#include <linux/module.h>+#include <linux/rwsem.h>+#include <linux/slab.h>+#include <linux/spinlock.h>+#include <linux/string.h>+#include <linux/freezer.h>+#include <linux/utsname.h>++#include <linux/usb/ch9.h>+#include <linux/usb/gadget.h>++#include "gadget_chips.h"++++/*+ * Kbuild is not very cooperative with respect to linking separately+ * compiled library objects into one module.  So for now we won't use+ * separate compilation ... ensuring init/exit sections work to shrink+ * the runtime footprint, and giving us at least some parts of what+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.+ */+#include "usbstring.c"+#include "config.c"+#include "epautoconf.c"++/*-------------------------------------------------------------------------*/++#define DRIVER_DESC		"File-backed Storage Gadget"+#define DRIVER_NAME		"g_file_storage"+#define DRIVER_VERSION		"1 September 2010"++static       char fsg_string_manufacturer[64];+static const char fsg_string_product[] = DRIVER_DESC;+static const char fsg_string_config[] = "Self-powered";+static const char fsg_string_interface[] = "Mass Storage";+++#include "storage_common.c"+++MODULE_DESCRIPTION(DRIVER_DESC);+MODULE_AUTHOR("Alan Stern");+MODULE_LICENSE("Dual BSD/GPL");++/*+ * This driver assumes self-powered hardware and has no way for users to+ * trigger remote wakeup.  It uses autoconfiguration to select endpoints+ * and endpoint addresses.+ */+++/*-------------------------------------------------------------------------*/+++/* Encapsulate the module parameter settings */++static struct {+	char		*file[FSG_MAX_LUNS];+	char		*serial;+	bool		ro[FSG_MAX_LUNS];+	bool		nofua[FSG_MAX_LUNS];+	unsigned int	num_filenames;+	unsigned int	num_ros;+	unsigned int	num_nofuas;+	unsigned int	nluns;++	bool		removable;+	bool		can_stall;+	bool		cdrom;++	char		*transport_parm;+	char		*protocol_parm;+	unsigned short	vendor;+	unsigned short	product;+	unsigned short	release;+	unsigned int	buflen;++	int		transport_type;+	char		*transport_name;+	int		protocol_type;+	char		*protocol_name;++} mod_data = {					// Default values+	.transport_parm		= "BBB",+	.protocol_parm		= "SCSI",+	.removable		= 0,+	.can_stall		= 1,+	.cdrom			= 0,+	.vendor			= FSG_VENDOR_ID,+	.product		= FSG_PRODUCT_ID,+	.release		= 0xffff,	// Use controller chip type+	.buflen			= 16384,+	};+++module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,+		S_IRUGO);+MODULE_PARM_DESC(file, "names of backing files or devices");++module_param_named(serial, mod_data.serial, charp, S_IRUGO);+MODULE_PARM_DESC(serial, "USB serial number");++module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);+MODULE_PARM_DESC(ro, "true to force read-only");++module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas,+		S_IRUGO);+MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit");++module_param_named(luns, mod_data.nluns, uint, S_IRUGO);+MODULE_PARM_DESC(luns, "number of LUNs");++module_param_named(removable, mod_data.removable, bool, S_IRUGO);+MODULE_PARM_DESC(removable, "true to simulate removable media");++module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);+MODULE_PARM_DESC(stall, "false to prevent bulk stalls");++module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);+MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");++/* In the non-TEST version, only the module parameters listed above+ * are available. */+#ifdef CONFIG_USB_FILE_STORAGE_TEST++module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO);+MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)");++module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO);+MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, "+		"8070, or SCSI)");++module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);+MODULE_PARM_DESC(vendor, "USB Vendor ID");++module_param_named(product, mod_data.product, ushort, S_IRUGO);+MODULE_PARM_DESC(product, "USB Product ID");++module_param_named(release, mod_data.release, ushort, S_IRUGO);+MODULE_PARM_DESC(release, "USB release number");++module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);+MODULE_PARM_DESC(buflen, "I/O buffer size");++#endif /* CONFIG_USB_FILE_STORAGE_TEST */+++/*+ * These definitions will permit the compiler to avoid generating code for+ * parts of the driver that aren't used in the non-TEST version.  Even gcc+ * can recognize when a test of a constant expression yields a dead code+ * path.+ */++#ifdef CONFIG_USB_FILE_STORAGE_TEST++#define transport_is_bbb()	(mod_data.transport_type == USB_PR_BULK)+#define transport_is_cbi()	(mod_data.transport_type == USB_PR_CBI)+#define protocol_is_scsi()	(mod_data.protocol_type == USB_SC_SCSI)++#else++#define transport_is_bbb()	1+#define transport_is_cbi()	0+#define protocol_is_scsi()	1++#endif /* CONFIG_USB_FILE_STORAGE_TEST */+++/*-------------------------------------------------------------------------*/+++struct fsg_dev {+	/* lock protects: state, all the req_busy's, and cbbuf_cmnd */+	spinlock_t		lock;+	struct usb_gadget	*gadget;++	/* filesem protects: backing files in use */+	struct rw_semaphore	filesem;++	/* reference counting: wait until all LUNs are released */+	struct kref		ref;++	struct usb_ep		*ep0;		// Handy copy of gadget->ep0+	struct usb_request	*ep0req;	// For control responses+	unsigned int		ep0_req_tag;+	const char		*ep0req_name;++	struct usb_request	*intreq;	// For interrupt responses+	int			intreq_busy;+	struct fsg_buffhd	*intr_buffhd;++	unsigned int		bulk_out_maxpacket;+	enum fsg_state		state;		// For exception handling+	unsigned int		exception_req_tag;++	u8			config, new_config;++	unsigned int		running : 1;+	unsigned int		bulk_in_enabled : 1;+	unsigned int		bulk_out_enabled : 1;+	unsigned int		intr_in_enabled : 1;+	unsigned int		phase_error : 1;+	unsigned int		short_packet_received : 1;+	unsigned int		bad_lun_okay : 1;++	unsigned long		atomic_bitflags;+#define REGISTERED		0+#define IGNORE_BULK_OUT		1+#define SUSPENDED		2++	struct usb_ep		*bulk_in;+	struct usb_ep		*bulk_out;+	struct usb_ep		*intr_in;++	struct fsg_buffhd	*next_buffhd_to_fill;+	struct fsg_buffhd	*next_buffhd_to_drain;++	int			thread_wakeup_needed;+	struct completion	thread_notifier;+	struct task_struct	*thread_task;++	int			cmnd_size;+	u8			cmnd[MAX_COMMAND_SIZE];+	enum data_direction	data_dir;+	u32			data_size;+	u32			data_size_from_cmnd;+	u32			tag;+	unsigned int		lun;+	u32			residue;+	u32			usb_amount_left;++	/* The CB protocol offers no way for a host to know when a command+	 * has completed.  As a result the next command may arrive early,+	 * and we will still have to handle it.  For that reason we need+	 * a buffer to store new commands when using CB (or CBI, which+	 * does not oblige a host to wait for command completion either). */+	int			cbbuf_cmnd_size;+	u8			cbbuf_cmnd[MAX_COMMAND_SIZE];++	unsigned int		nluns;+	struct fsg_lun		*luns;+	struct fsg_lun		*curlun;+	/* Must be the last entry */+	struct fsg_buffhd	buffhds[];+};++typedef void (*fsg_routine_t)(struct fsg_dev *);++static int exception_in_progress(struct fsg_dev *fsg)+{+	return (fsg->state > FSG_STATE_IDLE);+}++/* Make bulk-out requests be divisible by the maxpacket size */+static void set_bulk_out_req_length(struct fsg_dev *fsg,+		struct fsg_buffhd *bh, unsigned int length)+{+	unsigned int	rem;++	bh->bulk_out_intended_length = length;+	rem = length % fsg->bulk_out_maxpacket;+	if (rem > 0)+		length += fsg->bulk_out_maxpacket - rem;+	bh->outreq->length = length;+}++static struct fsg_dev			*the_fsg;+static struct usb_gadget_driver		fsg_driver;+++/*-------------------------------------------------------------------------*/++static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)+{+	const char	*name;++	if (ep == fsg->bulk_in)+		name = "bulk-in";+	else if (ep == fsg->bulk_out)+		name = "bulk-out";+	else+		name = ep->name;+	DBG(fsg, "%s set halt\n", name);+	return usb_ep_set_halt(ep);+}+++/*-------------------------------------------------------------------------*/++/*+ * DESCRIPTORS ... most are static, but strings and (full) configuration+ * descriptors are built on demand.  Also the (static) config and interface+ * descriptors are adjusted during fsg_bind().+ */++/* There is only one configuration. */+#define	CONFIG_VALUE		1++static struct usb_device_descriptor+device_desc = {+	.bLength =		sizeof device_desc,+	.bDescriptorType =	USB_DT_DEVICE,++	.bcdUSB =		cpu_to_le16(0x0200),+	.bDeviceClass =		USB_CLASS_PER_INTERFACE,++	/* The next three values can be overridden by module parameters */+	.idVendor =		cpu_to_le16(FSG_VENDOR_ID),+	.idProduct =		cpu_to_le16(FSG_PRODUCT_ID),+	.bcdDevice =		cpu_to_le16(0xffff),++	.iManufacturer =	FSG_STRING_MANUFACTURER,+	.iProduct =		FSG_STRING_PRODUCT,+	.iSerialNumber =	FSG_STRING_SERIAL,+	.bNumConfigurations =	1,+};++static struct usb_config_descriptor+config_desc = {+	.bLength =		sizeof config_desc,+	.bDescriptorType =	USB_DT_CONFIG,++	/* wTotalLength computed by usb_gadget_config_buf() */+	.bNumInterfaces =	1,+	.bConfigurationValue =	CONFIG_VALUE,+	.iConfiguration =	FSG_STRING_CONFIG,+	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,+	.bMaxPower =		CONFIG_USB_GADGET_VBUS_DRAW / 2,+};+++static struct usb_qualifier_descriptor+dev_qualifier = {+	.bLength =		sizeof dev_qualifier,+	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,++	.bcdUSB =		cpu_to_le16(0x0200),+	.bDeviceClass =		USB_CLASS_PER_INTERFACE,++	.bNumConfigurations =	1,+};++static int populate_bos(struct fsg_dev *fsg, u8 *buf)+{+	memcpy(buf, &fsg_bos_desc, USB_DT_BOS_SIZE);+	buf += USB_DT_BOS_SIZE;++	memcpy(buf, &fsg_ext_cap_desc, USB_DT_USB_EXT_CAP_SIZE);+	buf += USB_DT_USB_EXT_CAP_SIZE;++	memcpy(buf, &fsg_ss_cap_desc, USB_DT_USB_SS_CAP_SIZE);++	return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE+		+ USB_DT_USB_EXT_CAP_SIZE;+}++/*+ * Config descriptors must agree with the code that sets configurations+ * and with code managing interfaces and their altsettings.  They must+ * also handle different speeds and other-speed requests.+ */+static int populate_config_buf(struct usb_gadget *gadget,+		u8 *buf, u8 type, unsigned index)+{+	enum usb_device_speed			speed = gadget->speed;+	int					len;+	const struct usb_descriptor_header	**function;++	if (index > 0)+		return -EINVAL;++	if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG)+		speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed;+	function = gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH+		? (const struct usb_descriptor_header **)fsg_hs_function+		: (const struct usb_descriptor_header **)fsg_fs_function;++	/* for now, don't advertise srp-only devices */+	if (!gadget_is_otg(gadget))+		function++;++	len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);+	((struct usb_config_descriptor *) buf)->bDescriptorType = type;+	return len;+}+++/*-------------------------------------------------------------------------*/++/* These routines may be called in process context or in_irq */++/* Caller must hold fsg->lock */+static void wakeup_thread(struct fsg_dev *fsg)+{+	/* Tell the main thread that something has happened */+	fsg->thread_wakeup_needed = 1;+	if (fsg->thread_task)+		wake_up_process(fsg->thread_task);+}+++static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)+{+	unsigned long		flags;++	/* Do nothing if a higher-priority exception is already in progress.+	 * If a lower-or-equal priority exception is in progress, preempt it+	 * and notify the main thread by sending it a signal. */+	spin_lock_irqsave(&fsg->lock, flags);+	if (fsg->state <= new_state) {+		fsg->exception_req_tag = fsg->ep0_req_tag;+		fsg->state = new_state;+		if (fsg->thread_task)+			send_sig_info(SIGUSR1, SEND_SIG_FORCED,+					fsg->thread_task);+	}+	spin_unlock_irqrestore(&fsg->lock, flags);+}+++/*-------------------------------------------------------------------------*/++/* The disconnect callback and ep0 routines.  These always run in_irq,+ * except that ep0_queue() is called in the main thread to acknowledge+ * completion of various requests: set config, set interface, and+ * Bulk-only device reset. */++static void fsg_disconnect(struct usb_gadget *gadget)+{+	struct fsg_dev		*fsg = get_gadget_data(gadget);++	DBG(fsg, "disconnect or port reset\n");+	raise_exception(fsg, FSG_STATE_DISCONNECT);+}+++static int ep0_queue(struct fsg_dev *fsg)+{+	int	rc;++	rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC);+	if (rc != 0 && rc != -ESHUTDOWN) {++		/* We can't do much more than wait for a reset */+		WARNING(fsg, "error in submission: %s --> %d\n",+				fsg->ep0->name, rc);+	}+	return rc;+}++static void ep0_complete(struct usb_ep *ep, struct usb_request *req)+{+	struct fsg_dev		*fsg = ep->driver_data;++	if (req->actual > 0)+		dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);+	if (req->status || req->actual != req->length)+		DBG(fsg, "%s --> %d, %u/%u\n", __func__,+				req->status, req->actual, req->length);+	if (req->status == -ECONNRESET)		// Request was cancelled+		usb_ep_fifo_flush(ep);++	if (req->status == 0 && req->context)+		((fsg_routine_t) (req->context))(fsg);+}+++/*-------------------------------------------------------------------------*/++/* Bulk and interrupt endpoint completion handlers.+ * These always run in_irq. */++static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)+{+	struct fsg_dev		*fsg = ep->driver_data;+	struct fsg_buffhd	*bh = req->context;++	if (req->status || req->actual != req->length)+		DBG(fsg, "%s --> %d, %u/%u\n", __func__,+				req->status, req->actual, req->length);+	if (req->status == -ECONNRESET)		// Request was cancelled+		usb_ep_fifo_flush(ep);++	/* Hold the lock while we update the request and buffer states */+	smp_wmb();+	spin_lock(&fsg->lock);+	bh->inreq_busy = 0;+	bh->state = BUF_STATE_EMPTY;+	wakeup_thread(fsg);+	spin_unlock(&fsg->lock);+}++static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)+{+	struct fsg_dev		*fsg = ep->driver_data;+	struct fsg_buffhd	*bh = req->context;++	dump_msg(fsg, "bulk-out", req->buf, req->actual);+	if (req->status || req->actual != bh->bulk_out_intended_length)+		DBG(fsg, "%s --> %d, %u/%u\n", __func__,+				req->status, req->actual,+				bh->bulk_out_intended_length);+	if (req->status == -ECONNRESET)		// Request was cancelled+		usb_ep_fifo_flush(ep);++	/* Hold the lock while we update the request and buffer states */+	smp_wmb();+	spin_lock(&fsg->lock);+	bh->outreq_busy = 0;+	bh->state = BUF_STATE_FULL;+	wakeup_thread(fsg);+	spin_unlock(&fsg->lock);+}+++#ifdef CONFIG_USB_FILE_STORAGE_TEST+static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)+{+	struct fsg_dev		*fsg = ep->driver_data;+	struct fsg_buffhd	*bh = req->context;++	if (req->status || req->actual != req->length)+		DBG(fsg, "%s --> %d, %u/%u\n", __func__,+				req->status, req->actual, req->length);+	if (req->status == -ECONNRESET)		// Request was cancelled+		usb_ep_fifo_flush(ep);++	/* Hold the lock while we update the request and buffer states */+	smp_wmb();+	spin_lock(&fsg->lock);+	fsg->intreq_busy = 0;+	bh->state = BUF_STATE_EMPTY;+	wakeup_thread(fsg);+	spin_unlock(&fsg->lock);+}++#else+static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)+{}+#endif /* CONFIG_USB_FILE_STORAGE_TEST */+++/*-------------------------------------------------------------------------*/++/* Ep0 class-specific handlers.  These always run in_irq. */++#ifdef CONFIG_USB_FILE_STORAGE_TEST+static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)+{+	struct usb_request	*req = fsg->ep0req;+	static u8		cbi_reset_cmnd[6] = {+			SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};++	/* Error in command transfer? */+	if (req->status || req->length != req->actual ||+			req->actual < 6 || req->actual > MAX_COMMAND_SIZE) {++		/* Not all controllers allow a protocol stall after+		 * receiving control-out data, but we'll try anyway. */+		fsg_set_halt(fsg, fsg->ep0);+		return;			// Wait for reset+	}++	/* Is it the special reset command? */+	if (req->actual >= sizeof cbi_reset_cmnd &&+			memcmp(req->buf, cbi_reset_cmnd,+				sizeof cbi_reset_cmnd) == 0) {++		/* Raise an exception to stop the current operation+		 * and reinitialize our state. */+		DBG(fsg, "cbi reset request\n");+		raise_exception(fsg, FSG_STATE_RESET);+		return;+	}++	VDBG(fsg, "CB[I] accept device-specific command\n");+	spin_lock(&fsg->lock);++	/* Save the command for later */+	if (fsg->cbbuf_cmnd_size)+		WARNING(fsg, "CB[I] overwriting previous command\n");+	fsg->cbbuf_cmnd_size = req->actual;+	memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);++	wakeup_thread(fsg);+	spin_unlock(&fsg->lock);+}++#else+static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)+{}+#endif /* CONFIG_USB_FILE_STORAGE_TEST */+++static int class_setup_req(struct fsg_dev *fsg,+		const struct usb_ctrlrequest *ctrl)+{+	struct usb_request	*req = fsg->ep0req;+	int			value = -EOPNOTSUPP;+	u16			w_index = le16_to_cpu(ctrl->wIndex);+	u16                     w_value = le16_to_cpu(ctrl->wValue);+	u16			w_length = le16_to_cpu(ctrl->wLength);++	if (!fsg->config)+		return value;++	/* Handle Bulk-only class-specific requests */+	if (transport_is_bbb()) {+		switch (ctrl->bRequest) {++		case US_BULK_RESET_REQUEST:+			if (ctrl->bRequestType != (USB_DIR_OUT |+					USB_TYPE_CLASS | USB_RECIP_INTERFACE))+				break;+			if (w_index != 0 || w_value != 0 || w_length != 0) {+				value = -EDOM;+				break;+			}++			/* Raise an exception to stop the current operation+			 * and reinitialize our state. */+			DBG(fsg, "bulk reset request\n");+			raise_exception(fsg, FSG_STATE_RESET);+			value = DELAYED_STATUS;+			break;++		case US_BULK_GET_MAX_LUN:+			if (ctrl->bRequestType != (USB_DIR_IN |+					USB_TYPE_CLASS | USB_RECIP_INTERFACE))+				break;+			if (w_index != 0 || w_value != 0 || w_length != 1) {+				value = -EDOM;+				break;+			}+			VDBG(fsg, "get max LUN\n");+			*(u8 *) req->buf = fsg->nluns - 1;+			value = 1;+			break;+		}+	}++	/* Handle CBI class-specific requests */+	else {+		switch (ctrl->bRequest) {++		case USB_CBI_ADSC_REQUEST:+			if (ctrl->bRequestType != (USB_DIR_OUT |+					USB_TYPE_CLASS | USB_RECIP_INTERFACE))+				break;+			if (w_index != 0 || w_value != 0) {+				value = -EDOM;+				break;+			}+			if (w_length > MAX_COMMAND_SIZE) {+				value = -EOVERFLOW;+				break;+			}+			value = w_length;+			fsg->ep0req->context = received_cbi_adsc;+			break;+		}+	}++	if (value == -EOPNOTSUPP)+		VDBG(fsg,+			"unknown class-specific control req "+			"%02x.%02x v%04x i%04x l%u\n",+			ctrl->bRequestType, ctrl->bRequest,+			le16_to_cpu(ctrl->wValue), w_index, w_length);+	return value;+}+++/*-------------------------------------------------------------------------*/++/* Ep0 standard request handlers.  These always run in_irq. */++static int standard_setup_req(struct fsg_dev *fsg,+		const struct usb_ctrlrequest *ctrl)+{+	struct usb_request	*req = fsg->ep0req;+	int			value = -EOPNOTSUPP;+	u16			w_index = le16_to_cpu(ctrl->wIndex);+	u16			w_value = le16_to_cpu(ctrl->wValue);++	/* Usually this just stores reply data in the pre-allocated ep0 buffer,+	 * but config change events will also reconfigure hardware. */+	switch (ctrl->bRequest) {++	case USB_REQ_GET_DESCRIPTOR:+		if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |+				USB_RECIP_DEVICE))+			break;+		switch (w_value >> 8) {++		case USB_DT_DEVICE:+			VDBG(fsg, "get device descriptor\n");+			device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;+			value = sizeof device_desc;+			memcpy(req->buf, &device_desc, value);+			break;+		case USB_DT_DEVICE_QUALIFIER:+			VDBG(fsg, "get device qualifier\n");+			if (!gadget_is_dualspeed(fsg->gadget) ||+					fsg->gadget->speed == USB_SPEED_SUPER)+				break;+			/*+			 * Assume ep0 uses the same maxpacket value for both+			 * speeds+			 */+			dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;+			value = sizeof dev_qualifier;+			memcpy(req->buf, &dev_qualifier, value);+			break;++		case USB_DT_OTHER_SPEED_CONFIG:+			VDBG(fsg, "get other-speed config descriptor\n");+			if (!gadget_is_dualspeed(fsg->gadget) ||+					fsg->gadget->speed == USB_SPEED_SUPER)+				break;+			goto get_config;+		case USB_DT_CONFIG:+			VDBG(fsg, "get configuration descriptor\n");+get_config:+			value = populate_config_buf(fsg->gadget,+					req->buf,+					w_value >> 8,+					w_value & 0xff);+			break;++		case USB_DT_STRING:+			VDBG(fsg, "get string descriptor\n");++			/* wIndex == language code */+			value = usb_gadget_get_string(&fsg_stringtab,+					w_value & 0xff, req->buf);+			break;++		case USB_DT_BOS:+			VDBG(fsg, "get bos descriptor\n");++			if (gadget_is_superspeed(fsg->gadget))+				value = populate_bos(fsg, req->buf);+			break;+		}++		break;++	/* One config, two speeds */+	case USB_REQ_SET_CONFIGURATION:+		if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |+				USB_RECIP_DEVICE))+			break;+		VDBG(fsg, "set configuration\n");+		if (w_value == CONFIG_VALUE || w_value == 0) {+			fsg->new_config = w_value;++			/* Raise an exception to wipe out previous transaction+			 * state (queued bufs, etc) and set the new config. */+			raise_exception(fsg, FSG_STATE_CONFIG_CHANGE);+			value = DELAYED_STATUS;+		}+		break;+	case USB_REQ_GET_CONFIGURATION:+		if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |+				USB_RECIP_DEVICE))+			break;+		VDBG(fsg, "get configuration\n");+		*(u8 *) req->buf = fsg->config;+		value = 1;+		break;++	case USB_REQ_SET_INTERFACE:+		if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD |+				USB_RECIP_INTERFACE))+			break;+		if (fsg->config && w_index == 0) {++			/* Raise an exception to wipe out previous transaction+			 * state (queued bufs, etc) and install the new+			 * interface altsetting. */+			raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE);+			value = DELAYED_STATUS;+		}+		break;+	case USB_REQ_GET_INTERFACE:+		if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |+				USB_RECIP_INTERFACE))+			break;+		if (!fsg->config)+			break;+		if (w_index != 0) {+			value = -EDOM;+			break;+		}+		VDBG(fsg, "get interface\n");+		*(u8 *) req->buf = 0;+		value = 1;+		break;++	default:+		VDBG(fsg,+			"unknown control req %02x.%02x v%04x i%04x l%u\n",+			ctrl->bRequestType, ctrl->bRequest,+			w_value, w_index, le16_to_cpu(ctrl->wLength));+	}++	return value;+}+++static int fsg_setup(struct usb_gadget *gadget,+		const struct usb_ctrlrequest *ctrl)+{+	struct fsg_dev		*fsg = get_gadget_data(gadget);+	int			rc;+	int			w_length = le16_to_cpu(ctrl->wLength);++	++fsg->ep0_req_tag;		// Record arrival of a new request+	fsg->ep0req->context = NULL;+	fsg->ep0req->length = 0;+	dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl));++	if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)+		rc = class_setup_req(fsg, ctrl);+	else+		rc = standard_setup_req(fsg, ctrl);++	/* Respond with data/status or defer until later? */+	if (rc >= 0 && rc != DELAYED_STATUS) {+		rc = min(rc, w_length);+		fsg->ep0req->length = rc;+		fsg->ep0req->zero = rc < w_length;+		fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?+				"ep0-in" : "ep0-out");+		rc = ep0_queue(fsg);+	}++	/* Device either stalls (rc < 0) or reports success */+	return rc;+}+++/*-------------------------------------------------------------------------*/++/* All the following routines run in process context */+++/* Use this for bulk or interrupt transfers, not ep0 */+static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,+		struct usb_request *req, int *pbusy,+		enum fsg_buffer_state *state)+{+	int	rc;++	if (ep == fsg->bulk_in)+		dump_msg(fsg, "bulk-in", req->buf, req->length);+	else if (ep == fsg->intr_in)+		dump_msg(fsg, "intr-in", req->buf, req->length);++	spin_lock_irq(&fsg->lock);+	*pbusy = 1;+	*state = BUF_STATE_BUSY;+	spin_unlock_irq(&fsg->lock);+	rc = usb_ep_queue(ep, req, GFP_KERNEL);+	if (rc != 0) {+		*pbusy = 0;+		*state = BUF_STATE_EMPTY;++		/* We can't do much more than wait for a reset */++		/* Note: currently the net2280 driver fails zero-length+		 * submissions if DMA is enabled. */+		if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP &&+						req->length == 0))+			WARNING(fsg, "error in submission: %s --> %d\n",+					ep->name, rc);+	}+}+++static int sleep_thread(struct fsg_dev *fsg)+{+	int	rc = 0;++	/* Wait until a signal arrives or we are woken up */+	for (;;) {+		try_to_freeze();+		set_current_state(TASK_INTERRUPTIBLE);+		if (signal_pending(current)) {+			rc = -EINTR;+			break;+		}+		if (fsg->thread_wakeup_needed)+			break;+		schedule();+	}+	__set_current_state(TASK_RUNNING);+	fsg->thread_wakeup_needed = 0;+	return rc;+}+++/*-------------------------------------------------------------------------*/++static int do_read(struct fsg_dev *fsg)+{+	struct fsg_lun		*curlun = fsg->curlun;+	u32			lba;+	struct fsg_buffhd	*bh;+	int			rc;+	u32			amount_left;+	loff_t			file_offset, file_offset_tmp;+	unsigned int		amount;+	ssize_t			nread;++	/* Get the starting Logical Block Address and check that it's+	 * not too big */+	if (fsg->cmnd[0] == READ_6)+		lba = get_unaligned_be24(&fsg->cmnd[1]);+	else {+		lba = get_unaligned_be32(&fsg->cmnd[2]);++		/* We allow DPO (Disable Page Out = don't save data in the+		 * cache) and FUA (Force Unit Access = don't read from the+		 * cache), but we don't implement them. */+		if ((fsg->cmnd[1] & ~0x18) != 0) {+			curlun->sense_data = SS_INVALID_FIELD_IN_CDB;+			return -EINVAL;+		}+	}+	if (lba >= curlun->num_sectors) {+		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;+		return -EINVAL;+	}+	file_offset = ((loff_t) lba) << curlun->blkbits;++	/* Carry out the file reads */+	amount_left = fsg->data_size_from_cmnd;+	if (unlikely(amount_left == 0))+		return -EIO;		// No default reply++	for (;;) {++		/* Figure out how much we need to read:+		 * Try to read the remaining amount.+		 * But don't read more than the buffer size.+		 * And don't try to read past the end of the file.+		 */+		amount = min((unsigned int) amount_left, mod_data.buflen);+		amount = min((loff_t) amount,+				curlun->file_length - file_offset);++		/* Wait for the next buffer to become available */+		bh = fsg->next_buffhd_to_fill;+		while (bh->state != BUF_STATE_EMPTY) {+			rc = sleep_thread(fsg);+			if (rc)+				return rc;+		}++		/* If we were asked to read past the end of file,+		 * end with an empty buffer. */+		if (amount == 0) {+			curlun->sense_data =+					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;+			curlun->sense_data_info = file_offset >> curlun->blkbits;+			curlun->info_valid = 1;+			bh->inreq->length = 0;+			bh->state = BUF_STATE_FULL;+			break;+		}++		/* Perform the read */+		file_offset_tmp = file_offset;+		nread = vfs_read(curlun->filp,+				(char __user *) bh->buf,+				amount, &file_offset_tmp);+		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,+				(unsigned long long) file_offset,+				(int) nread);+		if (signal_pending(current))+			return -EINTR;++		if (nread < 0) {+			LDBG(curlun, "error in file read: %d\n",+					(int) nread);+			nread = 0;+		} else if (nread < amount) {+			LDBG(curlun, "partial file read: %d/%u\n",+					(int) nread, amount);+			nread = round_down(nread, curlun->blksize);+		}+		file_offset  += nread;+		amount_left  -= nread;+		fsg->residue -= nread;++		/* Except at the end of the transfer, nread will be+		 * equal to the buffer size, which is divisible by the+		 * bulk-in maxpacket size.+		 */+		bh->inreq->length = nread;+		bh->state = BUF_STATE_FULL;++		/* If an error occurred, report it and its position */+		if (nread < amount) {+			curlun->sense_data = SS_UNRECOVERED_READ_ERROR;+			curlun->sense_data_info = file_offset >> curlun->blkbits;+			curlun->info_valid = 1;+			break;+		}++		if (amount_left == 0)+			break;		// No more left to read++		/* Send this buffer and go read some more */+		bh->inreq->zero = 0;+		start_transfer(fsg, fsg->bulk_in, bh->inreq,+				&bh->inreq_busy, &bh->state);+		fsg->next_buffhd_to_fill = bh->next;+	}++	return -EIO;		// No default reply+}+++/*-------------------------------------------------------------------------*/++static int do_write(struct fsg_dev *fsg)+{+	struct fsg_lun		*curlun = fsg->curlun;+	u32			lba;+	struct fsg_buffhd	*bh;+	int			get_some_more;+	u32			amount_left_to_req, amount_left_to_write;+	loff_t			usb_offset, file_offset, file_offset_tmp;+	unsigned int		amount;+	ssize_t			nwritten;+	int			rc;++	if (curlun->ro) {+		curlun->sense_data = SS_WRITE_PROTECTED;+		return -EINVAL;+	}+	spin_lock(&curlun->filp->f_lock);+	curlun->filp->f_flags &= ~O_SYNC;	// Default is not to wait+	spin_unlock(&curlun->filp->f_lock);++	/* Get the starting Logical Block Address and check that it's+	 * not too big */+	if (fsg->cmnd[0] == WRITE_6)+		lba = get_unaligned_be24(&fsg->cmnd[1]);+	else {+		lba = get_unaligned_be32(&fsg->cmnd[2]);++		/* We allow DPO (Disable Page Out = don't save data in the+		 * cache) and FUA (Force Unit Access = write directly to the+		 * medium).  We don't implement DPO; we implement FUA by+		 * performing synchronous output. */+		if ((fsg->cmnd[1] & ~0x18) != 0) {+			curlun->sense_data = SS_INVALID_FIELD_IN_CDB;+			return -EINVAL;+		}+		/* FUA */+		if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) {+			spin_lock(&curlun->filp->f_lock);+			curlun->filp->f_flags |= O_DSYNC;+			spin_unlock(&curlun->filp->f_lock);+		}+	}+	if (lba >= curlun->num_sectors) {+		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;+		return -EINVAL;+	}++	/* Carry out the file writes */+	get_some_more = 1;+	file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits;+	amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd;++	while (amount_left_to_write > 0) {++		/* Queue a request for more data from the host */+		bh = fsg->next_buffhd_to_fill;+		if (bh->state == BUF_STATE_EMPTY && get_some_more) {++			/* Figure out how much we want to get:+			 * Try to get the remaining amount,+			 * but not more than the buffer size.+			 */+			amount = min(amount_left_to_req, mod_data.buflen);++			/* Beyond the end of the backing file? */+			if (usb_offset >= curlun->file_length) {+				get_some_more = 0;+				curlun->sense_data =+					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;+				curlun->sense_data_info = usb_offset >> curlun->blkbits;+				curlun->info_valid = 1;+				continue;+			}++			/* Get the next buffer */+			usb_offset += amount;+			fsg->usb_amount_left -= amount;+			amount_left_to_req -= amount;+			if (amount_left_to_req == 0)+				get_some_more = 0;++			/* Except at the end of the transfer, amount will be+			 * equal to the buffer size, which is divisible by+			 * the bulk-out maxpacket size.+			 */+			set_bulk_out_req_length(fsg, bh, amount);+			start_transfer(fsg, fsg->bulk_out, bh->outreq,+					&bh->outreq_busy, &bh->state);+			fsg->next_buffhd_to_fill = bh->next;+			continue;+		}++		/* Write the received data to the backing file */+		bh = fsg->next_buffhd_to_drain;+		if (bh->state == BUF_STATE_EMPTY && !get_some_more)+			break;			// We stopped early+		if (bh->state == BUF_STATE_FULL) {+			smp_rmb();+			fsg->next_buffhd_to_drain = bh->next;+			bh->state = BUF_STATE_EMPTY;++			/* Did something go wrong with the transfer? */+			if (bh->outreq->status != 0) {+				curlun->sense_data = SS_COMMUNICATION_FAILURE;+				curlun->sense_data_info = file_offset >> curlun->blkbits;+				curlun->info_valid = 1;+				break;+			}++			amount = bh->outreq->actual;+			if (curlun->file_length - file_offset < amount) {+				LERROR(curlun,+	"write %u @ %llu beyond end %llu\n",+	amount, (unsigned long long) file_offset,+	(unsigned long long) curlun->file_length);+				amount = curlun->file_length - file_offset;+			}++			/* Don't accept excess data.  The spec doesn't say+			 * what to do in this case.  We'll ignore the error.+			 */+			amount = min(amount, bh->bulk_out_intended_length);++			/* Don't write a partial block */+			amount = round_down(amount, curlun->blksize);+			if (amount == 0)+				goto empty_write;++			/* Perform the write */+			file_offset_tmp = file_offset;+			nwritten = vfs_write(curlun->filp,+					(char __user *) bh->buf,+					amount, &file_offset_tmp);+			VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,+					(unsigned long long) file_offset,+					(int) nwritten);+			if (signal_pending(current))+				return -EINTR;		// Interrupted!++			if (nwritten < 0) {+				LDBG(curlun, "error in file write: %d\n",+						(int) nwritten);+				nwritten = 0;+			} else if (nwritten < amount) {+				LDBG(curlun, "partial file write: %d/%u\n",+						(int) nwritten, amount);+				nwritten = round_down(nwritten, curlun->blksize);+			}+			file_offset += nwritten;+			amount_left_to_write -= nwritten;+			fsg->residue -= nwritten;++			/* If an error occurred, report it and its position */+			if (nwritten < amount) {+				curlun->sense_data = SS_WRITE_ERROR;+				curlun->sense_data_info = file_offset >> curlun->blkbits;+				curlun->info_valid = 1;+				break;+			}++ empty_write:+			/* Did the host decide to stop early? */+			if (bh->outreq->actual < bh->bulk_out_intended_length) {+				fsg->short_packet_received = 1;+				break;+			}+			continue;+		}++		/* Wait for something to happen */+		rc = sleep_thread(fsg);+		if (rc)+			return rc;+	}++	return -EIO;		// No default reply+}+++/*-------------------------------------------------------------------------*/++static int do_synchronize_cache(struct fsg_dev *fsg)+{+	struct fsg_lun	*curlun = fsg->curlun;+	int		rc;++	/* We ignore the requested LBA and write out all file's+	 * dirty data buffers. */+	rc = fsg_lun_fsync_sub(curlun);+	if (rc)+		curlun->sense_data = SS_WRITE_ERROR;+	return 0;+}+++/*-------------------------------------------------------------------------*/++static void invalidate_sub(struct fsg_lun *curlun)+{+	struct file	*filp = curlun->filp;+	struct inode	*inode = filp->f_path.dentry->d_inode;+	unsigned long	rc;++	rc = invalidate_mapping_pages(inode->i_mapping, 0, -1);+	VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc);+}++static int do_verify(struct fsg_dev *fsg)+{+	struct fsg_lun		*curlun = fsg->curlun;+	u32			lba;+	u32			verification_length;+	struct fsg_buffhd	*bh = fsg->next_buffhd_to_fill;+	loff_t			file_offset, file_offset_tmp;+	u32			amount_left;+	unsigned int		amount;+	ssize_t			nread;++	/* Get the starting Logical Block Address and check that it's+	 * not too big */+	lba = get_unaligned_be32(&fsg->cmnd[2]);+	if (lba >= curlun->num_sectors) {+		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;+		return -EINVAL;+	}++	/* We allow DPO (Disable Page Out = don't save data in the+	 * cache) but we don't implement it. */+	if ((fsg->cmnd[1] & ~0x10) != 0) {+		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;+		return -EINVAL;+	}++	verification_length = get_unaligned_be16(&fsg->cmnd[7]);+	if (unlikely(verification_length == 0))+		return -EIO;		// No default reply++	/* Prepare to carry out the file verify */+	amount_left = verification_length << curlun->blkbits;+	file_offset = ((loff_t) lba) << curlun->blkbits;++	/* Write out all the dirty buffers before invalidating them */+	fsg_lun_fsync_sub(curlun);+	if (signal_pending(current))+		return -EINTR;++	invalidate_sub(curlun);+	if (signal_pending(current))+		return -EINTR;++	/* Just try to read the requested blocks */+	while (amount_left > 0) {++		/* Figure out how much we need to read:+		 * Try to read the remaining amount, but not more than+		 * the buffer size.+		 * And don't try to read past the end of the file.+		 */+		amount = min((unsigned int) amount_left, mod_data.buflen);+		amount = min((loff_t) amount,+				curlun->file_length - file_offset);+		if (amount == 0) {+			curlun->sense_data =+					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;+			curlun->sense_data_info = file_offset >> curlun->blkbits;+			curlun->info_valid = 1;+			break;+		}++		/* Perform the read */+		file_offset_tmp = file_offset;+		nread = vfs_read(curlun->filp,+				(char __user *) bh->buf,+				amount, &file_offset_tmp);+		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,+				(unsigned long long) file_offset,+				(int) nread);+		if (signal_pending(current))+			return -EINTR;++		if (nread < 0) {+			LDBG(curlun, "error in file verify: %d\n",+					(int) nread);+			nread = 0;+		} else if (nread < amount) {+			LDBG(curlun, "partial file verify: %d/%u\n",+					(int) nread, amount);+			nread = round_down(nread, curlun->blksize);+		}+		if (nread == 0) {+			curlun->sense_data = SS_UNRECOVERED_READ_ERROR;+			curlun->sense_data_info = file_offset >> curlun->blkbits;+			curlun->info_valid = 1;+			break;+		}+		file_offset += nread;+		amount_left -= nread;+	}+	return 0;+}+++/*-------------------------------------------------------------------------*/++static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)+{+	u8	*buf = (u8 *) bh->buf;++	static char vendor_id[] = "Linux   ";+	static char product_disk_id[] = "File-Stor Gadget";+	static char product_cdrom_id[] = "File-CD Gadget  ";++	if (!fsg->curlun) {		// Unsupported LUNs are okay+		fsg->bad_lun_okay = 1;+		memset(buf, 0, 36);+		buf[0] = 0x7f;		// Unsupported, no device-type+		buf[4] = 31;		// Additional length+		return 36;+	}++	memset(buf, 0, 8);+	buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK);+	if (mod_data.removable)+		buf[1] = 0x80;+	buf[2] = 2;		// ANSI SCSI level 2+	buf[3] = 2;		// SCSI-2 INQUIRY data format+	buf[4] = 31;		// Additional length+				// No special options+	sprintf(buf + 8, "%-8s%-16s%04x", vendor_id,+			(mod_data.cdrom ? product_cdrom_id :+				product_disk_id),+			mod_data.release);+	return 36;+}+++static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)+{+	struct fsg_lun	*curlun = fsg->curlun;+	u8		*buf = (u8 *) bh->buf;+	u32		sd, sdinfo;+	int		valid;++	/*+	 * From the SCSI-2 spec., section 7.9 (Unit attention condition):+	 *+	 * If a REQUEST SENSE command is received from an initiator+	 * with a pending unit attention condition (before the target+	 * generates the contingent allegiance condition), then the+	 * target shall either:+	 *   a) report any pending sense data and preserve the unit+	 *	attention condition on the logical unit, or,+	 *   b) report the unit attention condition, may discard any+	 *	pending sense data, and clear the unit attention+	 *	condition on the logical unit for that initiator.+	 *+	 * FSG normally uses option a); enable this code to use option b).+	 */+#if 0+	if (curlun && curlun->unit_attention_data != SS_NO_SENSE) {+		curlun->sense_data = curlun->unit_attention_data;+		curlun->unit_attention_data = SS_NO_SENSE;+	}+#endif++	if (!curlun) {		// Unsupported LUNs are okay+		fsg->bad_lun_okay = 1;+		sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;+		sdinfo = 0;+		valid = 0;+	} else {+		sd = curlun->sense_data;+		sdinfo = curlun->sense_data_info;+		valid = curlun->info_valid << 7;+		curlun->sense_data = SS_NO_SENSE;+		curlun->sense_data_info = 0;+		curlun->info_valid = 0;+	}++	memset(buf, 0, 18);+	buf[0] = valid | 0x70;			// Valid, current error+	buf[2] = SK(sd);+	put_unaligned_be32(sdinfo, &buf[3]);	/* Sense information */+	buf[7] = 18 - 8;			// Additional sense length+	buf[12] = ASC(sd);+	buf[13] = ASCQ(sd);+	return 18;+}+++static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)+{+	struct fsg_lun	*curlun = fsg->curlun;+	u32		lba = get_unaligned_be32(&fsg->cmnd[2]);+	int		pmi = fsg->cmnd[8];+	u8		*buf = (u8 *) bh->buf;++	/* Check the PMI and LBA fields */+	if (pmi > 1 || (pmi == 0 && lba != 0)) {+		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;+		return -EINVAL;+	}++	put_unaligned_be32(curlun->num_sectors - 1, &buf[0]);+						/* Max logical block */+	put_unaligned_be32(curlun->blksize, &buf[4]);	/* Block length */+	return 8;+}+++static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh)+{+	struct fsg_lun	*curlun = fsg->curlun;+	int		msf = fsg->cmnd[1] & 0x02;+	u32		lba = get_unaligned_be32(&fsg->cmnd[2]);+	u8		*buf = (u8 *) bh->buf;++	if ((fsg->cmnd[1] & ~0x02) != 0) {		/* Mask away MSF */+		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;+		return -EINVAL;+	}+	if (lba >= curlun->num_sectors) {+		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;+		return -EINVAL;+	}++	memset(buf, 0, 8);+	buf[0] = 0x01;		/* 2048 bytes of user data, rest is EC */+	store_cdrom_address(&buf[4], msf, lba);+	return 8;+}+++static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh)+{+	struct fsg_lun	*curlun = fsg->curlun;+	int		msf = fsg->cmnd[1] & 0x02;+	int		start_track = fsg->cmnd[6];+	u8		*buf = (u8 *) bh->buf;++	if ((fsg->cmnd[1] & ~0x02) != 0 ||		/* Mask away MSF */+			start_track > 1) {+		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;+		return -EINVAL;+	}++	memset(buf, 0, 20);+	buf[1] = (20-2);		/* TOC data length */+	buf[2] = 1;			/* First track number */+	buf[3] = 1;			/* Last track number */+	buf[5] = 0x16;			/* Data track, copying allowed */+	buf[6] = 0x01;			/* Only track is number 1 */+	store_cdrom_address(&buf[8], msf, 0);++	buf[13] = 0x16;			/* Lead-out track is data */+	buf[14] = 0xAA;			/* Lead-out track number */+	store_cdrom_address(&buf[16], msf, curlun->num_sectors);+	return 20;+}+++static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)+{+	struct fsg_lun	*curlun = fsg->curlun;+	int		mscmnd = fsg->cmnd[0];+	u8		*buf = (u8 *) bh->buf;+	u8		*buf0 = buf;+	int		pc, page_code;+	int		changeable_values, all_pages;+	int		valid_page = 0;+	int		len, limit;++	if ((fsg->cmnd[1] & ~0x08) != 0) {		// Mask away DBD+		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;+		return -EINVAL;+	}+	pc = fsg->cmnd[2] >> 6;+	page_code = fsg->cmnd[2] & 0x3f;+	if (pc == 3) {+		curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;+		return -EINVAL;+	}+	changeable_values = (pc == 1);+	all_pages = (page_code == 0x3f);++	/* Write the mode parameter header.  Fixed values are: default+	 * medium type, no cache control (DPOFUA), and no block descriptors.+	 * The only variable value is the WriteProtect bit.  We will fill in+	 * the mode data length later. */+	memset(buf, 0, 8);+	if (mscmnd == MODE_SENSE) {+		buf[2] = (curlun->ro ? 0x80 : 0x00);		// WP, DPOFUA+		buf += 4;+		limit = 255;+	} else {			// MODE_SENSE_10+		buf[3] = (curlun->ro ? 0x80 : 0x00);		// WP, DPOFUA+		buf += 8;+		limit = 65535;		// Should really be mod_data.buflen+	}++	/* No block descriptors */++	/* The mode pages, in numerical order.  The only page we support+	 * is the Caching page. */+	if (page_code == 0x08 || all_pages) {+		valid_page = 1;+		buf[0] = 0x08;		// Page code+		buf[1] = 10;		// Page length+		memset(buf+2, 0, 10);	// None of the fields are changeable++		if (!changeable_values) {+			buf[2] = 0x04;	// Write cache enable,+					// Read cache not disabled+					// No cache retention priorities+			put_unaligned_be16(0xffff, &buf[4]);+					/* Don't disable prefetch */+					/* Minimum prefetch = 0 */+			put_unaligned_be16(0xffff, &buf[8]);+					/* Maximum prefetch */+			put_unaligned_be16(0xffff, &buf[10]);+					/* Maximum prefetch ceiling */+		}+		buf += 12;+	}++	/* Check that a valid page was requested and the mode data length+	 * isn't too long. */+	len = buf - buf0;+	if (!valid_page || len > limit) {+		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;+		return -EINVAL;+	}++	/*  Store the mode data length */+	if (mscmnd == MODE_SENSE)+		buf0[0] = len - 1;+	else+		put_unaligned_be16(len - 2, buf0);+	return len;+}+++static int do_start_stop(struct fsg_dev *fsg)+{+	struct fsg_lun	*curlun = fsg->curlun;+	int		loej, start;++	if (!mod_data.removable) {+		curlun->sense_data = SS_INVALID_COMMAND;+		return -EINVAL;+	}++	// int immed = fsg->cmnd[1] & 0x01;+	loej = fsg->cmnd[4] & 0x02;+	start = fsg->cmnd[4] & 0x01;++#ifdef CONFIG_USB_FILE_STORAGE_TEST+	if ((fsg->cmnd[1] & ~0x01) != 0 ||		// Mask away Immed+			(fsg->cmnd[4] & ~0x03) != 0) {	// Mask LoEj, Start+		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;+		return -EINVAL;+	}++	if (!start) {++		/* Are we allowed to unload the media? */+		if (curlun->prevent_medium_removal) {+			LDBG(curlun, "unload attempt prevented\n");+			curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;+			return -EINVAL;+		}+		if (loej) {		// Simulate an unload/eject+			up_read(&fsg->filesem);+			down_write(&fsg->filesem);+			fsg_lun_close(curlun);+			up_write(&fsg->filesem);+			down_read(&fsg->filesem);+		}+	} else {++		/* Our emulation doesn't support mounting; the medium is+		 * available for use as soon as it is loaded. */+		if (!fsg_lun_is_open(curlun)) {+			curlun->sense_data = SS_MEDIUM_NOT_PRESENT;+			return -EINVAL;+		}+	}+#endif+	return 0;+}+++static int do_prevent_allow(struct fsg_dev *fsg)+{+	struct fsg_lun	*curlun = fsg->curlun;+	int		prevent;++	if (!mod_data.removable) {+		curlun->sense_data = SS_INVALID_COMMAND;+		return -EINVAL;+	}++	prevent = fsg->cmnd[4] & 0x01;+	if ((fsg->cmnd[4] & ~0x01) != 0) {		// Mask away Prevent+		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;+		return -EINVAL;+	}++	if (curlun->prevent_medium_removal && !prevent)+		fsg_lun_fsync_sub(curlun);+	curlun->prevent_medium_removal = prevent;+	return 0;+}+++static int do_read_format_capacities(struct fsg_dev *fsg,+			struct fsg_buffhd *bh)+{+	struct fsg_lun	*curlun = fsg->curlun;+	u8		*buf = (u8 *) bh->buf;++	buf[0] = buf[1] = buf[2] = 0;+	buf[3] = 8;		// Only the Current/Maximum Capacity Descriptor+	buf += 4;++	put_unaligned_be32(curlun->num_sectors, &buf[0]);+						/* Number of blocks */+	put_unaligned_be32(curlun->blksize, &buf[4]);	/* Block length */+	buf[4] = 0x02;				/* Current capacity */+	return 12;+}+++static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh)+{+	struct fsg_lun	*curlun = fsg->curlun;++	/* We don't support MODE SELECT */+	curlun->sense_data = SS_INVALID_COMMAND;+	return -EINVAL;+}+++/*-------------------------------------------------------------------------*/++static int halt_bulk_in_endpoint(struct fsg_dev *fsg)+{+	int	rc;++	rc = fsg_set_halt(fsg, fsg->bulk_in);+	if (rc == -EAGAIN)+		VDBG(fsg, "delayed bulk-in endpoint halt\n");+	while (rc != 0) {+		if (rc != -EAGAIN) {+			WARNING(fsg, "usb_ep_set_halt -> %d\n", rc);+			rc = 0;+			break;+		}++		/* Wait for a short time and then try again */+		if (msleep_interruptible(100) != 0)+			return -EINTR;+		rc = usb_ep_set_halt(fsg->bulk_in);+	}+	return rc;+}++static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)+{+	int	rc;++	DBG(fsg, "bulk-in set wedge\n");+	rc = usb_ep_set_wedge(fsg->bulk_in);+	if (rc == -EAGAIN)+		VDBG(fsg, "delayed bulk-in endpoint wedge\n");+	while (rc != 0) {+		if (rc != -EAGAIN) {+			WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc);+			rc = 0;+			break;+		}++		/* Wait for a short time and then try again */+		if (msleep_interruptible(100) != 0)+			return -EINTR;+		rc = usb_ep_set_wedge(fsg->bulk_in);+	}+	return rc;+}++static int throw_away_data(struct fsg_dev *fsg)+{+	struct fsg_buffhd	*bh;+	u32			amount;+	int			rc;++	while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY ||+			fsg->usb_amount_left > 0) {++		/* Throw away the data in a filled buffer */+		if (bh->state == BUF_STATE_FULL) {+			smp_rmb();+			bh->state = BUF_STATE_EMPTY;+			fsg->next_buffhd_to_drain = bh->next;++			/* A short packet or an error ends everything */+			if (bh->outreq->actual < bh->bulk_out_intended_length ||+					bh->outreq->status != 0) {+				raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);+				return -EINTR;+			}+			continue;+		}++		/* Try to submit another request if we need one */+		bh = fsg->next_buffhd_to_fill;+		if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) {+			amount = min(fsg->usb_amount_left,+					(u32) mod_data.buflen);++			/* Except at the end of the transfer, amount will be+			 * equal to the buffer size, which is divisible by+			 * the bulk-out maxpacket size.+			 */+			set_bulk_out_req_length(fsg, bh, amount);+			start_transfer(fsg, fsg->bulk_out, bh->outreq,+					&bh->outreq_busy, &bh->state);+			fsg->next_buffhd_to_fill = bh->next;+			fsg->usb_amount_left -= amount;+			continue;+		}++		/* Otherwise wait for something to happen */+		rc = sleep_thread(fsg);+		if (rc)+			return rc;+	}+	return 0;+}+++static int finish_reply(struct fsg_dev *fsg)+{+	struct fsg_buffhd	*bh = fsg->next_buffhd_to_fill;+	int			rc = 0;++	switch (fsg->data_dir) {+	case DATA_DIR_NONE:+		break;			// Nothing to send++	/* If we don't know whether the host wants to read or write,+	 * this must be CB or CBI with an unknown command.  We mustn't+	 * try to send or receive any data.  So stall both bulk pipes+	 * if we can and wait for a reset. */+	case DATA_DIR_UNKNOWN:+		if (mod_data.can_stall) {+			fsg_set_halt(fsg, fsg->bulk_out);+			rc = halt_bulk_in_endpoint(fsg);+		}+		break;++	/* All but the last buffer of data must have already been sent */+	case DATA_DIR_TO_HOST:+		if (fsg->data_size == 0)+			;		// Nothing to send++		/* If there's no residue, simply send the last buffer */+		else if (fsg->residue == 0) {+			bh->inreq->zero = 0;+			start_transfer(fsg, fsg->bulk_in, bh->inreq,+					&bh->inreq_busy, &bh->state);+			fsg->next_buffhd_to_fill = bh->next;+		}++		/* There is a residue.  For CB and CBI, simply mark the end+		 * of the data with a short packet.  However, if we are+		 * allowed to stall, there was no data at all (residue ==+		 * data_size), and the command failed (invalid LUN or+		 * sense data is set), then halt the bulk-in endpoint+		 * instead. */+		else if (!transport_is_bbb()) {+			if (mod_data.can_stall &&+					fsg->residue == fsg->data_size &&+	(!fsg->curlun || fsg->curlun->sense_data != SS_NO_SENSE)) {+				bh->state = BUF_STATE_EMPTY;+				rc = halt_bulk_in_endpoint(fsg);+			} else {+				bh->inreq->zero = 1;+				start_transfer(fsg, fsg->bulk_in, bh->inreq,+						&bh->inreq_busy, &bh->state);+				fsg->next_buffhd_to_fill = bh->next;+			}+		}++		/*+		 * For Bulk-only, mark the end of the data with a short+		 * packet.  If we are allowed to stall, halt the bulk-in+		 * endpoint.  (Note: This violates the Bulk-Only Transport+		 * specification, which requires us to pad the data if we+		 * don't halt the endpoint.  Presumably nobody will mind.)+		 */+		else {+			bh->inreq->zero = 1;+			start_transfer(fsg, fsg->bulk_in, bh->inreq,+					&bh->inreq_busy, &bh->state);+			fsg->next_buffhd_to_fill = bh->next;+			if (mod_data.can_stall)+				rc = halt_bulk_in_endpoint(fsg);+		}+		break;++	/* We have processed all we want from the data the host has sent.+	 * There may still be outstanding bulk-out requests. */+	case DATA_DIR_FROM_HOST:+		if (fsg->residue == 0)+			;		// Nothing to receive++		/* Did the host stop sending unexpectedly early? */+		else if (fsg->short_packet_received) {+			raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);+			rc = -EINTR;+		}++		/* We haven't processed all the incoming data.  Even though+		 * we may be allowed to stall, doing so would cause a race.+		 * The controller may already have ACK'ed all the remaining+		 * bulk-out packets, in which case the host wouldn't see a+		 * STALL.  Not realizing the endpoint was halted, it wouldn't+		 * clear the halt -- leading to problems later on. */+#if 0+		else if (mod_data.can_stall) {+			fsg_set_halt(fsg, fsg->bulk_out);+			raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);+			rc = -EINTR;+		}+#endif++		/* We can't stall.  Read in the excess data and throw it+		 * all away. */+		else+			rc = throw_away_data(fsg);+		break;+	}+	return rc;+}+++static int send_status(struct fsg_dev *fsg)+{+	struct fsg_lun		*curlun = fsg->curlun;+	struct fsg_buffhd	*bh;+	int			rc;+	u8			status = US_BULK_STAT_OK;+	u32			sd, sdinfo = 0;++	/* Wait for the next buffer to become available */+	bh = fsg->next_buffhd_to_fill;+	while (bh->state != BUF_STATE_EMPTY) {+		rc = sleep_thread(fsg);+		if (rc)+			return rc;+	}++	if (curlun) {+		sd = curlun->sense_data;+		sdinfo = curlun->sense_data_info;+	} else if (fsg->bad_lun_okay)+		sd = SS_NO_SENSE;+	else+		sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;++	if (fsg->phase_error) {+		DBG(fsg, "sending phase-error status\n");+		status = US_BULK_STAT_PHASE;+		sd = SS_INVALID_COMMAND;+	} else if (sd != SS_NO_SENSE) {+		DBG(fsg, "sending command-failure status\n");+		status = US_BULK_STAT_FAIL;+		VDBG(fsg, "  sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"+				"  info x%x\n",+				SK(sd), ASC(sd), ASCQ(sd), sdinfo);+	}++	if (transport_is_bbb()) {+		struct bulk_cs_wrap	*csw = bh->buf;++		/* Store and send the Bulk-only CSW */+		csw->Signature = cpu_to_le32(US_BULK_CS_SIGN);+		csw->Tag = fsg->tag;+		csw->Residue = cpu_to_le32(fsg->residue);+		csw->Status = status;++		bh->inreq->length = US_BULK_CS_WRAP_LEN;+		bh->inreq->zero = 0;+		start_transfer(fsg, fsg->bulk_in, bh->inreq,+				&bh->inreq_busy, &bh->state);++	} else if (mod_data.transport_type == USB_PR_CB) {++		/* Control-Bulk transport has no status phase! */+		return 0;++	} else {			// USB_PR_CBI+		struct interrupt_data	*buf = bh->buf;++		/* Store and send the Interrupt data.  UFI sends the ASC+		 * and ASCQ bytes.  Everything else sends a Type (which+		 * is always 0) and the status Value. */+		if (mod_data.protocol_type == USB_SC_UFI) {+			buf->bType = ASC(sd);+			buf->bValue = ASCQ(sd);+		} else {+			buf->bType = 0;+			buf->bValue = status;+		}+		fsg->intreq->length = CBI_INTERRUPT_DATA_LEN;++		fsg->intr_buffhd = bh;		// Point to the right buffhd+		fsg->intreq->buf = bh->inreq->buf;+		fsg->intreq->context = bh;+		start_transfer(fsg, fsg->intr_in, fsg->intreq,+				&fsg->intreq_busy, &bh->state);+	}++	fsg->next_buffhd_to_fill = bh->next;+	return 0;+}+++/*-------------------------------------------------------------------------*/++/* Check whether the command is properly formed and whether its data size+ * and direction agree with the values we already have. */+static int check_command(struct fsg_dev *fsg, int cmnd_size,+		enum data_direction data_dir, unsigned int mask,+		int needs_medium, const char *name)+{+	int			i;+	int			lun = fsg->cmnd[1] >> 5;+	static const char	dirletter[4] = {'u', 'o', 'i', 'n'};+	char			hdlen[20];+	struct fsg_lun		*curlun;++	/* Adjust the expected cmnd_size for protocol encapsulation padding.+	 * Transparent SCSI doesn't pad. */+	if (protocol_is_scsi())+		;++	/* There's some disagreement as to whether RBC pads commands or not.+	 * We'll play it safe and accept either form. */+	else if (mod_data.protocol_type == USB_SC_RBC) {+		if (fsg->cmnd_size == 12)+			cmnd_size = 12;++	/* All the other protocols pad to 12 bytes */+	} else+		cmnd_size = 12;++	hdlen[0] = 0;+	if (fsg->data_dir != DATA_DIR_UNKNOWN)+		sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir],+				fsg->data_size);+	VDBG(fsg, "SCSI command: %s;  Dc=%d, D%c=%u;  Hc=%d%s\n",+			name, cmnd_size, dirletter[(int) data_dir],+			fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen);++	/* We can't reply at all until we know the correct data direction+	 * and size. */+	if (fsg->data_size_from_cmnd == 0)+		data_dir = DATA_DIR_NONE;+	if (fsg->data_dir == DATA_DIR_UNKNOWN) {	// CB or CBI+		fsg->data_dir = data_dir;+		fsg->data_size = fsg->data_size_from_cmnd;++	} else {					// Bulk-only+		if (fsg->data_size < fsg->data_size_from_cmnd) {++			/* Host data size < Device data size is a phase error.+			 * Carry out the command, but only transfer as much+			 * as we are allowed. */+			fsg->data_size_from_cmnd = fsg->data_size;+			fsg->phase_error = 1;+		}+	}+	fsg->residue = fsg->usb_amount_left = fsg->data_size;++	/* Conflicting data directions is a phase error */+	if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) {+		fsg->phase_error = 1;+		return -EINVAL;+	}++	/* Verify the length of the command itself */+	if (cmnd_size != fsg->cmnd_size) {++		/* Special case workaround: There are plenty of buggy SCSI+		 * implementations. Many have issues with cbw->Length+		 * field passing a wrong command size. For those cases we+		 * always try to work around the problem by using the length+		 * sent by the host side provided it is at least as large+		 * as the correct command length.+		 * Examples of such cases would be MS-Windows, which issues+		 * REQUEST SENSE with cbw->Length == 12 where it should+		 * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and+		 * REQUEST SENSE with cbw->Length == 10 where it should+		 * be 6 as well.+		 */+		if (cmnd_size <= fsg->cmnd_size) {+			DBG(fsg, "%s is buggy! Expected length %d "+					"but we got %d\n", name,+					cmnd_size, fsg->cmnd_size);+			cmnd_size = fsg->cmnd_size;+		} else {+			fsg->phase_error = 1;+			return -EINVAL;+		}+	}++	/* Check that the LUN values are consistent */+	if (transport_is_bbb()) {+		if (fsg->lun != lun)+			DBG(fsg, "using LUN %d from CBW, "+					"not LUN %d from CDB\n",+					fsg->lun, lun);+	}++	/* Check the LUN */+	curlun = fsg->curlun;+	if (curlun) {+		if (fsg->cmnd[0] != REQUEST_SENSE) {+			curlun->sense_data = SS_NO_SENSE;+			curlun->sense_data_info = 0;+			curlun->info_valid = 0;+		}+	} else {+		fsg->bad_lun_okay = 0;++		/* INQUIRY and REQUEST SENSE commands are explicitly allowed+		 * to use unsupported LUNs; all others may not. */+		if (fsg->cmnd[0] != INQUIRY &&+				fsg->cmnd[0] != REQUEST_SENSE) {+			DBG(fsg, "unsupported LUN %d\n", fsg->lun);+			return -EINVAL;+		}+	}++	/* If a unit attention condition exists, only INQUIRY and+	 * REQUEST SENSE commands are allowed; anything else must fail. */+	if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&+			fsg->cmnd[0] != INQUIRY &&+			fsg->cmnd[0] != REQUEST_SENSE) {+		curlun->sense_data = curlun->unit_attention_data;+		curlun->unit_attention_data = SS_NO_SENSE;+		return -EINVAL;+	}++	/* Check that only command bytes listed in the mask are non-zero */+	fsg->cmnd[1] &= 0x1f;			// Mask away the LUN+	for (i = 1; i < cmnd_size; ++i) {+		if (fsg->cmnd[i] && !(mask & (1 << i))) {+			if (curlun)+				curlun->sense_data = SS_INVALID_FIELD_IN_CDB;+			return -EINVAL;+		}+	}++	/* If the medium isn't mounted and the command needs to access+	 * it, return an error. */+	if (curlun && !fsg_lun_is_open(curlun) && needs_medium) {+		curlun->sense_data = SS_MEDIUM_NOT_PRESENT;+		return -EINVAL;+	}++	return 0;+}++/* wrapper of check_command for data size in blocks handling */+static int check_command_size_in_blocks(struct fsg_dev *fsg, int cmnd_size,+		enum data_direction data_dir, unsigned int mask,+		int needs_medium, const char *name)+{+	if (fsg->curlun)+		fsg->data_size_from_cmnd <<= fsg->curlun->blkbits;+	return check_command(fsg, cmnd_size, data_dir,+			mask, needs_medium, name);+}++static int do_scsi_command(struct fsg_dev *fsg)+{+	struct fsg_buffhd	*bh;+	int			rc;+	int			reply = -EINVAL;+	int			i;+	static char		unknown[16];++	dump_cdb(fsg);++	/* Wait for the next buffer to become available for data or status */+	bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill;+	while (bh->state != BUF_STATE_EMPTY) {+		rc = sleep_thread(fsg);+		if (rc)+			return rc;+	}+	fsg->phase_error = 0;+	fsg->short_packet_received = 0;++	down_read(&fsg->filesem);	// We're using the backing file+	switch (fsg->cmnd[0]) {++	case INQUIRY:+		fsg->data_size_from_cmnd = fsg->cmnd[4];+		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,+				(1<<4), 0,+				"INQUIRY")) == 0)+			reply = do_inquiry(fsg, bh);+		break;++	case MODE_SELECT:+		fsg->data_size_from_cmnd = fsg->cmnd[4];+		if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,+				(1<<1) | (1<<4), 0,+				"MODE SELECT(6)")) == 0)+			reply = do_mode_select(fsg, bh);+		break;++	case MODE_SELECT_10:+		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);+		if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,+				(1<<1) | (3<<7), 0,+				"MODE SELECT(10)")) == 0)+			reply = do_mode_select(fsg, bh);+		break;++	case MODE_SENSE:+		fsg->data_size_from_cmnd = fsg->cmnd[4];+		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,+				(1<<1) | (1<<2) | (1<<4), 0,+				"MODE SENSE(6)")) == 0)+			reply = do_mode_sense(fsg, bh);+		break;++	case MODE_SENSE_10:+		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);+		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,+				(1<<1) | (1<<2) | (3<<7), 0,+				"MODE SENSE(10)")) == 0)+			reply = do_mode_sense(fsg, bh);+		break;++	case ALLOW_MEDIUM_REMOVAL:+		fsg->data_size_from_cmnd = 0;+		if ((reply = check_command(fsg, 6, DATA_DIR_NONE,+				(1<<4), 0,+				"PREVENT-ALLOW MEDIUM REMOVAL")) == 0)+			reply = do_prevent_allow(fsg);+		break;++	case READ_6:+		i = fsg->cmnd[4];+		fsg->data_size_from_cmnd = (i == 0) ? 256 : i;+		if ((reply = check_command_size_in_blocks(fsg, 6,+				DATA_DIR_TO_HOST,+				(7<<1) | (1<<4), 1,+				"READ(6)")) == 0)+			reply = do_read(fsg);+		break;++	case READ_10:+		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);+		if ((reply = check_command_size_in_blocks(fsg, 10,+				DATA_DIR_TO_HOST,+				(1<<1) | (0xf<<2) | (3<<7), 1,+				"READ(10)")) == 0)+			reply = do_read(fsg);+		break;++	case READ_12:+		fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);+		if ((reply = check_command_size_in_blocks(fsg, 12,+				DATA_DIR_TO_HOST,+				(1<<1) | (0xf<<2) | (0xf<<6), 1,+				"READ(12)")) == 0)+			reply = do_read(fsg);+		break;++	case READ_CAPACITY:+		fsg->data_size_from_cmnd = 8;+		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,+				(0xf<<2) | (1<<8), 1,+				"READ CAPACITY")) == 0)+			reply = do_read_capacity(fsg, bh);+		break;++	case READ_HEADER:+		if (!mod_data.cdrom)+			goto unknown_cmnd;+		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);+		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,+				(3<<7) | (0x1f<<1), 1,+				"READ HEADER")) == 0)+			reply = do_read_header(fsg, bh);+		break;++	case READ_TOC:+		if (!mod_data.cdrom)+			goto unknown_cmnd;+		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);+		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,+				(7<<6) | (1<<1), 1,+				"READ TOC")) == 0)+			reply = do_read_toc(fsg, bh);+		break;++	case READ_FORMAT_CAPACITIES:+		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);+		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,+				(3<<7), 1,+				"READ FORMAT CAPACITIES")) == 0)+			reply = do_read_format_capacities(fsg, bh);+		break;++	case REQUEST_SENSE:+		fsg->data_size_from_cmnd = fsg->cmnd[4];+		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,+				(1<<4), 0,+				"REQUEST SENSE")) == 0)+			reply = do_request_sense(fsg, bh);+		break;++	case START_STOP:+		fsg->data_size_from_cmnd = 0;+		if ((reply = check_command(fsg, 6, DATA_DIR_NONE,+				(1<<1) | (1<<4), 0,+				"START-STOP UNIT")) == 0)+			reply = do_start_stop(fsg);+		break;++	case SYNCHRONIZE_CACHE:+		fsg->data_size_from_cmnd = 0;+		if ((reply = check_command(fsg, 10, DATA_DIR_NONE,+				(0xf<<2) | (3<<7), 1,+				"SYNCHRONIZE CACHE")) == 0)+			reply = do_synchronize_cache(fsg);+		break;++	case TEST_UNIT_READY:+		fsg->data_size_from_cmnd = 0;+		reply = check_command(fsg, 6, DATA_DIR_NONE,+				0, 1,+				"TEST UNIT READY");+		break;++	/* Although optional, this command is used by MS-Windows.  We+	 * support a minimal version: BytChk must be 0. */+	case VERIFY:+		fsg->data_size_from_cmnd = 0;+		if ((reply = check_command(fsg, 10, DATA_DIR_NONE,+				(1<<1) | (0xf<<2) | (3<<7), 1,+				"VERIFY")) == 0)+			reply = do_verify(fsg);+		break;++	case WRITE_6:+		i = fsg->cmnd[4];+		fsg->data_size_from_cmnd = (i == 0) ? 256 : i;+		if ((reply = check_command_size_in_blocks(fsg, 6,+				DATA_DIR_FROM_HOST,+				(7<<1) | (1<<4), 1,+				"WRITE(6)")) == 0)+			reply = do_write(fsg);+		break;++	case WRITE_10:+		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);+		if ((reply = check_command_size_in_blocks(fsg, 10,+				DATA_DIR_FROM_HOST,+				(1<<1) | (0xf<<2) | (3<<7), 1,+				"WRITE(10)")) == 0)+			reply = do_write(fsg);+		break;++	case WRITE_12:+		fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);+		if ((reply = check_command_size_in_blocks(fsg, 12,+				DATA_DIR_FROM_HOST,+				(1<<1) | (0xf<<2) | (0xf<<6), 1,+				"WRITE(12)")) == 0)+			reply = do_write(fsg);+		break;++	/* Some mandatory commands that we recognize but don't implement.+	 * They don't mean much in this setting.  It's left as an exercise+	 * for anyone interested to implement RESERVE and RELEASE in terms+	 * of Posix locks. */+	case FORMAT_UNIT:+	case RELEASE:+	case RESERVE:+	case SEND_DIAGNOSTIC:+		// Fall through++	default:+ unknown_cmnd:+		fsg->data_size_from_cmnd = 0;+		sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);+		if ((reply = check_command(fsg, fsg->cmnd_size,+				DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) {+			fsg->curlun->sense_data = SS_INVALID_COMMAND;+			reply = -EINVAL;+		}+		break;+	}+	up_read(&fsg->filesem);++	if (reply == -EINTR || signal_pending(current))+		return -EINTR;++	/* Set up the single reply buffer for finish_reply() */+	if (reply == -EINVAL)+		reply = 0;		// Error reply length+	if (reply >= 0 && fsg->data_dir == DATA_DIR_TO_HOST) {+		reply = min((u32) reply, fsg->data_size_from_cmnd);+		bh->inreq->length = reply;+		bh->state = BUF_STATE_FULL;+		fsg->residue -= reply;+	}				// Otherwise it's already set++	return 0;+}+++/*-------------------------------------------------------------------------*/++static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)+{+	struct usb_request		*req = bh->outreq;+	struct bulk_cb_wrap	*cbw = req->buf;++	/* Was this a real packet?  Should it be ignored? */+	if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))+		return -EINVAL;++	/* Is the CBW valid? */+	if (req->actual != US_BULK_CB_WRAP_LEN ||+			cbw->Signature != cpu_to_le32(+				US_BULK_CB_SIGN)) {+		DBG(fsg, "invalid CBW: len %u sig 0x%x\n",+				req->actual,+				le32_to_cpu(cbw->Signature));++		/* The Bulk-only spec says we MUST stall the IN endpoint+		 * (6.6.1), so it's unavoidable.  It also says we must+		 * retain this state until the next reset, but there's+		 * no way to tell the controller driver it should ignore+		 * Clear-Feature(HALT) requests.+		 *+		 * We aren't required to halt the OUT endpoint; instead+		 * we can simply accept and discard any data received+		 * until the next reset. */+		wedge_bulk_in_endpoint(fsg);+		set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);+		return -EINVAL;+	}++	/* Is the CBW meaningful? */+	if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||+			cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {+		DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "+				"cmdlen %u\n",+				cbw->Lun, cbw->Flags, cbw->Length);++		/* We can do anything we want here, so let's stall the+		 * bulk pipes if we are allowed to. */+		if (mod_data.can_stall) {+			fsg_set_halt(fsg, fsg->bulk_out);+			halt_bulk_in_endpoint(fsg);+		}+		return -EINVAL;+	}++	/* Save the command for later */+	fsg->cmnd_size = cbw->Length;+	memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size);+	if (cbw->Flags & US_BULK_FLAG_IN)+		fsg->data_dir = DATA_DIR_TO_HOST;+	else+		fsg->data_dir = DATA_DIR_FROM_HOST;+	fsg->data_size = le32_to_cpu(cbw->DataTransferLength);+	if (fsg->data_size == 0)+		fsg->data_dir = DATA_DIR_NONE;+	fsg->lun = cbw->Lun;+	fsg->tag = cbw->Tag;+	return 0;+}+++static int get_next_command(struct fsg_dev *fsg)+{+	struct fsg_buffhd	*bh;+	int			rc = 0;++	if (transport_is_bbb()) {++		/* Wait for the next buffer to become available */+		bh = fsg->next_buffhd_to_fill;+		while (bh->state != BUF_STATE_EMPTY) {+			rc = sleep_thread(fsg);+			if (rc)+				return rc;+		}++		/* Queue a request to read a Bulk-only CBW */+		set_bulk_out_req_length(fsg, bh, US_BULK_CB_WRAP_LEN);+		start_transfer(fsg, fsg->bulk_out, bh->outreq,+				&bh->outreq_busy, &bh->state);++		/* We will drain the buffer in software, which means we+		 * can reuse it for the next filling.  No need to advance+		 * next_buffhd_to_fill. */++		/* Wait for the CBW to arrive */+		while (bh->state != BUF_STATE_FULL) {+			rc = sleep_thread(fsg);+			if (rc)+				return rc;+		}+		smp_rmb();+		rc = received_cbw(fsg, bh);+		bh->state = BUF_STATE_EMPTY;++	} else {		// USB_PR_CB or USB_PR_CBI++		/* Wait for the next command to arrive */+		while (fsg->cbbuf_cmnd_size == 0) {+			rc = sleep_thread(fsg);+			if (rc)+				return rc;+		}++		/* Is the previous status interrupt request still busy?+		 * The host is allowed to skip reading the status,+		 * so we must cancel it. */+		if (fsg->intreq_busy)+			usb_ep_dequeue(fsg->intr_in, fsg->intreq);++		/* Copy the command and mark the buffer empty */+		fsg->data_dir = DATA_DIR_UNKNOWN;+		spin_lock_irq(&fsg->lock);+		fsg->cmnd_size = fsg->cbbuf_cmnd_size;+		memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size);+		fsg->cbbuf_cmnd_size = 0;+		spin_unlock_irq(&fsg->lock);++		/* Use LUN from the command */+		fsg->lun = fsg->cmnd[1] >> 5;+	}++	/* Update current lun */+	if (fsg->lun >= 0 && fsg->lun < fsg->nluns)+		fsg->curlun = &fsg->luns[fsg->lun];+	else+		fsg->curlun = NULL;++	return rc;+}+++/*-------------------------------------------------------------------------*/++static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep,+		const struct usb_endpoint_descriptor *d)+{+	int	rc;++	ep->driver_data = fsg;+	ep->desc = d;+	rc = usb_ep_enable(ep);+	if (rc)+		ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc);+	return rc;+}++static int alloc_request(struct fsg_dev *fsg, struct usb_ep *ep,+		struct usb_request **preq)+{+	*preq = usb_ep_alloc_request(ep, GFP_ATOMIC);+	if (*preq)+		return 0;+	ERROR(fsg, "can't allocate request for %s\n", ep->name);+	return -ENOMEM;+}++/*+ * Reset interface setting and re-init endpoint state (toggle etc).+ * Call with altsetting < 0 to disable the interface.  The only other+ * available altsetting is 0, which enables the interface.+ */+static int do_set_interface(struct fsg_dev *fsg, int altsetting)+{+	int	rc = 0;+	int	i;+	const struct usb_endpoint_descriptor	*d;++	if (fsg->running)+		DBG(fsg, "reset interface\n");++reset:+	/* Deallocate the requests */+	for (i = 0; i < fsg_num_buffers; ++i) {+		struct fsg_buffhd *bh = &fsg->buffhds[i];++		if (bh->inreq) {+			usb_ep_free_request(fsg->bulk_in, bh->inreq);+			bh->inreq = NULL;+		}+		if (bh->outreq) {+			usb_ep_free_request(fsg->bulk_out, bh->outreq);+			bh->outreq = NULL;+		}+	}+	if (fsg->intreq) {+		usb_ep_free_request(fsg->intr_in, fsg->intreq);+		fsg->intreq = NULL;+	}++	/* Disable the endpoints */+	if (fsg->bulk_in_enabled) {+		usb_ep_disable(fsg->bulk_in);+		fsg->bulk_in_enabled = 0;+	}+	if (fsg->bulk_out_enabled) {+		usb_ep_disable(fsg->bulk_out);+		fsg->bulk_out_enabled = 0;+	}+	if (fsg->intr_in_enabled) {+		usb_ep_disable(fsg->intr_in);+		fsg->intr_in_enabled = 0;+	}++	fsg->running = 0;+	if (altsetting < 0 || rc != 0)+		return rc;++	DBG(fsg, "set interface %d\n", altsetting);++	/* Enable the endpoints */+	d = fsg_ep_desc(fsg->gadget,+			&fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc,+			&fsg_ss_bulk_in_desc);+	if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0)+		goto reset;+	fsg->bulk_in_enabled = 1;++	d = fsg_ep_desc(fsg->gadget,+			&fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc,+			&fsg_ss_bulk_out_desc);+	if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0)+		goto reset;+	fsg->bulk_out_enabled = 1;+	fsg->bulk_out_maxpacket = usb_endpoint_maxp(d);+	clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);++	if (transport_is_cbi()) {+		d = fsg_ep_desc(fsg->gadget,+				&fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc,+				&fsg_ss_intr_in_desc);+		if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0)+			goto reset;+		fsg->intr_in_enabled = 1;+	}++	/* Allocate the requests */+	for (i = 0; i < fsg_num_buffers; ++i) {+		struct fsg_buffhd	*bh = &fsg->buffhds[i];++		if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0)+			goto reset;+		if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0)+			goto reset;+		bh->inreq->buf = bh->outreq->buf = bh->buf;+		bh->inreq->context = bh->outreq->context = bh;+		bh->inreq->complete = bulk_in_complete;+		bh->outreq->complete = bulk_out_complete;+	}+	if (transport_is_cbi()) {+		if ((rc = alloc_request(fsg, fsg->intr_in, &fsg->intreq)) != 0)+			goto reset;+		fsg->intreq->complete = intr_in_complete;+	}++	fsg->running = 1;+	for (i = 0; i < fsg->nluns; ++i)+		fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;+	return rc;+}+++/*+ * Change our operational configuration.  This code must agree with the code+ * that returns config descriptors, and with interface altsetting code.+ *+ * It's also responsible for power management interactions.  Some+ * configurations might not work with our current power sources.+ * For now we just assume the gadget is always self-powered.+ */+static int do_set_config(struct fsg_dev *fsg, u8 new_config)+{+	int	rc = 0;++	/* Disable the single interface */+	if (fsg->config != 0) {+		DBG(fsg, "reset config\n");+		fsg->config = 0;+		rc = do_set_interface(fsg, -1);+	}++	/* Enable the interface */+	if (new_config != 0) {+		fsg->config = new_config;+		if ((rc = do_set_interface(fsg, 0)) != 0)+			fsg->config = 0;	// Reset on errors+		else+			INFO(fsg, "%s config #%d\n",+			     usb_speed_string(fsg->gadget->speed),+			     fsg->config);+	}+	return rc;+}+++/*-------------------------------------------------------------------------*/++static void handle_exception(struct fsg_dev *fsg)+{+	siginfo_t		info;+	int			sig;+	int			i;+	int			num_active;+	struct fsg_buffhd	*bh;+	enum fsg_state		old_state;+	u8			new_config;+	struct fsg_lun		*curlun;+	unsigned int		exception_req_tag;+	int			rc;++	/* Clear the existing signals.  Anything but SIGUSR1 is converted+	 * into a high-priority EXIT exception. */+	for (;;) {+		sig = dequeue_signal_lock(current, ¤t->blocked, &info);+		if (!sig)+			break;+		if (sig != SIGUSR1) {+			if (fsg->state < FSG_STATE_EXIT)+				DBG(fsg, "Main thread exiting on signal\n");+			raise_exception(fsg, FSG_STATE_EXIT);+		}+	}++	/* Cancel all the pending transfers */+	if (fsg->intreq_busy)+		usb_ep_dequeue(fsg->intr_in, fsg->intreq);+	for (i = 0; i < fsg_num_buffers; ++i) {+		bh = &fsg->buffhds[i];+		if (bh->inreq_busy)+			usb_ep_dequeue(fsg->bulk_in, bh->inreq);+		if (bh->outreq_busy)+			usb_ep_dequeue(fsg->bulk_out, bh->outreq);+	}++	/* Wait until everything is idle */+	for (;;) {+		num_active = fsg->intreq_busy;+		for (i = 0; i < fsg_num_buffers; ++i) {+			bh = &fsg->buffhds[i];+			num_active += bh->inreq_busy + bh->outreq_busy;+		}+		if (num_active == 0)+			break;+		if (sleep_thread(fsg))+			return;+	}++	/* Clear out the controller's fifos */+	if (fsg->bulk_in_enabled)+		usb_ep_fifo_flush(fsg->bulk_in);+	if (fsg->bulk_out_enabled)+		usb_ep_fifo_flush(fsg->bulk_out);+	if (fsg->intr_in_enabled)+		usb_ep_fifo_flush(fsg->intr_in);++	/* Reset the I/O buffer states and pointers, the SCSI+	 * state, and the exception.  Then invoke the handler. */+	spin_lock_irq(&fsg->lock);++	for (i = 0; i < fsg_num_buffers; ++i) {+		bh = &fsg->buffhds[i];+		bh->state = BUF_STATE_EMPTY;+	}+	fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain =+			&fsg->buffhds[0];++	exception_req_tag = fsg->exception_req_tag;+	new_config = fsg->new_config;+	old_state = fsg->state;++	if (old_state == FSG_STATE_ABORT_BULK_OUT)+		fsg->state = FSG_STATE_STATUS_PHASE;+	else {+		for (i = 0; i < fsg->nluns; ++i) {+			curlun = &fsg->luns[i];+			curlun->prevent_medium_removal = 0;+			curlun->sense_data = curlun->unit_attention_data =+					SS_NO_SENSE;+			curlun->sense_data_info = 0;+			curlun->info_valid = 0;+		}+		fsg->state = FSG_STATE_IDLE;+	}+	spin_unlock_irq(&fsg->lock);++	/* Carry out any extra actions required for the exception */+	switch (old_state) {+	default:+		break;++	case FSG_STATE_ABORT_BULK_OUT:+		send_status(fsg);+		spin_lock_irq(&fsg->lock);+		if (fsg->state == FSG_STATE_STATUS_PHASE)+			fsg->state = FSG_STATE_IDLE;+		spin_unlock_irq(&fsg->lock);+		break;++	case FSG_STATE_RESET:+		/* In case we were forced against our will to halt a+		 * bulk endpoint, clear the halt now.  (The SuperH UDC+		 * requires this.) */+		if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))+			usb_ep_clear_halt(fsg->bulk_in);++		if (transport_is_bbb()) {+			if (fsg->ep0_req_tag == exception_req_tag)+				ep0_queue(fsg);	// Complete the status stage++		} else if (transport_is_cbi())+			send_status(fsg);	// Status by interrupt pipe++		/* Technically this should go here, but it would only be+		 * a waste of time.  Ditto for the INTERFACE_CHANGE and+		 * CONFIG_CHANGE cases. */+		// for (i = 0; i < fsg->nluns; ++i)+		//	fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;+		break;++	case FSG_STATE_INTERFACE_CHANGE:+		rc = do_set_interface(fsg, 0);+		if (fsg->ep0_req_tag != exception_req_tag)+			break;+		if (rc != 0)			// STALL on errors+			fsg_set_halt(fsg, fsg->ep0);+		else				// Complete the status stage+			ep0_queue(fsg);+		break;++	case FSG_STATE_CONFIG_CHANGE:+		rc = do_set_config(fsg, new_config);+		if (fsg->ep0_req_tag != exception_req_tag)+			break;+		if (rc != 0)			// STALL on errors+			fsg_set_halt(fsg, fsg->ep0);+		else				// Complete the status stage+			ep0_queue(fsg);+		break;++	case FSG_STATE_DISCONNECT:+		for (i = 0; i < fsg->nluns; ++i)+			fsg_lun_fsync_sub(fsg->luns + i);+		do_set_config(fsg, 0);		// Unconfigured state+		break;++	case FSG_STATE_EXIT:+	case FSG_STATE_TERMINATED:+		do_set_config(fsg, 0);			// Free resources+		spin_lock_irq(&fsg->lock);+		fsg->state = FSG_STATE_TERMINATED;	// Stop the thread+		spin_unlock_irq(&fsg->lock);+		break;+	}+}+++/*-------------------------------------------------------------------------*/++static int fsg_main_thread(void *fsg_)+{+	struct fsg_dev		*fsg = fsg_;++	/* Allow the thread to be killed by a signal, but set the signal mask+	 * to block everything but INT, TERM, KILL, and USR1. */+	allow_signal(SIGINT);+	allow_signal(SIGTERM);+	allow_signal(SIGKILL);+	allow_signal(SIGUSR1);++	/* Allow the thread to be frozen */+	set_freezable();++	/* Arrange for userspace references to be interpreted as kernel+	 * pointers.  That way we can pass a kernel pointer to a routine+	 * that expects a __user pointer and it will work okay. */+	set_fs(get_ds());++	/* The main loop */+	while (fsg->state != FSG_STATE_TERMINATED) {+		if (exception_in_progress(fsg) || signal_pending(current)) {+			handle_exception(fsg);+			continue;+		}++		if (!fsg->running) {+			sleep_thread(fsg);+			continue;+		}++		if (get_next_command(fsg))+			continue;++		spin_lock_irq(&fsg->lock);+		if (!exception_in_progress(fsg))+			fsg->state = FSG_STATE_DATA_PHASE;+		spin_unlock_irq(&fsg->lock);++		if (do_scsi_command(fsg) || finish_reply(fsg))+			continue;++		spin_lock_irq(&fsg->lock);+		if (!exception_in_progress(fsg))+			fsg->state = FSG_STATE_STATUS_PHASE;+		spin_unlock_irq(&fsg->lock);++		if (send_status(fsg))+			continue;++		spin_lock_irq(&fsg->lock);+		if (!exception_in_progress(fsg))+			fsg->state = FSG_STATE_IDLE;+		spin_unlock_irq(&fsg->lock);+		}++	spin_lock_irq(&fsg->lock);+	fsg->thread_task = NULL;+	spin_unlock_irq(&fsg->lock);++	/* If we are exiting because of a signal, unregister the+	 * gadget driver. */+	if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))+		usb_gadget_unregister_driver(&fsg_driver);++	/* Let the unbind and cleanup routines know the thread has exited */+	complete_and_exit(&fsg->thread_notifier, 0);+}+++/*-------------------------------------------------------------------------*/+++/* The write permissions and store_xxx pointers are set in fsg_bind() */+static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL);+static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL);+static DEVICE_ATTR(file, 0444, fsg_show_file, NULL);+++/*-------------------------------------------------------------------------*/++static void fsg_release(struct kref *ref)+{+	struct fsg_dev	*fsg = container_of(ref, struct fsg_dev, ref);++	kfree(fsg->luns);+	kfree(fsg);+}++static void lun_release(struct device *dev)+{+	struct rw_semaphore	*filesem = dev_get_drvdata(dev);+	struct fsg_dev		*fsg =+		container_of(filesem, struct fsg_dev, filesem);++	kref_put(&fsg->ref, fsg_release);+}++static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)+{+	struct fsg_dev		*fsg = get_gadget_data(gadget);+	int			i;+	struct fsg_lun		*curlun;+	struct usb_request	*req = fsg->ep0req;++	DBG(fsg, "unbind\n");+	clear_bit(REGISTERED, &fsg->atomic_bitflags);++	/* If the thread isn't already dead, tell it to exit now */+	if (fsg->state != FSG_STATE_TERMINATED) {+		raise_exception(fsg, FSG_STATE_EXIT);+		wait_for_completion(&fsg->thread_notifier);++		/* The cleanup routine waits for this completion also */+		complete(&fsg->thread_notifier);+	}++	/* Unregister the sysfs attribute files and the LUNs */+	for (i = 0; i < fsg->nluns; ++i) {+		curlun = &fsg->luns[i];+		if (curlun->registered) {+			device_remove_file(&curlun->dev, &dev_attr_nofua);+			device_remove_file(&curlun->dev, &dev_attr_ro);+			device_remove_file(&curlun->dev, &dev_attr_file);+			fsg_lun_close(curlun);+			device_unregister(&curlun->dev);+			curlun->registered = 0;+		}+	}++	/* Free the data buffers */+	for (i = 0; i < fsg_num_buffers; ++i)+		kfree(fsg->buffhds[i].buf);++	/* Free the request and buffer for endpoint 0 */+	if (req) {+		kfree(req->buf);+		usb_ep_free_request(fsg->ep0, req);+	}++	set_gadget_data(gadget, NULL);+}+++static int __init check_parameters(struct fsg_dev *fsg)+{+	int	prot;+	int	gcnum;++	/* Store the default values */+	mod_data.transport_type = USB_PR_BULK;+	mod_data.transport_name = "Bulk-only";+	mod_data.protocol_type = USB_SC_SCSI;+	mod_data.protocol_name = "Transparent SCSI";++	/* Some peripheral controllers are known not to be able to+	 * halt bulk endpoints correctly.  If one of them is present,+	 * disable stalls.+	 */+	if (gadget_is_at91(fsg->gadget))+		mod_data.can_stall = 0;++	if (mod_data.release == 0xffff) {	// Parameter wasn't set+		gcnum = usb_gadget_controller_number(fsg->gadget);+		if (gcnum >= 0)+			mod_data.release = 0x0300 + gcnum;+		else {+			WARNING(fsg, "controller '%s' not recognized\n",+				fsg->gadget->name);+			mod_data.release = 0x0399;+		}+	}++	prot = simple_strtol(mod_data.protocol_parm, NULL, 0);++#ifdef CONFIG_USB_FILE_STORAGE_TEST+	if (strnicmp(mod_data.transport_parm, "BBB", 10) == 0) {+		;		// Use default setting+	} else if (strnicmp(mod_data.transport_parm, "CB", 10) == 0) {+		mod_data.transport_type = USB_PR_CB;+		mod_data.transport_name = "Control-Bulk";+	} else if (strnicmp(mod_data.transport_parm, "CBI", 10) == 0) {+		mod_data.transport_type = USB_PR_CBI;+		mod_data.transport_name = "Control-Bulk-Interrupt";+	} else {+		ERROR(fsg, "invalid transport: %s\n", mod_data.transport_parm);+		return -EINVAL;+	}++	if (strnicmp(mod_data.protocol_parm, "SCSI", 10) == 0 ||+			prot == USB_SC_SCSI) {+		;		// Use default setting+	} else if (strnicmp(mod_data.protocol_parm, "RBC", 10) == 0 ||+			prot == USB_SC_RBC) {+		mod_data.protocol_type = USB_SC_RBC;+		mod_data.protocol_name = "RBC";+	} else if (strnicmp(mod_data.protocol_parm, "8020", 4) == 0 ||+			strnicmp(mod_data.protocol_parm, "ATAPI", 10) == 0 ||+			prot == USB_SC_8020) {+		mod_data.protocol_type = USB_SC_8020;+		mod_data.protocol_name = "8020i (ATAPI)";+	} else if (strnicmp(mod_data.protocol_parm, "QIC", 3) == 0 ||+			prot == USB_SC_QIC) {+		mod_data.protocol_type = USB_SC_QIC;+		mod_data.protocol_name = "QIC-157";+	} else if (strnicmp(mod_data.protocol_parm, "UFI", 10) == 0 ||+			prot == USB_SC_UFI) {+		mod_data.protocol_type = USB_SC_UFI;+		mod_data.protocol_name = "UFI";+	} else if (strnicmp(mod_data.protocol_parm, "8070", 4) == 0 ||+			prot == USB_SC_8070) {+		mod_data.protocol_type = USB_SC_8070;+		mod_data.protocol_name = "8070i";+	} else {+		ERROR(fsg, "invalid protocol: %s\n", mod_data.protocol_parm);+		return -EINVAL;+	}++	mod_data.buflen &= PAGE_CACHE_MASK;+	if (mod_data.buflen <= 0) {+		ERROR(fsg, "invalid buflen\n");+		return -ETOOSMALL;+	}++#endif /* CONFIG_USB_FILE_STORAGE_TEST */++	/* Serial string handling.+	 * On a real device, the serial string would be loaded+	 * from permanent storage. */+	if (mod_data.serial) {+		const char *ch;+		unsigned len = 0;++		/* Sanity check :+		 * The CB[I] specification limits the serial string to+		 * 12 uppercase hexadecimal characters.+		 * BBB need at least 12 uppercase hexadecimal characters,+		 * with a maximum of 126. */+		for (ch = mod_data.serial; *ch; ++ch) {+			++len;+			if ((*ch < '0' || *ch > '9') &&+			    (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */+				WARNING(fsg,+					"Invalid serial string character: %c\n",+					*ch);+				goto no_serial;+			}+		}+		if (len > 126 ||+		    (mod_data.transport_type == USB_PR_BULK && len < 12) ||+		    (mod_data.transport_type != USB_PR_BULK && len > 12)) {+			WARNING(fsg, "Invalid serial string length!\n");+			goto no_serial;+		}+		fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial;+	} else {+		WARNING(fsg, "No serial-number string provided!\n");+ no_serial:+		device_desc.iSerialNumber = 0;+	}++	return 0;+}+++static int __init fsg_bind(struct usb_gadget *gadget)+{+	struct fsg_dev		*fsg = the_fsg;+	int			rc;+	int			i;+	struct fsg_lun		*curlun;+	struct usb_ep		*ep;+	struct usb_request	*req;+	char			*pathbuf, *p;++	fsg->gadget = gadget;+	set_gadget_data(gadget, fsg);+	fsg->ep0 = gadget->ep0;+	fsg->ep0->driver_data = fsg;++	if ((rc = check_parameters(fsg)) != 0)+		goto out;++	if (mod_data.removable) {	// Enable the store_xxx attributes+		dev_attr_file.attr.mode = 0644;+		dev_attr_file.store = fsg_store_file;+		if (!mod_data.cdrom) {+			dev_attr_ro.attr.mode = 0644;+			dev_attr_ro.store = fsg_store_ro;+		}+	}++	/* Only for removable media? */+	dev_attr_nofua.attr.mode = 0644;+	dev_attr_nofua.store = fsg_store_nofua;++	/* Find out how many LUNs there should be */+	i = mod_data.nluns;+	if (i == 0)+		i = max(mod_data.num_filenames, 1u);+	if (i > FSG_MAX_LUNS) {+		ERROR(fsg, "invalid number of LUNs: %d\n", i);+		rc = -EINVAL;+		goto out;+	}++	/* Create the LUNs, open their backing files, and register the+	 * LUN devices in sysfs. */+	fsg->luns = kzalloc(i * sizeof(struct fsg_lun), GFP_KERNEL);+	if (!fsg->luns) {+		rc = -ENOMEM;+		goto out;+	}+	fsg->nluns = i;++	for (i = 0; i < fsg->nluns; ++i) {+		curlun = &fsg->luns[i];+		curlun->cdrom = !!mod_data.cdrom;+		curlun->ro = mod_data.cdrom || mod_data.ro[i];+		curlun->initially_ro = curlun->ro;+		curlun->removable = mod_data.removable;+		curlun->nofua = mod_data.nofua[i];+		curlun->dev.release = lun_release;+		curlun->dev.parent = &gadget->dev;+		curlun->dev.driver = &fsg_driver.driver;+		dev_set_drvdata(&curlun->dev, &fsg->filesem);+		dev_set_name(&curlun->dev,"%s-lun%d",+			     dev_name(&gadget->dev), i);++		kref_get(&fsg->ref);+		rc = device_register(&curlun->dev);+		if (rc) {+			INFO(fsg, "failed to register LUN%d: %d\n", i, rc);+			put_device(&curlun->dev);+			goto out;+		}+		curlun->registered = 1;++		rc = device_create_file(&curlun->dev, &dev_attr_ro);+		if (rc)+			goto out;+		rc = device_create_file(&curlun->dev, &dev_attr_nofua);+		if (rc)+			goto out;+		rc = device_create_file(&curlun->dev, &dev_attr_file);+		if (rc)+			goto out;++		if (mod_data.file[i] && *mod_data.file[i]) {+			rc = fsg_lun_open(curlun, mod_data.file[i]);+			if (rc)+				goto out;+		} else if (!mod_data.removable) {+			ERROR(fsg, "no file given for LUN%d\n", i);+			rc = -EINVAL;+			goto out;+		}+	}++	/* Find all the endpoints we will use */+	usb_ep_autoconfig_reset(gadget);+	ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc);+	if (!ep)+		goto autoconf_fail;+	ep->driver_data = fsg;		// claim the endpoint+	fsg->bulk_in = ep;++	ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc);+	if (!ep)+		goto autoconf_fail;+	ep->driver_data = fsg;		// claim the endpoint+	fsg->bulk_out = ep;++	if (transport_is_cbi()) {+		ep = usb_ep_autoconfig(gadget, &fsg_fs_intr_in_desc);+		if (!ep)+			goto autoconf_fail;+		ep->driver_data = fsg;		// claim the endpoint+		fsg->intr_in = ep;+	}++	/* Fix up the descriptors */+	device_desc.idVendor = cpu_to_le16(mod_data.vendor);+	device_desc.idProduct = cpu_to_le16(mod_data.product);+	device_desc.bcdDevice = cpu_to_le16(mod_data.release);++	i = (transport_is_cbi() ? 3 : 2);	// Number of endpoints+	fsg_intf_desc.bNumEndpoints = i;+	fsg_intf_desc.bInterfaceSubClass = mod_data.protocol_type;+	fsg_intf_desc.bInterfaceProtocol = mod_data.transport_type;+	fsg_fs_function[i + FSG_FS_FUNCTION_PRE_EP_ENTRIES] = NULL;++	if (gadget_is_dualspeed(gadget)) {+		fsg_hs_function[i + FSG_HS_FUNCTION_PRE_EP_ENTRIES] = NULL;++		/* Assume endpoint addresses are the same for both speeds */+		fsg_hs_bulk_in_desc.bEndpointAddress =+			fsg_fs_bulk_in_desc.bEndpointAddress;+		fsg_hs_bulk_out_desc.bEndpointAddress =+			fsg_fs_bulk_out_desc.bEndpointAddress;+		fsg_hs_intr_in_desc.bEndpointAddress =+			fsg_fs_intr_in_desc.bEndpointAddress;+	}++	if (gadget_is_superspeed(gadget)) {+		unsigned		max_burst;++		fsg_ss_function[i + FSG_SS_FUNCTION_PRE_EP_ENTRIES] = NULL;++		/* Calculate bMaxBurst, we know packet size is 1024 */+		max_burst = min_t(unsigned, mod_data.buflen / 1024, 15);++		/* Assume endpoint addresses are the same for both speeds */+		fsg_ss_bulk_in_desc.bEndpointAddress =+			fsg_fs_bulk_in_desc.bEndpointAddress;+		fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;++		fsg_ss_bulk_out_desc.bEndpointAddress =+			fsg_fs_bulk_out_desc.bEndpointAddress;+		fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;+	}++	if (gadget_is_otg(gadget))+		fsg_otg_desc.bmAttributes |= USB_OTG_HNP;++	rc = -ENOMEM;++	/* Allocate the request and buffer for endpoint 0 */+	fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);+	if (!req)+		goto out;+	req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL);+	if (!req->buf)+		goto out;+	req->complete = ep0_complete;++	/* Allocate the data buffers */+	for (i = 0; i < fsg_num_buffers; ++i) {+		struct fsg_buffhd	*bh = &fsg->buffhds[i];++		/* Allocate for the bulk-in endpoint.  We assume that+		 * the buffer will also work with the bulk-out (and+		 * interrupt-in) endpoint. */+		bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL);+		if (!bh->buf)+			goto out;+		bh->next = bh + 1;+	}+	fsg->buffhds[fsg_num_buffers - 1].next = &fsg->buffhds[0];++	/* This should reflect the actual gadget power source */+	usb_gadget_set_selfpowered(gadget);++	snprintf(fsg_string_manufacturer, sizeof fsg_string_manufacturer,+			"%s %s with %s",+			init_utsname()->sysname, init_utsname()->release,+			gadget->name);++	fsg->thread_task = kthread_create(fsg_main_thread, fsg,+			"file-storage-gadget");+	if (IS_ERR(fsg->thread_task)) {+		rc = PTR_ERR(fsg->thread_task);+		goto out;+	}++	INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");+	INFO(fsg, "NOTE: This driver is deprecated.  "+			"Consider using g_mass_storage instead.\n");+	INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);++	pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);+	for (i = 0; i < fsg->nluns; ++i) {+		curlun = &fsg->luns[i];+		if (fsg_lun_is_open(curlun)) {+			p = NULL;+			if (pathbuf) {+				p = d_path(&curlun->filp->f_path,+					   pathbuf, PATH_MAX);+				if (IS_ERR(p))+					p = NULL;+			}+			LINFO(curlun, "ro=%d, nofua=%d, file: %s\n",+			      curlun->ro, curlun->nofua, (p ? p : "(error)"));+		}+	}+	kfree(pathbuf);++	DBG(fsg, "transport=%s (x%02x)\n",+			mod_data.transport_name, mod_data.transport_type);+	DBG(fsg, "protocol=%s (x%02x)\n",+			mod_data.protocol_name, mod_data.protocol_type);+	DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n",+			mod_data.vendor, mod_data.product, mod_data.release);+	DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n",+			mod_data.removable, mod_data.can_stall,+			mod_data.cdrom, mod_data.buflen);+	DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task));++	set_bit(REGISTERED, &fsg->atomic_bitflags);++	/* Tell the thread to start working */+	wake_up_process(fsg->thread_task);+	return 0;++autoconf_fail:+	ERROR(fsg, "unable to autoconfigure all endpoints\n");+	rc = -ENOTSUPP;++out:+	fsg->state = FSG_STATE_TERMINATED;	// The thread is dead+	fsg_unbind(gadget);+	complete(&fsg->thread_notifier);+	return rc;+}+++/*-------------------------------------------------------------------------*/++static void fsg_suspend(struct usb_gadget *gadget)+{+	struct fsg_dev		*fsg = get_gadget_data(gadget);++	DBG(fsg, "suspend\n");+	set_bit(SUSPENDED, &fsg->atomic_bitflags);+}++static void fsg_resume(struct usb_gadget *gadget)+{+	struct fsg_dev		*fsg = get_gadget_data(gadget);++	DBG(fsg, "resume\n");+	clear_bit(SUSPENDED, &fsg->atomic_bitflags);+}+++/*-------------------------------------------------------------------------*/++static struct usb_gadget_driver		fsg_driver = {+	.max_speed	= USB_SPEED_SUPER,+	.function	= (char *) fsg_string_product,+	.unbind		= fsg_unbind,+	.disconnect	= fsg_disconnect,+	.setup		= fsg_setup,+	.suspend	= fsg_suspend,+	.resume		= fsg_resume,++	.driver		= {+		.name		= DRIVER_NAME,+		.owner		= THIS_MODULE,+		// .release = ...+		// .suspend = ...+		// .resume = ...+	},+};+++static int __init fsg_alloc(void)+{+	struct fsg_dev		*fsg;++	fsg = kzalloc(sizeof *fsg ++		      fsg_num_buffers * sizeof *(fsg->buffhds), GFP_KERNEL);++	if (!fsg)+		return -ENOMEM;+	spin_lock_init(&fsg->lock);+	init_rwsem(&fsg->filesem);+	kref_init(&fsg->ref);+	init_completion(&fsg->thread_notifier);++	the_fsg = fsg;+	return 0;+}+++static int __init fsg_init(void)+{+	int		rc;+	struct fsg_dev	*fsg;++	rc = fsg_num_buffers_validate();+	if (rc != 0)+		return rc;++	if ((rc = fsg_alloc()) != 0)+		return rc;+	fsg = the_fsg;+	if ((rc = usb_gadget_probe_driver(&fsg_driver, fsg_bind)) != 0)+		kref_put(&fsg->ref, fsg_release);+	return rc;+}+module_init(fsg_init);+++static void __exit fsg_cleanup(void)+{+	struct fsg_dev	*fsg = the_fsg;++	/* Unregister the driver iff the thread hasn't already done so */+	if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))+		usb_gadget_unregister_driver(&fsg_driver);++	/* Wait for the thread to finish up */+	wait_for_completion(&fsg->thread_notifier);++	kref_put(&fsg->ref, fsg_release);+}+module_exit(fsg_cleanup);diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/changes.txt linux-3.11.10/drivers/usb/host/dwc_common_port/changes.txt--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/changes.txt	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/changes.txt	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,174 @@++dwc_read_reg32() and friends now take an additional parameter, a pointer to an+IO context struct. The IO context struct should live in an os-dependent struct+in your driver. As an example, the dwc_usb3 driver has an os-dependent struct+named 'os_dep' embedded in the main device struct. So there these calls look+like this:++	dwc_read_reg32(&usb3_dev->os_dep.ioctx, &pcd->dev_global_regs->dcfg);++	dwc_write_reg32(&usb3_dev->os_dep.ioctx,+			&pcd->dev_global_regs->dcfg, 0);++Note that for the existing Linux driver ports, it is not necessary to actually+define the 'ioctx' member in the os-dependent struct. Since Linux does not+require an IO context, its macros for dwc_read_reg32() and friends do not+use the context pointer, so it is optimized away by the compiler. But it is+necessary to add the pointer parameter to all of the call sites, to be ready+for any future ports (such as FreeBSD) which do require an IO context.+++Similarly, dwc_alloc(), dwc_alloc_atomic(), dwc_strdup(), and dwc_free() now+take an additional parameter, a pointer to a memory context. Examples:++	addr = dwc_alloc(&usb3_dev->os_dep.memctx, size);++	dwc_free(&usb3_dev->os_dep.memctx, addr);++Again, for the Linux ports, it is not necessary to actually define the memctx+member, but it is necessary to add the pointer parameter to all of the call+sites.+++Same for dwc_dma_alloc() and dwc_dma_free(). Examples:++	virt_addr = dwc_dma_alloc(&usb3_dev->os_dep.dmactx, size, &phys_addr);++	dwc_dma_free(&usb3_dev->os_dep.dmactx, size, virt_addr, phys_addr);+++Same for dwc_mutex_alloc() and dwc_mutex_free(). Examples:++	mutex = dwc_mutex_alloc(&usb3_dev->os_dep.mtxctx);++	dwc_mutex_free(&usb3_dev->os_dep.mtxctx, mutex);+++Same for dwc_spinlock_alloc() and dwc_spinlock_free(). Examples:++	lock = dwc_spinlock_alloc(&usb3_dev->osdep.splctx);++	dwc_spinlock_free(&usb3_dev->osdep.splctx, lock);+++Same for dwc_timer_alloc(). Example:++	timer = dwc_timer_alloc(&usb3_dev->os_dep.tmrctx, "dwc_usb3_tmr1",+				cb_func, cb_data);+++Same for dwc_waitq_alloc(). Example:++	waitq = dwc_waitq_alloc(&usb3_dev->os_dep.wtqctx);+++Same for dwc_thread_run(). Example:++	thread = dwc_thread_run(&usb3_dev->os_dep.thdctx, func,+				"dwc_usb3_thd1", data);+++Same for dwc_workq_alloc(). Example:++	workq = dwc_workq_alloc(&usb3_dev->osdep.wkqctx, "dwc_usb3_wkq1");+++Same for dwc_task_alloc(). Example:++	task = dwc_task_alloc(&usb3_dev->os_dep.tskctx, "dwc_usb3_tsk1",+			      cb_func, cb_data);+++In addition to the context pointer additions, a few core functions have had+other changes made to their parameters:++The 'flags' parameter to dwc_spinlock_irqsave() and dwc_spinunlock_irqrestore()+has been changed from a uint64_t to a dwc_irqflags_t.++dwc_thread_should_stop() now takes a 'dwc_thread_t *' parameter, because the+FreeBSD equivalent of that function requires it.++And, in addition to the context pointer, dwc_task_alloc() also adds a+'char *name' parameter, to be consistent with dwc_thread_run() and+dwc_workq_alloc(), and because the FreeBSD equivalent of that function+requires a unique name.+++Here is a complete list of the core functions that now take a pointer to a+context as their first parameter:++	dwc_read_reg32+	dwc_read_reg64+	dwc_write_reg32+	dwc_write_reg64+	dwc_modify_reg32+	dwc_modify_reg64+	dwc_alloc+	dwc_alloc_atomic+	dwc_strdup+	dwc_free+	dwc_dma_alloc+	dwc_dma_free+	dwc_mutex_alloc+	dwc_mutex_free+	dwc_spinlock_alloc+	dwc_spinlock_free+	dwc_timer_alloc+	dwc_waitq_alloc+	dwc_thread_run+	dwc_workq_alloc+	dwc_task_alloc     Also adds a 'char *name' as its 2nd parameter++And here are the core functions that have other changes to their parameters:++	dwc_spinlock_irqsave      'flags' param is now a 'dwc_irqflags_t *'+	dwc_spinunlock_irqrestore 'flags' param is now a 'dwc_irqflags_t'+	dwc_thread_should_stop    Adds a 'dwc_thread_t *' parameter++++The changes to the core functions also require some of the other library+functions to change:++	dwc_cc_if_alloc() and dwc_cc_if_free() now take a 'void *memctx'+	(for memory allocation) as the 1st param and a 'void *mtxctx'+	(for mutex allocation) as the 2nd param.++	dwc_cc_clear(), dwc_cc_add(), dwc_cc_change(), dwc_cc_remove(),+	dwc_cc_data_for_save(), and dwc_cc_restore_from_data() now take a+	'void *memctx' as the 1st param.++	dwc_dh_modpow(), dwc_dh_pk(), and dwc_dh_derive_keys() now take a+	'void *memctx' as the 1st param.++	dwc_modpow() now takes a 'void *memctx' as the 1st param.++	dwc_alloc_notification_manager() now takes a 'void *memctx' as the+	1st param and a 'void *wkqctx' (for work queue allocation) as the 2nd+	param, and also now returns an integer value that is non-zero if+	allocation of its data structures or work queue fails.++	dwc_register_notifier() now takes a 'void *memctx' as the 1st param.++	dwc_memory_debug_start() now takes a 'void *mem_ctx' as the first+	param, and also now returns an integer value that is non-zero if+	allocation of its data structures fails.++++Other miscellaneous changes:++The DEBUG_MEMORY and DEBUG_REGS #define's have been renamed to+DWC_DEBUG_MEMORY and DWC_DEBUG_REGS.++The following #define's have been added to allow selectively compiling library+features:++	DWC_CCLIB+	DWC_CRYPTOLIB+	DWC_NOTIFYLIB+	DWC_UTFLIB++A DWC_LIBMODULE #define has also been added. If this is not defined, then the+module code in dwc_common_linux.c is not compiled in. This allows linking the+library code directly into a driver module, instead of as a standalone module.diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/doc/doxygen.cfg linux-3.11.10/drivers/usb/host/dwc_common_port/doc/doxygen.cfg--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/doc/doxygen.cfg	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/doc/doxygen.cfg	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,270 @@+# Doxyfile 1.4.5++#---------------------------------------------------------------------------+# Project related configuration options+#---------------------------------------------------------------------------+PROJECT_NAME           = "Synopsys DWC Portability and Common Library for UWB"+PROJECT_NUMBER         =+OUTPUT_DIRECTORY       = doc+CREATE_SUBDIRS         = NO+OUTPUT_LANGUAGE        = English+BRIEF_MEMBER_DESC      = YES+REPEAT_BRIEF           = YES+ABBREVIATE_BRIEF       = "The $name class" \+                         "The $name widget" \+                         "The $name file" \+                         is \+                         provides \+                         specifies \+                         contains \+                         represents \+                         a \+                         an \+                         the+ALWAYS_DETAILED_SEC    = YES+INLINE_INHERITED_MEMB  = NO+FULL_PATH_NAMES        = NO+STRIP_FROM_PATH        = ..+STRIP_FROM_INC_PATH    =+SHORT_NAMES            = NO+JAVADOC_AUTOBRIEF      = YES+MULTILINE_CPP_IS_BRIEF = NO+DETAILS_AT_TOP         = YES+INHERIT_DOCS           = YES+SEPARATE_MEMBER_PAGES  = NO+TAB_SIZE               = 8+ALIASES                =+OPTIMIZE_OUTPUT_FOR_C  = YES+OPTIMIZE_OUTPUT_JAVA   = NO+BUILTIN_STL_SUPPORT    = NO+DISTRIBUTE_GROUP_DOC   = NO+SUBGROUPING            = NO+#---------------------------------------------------------------------------+# Build related configuration options+#---------------------------------------------------------------------------+EXTRACT_ALL            = NO+EXTRACT_PRIVATE        = NO+EXTRACT_STATIC         = YES+EXTRACT_LOCAL_CLASSES  = NO+EXTRACT_LOCAL_METHODS  = NO+HIDE_UNDOC_MEMBERS     = NO+HIDE_UNDOC_CLASSES     = NO+HIDE_FRIEND_COMPOUNDS  = NO+HIDE_IN_BODY_DOCS      = NO+INTERNAL_DOCS          = NO+CASE_SENSE_NAMES       = YES+HIDE_SCOPE_NAMES       = NO+SHOW_INCLUDE_FILES     = NO+INLINE_INFO            = YES+SORT_MEMBER_DOCS       = NO+SORT_BRIEF_DOCS        = NO+SORT_BY_SCOPE_NAME     = NO+GENERATE_TODOLIST      = YES+GENERATE_TESTLIST      = YES+GENERATE_BUGLIST       = YES+GENERATE_DEPRECATEDLIST= YES+ENABLED_SECTIONS       =+MAX_INITIALIZER_LINES  = 30+SHOW_USED_FILES        = YES+SHOW_DIRECTORIES       = YES+FILE_VERSION_FILTER    =+#---------------------------------------------------------------------------+# configuration options related to warning and progress messages+#---------------------------------------------------------------------------+QUIET                  = YES+WARNINGS               = YES+WARN_IF_UNDOCUMENTED   = NO+WARN_IF_DOC_ERROR      = YES+WARN_NO_PARAMDOC       = YES+WARN_FORMAT            = "$file:$line: $text"+WARN_LOGFILE           =+#---------------------------------------------------------------------------+# configuration options related to the input files+#---------------------------------------------------------------------------+INPUT                  = .+FILE_PATTERNS          = *.c \+                         *.cc \+                         *.cxx \+                         *.cpp \+                         *.c++ \+                         *.d \+                         *.java \+                         *.ii \+                         *.ixx \+                         *.ipp \+                         *.i++ \+                         *.inl \+                         *.h \+                         *.hh \+                         *.hxx \+                         *.hpp \+                         *.h++ \+                         *.idl \+                         *.odl \+                         *.cs \+                         *.php \+                         *.php3 \+                         *.inc \+                         *.m \+                         *.mm \+                         *.dox \+                         *.py \+                         *.C \+                         *.CC \+                         *.C++ \+                         *.II \+                         *.I++ \+                         *.H \+                         *.HH \+                         *.H++ \+                         *.CS \+                         *.PHP \+                         *.PHP3 \+                         *.M \+                         *.MM \+                         *.PY+RECURSIVE              = NO+EXCLUDE                =+EXCLUDE_SYMLINKS       = NO+EXCLUDE_PATTERNS       =+EXAMPLE_PATH           =+EXAMPLE_PATTERNS       = *+EXAMPLE_RECURSIVE      = NO+IMAGE_PATH             =+INPUT_FILTER           =+FILTER_PATTERNS        =+FILTER_SOURCE_FILES    = NO+#---------------------------------------------------------------------------+# configuration options related to source browsing+#---------------------------------------------------------------------------+SOURCE_BROWSER         = NO+INLINE_SOURCES         = NO+STRIP_CODE_COMMENTS    = YES+REFERENCED_BY_RELATION = YES+REFERENCES_RELATION    = YES+USE_HTAGS              = NO+VERBATIM_HEADERS       = NO+#---------------------------------------------------------------------------+# configuration options related to the alphabetical class index+#---------------------------------------------------------------------------+ALPHABETICAL_INDEX     = NO+COLS_IN_ALPHA_INDEX    = 5+IGNORE_PREFIX          =+#---------------------------------------------------------------------------+# configuration options related to the HTML output+#---------------------------------------------------------------------------+GENERATE_HTML          = YES+HTML_OUTPUT            = html+HTML_FILE_EXTENSION    = .html+HTML_HEADER            =+HTML_FOOTER            =+HTML_STYLESHEET        =+HTML_ALIGN_MEMBERS     = YES+GENERATE_HTMLHELP      = NO+CHM_FILE               =+HHC_LOCATION           =+GENERATE_CHI           = NO+BINARY_TOC             = NO+TOC_EXPAND             = NO+DISABLE_INDEX          = NO+ENUM_VALUES_PER_LINE   = 4+GENERATE_TREEVIEW      = YES+TREEVIEW_WIDTH         = 250+#---------------------------------------------------------------------------+# configuration options related to the LaTeX output+#---------------------------------------------------------------------------+GENERATE_LATEX         = NO+LATEX_OUTPUT           = latex+LATEX_CMD_NAME         = latex+MAKEINDEX_CMD_NAME     = makeindex+COMPACT_LATEX          = NO+PAPER_TYPE             = a4wide+EXTRA_PACKAGES         =+LATEX_HEADER           =+PDF_HYPERLINKS         = NO+USE_PDFLATEX           = NO+LATEX_BATCHMODE        = NO+LATEX_HIDE_INDICES     = NO+#---------------------------------------------------------------------------+# configuration options related to the RTF output+#---------------------------------------------------------------------------+GENERATE_RTF           = NO+RTF_OUTPUT             = rtf+COMPACT_RTF            = NO+RTF_HYPERLINKS         = NO+RTF_STYLESHEET_FILE    =+RTF_EXTENSIONS_FILE    =+#---------------------------------------------------------------------------+# configuration options related to the man page output+#---------------------------------------------------------------------------+GENERATE_MAN           = NO+MAN_OUTPUT             = man+MAN_EXTENSION          = .3+MAN_LINKS              = NO+#---------------------------------------------------------------------------+# configuration options related to the XML output+#---------------------------------------------------------------------------+GENERATE_XML           = NO+XML_OUTPUT             = xml+XML_SCHEMA             =+XML_DTD                =+XML_PROGRAMLISTING     = YES+#---------------------------------------------------------------------------+# configuration options for the AutoGen Definitions output+#---------------------------------------------------------------------------+GENERATE_AUTOGEN_DEF   = NO+#---------------------------------------------------------------------------+# configuration options related to the Perl module output+#---------------------------------------------------------------------------+GENERATE_PERLMOD       = NO+PERLMOD_LATEX          = NO+PERLMOD_PRETTY         = YES+PERLMOD_MAKEVAR_PREFIX =+#---------------------------------------------------------------------------+# Configuration options related to the preprocessor+#---------------------------------------------------------------------------+ENABLE_PREPROCESSING   = YES+MACRO_EXPANSION        = NO+EXPAND_ONLY_PREDEF     = NO+SEARCH_INCLUDES        = YES+INCLUDE_PATH           =+INCLUDE_FILE_PATTERNS  =+PREDEFINED             = DEBUG DEBUG_MEMORY+EXPAND_AS_DEFINED      =+SKIP_FUNCTION_MACROS   = YES+#---------------------------------------------------------------------------+# Configuration::additions related to external references+#---------------------------------------------------------------------------+TAGFILES               =+GENERATE_TAGFILE       =+ALLEXTERNALS           = NO+EXTERNAL_GROUPS        = YES+PERL_PATH              = /usr/bin/perl+#---------------------------------------------------------------------------+# Configuration options related to the dot tool+#---------------------------------------------------------------------------+CLASS_DIAGRAMS         = YES+HIDE_UNDOC_RELATIONS   = YES+HAVE_DOT               = NO+CLASS_GRAPH            = YES+COLLABORATION_GRAPH    = YES+GROUP_GRAPHS           = YES+UML_LOOK               = NO+TEMPLATE_RELATIONS     = NO+INCLUDE_GRAPH          = NO+INCLUDED_BY_GRAPH      = YES+CALL_GRAPH             = NO+GRAPHICAL_HIERARCHY    = YES+DIRECTORY_GRAPH        = YES+DOT_IMAGE_FORMAT       = png+DOT_PATH               =+DOTFILE_DIRS           =+MAX_DOT_GRAPH_DEPTH    = 1000+DOT_TRANSPARENT        = NO+DOT_MULTI_TARGETS      = NO+GENERATE_LEGEND        = YES+DOT_CLEANUP            = YES+#---------------------------------------------------------------------------+# Configuration::additions related to the search engine+#---------------------------------------------------------------------------+SEARCHENGINE           = NOdiff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_cc.c linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_cc.c--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_cc.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_cc.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,532 @@+/* =========================================================================+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.c $+ * $Revision: #4 $+ * $Date: 2010/11/04 $+ * $Change: 1621692 $+ *+ * Synopsys Portability Library Software and documentation+ * (hereinafter, "Software") is an Unsupported proprietary work of+ * Synopsys, Inc. unless otherwise expressly agreed to in writing+ * between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product+ * under any End User Software License Agreement or Agreement for+ * Licensed Product with Synopsys or any supplement thereto. You are+ * permitted to use and redistribute this Software in source and binary+ * forms, with or without modification, provided that redistributions+ * of source code must retain this notice. You may not view, use,+ * disclose, copy or distribute this file or any information contained+ * herein except pursuant to this license grant from Synopsys. If you+ * do not agree with this notice, including the disclaimer below, then+ * you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS+ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL+ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================= */+#ifdef DWC_CCLIB++#include "dwc_cc.h"++typedef struct dwc_cc+{+	uint32_t uid;+	uint8_t chid[16];+	uint8_t cdid[16];+	uint8_t ck[16];+	uint8_t *name;+	uint8_t length;+        DWC_CIRCLEQ_ENTRY(dwc_cc) list_entry;+} dwc_cc_t;++DWC_CIRCLEQ_HEAD(context_list, dwc_cc);++/** The main structure for CC management.  */+struct dwc_cc_if+{+	dwc_mutex_t *mutex;+	char *filename;++	unsigned is_host:1;++	dwc_notifier_t *notifier;++	struct context_list list;+};++#ifdef DEBUG+static inline void dump_bytes(char *name, uint8_t *bytes, int len)+{+	int i;+	DWC_PRINTF("%s: ", name);+	for (i=0; i<len; i++) {+		DWC_PRINTF("%02x ", bytes[i]);+	}+	DWC_PRINTF("\n");+}+#else+#define dump_bytes(x...)+#endif++static dwc_cc_t *alloc_cc(void *mem_ctx, uint8_t *name, uint32_t length)+{+	dwc_cc_t *cc = dwc_alloc(mem_ctx, sizeof(dwc_cc_t));+	if (!cc) {+		return NULL;+	}+	DWC_MEMSET(cc, 0, sizeof(dwc_cc_t));++	if (name) {+		cc->length = length;+		cc->name = dwc_alloc(mem_ctx, length);+		if (!cc->name) {+			dwc_free(mem_ctx, cc);+			return NULL;+		}++		DWC_MEMCPY(cc->name, name, length);+	}++	return cc;+}++static void free_cc(void *mem_ctx, dwc_cc_t *cc)+{+	if (cc->name) {+		dwc_free(mem_ctx, cc->name);+	}+	dwc_free(mem_ctx, cc);+}++static uint32_t next_uid(dwc_cc_if_t *cc_if)+{+	uint32_t uid = 0;+	dwc_cc_t *cc;+	DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {+		if (cc->uid > uid) {+			uid = cc->uid;+		}+	}++	if (uid == 0) {+		uid = 255;+	}++	return uid + 1;+}++static dwc_cc_t *cc_find(dwc_cc_if_t *cc_if, uint32_t uid)+{+	dwc_cc_t *cc;+	DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {+		if (cc->uid == uid) {+			return cc;+		}+	}+	return NULL;+}++static unsigned int cc_data_size(dwc_cc_if_t *cc_if)+{+	unsigned int size = 0;+	dwc_cc_t *cc;+	DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {+		size += (48 + 1);+		if (cc->name) {+			size += cc->length;+		}+	}+	return size;+}++static uint32_t cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)+{+	uint32_t uid = 0;+	dwc_cc_t *cc;++	DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {+		if (DWC_MEMCMP(cc->chid, chid, 16) == 0) {+			uid = cc->uid;+			break;+		}+	}+	return uid;+}+static uint32_t cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)+{+	uint32_t uid = 0;+	dwc_cc_t *cc;++	DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {+		if (DWC_MEMCMP(cc->cdid, cdid, 16) == 0) {+			uid = cc->uid;+			break;+		}+	}+	return uid;+}++/* Internal cc_add */+static int32_t cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,+		      uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)+{+	dwc_cc_t *cc;+	uint32_t uid;++	if (cc_if->is_host) {+		uid = cc_match_cdid(cc_if, cdid);+	}+	else {+		uid = cc_match_chid(cc_if, chid);+	}++	if (uid) {+		DWC_DEBUGC("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length);+		cc = cc_find(cc_if, uid);+	}+	else {+		cc = alloc_cc(mem_ctx, name, length);+		cc->uid = next_uid(cc_if);+		DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry);+	}++	DWC_MEMCPY(&(cc->chid[0]), chid, 16);+	DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);+	DWC_MEMCPY(&(cc->ck[0]), ck, 16);++	DWC_DEBUGC("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length);+	dump_bytes("CHID", cc->chid, 16);+	dump_bytes("CDID", cc->cdid, 16);+	dump_bytes("CK", cc->ck, 16);+	return cc->uid;+}++/* Internal cc_clear */+static void cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)+{+	while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) {+		dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list);+		DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);+		free_cc(mem_ctx, cc);+	}+}++dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx,+			     dwc_notifier_t *notifier, unsigned is_host)+{+	dwc_cc_if_t *cc_if = NULL;++	/* Allocate a common_cc_if structure */+	cc_if = dwc_alloc(mem_ctx, sizeof(dwc_cc_if_t));++	if (!cc_if)+		return NULL;++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))+	DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex);+#else+	cc_if->mutex = dwc_mutex_alloc(mtx_ctx);+#endif+	if (!cc_if->mutex) {+		dwc_free(mem_ctx, cc_if);+		return NULL;+	}++	DWC_CIRCLEQ_INIT(&cc_if->list);+	cc_if->is_host = is_host;+	cc_if->notifier = notifier;+	return cc_if;+}++void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if)+{+#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))+	DWC_MUTEX_FREE(cc_if->mutex);+#else+	dwc_mutex_free(mtx_ctx, cc_if->mutex);+#endif+	cc_clear(mem_ctx, cc_if);+	dwc_free(mem_ctx, cc_if);+}++static void cc_changed(dwc_cc_if_t *cc_if)+{+	if (cc_if->notifier) {+		dwc_notify(cc_if->notifier, DWC_CC_LIST_CHANGED_NOTIFICATION, cc_if);+	}+}++void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)+{+	DWC_MUTEX_LOCK(cc_if->mutex);+	cc_clear(mem_ctx, cc_if);+	DWC_MUTEX_UNLOCK(cc_if->mutex);+	cc_changed(cc_if);+}++int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,+		   uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)+{+	uint32_t uid;++	DWC_MUTEX_LOCK(cc_if->mutex);+	uid = cc_add(mem_ctx, cc_if, chid, cdid, ck, name, length);+	DWC_MUTEX_UNLOCK(cc_if->mutex);+	cc_changed(cc_if);++	return uid;+}++void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid,+		   uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)+{+	dwc_cc_t* cc;++	DWC_DEBUGC("Change connection context %d", id);++	DWC_MUTEX_LOCK(cc_if->mutex);+	cc = cc_find(cc_if, id);+	if (!cc) {+		DWC_ERROR("Uid %d not found in cc list\n", id);+		DWC_MUTEX_UNLOCK(cc_if->mutex);+		return;+	}++	if (chid) {+		DWC_MEMCPY(&(cc->chid[0]), chid, 16);+	}+	if (cdid) {+		DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);+	}+	if (ck) {+		DWC_MEMCPY(&(cc->ck[0]), ck, 16);+	}++	if (name) {+		if (cc->name) {+			dwc_free(mem_ctx, cc->name);+		}+		cc->name = dwc_alloc(mem_ctx, length);+		if (!cc->name) {+			DWC_ERROR("Out of memory in dwc_cc_change()\n");+			DWC_MUTEX_UNLOCK(cc_if->mutex);+			return;+		}+		cc->length = length;+		DWC_MEMCPY(cc->name, name, length);+	}++	DWC_MUTEX_UNLOCK(cc_if->mutex);++	cc_changed(cc_if);++	DWC_DEBUGC("Changed connection context id=%d\n", id);+	dump_bytes("New CHID", cc->chid, 16);+	dump_bytes("New CDID", cc->cdid, 16);+	dump_bytes("New CK", cc->ck, 16);+}++void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id)+{+	dwc_cc_t *cc;++	DWC_DEBUGC("Removing connection context %d", id);++	DWC_MUTEX_LOCK(cc_if->mutex);+	cc = cc_find(cc_if, id);+	if (!cc) {+		DWC_ERROR("Uid %d not found in cc list\n", id);+		DWC_MUTEX_UNLOCK(cc_if->mutex);+		return;+	}++	DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);+	DWC_MUTEX_UNLOCK(cc_if->mutex);+	free_cc(mem_ctx, cc);++	cc_changed(cc_if);+}++uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, unsigned int *length)+{+	uint8_t *buf, *x;+	uint8_t zero = 0;+	dwc_cc_t *cc;++	DWC_MUTEX_LOCK(cc_if->mutex);+	*length = cc_data_size(cc_if);+	if (!(*length)) {+		DWC_MUTEX_UNLOCK(cc_if->mutex);+		return NULL;+	}++	DWC_DEBUGC("Creating data for saving (length=%d)", *length);++	buf = dwc_alloc(mem_ctx, *length);+	if (!buf) {+		*length = 0;+		DWC_MUTEX_UNLOCK(cc_if->mutex);+		return NULL;+	}++	x = buf;+	DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {+		DWC_MEMCPY(x, cc->chid, 16);+		x += 16;+		DWC_MEMCPY(x, cc->cdid, 16);+		x += 16;+		DWC_MEMCPY(x, cc->ck, 16);+		x += 16;+		if (cc->name) {+			DWC_MEMCPY(x, &cc->length, 1);+			x += 1;+			DWC_MEMCPY(x, cc->name, cc->length);+			x += cc->length;+		}+		else {+			DWC_MEMCPY(x, &zero, 1);+			x += 1;+		}+	}+	DWC_MUTEX_UNLOCK(cc_if->mutex);++	return buf;+}++void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length)+{+	uint8_t name_length;+	uint8_t *name;+	uint8_t *chid;+	uint8_t *cdid;+	uint8_t *ck;+	uint32_t i = 0;++	DWC_MUTEX_LOCK(cc_if->mutex);+	cc_clear(mem_ctx, cc_if);++	while (i < length) {+		chid = &data[i];+		i += 16;+		cdid = &data[i];+		i += 16;+		ck = &data[i];+		i += 16;++		name_length = data[i];+		i ++;++		if (name_length) {+			name = &data[i];+			i += name_length;+		}+		else {+			name = NULL;+		}++		/* check to see if we haven't overflown the buffer */+		if (i > length) {+			DWC_ERROR("Data format error while attempting to load CCs "+				  "(nlen=%d, iter=%d, buflen=%d).\n", name_length, i, length);+			break;+		}++		cc_add(mem_ctx, cc_if, chid, cdid, ck, name, name_length);+	}+	DWC_MUTEX_UNLOCK(cc_if->mutex);++	cc_changed(cc_if);+}++uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)+{+	uint32_t uid = 0;++	DWC_MUTEX_LOCK(cc_if->mutex);+	uid = cc_match_chid(cc_if, chid);+	DWC_MUTEX_UNLOCK(cc_if->mutex);+	return uid;+}+uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)+{+	uint32_t uid = 0;++	DWC_MUTEX_LOCK(cc_if->mutex);+	uid = cc_match_cdid(cc_if, cdid);+	DWC_MUTEX_UNLOCK(cc_if->mutex);+	return uid;+}++uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id)+{+	uint8_t *ck = NULL;+	dwc_cc_t *cc;++	DWC_MUTEX_LOCK(cc_if->mutex);+	cc = cc_find(cc_if, id);+	if (cc) {+		ck = cc->ck;+	}+	DWC_MUTEX_UNLOCK(cc_if->mutex);++	return ck;++}++uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id)+{+	uint8_t *retval = NULL;+	dwc_cc_t *cc;++	DWC_MUTEX_LOCK(cc_if->mutex);+	cc = cc_find(cc_if, id);+	if (cc) {+		retval = cc->chid;+	}+	DWC_MUTEX_UNLOCK(cc_if->mutex);++	return retval;+}++uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id)+{+	uint8_t *retval = NULL;+	dwc_cc_t *cc;++	DWC_MUTEX_LOCK(cc_if->mutex);+	cc = cc_find(cc_if, id);+	if (cc) {+		retval = cc->cdid;+	}+	DWC_MUTEX_UNLOCK(cc_if->mutex);++	return retval;+}++uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length)+{+	uint8_t *retval = NULL;+	dwc_cc_t *cc;++	DWC_MUTEX_LOCK(cc_if->mutex);+	*length = 0;+	cc = cc_find(cc_if, id);+	if (cc) {+		*length = cc->length;+		retval = cc->name;+	}+	DWC_MUTEX_UNLOCK(cc_if->mutex);++	return retval;+}++#endif	/* DWC_CCLIB */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_cc.h linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_cc.h--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_cc.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_cc.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,224 @@+/* =========================================================================+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.h $+ * $Revision: #4 $+ * $Date: 2010/09/28 $+ * $Change: 1596182 $+ *+ * Synopsys Portability Library Software and documentation+ * (hereinafter, "Software") is an Unsupported proprietary work of+ * Synopsys, Inc. unless otherwise expressly agreed to in writing+ * between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product+ * under any End User Software License Agreement or Agreement for+ * Licensed Product with Synopsys or any supplement thereto. You are+ * permitted to use and redistribute this Software in source and binary+ * forms, with or without modification, provided that redistributions+ * of source code must retain this notice. You may not view, use,+ * disclose, copy or distribute this file or any information contained+ * herein except pursuant to this license grant from Synopsys. If you+ * do not agree with this notice, including the disclaimer below, then+ * you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS+ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL+ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================= */+#ifndef _DWC_CC_H_+#define _DWC_CC_H_++#ifdef __cplusplus+extern "C" {+#endif++/** @file+ *+ * This file defines the Context Context library.+ *+ * The main data structure is dwc_cc_if_t which is returned by either the+ * dwc_cc_if_alloc function or returned by the module to the user via a provided+ * function. The data structure is opaque and should only be manipulated via the+ * functions provied in this API.+ *+ * It manages a list of connection contexts and operations can be performed to+ * add, remove, query, search, and change, those contexts.  Additionally,+ * a dwc_notifier_t object can be requested from the manager so that+ * the user can be notified whenever the context list has changed.+ */++#include "dwc_os.h"+#include "dwc_list.h"+#include "dwc_notifier.h"+++/* Notifications */+#define DWC_CC_LIST_CHANGED_NOTIFICATION "DWC_CC_LIST_CHANGED_NOTIFICATION"++struct dwc_cc_if;+typedef struct dwc_cc_if dwc_cc_if_t;+++/** @name Connection Context Operations */+/** @{ */++/** This function allocates memory for a dwc_cc_if_t structure, initializes+ * fields to default values, and returns a pointer to the structure or NULL on+ * error. */+extern dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx,+				    dwc_notifier_t *notifier, unsigned is_host);++/** Frees the memory for the specified CC structure allocated from+ * dwc_cc_if_alloc(). */+extern void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if);++/** Removes all contexts from the connection context list */+extern void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if);++/** Adds a connection context (CHID, CK, CDID, Name) to the connection context list.+ * If a CHID already exists, the CK and name are overwritten.  Statistics are+ * not overwritten.+ *+ * @param cc_if The cc_if structure.+ * @param chid A pointer to the 16-byte CHID.  This value will be copied.+ * @param ck A pointer to the 16-byte CK.  This value will be copied.+ * @param cdid A pointer to the 16-byte CDID.  This value will be copied.+ * @param name An optional host friendly name as defined in the association model+ * spec.  Must be a UTF16-LE unicode string.  Can be NULL to indicated no name.+ * @param length The length othe unicode string.+ * @return A unique identifier used to refer to this context that is valid for+ * as long as this context is still in the list. */+extern int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,+			  uint8_t *cdid, uint8_t *ck, uint8_t *name,+			  uint8_t length);++/** Changes the CHID, CK, CDID, or Name values of a connection context in the+ * list, preserving any accumulated statistics.  This would typically be called+ * if the host decideds to change the context with a SET_CONNECTION request.+ *+ * @param cc_if The cc_if structure.+ * @param id The identifier of the connection context.+ * @param chid A pointer to the 16-byte CHID.  This value will be copied.  NULL+ * indicates no change.+ * @param cdid A pointer to the 16-byte CDID.  This value will be copied.  NULL+ * indicates no change.+ * @param ck A pointer to the 16-byte CK.  This value will be copied.  NULL+ * indicates no change.+ * @param name Host friendly name UTF16-LE.  NULL indicates no change.+ * @param length Length of name. */+extern void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id,+			  uint8_t *chid, uint8_t *cdid, uint8_t *ck,+			  uint8_t *name, uint8_t length);++/** Remove the specified connection context.+ * @param cc_if The cc_if structure.+ * @param id The identifier of the connection context to remove. */+extern void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id);++/** Get a binary block of data for the connection context list and attributes.+ * This data can be used by the OS specific driver to save the connection+ * context list into non-volatile memory.+ *+ * @param cc_if The cc_if structure.+ * @param length Return the length of the data buffer.+ * @return A pointer to the data buffer.  The memory for this buffer should be+ * freed with DWC_FREE() after use. */+extern uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if,+				     unsigned int *length);++/** Restore the connection context list from the binary data that was previously+ * returned from a call to dwc_cc_data_for_save.  This can be used by the OS specific+ * driver to load a connection context list from non-volatile memory.+ *+ * @param cc_if The cc_if structure.+ * @param data The data bytes as returned from dwc_cc_data_for_save.+ * @param length The length of the data. */+extern void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if,+				     uint8_t *data, unsigned int length);++/** Find the connection context from the specified CHID.+ *+ * @param cc_if The cc_if structure.+ * @param chid A pointer to the CHID data.+ * @return A non-zero identifier of the connection context if the CHID matches.+ * Otherwise returns 0. */+extern uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid);++/** Find the connection context from the specified CDID.+ *+ * @param cc_if The cc_if structure.+ * @param cdid A pointer to the CDID data.+ * @return A non-zero identifier of the connection context if the CHID matches.+ * Otherwise returns 0. */+extern uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid);++/** Retrieve the CK from the specified connection context.+ *+ * @param cc_if The cc_if structure.+ * @param id The identifier of the connection context.+ * @return A pointer to the CK data.  The memory does not need to be freed. */+extern uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id);++/** Retrieve the CHID from the specified connection context.+ *+ * @param cc_if The cc_if structure.+ * @param id The identifier of the connection context.+ * @return A pointer to the CHID data.  The memory does not need to be freed. */+extern uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id);++/** Retrieve the CDID from the specified connection context.+ *+ * @param cc_if The cc_if structure.+ * @param id The identifier of the connection context.+ * @return A pointer to the CDID data.  The memory does not need to be freed. */+extern uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id);++extern uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length);++/** Checks a buffer for non-zero.+ * @param id A pointer to a 16 byte buffer.+ * @return true if the 16 byte value is non-zero. */+static inline unsigned dwc_assoc_is_not_zero_id(uint8_t *id) {+	int i;+	for (i=0; i<16; i++) {+		if (id[i]) return 1;+	}+	return 0;+}++/** Checks a buffer for zero.+ * @param id A pointer to a 16 byte buffer.+ * @return true if the 16 byte value is zero. */+static inline unsigned dwc_assoc_is_zero_id(uint8_t *id) {+	return !dwc_assoc_is_not_zero_id(id);+}++/** Prints an ASCII representation for the 16-byte chid, cdid, or ck, into+ * buffer. */+static inline int dwc_print_id_string(char *buffer, uint8_t *id) {+	char *ptr = buffer;+	int i;+	for (i=0; i<16; i++) {+		ptr += DWC_SPRINTF(ptr, "%02x", id[i]);+		if (i < 15) {+			ptr += DWC_SPRINTF(ptr, " ");+		}+	}+	return ptr - buffer;+}++/** @} */++#ifdef __cplusplus+}+#endif++#endif /* _DWC_CC_H_ */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,1308 @@+#include "dwc_os.h"+#include "dwc_list.h"++#ifdef DWC_CCLIB+# include "dwc_cc.h"+#endif++#ifdef DWC_CRYPTOLIB+# include "dwc_modpow.h"+# include "dwc_dh.h"+# include "dwc_crypto.h"+#endif++#ifdef DWC_NOTIFYLIB+# include "dwc_notifier.h"+#endif++/* OS-Level Implementations */++/* This is the FreeBSD 7.0 kernel implementation of the DWC platform library. */+++/* MISC */++void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)+{+	return memset(dest, byte, size);+}++void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)+{+	return memcpy(dest, src, size);+}++void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)+{+	bcopy(src, dest, size);+	return dest;+}++int DWC_MEMCMP(void *m1, void *m2, uint32_t size)+{+	return memcmp(m1, m2, size);+}++int DWC_STRNCMP(void *s1, void *s2, uint32_t size)+{+	return strncmp(s1, s2, size);+}++int DWC_STRCMP(void *s1, void *s2)+{+	return strcmp(s1, s2);+}++int DWC_STRLEN(char const *str)+{+	return strlen(str);+}++char *DWC_STRCPY(char *to, char const *from)+{+	return strcpy(to, from);+}++char *DWC_STRDUP(char const *str)+{+	int len = DWC_STRLEN(str) + 1;+	char *new = DWC_ALLOC_ATOMIC(len);++	if (!new) {+		return NULL;+	}++	DWC_MEMCPY(new, str, len);+	return new;+}++int DWC_ATOI(char *str, int32_t *value)+{+	char *end = NULL;++	*value = strtol(str, &end, 0);+	if (*end == '\0') {+		return 0;+	}++	return -1;+}++int DWC_ATOUI(char *str, uint32_t *value)+{+	char *end = NULL;++	*value = strtoul(str, &end, 0);+	if (*end == '\0') {+		return 0;+	}++	return -1;+}+++#ifdef DWC_UTFLIB+/* From usbstring.c */++int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)+{+	int	count = 0;+	u8	c;+	u16	uchar;++	/* this insists on correct encodings, though not minimal ones.+	 * BUT it currently rejects legit 4-byte UTF-8 code points,+	 * which need surrogate pairs.  (Unicode 3.1 can use them.)+	 */+	while (len != 0 && (c = (u8) *s++) != 0) {+		if (unlikely(c & 0x80)) {+			// 2-byte sequence:+			// 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx+			if ((c & 0xe0) == 0xc0) {+				uchar = (c & 0x1f) << 6;++				c = (u8) *s++;+				if ((c & 0xc0) != 0xc0)+					goto fail;+				c &= 0x3f;+				uchar |= c;++			// 3-byte sequence (most CJKV characters):+			// zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx+			} else if ((c & 0xf0) == 0xe0) {+				uchar = (c & 0x0f) << 12;++				c = (u8) *s++;+				if ((c & 0xc0) != 0xc0)+					goto fail;+				c &= 0x3f;+				uchar |= c << 6;++				c = (u8) *s++;+				if ((c & 0xc0) != 0xc0)+					goto fail;+				c &= 0x3f;+				uchar |= c;++				/* no bogus surrogates */+				if (0xd800 <= uchar && uchar <= 0xdfff)+					goto fail;++			// 4-byte sequence (surrogate pairs, currently rare):+			// 11101110wwwwzzzzyy + 110111yyyyxxxxxx+			//     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx+			// (uuuuu = wwww + 1)+			// FIXME accept the surrogate code points (only)+			} else+				goto fail;+		} else+			uchar = c;+		put_unaligned (cpu_to_le16 (uchar), cp++);+		count++;+		len--;+	}+	return count;+fail:+	return -1;+}++#endif	/* DWC_UTFLIB */+++/* dwc_debug.h */++dwc_bool_t DWC_IN_IRQ(void)+{+//	return in_irq();+	return 0;+}++dwc_bool_t DWC_IN_BH(void)+{+//	return in_softirq();+	return 0;+}++void DWC_VPRINTF(char *format, va_list args)+{+	vprintf(format, args);+}++int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)+{+	return vsnprintf(str, size, format, args);+}++void DWC_PRINTF(char *format, ...)+{+	va_list args;++	va_start(args, format);+	DWC_VPRINTF(format, args);+	va_end(args);+}++int DWC_SPRINTF(char *buffer, char *format, ...)+{+	int retval;+	va_list args;++	va_start(args, format);+	retval = vsprintf(buffer, format, args);+	va_end(args);+	return retval;+}++int DWC_SNPRINTF(char *buffer, int size, char *format, ...)+{+	int retval;+	va_list args;++	va_start(args, format);+	retval = vsnprintf(buffer, size, format, args);+	va_end(args);+	return retval;+}++void __DWC_WARN(char *format, ...)+{+	va_list args;++	va_start(args, format);+	DWC_VPRINTF(format, args);+	va_end(args);+}++void __DWC_ERROR(char *format, ...)+{+	va_list args;++	va_start(args, format);+	DWC_VPRINTF(format, args);+	va_end(args);+}++void DWC_EXCEPTION(char *format, ...)+{+	va_list args;++	va_start(args, format);+	DWC_VPRINTF(format, args);+	va_end(args);+//	BUG_ON(1);	???+}++#ifdef DEBUG+void __DWC_DEBUG(char *format, ...)+{+	va_list args;++	va_start(args, format);+	DWC_VPRINTF(format, args);+	va_end(args);+}+#endif+++/* dwc_mem.h */++#if 0+dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,+				uint32_t align,+				uint32_t alloc)+{+	struct dma_pool *pool = dma_pool_create("Pool", NULL,+						size, align, alloc);+	return (dwc_pool_t *)pool;+}++void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)+{+	dma_pool_destroy((struct dma_pool *)pool);+}++void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)+{+//	return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);+	return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr);+}++void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)+{+	void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);+	memset(..);+}++void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)+{+	dma_pool_free(pool, vaddr, daddr);+}+#endif++static void dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)+{+	if (error)+		return;+	*(bus_addr_t *)arg = segs[0].ds_addr;+}++void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)+{+	dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;+	int error;++	error = bus_dma_tag_create(+#if __FreeBSD_version >= 700000+			bus_get_dma_tag(dma->dev),	/* parent */+#else+			NULL,				/* parent */+#endif+			4, 0,				/* alignment, bounds */+			BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */+			BUS_SPACE_MAXADDR,		/* highaddr */+			NULL, NULL,			/* filter, filterarg */+			size,				/* maxsize */+			1,				/* nsegments */+			size,				/* maxsegsize */+			0,				/* flags */+			NULL,				/* lockfunc */+			NULL,				/* lockarg */+			&dma->dma_tag);+	if (error) {+		device_printf(dma->dev, "%s: bus_dma_tag_create failed: %d\n",+			      __func__, error);+		goto fail_0;+	}++	error = bus_dmamem_alloc(dma->dma_tag, &dma->dma_vaddr,+				 BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map);+	if (error) {+		device_printf(dma->dev, "%s: bus_dmamem_alloc(%ju) failed: %d\n",+			      __func__, (uintmax_t)size, error);+		goto fail_1;+	}++	dma->dma_paddr = 0;+	error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, size,+				dmamap_cb, &dma->dma_paddr, BUS_DMA_NOWAIT);+	if (error || dma->dma_paddr == 0) {+		device_printf(dma->dev, "%s: bus_dmamap_load failed: %d\n",+			      __func__, error);+		goto fail_2;+	}++	*dma_addr = dma->dma_paddr;+	return dma->dma_vaddr;++fail_2:+	bus_dmamap_unload(dma->dma_tag, dma->dma_map);+fail_1:+	bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);+	bus_dma_tag_destroy(dma->dma_tag);+fail_0:+	dma->dma_map = NULL;+	dma->dma_tag = NULL;++	return NULL;+}++void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)+{+	dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;++	if (dma->dma_tag == NULL)+		return;+	if (dma->dma_map != NULL) {+		bus_dmamap_sync(dma->dma_tag, dma->dma_map,+				BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);+		bus_dmamap_unload(dma->dma_tag, dma->dma_map);+		bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);+		dma->dma_map = NULL;+	}++	bus_dma_tag_destroy(dma->dma_tag);+	dma->dma_tag = NULL;+}++void *__DWC_ALLOC(void *mem_ctx, uint32_t size)+{+	return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);+}++void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)+{+	return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);+}++void __DWC_FREE(void *mem_ctx, void *addr)+{+	free(addr, M_DEVBUF);+}+++#ifdef DWC_CRYPTOLIB+/* dwc_crypto.h */++void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)+{+	get_random_bytes(buffer, length);+}++int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)+{+	struct crypto_blkcipher *tfm;+	struct blkcipher_desc desc;+	struct scatterlist sgd;+	struct scatterlist sgs;++	tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);+	if (tfm == NULL) {+		printk("failed to load transform for aes CBC\n");+		return -1;+	}++	crypto_blkcipher_setkey(tfm, key, keylen);+	crypto_blkcipher_set_iv(tfm, iv, 16);++	sg_init_one(&sgd, out, messagelen);+	sg_init_one(&sgs, message, messagelen);++	desc.tfm = tfm;+	desc.flags = 0;++	if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {+		crypto_free_blkcipher(tfm);+		DWC_ERROR("AES CBC encryption failed");+		return -1;+	}++	crypto_free_blkcipher(tfm);+	return 0;+}++int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)+{+	struct crypto_hash *tfm;+	struct hash_desc desc;+	struct scatterlist sg;++	tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);+	if (IS_ERR(tfm)) {+		DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm));+		return 0;+	}+	desc.tfm = tfm;+	desc.flags = 0;++	sg_init_one(&sg, message, len);+	crypto_hash_digest(&desc, &sg, len, out);+	crypto_free_hash(tfm);++	return 1;+}++int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,+		    uint8_t *key, uint32_t keylen, uint8_t *out)+{+	struct crypto_hash *tfm;+	struct hash_desc desc;+	struct scatterlist sg;++	tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);+	if (IS_ERR(tfm)) {+		DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm));+		return 0;+	}+	desc.tfm = tfm;+	desc.flags = 0;++	sg_init_one(&sg, message, messagelen);+	crypto_hash_setkey(tfm, key, keylen);+	crypto_hash_digest(&desc, &sg, messagelen, out);+	crypto_free_hash(tfm);++	return 1;+}++#endif	/* DWC_CRYPTOLIB */+++/* Byte Ordering Conversions */++uint32_t DWC_CPU_TO_LE32(uint32_t *p)+{+#ifdef __LITTLE_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;++	return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));+#endif+}++uint32_t DWC_CPU_TO_BE32(uint32_t *p)+{+#ifdef __BIG_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;++	return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));+#endif+}++uint32_t DWC_LE32_TO_CPU(uint32_t *p)+{+#ifdef __LITTLE_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;++	return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));+#endif+}++uint32_t DWC_BE32_TO_CPU(uint32_t *p)+{+#ifdef __BIG_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;++	return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));+#endif+}++uint16_t DWC_CPU_TO_LE16(uint16_t *p)+{+#ifdef __LITTLE_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;+	return (u_p[1] | (u_p[0] << 8));+#endif+}++uint16_t DWC_CPU_TO_BE16(uint16_t *p)+{+#ifdef __BIG_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;+	return (u_p[1] | (u_p[0] << 8));+#endif+}++uint16_t DWC_LE16_TO_CPU(uint16_t *p)+{+#ifdef __LITTLE_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;+	return (u_p[1] | (u_p[0] << 8));+#endif+}++uint16_t DWC_BE16_TO_CPU(uint16_t *p)+{+#ifdef __BIG_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;+	return (u_p[1] | (u_p[0] << 8));+#endif+}+++/* Registers */++uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg)+{+	dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;+	bus_size_t ior = (bus_size_t)reg;++	return bus_space_read_4(io->iot, io->ioh, ior);+}++#if 0+uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg)+{+	dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;+	bus_size_t ior = (bus_size_t)reg;++	return bus_space_read_8(io->iot, io->ioh, ior);+}+#endif++void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value)+{+	dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;+	bus_size_t ior = (bus_size_t)reg;++	bus_space_write_4(io->iot, io->ioh, ior, value);+}++#if 0+void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value)+{+	dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;+	bus_size_t ior = (bus_size_t)reg;++	bus_space_write_8(io->iot, io->ioh, ior, value);+}+#endif++void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask,+		      uint32_t set_mask)+{+	dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;+	bus_size_t ior = (bus_size_t)reg;++	bus_space_write_4(io->iot, io->ioh, ior,+			  (bus_space_read_4(io->iot, io->ioh, ior) &+			   ~clear_mask) | set_mask);+}++#if 0+void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask,+		      uint64_t set_mask)+{+	dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;+	bus_size_t ior = (bus_size_t)reg;++	bus_space_write_8(io->iot, io->ioh, ior,+			  (bus_space_read_8(io->iot, io->ioh, ior) &+			   ~clear_mask) | set_mask);+}+#endif+++/* Locking */++dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)+{+	struct mtx *sl = DWC_ALLOC(sizeof(*sl));++	if (!sl) {+		DWC_ERROR("Cannot allocate memory for spinlock");+		return NULL;+	}++	mtx_init(sl, "dw3spn", NULL, MTX_SPIN);+	return (dwc_spinlock_t *)sl;+}++void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)+{+	struct mtx *sl = (struct mtx *)lock;++	mtx_destroy(sl);+	DWC_FREE(sl);+}++void DWC_SPINLOCK(dwc_spinlock_t *lock)+{+	mtx_lock_spin((struct mtx *)lock);	// ???+}++void DWC_SPINUNLOCK(dwc_spinlock_t *lock)+{+	mtx_unlock_spin((struct mtx *)lock);	// ???+}++void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)+{+	mtx_lock_spin((struct mtx *)lock);+}++void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)+{+	mtx_unlock_spin((struct mtx *)lock);+}++dwc_mutex_t *DWC_MUTEX_ALLOC(void)+{+	struct mtx *m;+	dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mtx));++	if (!mutex) {+		DWC_ERROR("Cannot allocate memory for mutex");+		return NULL;+	}++	m = (struct mtx *)mutex;+	mtx_init(m, "dw3mtx", NULL, MTX_DEF);+	return mutex;+}++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))+#else+void DWC_MUTEX_FREE(dwc_mutex_t *mutex)+{+	mtx_destroy((struct mtx *)mutex);+	DWC_FREE(mutex);+}+#endif++void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)+{+	struct mtx *m = (struct mtx *)mutex;++	mtx_lock(m);+}++int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)+{+	struct mtx *m = (struct mtx *)mutex;++	return mtx_trylock(m);+}++void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)+{+	struct mtx *m = (struct mtx *)mutex;++	mtx_unlock(m);+}+++/* Timing */++void DWC_UDELAY(uint32_t usecs)+{+	DELAY(usecs);+}++void DWC_MDELAY(uint32_t msecs)+{+	do {+		DELAY(1000);+	} while (--msecs);+}++void DWC_MSLEEP(uint32_t msecs)+{+	struct timeval tv;++	tv.tv_sec = msecs / 1000;+	tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;+	pause("dw3slp", tvtohz(&tv));+}++uint32_t DWC_TIME(void)+{+	struct timeval tv;++	microuptime(&tv);	// or getmicrouptime? (less precise, but faster)+	return tv.tv_sec * 1000 + tv.tv_usec / 1000;+}+++/* Timers */++struct dwc_timer {+	struct callout t;+	char *name;+	dwc_spinlock_t *lock;+	dwc_timer_callback_t cb;+	void *data;+};++dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)+{+	dwc_timer_t *t = DWC_ALLOC(sizeof(*t));++	if (!t) {+		DWC_ERROR("Cannot allocate memory for timer");+		return NULL;+	}++	callout_init(&t->t, 1);++	t->name = DWC_STRDUP(name);+	if (!t->name) {+		DWC_ERROR("Cannot allocate memory for timer->name");+		goto no_name;+	}++	t->lock = DWC_SPINLOCK_ALLOC();+	if (!t->lock) {+		DWC_ERROR("Cannot allocate memory for lock");+		goto no_lock;+	}++	t->cb = cb;+	t->data = data;++	return t;++ no_lock:+	DWC_FREE(t->name);+ no_name:+	DWC_FREE(t);++	return NULL;+}++void DWC_TIMER_FREE(dwc_timer_t *timer)+{+	callout_stop(&timer->t);+	DWC_SPINLOCK_FREE(timer->lock);+	DWC_FREE(timer->name);+	DWC_FREE(timer);+}++void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)+{+	struct timeval tv;++	tv.tv_sec = time / 1000;+	tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;+	callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data);+}++void DWC_TIMER_CANCEL(dwc_timer_t *timer)+{+	callout_stop(&timer->t);+}+++/* Wait Queues */++struct dwc_waitq {+	struct mtx lock;+	int abort;+};++dwc_waitq_t *DWC_WAITQ_ALLOC(void)+{+	dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));++	if (!wq) {+		DWC_ERROR("Cannot allocate memory for waitqueue");+		return NULL;+	}++	mtx_init(&wq->lock, "dw3wtq", NULL, MTX_DEF);+	wq->abort = 0;++	return wq;+}++void DWC_WAITQ_FREE(dwc_waitq_t *wq)+{+	mtx_destroy(&wq->lock);+	DWC_FREE(wq);+}++int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)+{+//	intrmask_t ipl;+	int result = 0;++	mtx_lock(&wq->lock);+//	ipl = splbio();++	/* Skip the sleep if already aborted or triggered */+	if (!wq->abort && !cond(data)) {+//		splx(ipl);+		result = msleep(wq, &wq->lock, PCATCH, "dw3wat", 0); // infinite timeout+//		ipl = splbio();+	}++	if (result == ERESTART) {	// signaled - restart+		result = -DWC_E_RESTART;++	} else if (result == EINTR) {	// signaled - interrupt+		result = -DWC_E_ABORT;++	} else if (wq->abort) {+		result = -DWC_E_ABORT;++	} else {+		result = 0;+	}++	wq->abort = 0;+//	splx(ipl);+	mtx_unlock(&wq->lock);+	return result;+}++int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,+			       void *data, int32_t msecs)+{+	struct timeval tv, tv1, tv2;+//	intrmask_t ipl;+	int result = 0;++	tv.tv_sec = msecs / 1000;+	tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;++	mtx_lock(&wq->lock);+//	ipl = splbio();++	/* Skip the sleep if already aborted or triggered */+	if (!wq->abort && !cond(data)) {+//		splx(ipl);+		getmicrouptime(&tv1);+		result = msleep(wq, &wq->lock, PCATCH, "dw3wto", tvtohz(&tv));+		getmicrouptime(&tv2);+//		ipl = splbio();+	}++	if (result == 0) {			// awoken+		if (wq->abort) {+			result = -DWC_E_ABORT;+		} else {+			tv2.tv_usec -= tv1.tv_usec;+			if (tv2.tv_usec < 0) {+				tv2.tv_usec += 1000000;+				tv2.tv_sec--;+			}++			tv2.tv_sec -= tv1.tv_sec;+			result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;+			result = msecs - result;+			if (result <= 0)+				result = 1;+		}+	} else if (result == ERESTART) {	// signaled - restart+		result = -DWC_E_RESTART;++	} else if (result == EINTR) {		// signaled - interrupt+		result = -DWC_E_ABORT;++	} else {				// timed out+		result = -DWC_E_TIMEOUT;+	}++	wq->abort = 0;+//	splx(ipl);+	mtx_unlock(&wq->lock);+	return result;+}++void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)+{+	wakeup(wq);+}++void DWC_WAITQ_ABORT(dwc_waitq_t *wq)+{+//	intrmask_t ipl;++	mtx_lock(&wq->lock);+//	ipl = splbio();+	wq->abort = 1;+	wakeup(wq);+//	splx(ipl);+	mtx_unlock(&wq->lock);+}+++/* Threading */++struct dwc_thread {+	struct proc *proc;+	int abort;+};++dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)+{+	int retval;+	dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread));++	if (!thread) {+		return NULL;+	}++	thread->abort = 0;+	retval = kthread_create((void (*)(void *))func, data, &thread->proc,+				RFPROC | RFNOWAIT, 0, "%s", name);+	if (retval) {+		DWC_FREE(thread);+		return NULL;+	}++	return thread;+}++int DWC_THREAD_STOP(dwc_thread_t *thread)+{+	int retval;++	thread->abort = 1;+	retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz);++	if (retval == 0) {+		/* DWC_THREAD_EXIT() will free the thread struct */+		return 0;+	}++	/* NOTE: We leak the thread struct if thread doesn't die */++	if (retval == EWOULDBLOCK) {+		return -DWC_E_TIMEOUT;+	}++	return -DWC_E_UNKNOWN;+}++dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread)+{+	return thread->abort;+}++void DWC_THREAD_EXIT(dwc_thread_t *thread)+{+	wakeup(&thread->abort);+	DWC_FREE(thread);+	kthread_exit(0);+}+++/* tasklets+ - Runs in interrupt context (cannot sleep)+ - Each tasklet runs on a single CPU [ How can we ensure this on FreeBSD? Does it matter? ]+ - Different tasklets can be running simultaneously on different CPUs [ shouldn't matter ]+ */+struct dwc_tasklet {+	struct task t;+	dwc_tasklet_callback_t cb;+	void *data;+};++static void tasklet_callback(void *data, int pending)	// what to do with pending ???+{+	dwc_tasklet_t *task = (dwc_tasklet_t *)data;++	task->cb(task->data);+}++dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)+{+	dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task));++	if (task) {+		task->cb = cb;+		task->data = data;+		TASK_INIT(&task->t, 0, tasklet_callback, task);+	} else {+		DWC_ERROR("Cannot allocate memory for tasklet");+	}++	return task;+}++void DWC_TASK_FREE(dwc_tasklet_t *task)+{+	taskqueue_drain(taskqueue_fast, &task->t);	// ???+	DWC_FREE(task);+}++void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)+{+	/* Uses predefined system queue */+	taskqueue_enqueue_fast(taskqueue_fast, &task->t);+}+++/* workqueues+ - Runs in process context (can sleep)+ */+typedef struct work_container {+	dwc_work_callback_t cb;+	void *data;+	dwc_workq_t *wq;+	char *name;+	int hz;++#ifdef DEBUG+	DWC_CIRCLEQ_ENTRY(work_container) entry;+#endif+	struct task task;+} work_container_t;++#ifdef DEBUG+DWC_CIRCLEQ_HEAD(work_container_queue, work_container);+#endif++struct dwc_workq {+	struct taskqueue *taskq;+	dwc_spinlock_t *lock;+	dwc_waitq_t *waitq;+	int pending;++#ifdef DEBUG+	struct work_container_queue entries;+#endif+};++static void do_work(void *data, int pending)	// what to do with pending ???+{+	work_container_t *container = (work_container_t *)data;+	dwc_workq_t *wq = container->wq;+	dwc_irqflags_t flags;++	if (container->hz) {+		pause("dw3wrk", container->hz);+	}++	container->cb(container->data);+	DWC_DEBUG("Work done: %s, container=%p", container->name, container);++	DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);++#ifdef DEBUG+	DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry);+#endif+	if (container->name)+		DWC_FREE(container->name);+	DWC_FREE(container);+	wq->pending--;+	DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);+	DWC_WAITQ_TRIGGER(wq->waitq);+}++static int work_done(void *data)+{+	dwc_workq_t *workq = (dwc_workq_t *)data;++	return workq->pending == 0;+}++int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)+{+	return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);+}++dwc_workq_t *DWC_WORKQ_ALLOC(char *name)+{+	dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));++	if (!wq) {+		DWC_ERROR("Cannot allocate memory for workqueue");+		return NULL;+	}++	wq->taskq = taskqueue_create(name, M_NOWAIT, taskqueue_thread_enqueue, &wq->taskq);+	if (!wq->taskq) {+		DWC_ERROR("Cannot allocate memory for taskqueue");+		goto no_taskq;+	}++	wq->pending = 0;++	wq->lock = DWC_SPINLOCK_ALLOC();+	if (!wq->lock) {+		DWC_ERROR("Cannot allocate memory for spinlock");+		goto no_lock;+	}++	wq->waitq = DWC_WAITQ_ALLOC();+	if (!wq->waitq) {+		DWC_ERROR("Cannot allocate memory for waitqueue");+		goto no_waitq;+	}++	taskqueue_start_threads(&wq->taskq, 1, PWAIT, "%s taskq", "dw3tsk");++#ifdef DEBUG+	DWC_CIRCLEQ_INIT(&wq->entries);+#endif+	return wq;++ no_waitq:+	DWC_SPINLOCK_FREE(wq->lock);+ no_lock:+	taskqueue_free(wq->taskq);+ no_taskq:+	DWC_FREE(wq);++	return NULL;+}++void DWC_WORKQ_FREE(dwc_workq_t *wq)+{+#ifdef DEBUG+	dwc_irqflags_t flags;++	DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);++	if (wq->pending != 0) {+		struct work_container *container;++		DWC_ERROR("Destroying work queue with pending work");++		DWC_CIRCLEQ_FOREACH(container, &wq->entries, entry) {+			DWC_ERROR("Work %s still pending", container->name);+		}+	}++	DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);+#endif+	DWC_WAITQ_FREE(wq->waitq);+	DWC_SPINLOCK_FREE(wq->lock);+	taskqueue_free(wq->taskq);+	DWC_FREE(wq);+}++void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,+			char *format, ...)+{+	dwc_irqflags_t flags;+	work_container_t *container;+	static char name[128];+	va_list args;++	va_start(args, format);+	DWC_VSNPRINTF(name, 128, format, args);+	va_end(args);++	DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);+	wq->pending++;+	DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);+	DWC_WAITQ_TRIGGER(wq->waitq);++	container = DWC_ALLOC_ATOMIC(sizeof(*container));+	if (!container) {+		DWC_ERROR("Cannot allocate memory for container");+		return;+	}++	container->name = DWC_STRDUP(name);+	if (!container->name) {+		DWC_ERROR("Cannot allocate memory for container->name");+		DWC_FREE(container);+		return;+	}++	container->cb = cb;+	container->data = data;+	container->wq = wq;+	container->hz = 0;++	DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);++	TASK_INIT(&container->task, 0, do_work, container);++#ifdef DEBUG+	DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);+#endif+	taskqueue_enqueue_fast(wq->taskq, &container->task);+}++void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,+				void *data, uint32_t time, char *format, ...)+{+	dwc_irqflags_t flags;+	work_container_t *container;+	static char name[128];+	struct timeval tv;+	va_list args;++	va_start(args, format);+	DWC_VSNPRINTF(name, 128, format, args);+	va_end(args);++	DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);+	wq->pending++;+	DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);+	DWC_WAITQ_TRIGGER(wq->waitq);++	container = DWC_ALLOC_ATOMIC(sizeof(*container));+	if (!container) {+		DWC_ERROR("Cannot allocate memory for container");+		return;+	}++	container->name = DWC_STRDUP(name);+	if (!container->name) {+		DWC_ERROR("Cannot allocate memory for container->name");+		DWC_FREE(container);+		return;+	}++	container->cb = cb;+	container->data = data;+	container->wq = wq;++	tv.tv_sec = time / 1000;+	tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;+	container->hz = tvtohz(&tv);++	DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);++	TASK_INIT(&container->task, 0, do_work, container);++#ifdef DEBUG+	DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);+#endif+	taskqueue_enqueue_fast(wq->taskq, &container->task);+}++int DWC_WORKQ_PENDING(dwc_workq_t *wq)+{+	return wq->pending;+}diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_common_linux.c linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_common_linux.c--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_common_linux.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_common_linux.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,1431 @@+#include <linux/kernel.h>+#include <linux/init.h>+#include <linux/module.h>+#include <linux/kthread.h>++#ifdef DWC_CCLIB+# include "dwc_cc.h"+#endif++#ifdef DWC_CRYPTOLIB+# include "dwc_modpow.h"+# include "dwc_dh.h"+# include "dwc_crypto.h"+#endif++#ifdef DWC_NOTIFYLIB+# include "dwc_notifier.h"+#endif++/* OS-Level Implementations */++/* This is the Linux kernel implementation of the DWC platform library. */+#include <linux/moduleparam.h>+#include <linux/ctype.h>+#include <linux/crypto.h>+#include <linux/delay.h>+#include <linux/device.h>+#include <linux/dma-mapping.h>+#include <linux/cdev.h>+#include <linux/errno.h>+#include <linux/interrupt.h>+#include <linux/jiffies.h>+#include <linux/list.h>+#include <linux/pci.h>+#include <linux/random.h>+#include <linux/scatterlist.h>+#include <linux/slab.h>+#include <linux/stat.h>+#include <linux/string.h>+#include <linux/timer.h>+#include <linux/usb.h>++#include <linux/version.h>++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)+# include <linux/usb/gadget.h>+#else+# include <linux/usb_gadget.h>+#endif++#include <asm/io.h>+#include <asm/page.h>+#include <asm/uaccess.h>+#include <asm/unaligned.h>++#include "dwc_os.h"+#include "dwc_list.h"+++/* MISC */++void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)+{+	return memset(dest, byte, size);+}++void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)+{+	return memcpy(dest, src, size);+}++void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)+{+	return memmove(dest, src, size);+}++int DWC_MEMCMP(void *m1, void *m2, uint32_t size)+{+	return memcmp(m1, m2, size);+}++int DWC_STRNCMP(void *s1, void *s2, uint32_t size)+{+	return strncmp(s1, s2, size);+}++int DWC_STRCMP(void *s1, void *s2)+{+	return strcmp(s1, s2);+}++int DWC_STRLEN(char const *str)+{+	return strlen(str);+}++char *DWC_STRCPY(char *to, char const *from)+{+	return strcpy(to, from);+}++char *DWC_STRDUP(char const *str)+{+	int len = DWC_STRLEN(str) + 1;+	char *new = DWC_ALLOC_ATOMIC(len);++	if (!new) {+		return NULL;+	}++	DWC_MEMCPY(new, str, len);+	return new;+}++int DWC_ATOI(const char *str, int32_t *value)+{+	char *end = NULL;++	*value = simple_strtol(str, &end, 0);+	if (*end == '\0') {+		return 0;+	}++	return -1;+}++int DWC_ATOUI(const char *str, uint32_t *value)+{+	char *end = NULL;++	*value = simple_strtoul(str, &end, 0);+	if (*end == '\0') {+		return 0;+	}++	return -1;+}+++#ifdef DWC_UTFLIB+/* From usbstring.c */++int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)+{+	int	count = 0;+	u8	c;+	u16	uchar;++	/* this insists on correct encodings, though not minimal ones.+	 * BUT it currently rejects legit 4-byte UTF-8 code points,+	 * which need surrogate pairs.  (Unicode 3.1 can use them.)+	 */+	while (len != 0 && (c = (u8) *s++) != 0) {+		if (unlikely(c & 0x80)) {+			// 2-byte sequence:+			// 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx+			if ((c & 0xe0) == 0xc0) {+				uchar = (c & 0x1f) << 6;++				c = (u8) *s++;+				if ((c & 0xc0) != 0xc0)+					goto fail;+				c &= 0x3f;+				uchar |= c;++			// 3-byte sequence (most CJKV characters):+			// zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx+			} else if ((c & 0xf0) == 0xe0) {+				uchar = (c & 0x0f) << 12;++				c = (u8) *s++;+				if ((c & 0xc0) != 0xc0)+					goto fail;+				c &= 0x3f;+				uchar |= c << 6;++				c = (u8) *s++;+				if ((c & 0xc0) != 0xc0)+					goto fail;+				c &= 0x3f;+				uchar |= c;++				/* no bogus surrogates */+				if (0xd800 <= uchar && uchar <= 0xdfff)+					goto fail;++			// 4-byte sequence (surrogate pairs, currently rare):+			// 11101110wwwwzzzzyy + 110111yyyyxxxxxx+			//     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx+			// (uuuuu = wwww + 1)+			// FIXME accept the surrogate code points (only)+			} else+				goto fail;+		} else+			uchar = c;+		put_unaligned (cpu_to_le16 (uchar), cp++);+		count++;+		len--;+	}+	return count;+fail:+	return -1;+}+#endif	/* DWC_UTFLIB */+++/* dwc_debug.h */++dwc_bool_t DWC_IN_IRQ(void)+{+	return in_irq();+}++dwc_bool_t DWC_IN_BH(void)+{+	return in_softirq();+}++void DWC_VPRINTF(char *format, va_list args)+{+	vprintk(format, args);+}++int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)+{+	return vsnprintf(str, size, format, args);+}++void DWC_PRINTF(char *format, ...)+{+	va_list args;++	va_start(args, format);+	DWC_VPRINTF(format, args);+	va_end(args);+}++int DWC_SPRINTF(char *buffer, char *format, ...)+{+	int retval;+	va_list args;++	va_start(args, format);+	retval = vsprintf(buffer, format, args);+	va_end(args);+	return retval;+}++int DWC_SNPRINTF(char *buffer, int size, char *format, ...)+{+	int retval;+	va_list args;++	va_start(args, format);+	retval = vsnprintf(buffer, size, format, args);+	va_end(args);+	return retval;+}++void __DWC_WARN(char *format, ...)+{+	va_list args;++	va_start(args, format);+	DWC_PRINTF(KERN_WARNING);+	DWC_VPRINTF(format, args);+	va_end(args);+}++void __DWC_ERROR(char *format, ...)+{+	va_list args;++	va_start(args, format);+	DWC_PRINTF(KERN_ERR);+	DWC_VPRINTF(format, args);+	va_end(args);+}++void DWC_EXCEPTION(char *format, ...)+{+	va_list args;++	va_start(args, format);+	DWC_PRINTF(KERN_ERR);+	DWC_VPRINTF(format, args);+	va_end(args);+	BUG_ON(1);+}++#ifdef DEBUG+void __DWC_DEBUG(char *format, ...)+{+	va_list args;++	va_start(args, format);+	DWC_PRINTF(KERN_DEBUG);+	DWC_VPRINTF(format, args);+	va_end(args);+}+#endif+++/* dwc_mem.h */++#if 0+dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,+				uint32_t align,+				uint32_t alloc)+{+	struct dma_pool *pool = dma_pool_create("Pool", NULL,+						size, align, alloc);+	return (dwc_pool_t *)pool;+}++void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)+{+	dma_pool_destroy((struct dma_pool *)pool);+}++void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)+{+	return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);+}++void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)+{+	void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);+	memset(..);+}++void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)+{+	dma_pool_free(pool, vaddr, daddr);+}+#endif++void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)+{+#ifdef xxCOSIM /* Only works for 32-bit cosim */+	void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL);+#else+	void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL | GFP_DMA32);+#endif+	if (!buf) {+		return NULL;+	}++	memset(buf, 0, (size_t)size);+	return buf;+}++void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)+{+	void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC);+	if (!buf) {+		return NULL;+	}+	memset(buf, 0, (size_t)size);+	return buf;+}++void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)+{+	dma_free_coherent(dma_ctx, size, virt_addr, dma_addr);+}++void *__DWC_ALLOC(void *mem_ctx, uint32_t size)+{+	return kzalloc(size, GFP_KERNEL);+}++void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)+{+	return kzalloc(size, GFP_ATOMIC);+}++void __DWC_FREE(void *mem_ctx, void *addr)+{+	kfree(addr);+}+++#ifdef DWC_CRYPTOLIB+/* dwc_crypto.h */++void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)+{+	get_random_bytes(buffer, length);+}++int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)+{+	struct crypto_blkcipher *tfm;+	struct blkcipher_desc desc;+	struct scatterlist sgd;+	struct scatterlist sgs;++	tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);+	if (tfm == NULL) {+		printk("failed to load transform for aes CBC\n");+		return -1;+	}++	crypto_blkcipher_setkey(tfm, key, keylen);+	crypto_blkcipher_set_iv(tfm, iv, 16);++	sg_init_one(&sgd, out, messagelen);+	sg_init_one(&sgs, message, messagelen);++	desc.tfm = tfm;+	desc.flags = 0;++	if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {+		crypto_free_blkcipher(tfm);+		DWC_ERROR("AES CBC encryption failed");+		return -1;+	}++	crypto_free_blkcipher(tfm);+	return 0;+}++int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)+{+	struct crypto_hash *tfm;+	struct hash_desc desc;+	struct scatterlist sg;++	tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);+	if (IS_ERR(tfm)) {+		DWC_ERROR("Failed to load transform for sha256: %ld\n", PTR_ERR(tfm));+		return 0;+	}+	desc.tfm = tfm;+	desc.flags = 0;++	sg_init_one(&sg, message, len);+	crypto_hash_digest(&desc, &sg, len, out);+	crypto_free_hash(tfm);++	return 1;+}++int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,+		    uint8_t *key, uint32_t keylen, uint8_t *out)+{+	struct crypto_hash *tfm;+	struct hash_desc desc;+	struct scatterlist sg;++	tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);+	if (IS_ERR(tfm)) {+		DWC_ERROR("Failed to load transform for hmac(sha256): %ld\n", PTR_ERR(tfm));+		return 0;+	}+	desc.tfm = tfm;+	desc.flags = 0;++	sg_init_one(&sg, message, messagelen);+	crypto_hash_setkey(tfm, key, keylen);+	crypto_hash_digest(&desc, &sg, messagelen, out);+	crypto_free_hash(tfm);++	return 1;+}+#endif	/* DWC_CRYPTOLIB */+++/* Byte Ordering Conversions */++uint32_t DWC_CPU_TO_LE32(uint32_t *p)+{+#ifdef __LITTLE_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;++	return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));+#endif+}++uint32_t DWC_CPU_TO_BE32(uint32_t *p)+{+#ifdef __BIG_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;++	return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));+#endif+}++uint32_t DWC_LE32_TO_CPU(uint32_t *p)+{+#ifdef __LITTLE_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;++	return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));+#endif+}++uint32_t DWC_BE32_TO_CPU(uint32_t *p)+{+#ifdef __BIG_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;++	return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));+#endif+}++uint16_t DWC_CPU_TO_LE16(uint16_t *p)+{+#ifdef __LITTLE_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;+	return (u_p[1] | (u_p[0] << 8));+#endif+}++uint16_t DWC_CPU_TO_BE16(uint16_t *p)+{+#ifdef __BIG_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;+	return (u_p[1] | (u_p[0] << 8));+#endif+}++uint16_t DWC_LE16_TO_CPU(uint16_t *p)+{+#ifdef __LITTLE_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;+	return (u_p[1] | (u_p[0] << 8));+#endif+}++uint16_t DWC_BE16_TO_CPU(uint16_t *p)+{+#ifdef __BIG_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;+	return (u_p[1] | (u_p[0] << 8));+#endif+}+++/* Registers */++uint32_t DWC_READ_REG32(uint32_t volatile *reg)+{+	return readl(reg);+}++#if 0+uint64_t DWC_READ_REG64(uint64_t volatile *reg)+{+}+#endif++void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value)+{+	writel(value, reg);+}++#if 0+void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value)+{+}+#endif++void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)+{+	unsigned long flags;++	local_irq_save(flags);+	local_fiq_disable();+	writel((readl(reg) & ~clear_mask) | set_mask, reg);+	local_irq_restore(flags);+}++#if 0+void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask)+{+}+#endif+++/* Locking */++dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)+{+	spinlock_t *sl = (spinlock_t *)1;++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)+	sl = DWC_ALLOC(sizeof(*sl));+	if (!sl) {+		DWC_ERROR("Cannot allocate memory for spinlock\n");+		return NULL;+	}++	spin_lock_init(sl);+#endif+	return (dwc_spinlock_t *)sl;+}++void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)+{+#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)+	DWC_FREE(lock);+#endif+}++void DWC_SPINLOCK(dwc_spinlock_t *lock)+{+#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)+	spin_lock((spinlock_t *)lock);+#endif+}++void DWC_SPINUNLOCK(dwc_spinlock_t *lock)+{+#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)+	spin_unlock((spinlock_t *)lock);+#endif+}++void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)+{+	dwc_irqflags_t f;++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)+	spin_lock_irqsave((spinlock_t *)lock, f);+#else+	local_irq_save(f);+#endif+	*flags = f;+}++void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)+{+#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)+	spin_unlock_irqrestore((spinlock_t *)lock, flags);+#else+	local_irq_restore(flags);+#endif+}++dwc_mutex_t *DWC_MUTEX_ALLOC(void)+{+	struct mutex *m;+	dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex));++	if (!mutex) {+		DWC_ERROR("Cannot allocate memory for mutex\n");+		return NULL;+	}++	m = (struct mutex *)mutex;+	mutex_init(m);+	return mutex;+}++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))+#else+void DWC_MUTEX_FREE(dwc_mutex_t *mutex)+{+	mutex_destroy((struct mutex *)mutex);+	DWC_FREE(mutex);+}+#endif++void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)+{+	struct mutex *m = (struct mutex *)mutex;+	mutex_lock(m);+}++int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)+{+	struct mutex *m = (struct mutex *)mutex;+	return mutex_trylock(m);+}++void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)+{+	struct mutex *m = (struct mutex *)mutex;+	mutex_unlock(m);+}+++/* Timing */++void DWC_UDELAY(uint32_t usecs)+{+	udelay(usecs);+}++void DWC_MDELAY(uint32_t msecs)+{+	mdelay(msecs);+}++void DWC_MSLEEP(uint32_t msecs)+{+	msleep(msecs);+}++uint32_t DWC_TIME(void)+{+	return jiffies_to_msecs(jiffies);+}+++/* Timers */++struct dwc_timer {+	struct timer_list *t;+	char *name;+	dwc_timer_callback_t cb;+	void *data;+	uint8_t scheduled;+	dwc_spinlock_t *lock;+};++static void timer_callback(unsigned long data)+{+	dwc_timer_t *timer = (dwc_timer_t *)data;+	dwc_irqflags_t flags;++	DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);+	timer->scheduled = 0;+	DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);+	DWC_DEBUGC("Timer %s callback", timer->name);+	timer->cb(timer->data);+}++dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)+{+	dwc_timer_t *t = DWC_ALLOC(sizeof(*t));++	if (!t) {+		DWC_ERROR("Cannot allocate memory for timer");+		return NULL;+	}++	t->t = DWC_ALLOC(sizeof(*t->t));+	if (!t->t) {+		DWC_ERROR("Cannot allocate memory for timer->t");+		goto no_timer;+	}++	t->name = DWC_STRDUP(name);+	if (!t->name) {+		DWC_ERROR("Cannot allocate memory for timer->name");+		goto no_name;+	}++	t->lock = DWC_SPINLOCK_ALLOC();+	if (!t->lock) {+		DWC_ERROR("Cannot allocate memory for lock");+		goto no_lock;+	}++	t->scheduled = 0;+	t->t->base = &boot_tvec_bases;+	t->t->expires = jiffies;+	setup_timer(t->t, timer_callback, (unsigned long)t);++	t->cb = cb;+	t->data = data;++	return t;++ no_lock:+	DWC_FREE(t->name);+ no_name:+	DWC_FREE(t->t);+ no_timer:+	DWC_FREE(t);+	return NULL;+}++void DWC_TIMER_FREE(dwc_timer_t *timer)+{+	dwc_irqflags_t flags;++	DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);++	if (timer->scheduled) {+		del_timer(timer->t);+		timer->scheduled = 0;+	}++	DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);+	DWC_SPINLOCK_FREE(timer->lock);+	DWC_FREE(timer->t);+	DWC_FREE(timer->name);+	DWC_FREE(timer);+}++void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)+{+	dwc_irqflags_t flags;++	DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);++	if (!timer->scheduled) {+		timer->scheduled = 1;+		DWC_DEBUGC("Scheduling timer %s to expire in +%d msec", timer->name, time);+		timer->t->expires = jiffies + msecs_to_jiffies(time);+		add_timer(timer->t);+	} else {+		DWC_DEBUGC("Modifying timer %s to expire in +%d msec", timer->name, time);+		mod_timer(timer->t, jiffies + msecs_to_jiffies(time));+	}++	DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);+}++void DWC_TIMER_CANCEL(dwc_timer_t *timer)+{+	del_timer(timer->t);+}+++/* Wait Queues */++struct dwc_waitq {+	wait_queue_head_t queue;+	int abort;+};++dwc_waitq_t *DWC_WAITQ_ALLOC(void)+{+	dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));++	if (!wq) {+		DWC_ERROR("Cannot allocate memory for waitqueue\n");+		return NULL;+	}++	init_waitqueue_head(&wq->queue);+	wq->abort = 0;+	return wq;+}++void DWC_WAITQ_FREE(dwc_waitq_t *wq)+{+	DWC_FREE(wq);+}++int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)+{+	int result = wait_event_interruptible(wq->queue,+					      cond(data) || wq->abort);+	if (result == -ERESTARTSYS) {+		wq->abort = 0;+		return -DWC_E_RESTART;+	}++	if (wq->abort == 1) {+		wq->abort = 0;+		return -DWC_E_ABORT;+	}++	wq->abort = 0;++	if (result == 0) {+		return 0;+	}++	return -DWC_E_UNKNOWN;+}++int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,+			       void *data, int32_t msecs)+{+	int32_t tmsecs;+	int result = wait_event_interruptible_timeout(wq->queue,+						      cond(data) || wq->abort,+						      msecs_to_jiffies(msecs));+	if (result == -ERESTARTSYS) {+		wq->abort = 0;+		return -DWC_E_RESTART;+	}++	if (wq->abort == 1) {+		wq->abort = 0;+		return -DWC_E_ABORT;+	}++	wq->abort = 0;++	if (result > 0) {+		tmsecs = jiffies_to_msecs(result);+		if (!tmsecs) {+			return 1;+		}++		return tmsecs;+	}++	if (result == 0) {+		return -DWC_E_TIMEOUT;+	}++	return -DWC_E_UNKNOWN;+}++void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)+{+	wq->abort = 0;+	wake_up_interruptible(&wq->queue);+}++void DWC_WAITQ_ABORT(dwc_waitq_t *wq)+{+	wq->abort = 1;+	wake_up_interruptible(&wq->queue);+}+++/* Threading */++dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)+{+	struct task_struct *thread = kthread_run(func, data, name);++	if (thread == ERR_PTR(-ENOMEM)) {+		return NULL;+	}++	return (dwc_thread_t *)thread;+}++int DWC_THREAD_STOP(dwc_thread_t *thread)+{+	return kthread_stop((struct task_struct *)thread);+}++dwc_bool_t DWC_THREAD_SHOULD_STOP(void)+{+	return kthread_should_stop();+}+++/* tasklets+ - run in interrupt context (cannot sleep)+ - each tasklet runs on a single CPU+ - different tasklets can be running simultaneously on different CPUs+ */+struct dwc_tasklet {+	struct tasklet_struct t;+	dwc_tasklet_callback_t cb;+	void *data;+};++static void tasklet_callback(unsigned long data)+{+	dwc_tasklet_t *t = (dwc_tasklet_t *)data;+	t->cb(t->data);+}++dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)+{+	dwc_tasklet_t *t = DWC_ALLOC(sizeof(*t));++	if (t) {+		t->cb = cb;+		t->data = data;+		tasklet_init(&t->t, tasklet_callback, (unsigned long)t);+	} else {+		DWC_ERROR("Cannot allocate memory for tasklet\n");+	}++	return t;+}++void DWC_TASK_FREE(dwc_tasklet_t *task)+{+	DWC_FREE(task);+}++void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)+{+	tasklet_schedule(&task->t);+}++void DWC_TASK_HI_SCHEDULE(dwc_tasklet_t *task)+{+	tasklet_hi_schedule(&task->t);+}+++/* workqueues+ - run in process context (can sleep)+ */+typedef struct work_container {+	dwc_work_callback_t cb;+	void *data;+	dwc_workq_t *wq;+	char *name;++#ifdef DEBUG+	DWC_CIRCLEQ_ENTRY(work_container) entry;+#endif+	struct delayed_work work;+} work_container_t;++#ifdef DEBUG+DWC_CIRCLEQ_HEAD(work_container_queue, work_container);+#endif++struct dwc_workq {+	struct workqueue_struct *wq;+	dwc_spinlock_t *lock;+	dwc_waitq_t *waitq;+	int pending;++#ifdef DEBUG+	struct work_container_queue entries;+#endif+};++static void do_work(struct work_struct *work)+{+	dwc_irqflags_t flags;+	struct delayed_work *dw = container_of(work, struct delayed_work, work);+	work_container_t *container = container_of(dw, struct work_container, work);+	dwc_workq_t *wq = container->wq;++	container->cb(container->data);++#ifdef DEBUG+	DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry);+#endif+	DWC_DEBUGC("Work done: %s, container=%p", container->name, container);+	if (container->name) {+		DWC_FREE(container->name);+	}+	DWC_FREE(container);++	DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);+	wq->pending--;+	DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);+	DWC_WAITQ_TRIGGER(wq->waitq);+}++static int work_done(void *data)+{+	dwc_workq_t *workq = (dwc_workq_t *)data;+	return workq->pending == 0;+}++int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)+{+	return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);+}++dwc_workq_t *DWC_WORKQ_ALLOC(char *name)+{+	dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));++	if (!wq) {+		return NULL;+	}++	wq->wq = create_singlethread_workqueue(name);+	if (!wq->wq) {+		goto no_wq;+	}++	wq->pending = 0;++	wq->lock = DWC_SPINLOCK_ALLOC();+	if (!wq->lock) {+		goto no_lock;+	}++	wq->waitq = DWC_WAITQ_ALLOC();+	if (!wq->waitq) {+		goto no_waitq;+	}++#ifdef DEBUG+	DWC_CIRCLEQ_INIT(&wq->entries);+#endif+	return wq;++ no_waitq:+	DWC_SPINLOCK_FREE(wq->lock);+ no_lock:+	destroy_workqueue(wq->wq);+ no_wq:+	DWC_FREE(wq);++	return NULL;+}++void DWC_WORKQ_FREE(dwc_workq_t *wq)+{+#ifdef DEBUG+	if (wq->pending != 0) {+		struct work_container *wc;+		DWC_ERROR("Destroying work queue with pending work");+		DWC_CIRCLEQ_FOREACH(wc, &wq->entries, entry) {+			DWC_ERROR("Work %s still pending", wc->name);+		}+	}+#endif+	destroy_workqueue(wq->wq);+	DWC_SPINLOCK_FREE(wq->lock);+	DWC_WAITQ_FREE(wq->waitq);+	DWC_FREE(wq);+}++void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,+			char *format, ...)+{+	dwc_irqflags_t flags;+	work_container_t *container;+	static char name[128];+	va_list args;++	va_start(args, format);+	DWC_VSNPRINTF(name, 128, format, args);+	va_end(args);++	DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);+	wq->pending++;+	DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);+	DWC_WAITQ_TRIGGER(wq->waitq);++	container = DWC_ALLOC_ATOMIC(sizeof(*container));+	if (!container) {+		DWC_ERROR("Cannot allocate memory for container\n");+		return;+	}++	container->name = DWC_STRDUP(name);+	if (!container->name) {+		DWC_ERROR("Cannot allocate memory for container->name\n");+		DWC_FREE(container);+		return;+	}++	container->cb = cb;+	container->data = data;+	container->wq = wq;+	DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container);+	INIT_WORK(&container->work.work, do_work);++#ifdef DEBUG+	DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);+#endif+	queue_work(wq->wq, &container->work.work);+}++void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,+				void *data, uint32_t time, char *format, ...)+{+	dwc_irqflags_t flags;+	work_container_t *container;+	static char name[128];+	va_list args;++	va_start(args, format);+	DWC_VSNPRINTF(name, 128, format, args);+	va_end(args);++	DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);+	wq->pending++;+	DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);+	DWC_WAITQ_TRIGGER(wq->waitq);++	container = DWC_ALLOC_ATOMIC(sizeof(*container));+	if (!container) {+		DWC_ERROR("Cannot allocate memory for container\n");+		return;+	}++	container->name = DWC_STRDUP(name);+	if (!container->name) {+		DWC_ERROR("Cannot allocate memory for container->name\n");+		DWC_FREE(container);+		return;+	}++	container->cb = cb;+	container->data = data;+	container->wq = wq;+	DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container);+	INIT_DELAYED_WORK(&container->work, do_work);++#ifdef DEBUG+	DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);+#endif+	queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time));+}++int DWC_WORKQ_PENDING(dwc_workq_t *wq)+{+	return wq->pending;+}+++#ifdef DWC_LIBMODULE++#ifdef DWC_CCLIB+/* CC */+EXPORT_SYMBOL(dwc_cc_if_alloc);+EXPORT_SYMBOL(dwc_cc_if_free);+EXPORT_SYMBOL(dwc_cc_clear);+EXPORT_SYMBOL(dwc_cc_add);+EXPORT_SYMBOL(dwc_cc_remove);+EXPORT_SYMBOL(dwc_cc_change);+EXPORT_SYMBOL(dwc_cc_data_for_save);+EXPORT_SYMBOL(dwc_cc_restore_from_data);+EXPORT_SYMBOL(dwc_cc_match_chid);+EXPORT_SYMBOL(dwc_cc_match_cdid);+EXPORT_SYMBOL(dwc_cc_ck);+EXPORT_SYMBOL(dwc_cc_chid);+EXPORT_SYMBOL(dwc_cc_cdid);+EXPORT_SYMBOL(dwc_cc_name);+#endif	/* DWC_CCLIB */++#ifdef DWC_CRYPTOLIB+# ifndef CONFIG_MACH_IPMATE+/* Modpow */+EXPORT_SYMBOL(dwc_modpow);++/* DH */+EXPORT_SYMBOL(dwc_dh_modpow);+EXPORT_SYMBOL(dwc_dh_derive_keys);+EXPORT_SYMBOL(dwc_dh_pk);+# endif	/* CONFIG_MACH_IPMATE */++/* Crypto */+EXPORT_SYMBOL(dwc_wusb_aes_encrypt);+EXPORT_SYMBOL(dwc_wusb_cmf);+EXPORT_SYMBOL(dwc_wusb_prf);+EXPORT_SYMBOL(dwc_wusb_fill_ccm_nonce);+EXPORT_SYMBOL(dwc_wusb_gen_nonce);+EXPORT_SYMBOL(dwc_wusb_gen_key);+EXPORT_SYMBOL(dwc_wusb_gen_mic);+#endif	/* DWC_CRYPTOLIB */++/* Notification */+#ifdef DWC_NOTIFYLIB+EXPORT_SYMBOL(dwc_alloc_notification_manager);+EXPORT_SYMBOL(dwc_free_notification_manager);+EXPORT_SYMBOL(dwc_register_notifier);+EXPORT_SYMBOL(dwc_unregister_notifier);+EXPORT_SYMBOL(dwc_add_observer);+EXPORT_SYMBOL(dwc_remove_observer);+EXPORT_SYMBOL(dwc_notify);+#endif++/* Memory Debugging Routines */+#ifdef DWC_DEBUG_MEMORY+EXPORT_SYMBOL(dwc_alloc_debug);+EXPORT_SYMBOL(dwc_alloc_atomic_debug);+EXPORT_SYMBOL(dwc_free_debug);+EXPORT_SYMBOL(dwc_dma_alloc_debug);+EXPORT_SYMBOL(dwc_dma_free_debug);+#endif++EXPORT_SYMBOL(DWC_MEMSET);+EXPORT_SYMBOL(DWC_MEMCPY);+EXPORT_SYMBOL(DWC_MEMMOVE);+EXPORT_SYMBOL(DWC_MEMCMP);+EXPORT_SYMBOL(DWC_STRNCMP);+EXPORT_SYMBOL(DWC_STRCMP);+EXPORT_SYMBOL(DWC_STRLEN);+EXPORT_SYMBOL(DWC_STRCPY);+EXPORT_SYMBOL(DWC_STRDUP);+EXPORT_SYMBOL(DWC_ATOI);+EXPORT_SYMBOL(DWC_ATOUI);++#ifdef DWC_UTFLIB+EXPORT_SYMBOL(DWC_UTF8_TO_UTF16LE);+#endif	/* DWC_UTFLIB */++EXPORT_SYMBOL(DWC_IN_IRQ);+EXPORT_SYMBOL(DWC_IN_BH);+EXPORT_SYMBOL(DWC_VPRINTF);+EXPORT_SYMBOL(DWC_VSNPRINTF);+EXPORT_SYMBOL(DWC_PRINTF);+EXPORT_SYMBOL(DWC_SPRINTF);+EXPORT_SYMBOL(DWC_SNPRINTF);+EXPORT_SYMBOL(__DWC_WARN);+EXPORT_SYMBOL(__DWC_ERROR);+EXPORT_SYMBOL(DWC_EXCEPTION);++#ifdef DEBUG+EXPORT_SYMBOL(__DWC_DEBUG);+#endif++EXPORT_SYMBOL(__DWC_DMA_ALLOC);+EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC);+EXPORT_SYMBOL(__DWC_DMA_FREE);+EXPORT_SYMBOL(__DWC_ALLOC);+EXPORT_SYMBOL(__DWC_ALLOC_ATOMIC);+EXPORT_SYMBOL(__DWC_FREE);++#ifdef DWC_CRYPTOLIB+EXPORT_SYMBOL(DWC_RANDOM_BYTES);+EXPORT_SYMBOL(DWC_AES_CBC);+EXPORT_SYMBOL(DWC_SHA256);+EXPORT_SYMBOL(DWC_HMAC_SHA256);+#endif++EXPORT_SYMBOL(DWC_CPU_TO_LE32);+EXPORT_SYMBOL(DWC_CPU_TO_BE32);+EXPORT_SYMBOL(DWC_LE32_TO_CPU);+EXPORT_SYMBOL(DWC_BE32_TO_CPU);+EXPORT_SYMBOL(DWC_CPU_TO_LE16);+EXPORT_SYMBOL(DWC_CPU_TO_BE16);+EXPORT_SYMBOL(DWC_LE16_TO_CPU);+EXPORT_SYMBOL(DWC_BE16_TO_CPU);+EXPORT_SYMBOL(DWC_READ_REG32);+EXPORT_SYMBOL(DWC_WRITE_REG32);+EXPORT_SYMBOL(DWC_MODIFY_REG32);++#if 0+EXPORT_SYMBOL(DWC_READ_REG64);+EXPORT_SYMBOL(DWC_WRITE_REG64);+EXPORT_SYMBOL(DWC_MODIFY_REG64);+#endif++EXPORT_SYMBOL(DWC_SPINLOCK_ALLOC);+EXPORT_SYMBOL(DWC_SPINLOCK_FREE);+EXPORT_SYMBOL(DWC_SPINLOCK);+EXPORT_SYMBOL(DWC_SPINUNLOCK);+EXPORT_SYMBOL(DWC_SPINLOCK_IRQSAVE);+EXPORT_SYMBOL(DWC_SPINUNLOCK_IRQRESTORE);+EXPORT_SYMBOL(DWC_MUTEX_ALLOC);++#if (!defined(DWC_LINUX) || !defined(CONFIG_DEBUG_MUTEXES))+EXPORT_SYMBOL(DWC_MUTEX_FREE);+#endif++EXPORT_SYMBOL(DWC_MUTEX_LOCK);+EXPORT_SYMBOL(DWC_MUTEX_TRYLOCK);+EXPORT_SYMBOL(DWC_MUTEX_UNLOCK);+EXPORT_SYMBOL(DWC_UDELAY);+EXPORT_SYMBOL(DWC_MDELAY);+EXPORT_SYMBOL(DWC_MSLEEP);+EXPORT_SYMBOL(DWC_TIME);+EXPORT_SYMBOL(DWC_TIMER_ALLOC);+EXPORT_SYMBOL(DWC_TIMER_FREE);+EXPORT_SYMBOL(DWC_TIMER_SCHEDULE);+EXPORT_SYMBOL(DWC_TIMER_CANCEL);+EXPORT_SYMBOL(DWC_WAITQ_ALLOC);+EXPORT_SYMBOL(DWC_WAITQ_FREE);+EXPORT_SYMBOL(DWC_WAITQ_WAIT);+EXPORT_SYMBOL(DWC_WAITQ_WAIT_TIMEOUT);+EXPORT_SYMBOL(DWC_WAITQ_TRIGGER);+EXPORT_SYMBOL(DWC_WAITQ_ABORT);+EXPORT_SYMBOL(DWC_THREAD_RUN);+EXPORT_SYMBOL(DWC_THREAD_STOP);+EXPORT_SYMBOL(DWC_THREAD_SHOULD_STOP);+EXPORT_SYMBOL(DWC_TASK_ALLOC);+EXPORT_SYMBOL(DWC_TASK_FREE);+EXPORT_SYMBOL(DWC_TASK_SCHEDULE);+EXPORT_SYMBOL(DWC_WORKQ_WAIT_WORK_DONE);+EXPORT_SYMBOL(DWC_WORKQ_ALLOC);+EXPORT_SYMBOL(DWC_WORKQ_FREE);+EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE);+EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE_DELAYED);+EXPORT_SYMBOL(DWC_WORKQ_PENDING);++static int dwc_common_port_init_module(void)+{+	int result = 0;++	printk(KERN_DEBUG "Module dwc_common_port init\n" );++#ifdef DWC_DEBUG_MEMORY+	result = dwc_memory_debug_start(NULL);+	if (result) {+		printk(KERN_ERR+		       "dwc_memory_debug_start() failed with error %d\n",+		       result);+		return result;+	}+#endif++#ifdef DWC_NOTIFYLIB+	result = dwc_alloc_notification_manager(NULL, NULL);+	if (result) {+		printk(KERN_ERR+		       "dwc_alloc_notification_manager() failed with error %d\n",+		       result);+		return result;+	}+#endif+	return result;+}++static void dwc_common_port_exit_module(void)+{+	printk(KERN_DEBUG "Module dwc_common_port exit\n" );++#ifdef DWC_NOTIFYLIB+	dwc_free_notification_manager();+#endif++#ifdef DWC_DEBUG_MEMORY+	dwc_memory_debug_stop();+#endif+}++module_init(dwc_common_port_init_module);+module_exit(dwc_common_port_exit_module);++MODULE_DESCRIPTION("DWC Common Library - Portable version");+MODULE_AUTHOR("Synopsys Inc.");+MODULE_LICENSE ("GPL");++#endif	/* DWC_LIBMODULE */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,1275 @@+#include "dwc_os.h"+#include "dwc_list.h"++#ifdef DWC_CCLIB+# include "dwc_cc.h"+#endif++#ifdef DWC_CRYPTOLIB+# include "dwc_modpow.h"+# include "dwc_dh.h"+# include "dwc_crypto.h"+#endif++#ifdef DWC_NOTIFYLIB+# include "dwc_notifier.h"+#endif++/* OS-Level Implementations */++/* This is the NetBSD 4.0.1 kernel implementation of the DWC platform library. */+++/* MISC */++void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)+{+	return memset(dest, byte, size);+}++void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)+{+	return memcpy(dest, src, size);+}++void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)+{+	bcopy(src, dest, size);+	return dest;+}++int DWC_MEMCMP(void *m1, void *m2, uint32_t size)+{+	return memcmp(m1, m2, size);+}++int DWC_STRNCMP(void *s1, void *s2, uint32_t size)+{+	return strncmp(s1, s2, size);+}++int DWC_STRCMP(void *s1, void *s2)+{+	return strcmp(s1, s2);+}++int DWC_STRLEN(char const *str)+{+	return strlen(str);+}++char *DWC_STRCPY(char *to, char const *from)+{+	return strcpy(to, from);+}++char *DWC_STRDUP(char const *str)+{+	int len = DWC_STRLEN(str) + 1;+	char *new = DWC_ALLOC_ATOMIC(len);++	if (!new) {+		return NULL;+	}++	DWC_MEMCPY(new, str, len);+	return new;+}++int DWC_ATOI(char *str, int32_t *value)+{+	char *end = NULL;++	/* NetBSD doesn't have 'strtol' in the kernel, but 'strtoul'+	 * should be equivalent on 2's complement machines+	 */+	*value = strtoul(str, &end, 0);+	if (*end == '\0') {+		return 0;+	}++	return -1;+}++int DWC_ATOUI(char *str, uint32_t *value)+{+	char *end = NULL;++	*value = strtoul(str, &end, 0);+	if (*end == '\0') {+		return 0;+	}++	return -1;+}+++#ifdef DWC_UTFLIB+/* From usbstring.c */++int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)+{+	int	count = 0;+	u8	c;+	u16	uchar;++	/* this insists on correct encodings, though not minimal ones.+	 * BUT it currently rejects legit 4-byte UTF-8 code points,+	 * which need surrogate pairs.  (Unicode 3.1 can use them.)+	 */+	while (len != 0 && (c = (u8) *s++) != 0) {+		if (unlikely(c & 0x80)) {+			// 2-byte sequence:+			// 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx+			if ((c & 0xe0) == 0xc0) {+				uchar = (c & 0x1f) << 6;++				c = (u8) *s++;+				if ((c & 0xc0) != 0xc0)+					goto fail;+				c &= 0x3f;+				uchar |= c;++			// 3-byte sequence (most CJKV characters):+			// zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx+			} else if ((c & 0xf0) == 0xe0) {+				uchar = (c & 0x0f) << 12;++				c = (u8) *s++;+				if ((c & 0xc0) != 0xc0)+					goto fail;+				c &= 0x3f;+				uchar |= c << 6;++				c = (u8) *s++;+				if ((c & 0xc0) != 0xc0)+					goto fail;+				c &= 0x3f;+				uchar |= c;++				/* no bogus surrogates */+				if (0xd800 <= uchar && uchar <= 0xdfff)+					goto fail;++			// 4-byte sequence (surrogate pairs, currently rare):+			// 11101110wwwwzzzzyy + 110111yyyyxxxxxx+			//     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx+			// (uuuuu = wwww + 1)+			// FIXME accept the surrogate code points (only)+			} else+				goto fail;+		} else+			uchar = c;+		put_unaligned (cpu_to_le16 (uchar), cp++);+		count++;+		len--;+	}+	return count;+fail:+	return -1;+}++#endif	/* DWC_UTFLIB */+++/* dwc_debug.h */++dwc_bool_t DWC_IN_IRQ(void)+{+//	return in_irq();+	return 0;+}++dwc_bool_t DWC_IN_BH(void)+{+//	return in_softirq();+	return 0;+}++void DWC_VPRINTF(char *format, va_list args)+{+	vprintf(format, args);+}++int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)+{+	return vsnprintf(str, size, format, args);+}++void DWC_PRINTF(char *format, ...)+{+	va_list args;++	va_start(args, format);+	DWC_VPRINTF(format, args);+	va_end(args);+}++int DWC_SPRINTF(char *buffer, char *format, ...)+{+	int retval;+	va_list args;++	va_start(args, format);+	retval = vsprintf(buffer, format, args);+	va_end(args);+	return retval;+}++int DWC_SNPRINTF(char *buffer, int size, char *format, ...)+{+	int retval;+	va_list args;++	va_start(args, format);+	retval = vsnprintf(buffer, size, format, args);+	va_end(args);+	return retval;+}++void __DWC_WARN(char *format, ...)+{+	va_list args;++	va_start(args, format);+	DWC_VPRINTF(format, args);+	va_end(args);+}++void __DWC_ERROR(char *format, ...)+{+	va_list args;++	va_start(args, format);+	DWC_VPRINTF(format, args);+	va_end(args);+}++void DWC_EXCEPTION(char *format, ...)+{+	va_list args;++	va_start(args, format);+	DWC_VPRINTF(format, args);+	va_end(args);+//	BUG_ON(1);	???+}++#ifdef DEBUG+void __DWC_DEBUG(char *format, ...)+{+	va_list args;++	va_start(args, format);+	DWC_VPRINTF(format, args);+	va_end(args);+}+#endif+++/* dwc_mem.h */++#if 0+dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,+				uint32_t align,+				uint32_t alloc)+{+	struct dma_pool *pool = dma_pool_create("Pool", NULL,+						size, align, alloc);+	return (dwc_pool_t *)pool;+}++void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)+{+	dma_pool_destroy((struct dma_pool *)pool);+}++void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)+{+//	return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);+	return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr);+}++void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)+{+	void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);+	memset(..);+}++void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)+{+	dma_pool_free(pool, vaddr, daddr);+}+#endif++void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)+{+	dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;+	int error;++	error = bus_dmamem_alloc(dma->dma_tag, size, 1, size, dma->segs,+				 sizeof(dma->segs) / sizeof(dma->segs[0]),+				 &dma->nsegs, BUS_DMA_NOWAIT);+	if (error) {+		printf("%s: bus_dmamem_alloc(%ju) failed: %d\n", __func__,+		       (uintmax_t)size, error);+		goto fail_0;+	}++	error = bus_dmamem_map(dma->dma_tag, dma->segs, dma->nsegs, size,+			       (caddr_t *)&dma->dma_vaddr,+			       BUS_DMA_NOWAIT | BUS_DMA_COHERENT);+	if (error) {+		printf("%s: bus_dmamem_map failed: %d\n", __func__, error);+		goto fail_1;+	}++	error = bus_dmamap_create(dma->dma_tag, size, 1, size, 0,+				  BUS_DMA_NOWAIT, &dma->dma_map);+	if (error) {+		printf("%s: bus_dmamap_create failed: %d\n", __func__, error);+		goto fail_2;+	}++	error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr,+				size, NULL, BUS_DMA_NOWAIT);+	if (error) {+		printf("%s: bus_dmamap_load failed: %d\n", __func__, error);+		goto fail_3;+	}++	dma->dma_paddr = (bus_addr_t)dma->segs[0].ds_addr;+	*dma_addr = dma->dma_paddr;+	return dma->dma_vaddr;++fail_3:+	bus_dmamap_destroy(dma->dma_tag, dma->dma_map);+fail_2:+	bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size);+fail_1:+	bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs);+fail_0:+	dma->dma_map = NULL;+	dma->dma_vaddr = NULL;+	dma->nsegs = 0;++	return NULL;+}++void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)+{+	dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;++	if (dma->dma_map != NULL) {+		bus_dmamap_sync(dma->dma_tag, dma->dma_map, 0, size,+				BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);+		bus_dmamap_unload(dma->dma_tag, dma->dma_map);+		bus_dmamap_destroy(dma->dma_tag, dma->dma_map);+		bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size);+		bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs);+		dma->dma_paddr = 0;+		dma->dma_map = NULL;+		dma->dma_vaddr = NULL;+		dma->nsegs = 0;+	}+}++void *__DWC_ALLOC(void *mem_ctx, uint32_t size)+{+	return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);+}++void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)+{+	return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);+}++void __DWC_FREE(void *mem_ctx, void *addr)+{+	free(addr, M_DEVBUF);+}+++#ifdef DWC_CRYPTOLIB+/* dwc_crypto.h */++void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)+{+	get_random_bytes(buffer, length);+}++int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)+{+	struct crypto_blkcipher *tfm;+	struct blkcipher_desc desc;+	struct scatterlist sgd;+	struct scatterlist sgs;++	tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);+	if (tfm == NULL) {+		printk("failed to load transform for aes CBC\n");+		return -1;+	}++	crypto_blkcipher_setkey(tfm, key, keylen);+	crypto_blkcipher_set_iv(tfm, iv, 16);++	sg_init_one(&sgd, out, messagelen);+	sg_init_one(&sgs, message, messagelen);++	desc.tfm = tfm;+	desc.flags = 0;++	if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {+		crypto_free_blkcipher(tfm);+		DWC_ERROR("AES CBC encryption failed");+		return -1;+	}++	crypto_free_blkcipher(tfm);+	return 0;+}++int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)+{+	struct crypto_hash *tfm;+	struct hash_desc desc;+	struct scatterlist sg;++	tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);+	if (IS_ERR(tfm)) {+		DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm));+		return 0;+	}+	desc.tfm = tfm;+	desc.flags = 0;++	sg_init_one(&sg, message, len);+	crypto_hash_digest(&desc, &sg, len, out);+	crypto_free_hash(tfm);++	return 1;+}++int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,+		    uint8_t *key, uint32_t keylen, uint8_t *out)+{+	struct crypto_hash *tfm;+	struct hash_desc desc;+	struct scatterlist sg;++	tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);+	if (IS_ERR(tfm)) {+		DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm));+		return 0;+	}+	desc.tfm = tfm;+	desc.flags = 0;++	sg_init_one(&sg, message, messagelen);+	crypto_hash_setkey(tfm, key, keylen);+	crypto_hash_digest(&desc, &sg, messagelen, out);+	crypto_free_hash(tfm);++	return 1;+}++#endif	/* DWC_CRYPTOLIB */+++/* Byte Ordering Conversions */++uint32_t DWC_CPU_TO_LE32(uint32_t *p)+{+#ifdef __LITTLE_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;++	return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));+#endif+}++uint32_t DWC_CPU_TO_BE32(uint32_t *p)+{+#ifdef __BIG_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;++	return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));+#endif+}++uint32_t DWC_LE32_TO_CPU(uint32_t *p)+{+#ifdef __LITTLE_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;++	return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));+#endif+}++uint32_t DWC_BE32_TO_CPU(uint32_t *p)+{+#ifdef __BIG_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;++	return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));+#endif+}++uint16_t DWC_CPU_TO_LE16(uint16_t *p)+{+#ifdef __LITTLE_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;+	return (u_p[1] | (u_p[0] << 8));+#endif+}++uint16_t DWC_CPU_TO_BE16(uint16_t *p)+{+#ifdef __BIG_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;+	return (u_p[1] | (u_p[0] << 8));+#endif+}++uint16_t DWC_LE16_TO_CPU(uint16_t *p)+{+#ifdef __LITTLE_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;+	return (u_p[1] | (u_p[0] << 8));+#endif+}++uint16_t DWC_BE16_TO_CPU(uint16_t *p)+{+#ifdef __BIG_ENDIAN+	return *p;+#else+	uint8_t *u_p = (uint8_t *)p;+	return (u_p[1] | (u_p[0] << 8));+#endif+}+++/* Registers */++uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg)+{+	dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;+	bus_size_t ior = (bus_size_t)reg;++	return bus_space_read_4(io->iot, io->ioh, ior);+}++#if 0+uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg)+{+	dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;+	bus_size_t ior = (bus_size_t)reg;++	return bus_space_read_8(io->iot, io->ioh, ior);+}+#endif++void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value)+{+	dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;+	bus_size_t ior = (bus_size_t)reg;++	bus_space_write_4(io->iot, io->ioh, ior, value);+}++#if 0+void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value)+{+	dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;+	bus_size_t ior = (bus_size_t)reg;++	bus_space_write_8(io->iot, io->ioh, ior, value);+}+#endif++void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask,+		      uint32_t set_mask)+{+	dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;+	bus_size_t ior = (bus_size_t)reg;++	bus_space_write_4(io->iot, io->ioh, ior,+			  (bus_space_read_4(io->iot, io->ioh, ior) &+			   ~clear_mask) | set_mask);+}++#if 0+void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask,+		      uint64_t set_mask)+{+	dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;+	bus_size_t ior = (bus_size_t)reg;++	bus_space_write_8(io->iot, io->ioh, ior,+			  (bus_space_read_8(io->iot, io->ioh, ior) &+			   ~clear_mask) | set_mask);+}+#endif+++/* Locking */++dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)+{+	struct simplelock *sl = DWC_ALLOC(sizeof(*sl));++	if (!sl) {+		DWC_ERROR("Cannot allocate memory for spinlock");+		return NULL;+	}++	simple_lock_init(sl);+	return (dwc_spinlock_t *)sl;+}++void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)+{+	struct simplelock *sl = (struct simplelock *)lock;++	DWC_FREE(sl);+}++void DWC_SPINLOCK(dwc_spinlock_t *lock)+{+	simple_lock((struct simplelock *)lock);+}++void DWC_SPINUNLOCK(dwc_spinlock_t *lock)+{+	simple_unlock((struct simplelock *)lock);+}++void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)+{+	simple_lock((struct simplelock *)lock);+	*flags = splbio();+}++void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)+{+	splx(flags);+	simple_unlock((struct simplelock *)lock);+}++dwc_mutex_t *DWC_MUTEX_ALLOC(void)+{+	dwc_mutex_t *mutex = DWC_ALLOC(sizeof(struct lock));++	if (!mutex) {+		DWC_ERROR("Cannot allocate memory for mutex");+		return NULL;+	}++	lockinit((struct lock *)mutex, 0, "dw3mtx", 0, 0);+	return mutex;+}++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))+#else+void DWC_MUTEX_FREE(dwc_mutex_t *mutex)+{+	DWC_FREE(mutex);+}+#endif++void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)+{+	lockmgr((struct lock *)mutex, LK_EXCLUSIVE, NULL);+}++int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)+{+	int status;++	status = lockmgr((struct lock *)mutex, LK_EXCLUSIVE | LK_NOWAIT, NULL);+	return status == 0;+}++void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)+{+	lockmgr((struct lock *)mutex, LK_RELEASE, NULL);+}+++/* Timing */++void DWC_UDELAY(uint32_t usecs)+{+	DELAY(usecs);+}++void DWC_MDELAY(uint32_t msecs)+{+	do {+		DELAY(1000);+	} while (--msecs);+}++void DWC_MSLEEP(uint32_t msecs)+{+	struct timeval tv;++	tv.tv_sec = msecs / 1000;+	tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;+	tsleep(&tv, 0, "dw3slp", tvtohz(&tv));+}++uint32_t DWC_TIME(void)+{+	struct timeval tv;++	microuptime(&tv);	// or getmicrouptime? (less precise, but faster)+	return tv.tv_sec * 1000 + tv.tv_usec / 1000;+}+++/* Timers */++struct dwc_timer {+	struct callout t;+	char *name;+	dwc_spinlock_t *lock;+	dwc_timer_callback_t cb;+	void *data;+};++dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)+{+	dwc_timer_t *t = DWC_ALLOC(sizeof(*t));++	if (!t) {+		DWC_ERROR("Cannot allocate memory for timer");+		return NULL;+	}++	callout_init(&t->t);++	t->name = DWC_STRDUP(name);+	if (!t->name) {+		DWC_ERROR("Cannot allocate memory for timer->name");+		goto no_name;+	}++	t->lock = DWC_SPINLOCK_ALLOC();+	if (!t->lock) {+		DWC_ERROR("Cannot allocate memory for timer->lock");+		goto no_lock;+	}++	t->cb = cb;+	t->data = data;++	return t;++ no_lock:+	DWC_FREE(t->name);+ no_name:+	DWC_FREE(t);++	return NULL;+}++void DWC_TIMER_FREE(dwc_timer_t *timer)+{+	callout_stop(&timer->t);+	DWC_SPINLOCK_FREE(timer->lock);+	DWC_FREE(timer->name);+	DWC_FREE(timer);+}++void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)+{+	struct timeval tv;++	tv.tv_sec = time / 1000;+	tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;+	callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data);+}++void DWC_TIMER_CANCEL(dwc_timer_t *timer)+{+	callout_stop(&timer->t);+}+++/* Wait Queues */++struct dwc_waitq {+	struct simplelock lock;+	int abort;+};++dwc_waitq_t *DWC_WAITQ_ALLOC(void)+{+	dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));++	if (!wq) {+		DWC_ERROR("Cannot allocate memory for waitqueue");+		return NULL;+	}++	simple_lock_init(&wq->lock);+	wq->abort = 0;++	return wq;+}++void DWC_WAITQ_FREE(dwc_waitq_t *wq)+{+	DWC_FREE(wq);+}++int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)+{+	int ipl;+	int result = 0;++	simple_lock(&wq->lock);+	ipl = splbio();++	/* Skip the sleep if already aborted or triggered */+	if (!wq->abort && !cond(data)) {+		splx(ipl);+		result = ltsleep(wq, PCATCH, "dw3wat", 0, &wq->lock); // infinite timeout+		ipl = splbio();+	}++	if (result == 0) {			// awoken+		if (wq->abort) {+			wq->abort = 0;+			result = -DWC_E_ABORT;+		} else {+			result = 0;+		}++		splx(ipl);+		simple_unlock(&wq->lock);+	} else {+		wq->abort = 0;+		splx(ipl);+		simple_unlock(&wq->lock);++		if (result == ERESTART) {	// signaled - restart+			result = -DWC_E_RESTART;+		} else {			// signaled - must be EINTR+			result = -DWC_E_ABORT;+		}+	}++	return result;+}++int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,+			       void *data, int32_t msecs)+{+	struct timeval tv, tv1, tv2;+	int ipl;+	int result = 0;++	tv.tv_sec = msecs / 1000;+	tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;++	simple_lock(&wq->lock);+	ipl = splbio();++	/* Skip the sleep if already aborted or triggered */+	if (!wq->abort && !cond(data)) {+		splx(ipl);+		getmicrouptime(&tv1);+		result = ltsleep(wq, PCATCH, "dw3wto", tvtohz(&tv), &wq->lock);+		getmicrouptime(&tv2);+		ipl = splbio();+	}++	if (result == 0) {			// awoken+		if (wq->abort) {+			wq->abort = 0;+			splx(ipl);+			simple_unlock(&wq->lock);+			result = -DWC_E_ABORT;+		} else {+			splx(ipl);+			simple_unlock(&wq->lock);++			tv2.tv_usec -= tv1.tv_usec;+			if (tv2.tv_usec < 0) {+				tv2.tv_usec += 1000000;+				tv2.tv_sec--;+			}++			tv2.tv_sec -= tv1.tv_sec;+			result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;+			result = msecs - result;+			if (result <= 0)+				result = 1;+		}+	} else {+		wq->abort = 0;+		splx(ipl);+		simple_unlock(&wq->lock);++		if (result == ERESTART) {	// signaled - restart+			result = -DWC_E_RESTART;++		} else if (result == EINTR) {		// signaled - interrupt+			result = -DWC_E_ABORT;++		} else {				// timed out+			result = -DWC_E_TIMEOUT;+		}+	}++	return result;+}++void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)+{+	wakeup(wq);+}++void DWC_WAITQ_ABORT(dwc_waitq_t *wq)+{+	int ipl;++	simple_lock(&wq->lock);+	ipl = splbio();+	wq->abort = 1;+	wakeup(wq);+	splx(ipl);+	simple_unlock(&wq->lock);+}+++/* Threading */++struct dwc_thread {+	struct proc *proc;+	int abort;+};++dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)+{+	int retval;+	dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread));++	if (!thread) {+		return NULL;+	}++	thread->abort = 0;+	retval = kthread_create1((void (*)(void *))func, data, &thread->proc,+				 "%s", name);+	if (retval) {+		DWC_FREE(thread);+		return NULL;+	}++	return thread;+}++int DWC_THREAD_STOP(dwc_thread_t *thread)+{+	int retval;++	thread->abort = 1;+	retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz);++	if (retval == 0) {+		/* DWC_THREAD_EXIT() will free the thread struct */+		return 0;+	}++	/* NOTE: We leak the thread struct if thread doesn't die */++	if (retval == EWOULDBLOCK) {+		return -DWC_E_TIMEOUT;+	}++	return -DWC_E_UNKNOWN;+}++dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread)+{+	return thread->abort;+}++void DWC_THREAD_EXIT(dwc_thread_t *thread)+{+	wakeup(&thread->abort);+	DWC_FREE(thread);+	kthread_exit(0);+}++/* tasklets+ - Runs in interrupt context (cannot sleep)+ - Each tasklet runs on a single CPU+ - Different tasklets can be running simultaneously on different CPUs+ [ On NetBSD there is no corresponding mechanism, drivers don't have bottom-+   halves. So we just call the callback directly from DWC_TASK_SCHEDULE() ]+ */+struct dwc_tasklet {+	dwc_tasklet_callback_t cb;+	void *data;+};++static void tasklet_callback(void *data)+{+	dwc_tasklet_t *task = (dwc_tasklet_t *)data;++	task->cb(task->data);+}++dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)+{+	dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task));++	if (task) {+		task->cb = cb;+		task->data = data;+	} else {+		DWC_ERROR("Cannot allocate memory for tasklet");+	}++	return task;+}++void DWC_TASK_FREE(dwc_tasklet_t *task)+{+	DWC_FREE(task);+}++void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)+{+	tasklet_callback(task);+}+++/* workqueues+ - Runs in process context (can sleep)+ */+typedef struct work_container {+	dwc_work_callback_t cb;+	void *data;+	dwc_workq_t *wq;+	char *name;+	int hz;+	struct work task;+} work_container_t;++struct dwc_workq {+	struct workqueue *taskq;+	dwc_spinlock_t *lock;+	dwc_waitq_t *waitq;+	int pending;+	struct work_container *container;+};++static void do_work(struct work *task, void *data)+{+	dwc_workq_t *wq = (dwc_workq_t *)data;+	work_container_t *container = wq->container;+	dwc_irqflags_t flags;++	if (container->hz) {+		tsleep(container, 0, "dw3wrk", container->hz);+	}++	container->cb(container->data);+	DWC_DEBUG("Work done: %s, container=%p", container->name, container);++	DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);+	if (container->name)+		DWC_FREE(container->name);+	DWC_FREE(container);+	wq->pending--;+	DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);+	DWC_WAITQ_TRIGGER(wq->waitq);+}++static int work_done(void *data)+{+	dwc_workq_t *workq = (dwc_workq_t *)data;++	return workq->pending == 0;+}++int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)+{+	return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);+}++dwc_workq_t *DWC_WORKQ_ALLOC(char *name)+{+	int result;+	dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));++	if (!wq) {+		DWC_ERROR("Cannot allocate memory for workqueue");+		return NULL;+	}++	result = workqueue_create(&wq->taskq, name, do_work, wq, 0 /*PWAIT*/,+				  IPL_BIO, 0);+	if (result) {+		DWC_ERROR("Cannot create workqueue");+		goto no_taskq;+	}++	wq->pending = 0;++	wq->lock = DWC_SPINLOCK_ALLOC();+	if (!wq->lock) {+		DWC_ERROR("Cannot allocate memory for spinlock");+		goto no_lock;+	}++	wq->waitq = DWC_WAITQ_ALLOC();+	if (!wq->waitq) {+		DWC_ERROR("Cannot allocate memory for waitqueue");+		goto no_waitq;+	}++	return wq;++ no_waitq:+	DWC_SPINLOCK_FREE(wq->lock);+ no_lock:+	workqueue_destroy(wq->taskq);+ no_taskq:+	DWC_FREE(wq);++	return NULL;+}++void DWC_WORKQ_FREE(dwc_workq_t *wq)+{+#ifdef DEBUG+	dwc_irqflags_t flags;++	DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);++	if (wq->pending != 0) {+		struct work_container *container = wq->container;++		DWC_ERROR("Destroying work queue with pending work");++		if (container && container->name) {+			DWC_ERROR("Work %s still pending", container->name);+		}+	}++	DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);+#endif+	DWC_WAITQ_FREE(wq->waitq);+	DWC_SPINLOCK_FREE(wq->lock);+	workqueue_destroy(wq->taskq);+	DWC_FREE(wq);+}++void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,+			char *format, ...)+{+	dwc_irqflags_t flags;+	work_container_t *container;+	static char name[128];+	va_list args;++	va_start(args, format);+	DWC_VSNPRINTF(name, 128, format, args);+	va_end(args);++	DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);+	wq->pending++;+	DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);+	DWC_WAITQ_TRIGGER(wq->waitq);++	container = DWC_ALLOC_ATOMIC(sizeof(*container));+	if (!container) {+		DWC_ERROR("Cannot allocate memory for container");+		return;+	}++	container->name = DWC_STRDUP(name);+	if (!container->name) {+		DWC_ERROR("Cannot allocate memory for container->name");+		DWC_FREE(container);+		return;+	}++	container->cb = cb;+	container->data = data;+	container->wq = wq;+	container->hz = 0;+	wq->container = container;++	DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);+	workqueue_enqueue(wq->taskq, &container->task);+}++void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,+				void *data, uint32_t time, char *format, ...)+{+	dwc_irqflags_t flags;+	work_container_t *container;+	static char name[128];+	struct timeval tv;+	va_list args;++	va_start(args, format);+	DWC_VSNPRINTF(name, 128, format, args);+	va_end(args);++	DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);+	wq->pending++;+	DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);+	DWC_WAITQ_TRIGGER(wq->waitq);++	container = DWC_ALLOC_ATOMIC(sizeof(*container));+	if (!container) {+		DWC_ERROR("Cannot allocate memory for container");+		return;+	}++	container->name = DWC_STRDUP(name);+	if (!container->name) {+		DWC_ERROR("Cannot allocate memory for container->name");+		DWC_FREE(container);+		return;+	}++	container->cb = cb;+	container->data = data;+	container->wq = wq;+	tv.tv_sec = time / 1000;+	tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;+	container->hz = tvtohz(&tv);+	wq->container = container;++	DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);+	workqueue_enqueue(wq->taskq, &container->task);+}++int DWC_WORKQ_PENDING(dwc_workq_t *wq)+{+	return wq->pending;+}diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_crypto.c linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_crypto.c--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_crypto.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_crypto.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,308 @@+/* =========================================================================+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.c $+ * $Revision: #5 $+ * $Date: 2010/09/28 $+ * $Change: 1596182 $+ *+ * Synopsys Portability Library Software and documentation+ * (hereinafter, "Software") is an Unsupported proprietary work of+ * Synopsys, Inc. unless otherwise expressly agreed to in writing+ * between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product+ * under any End User Software License Agreement or Agreement for+ * Licensed Product with Synopsys or any supplement thereto. You are+ * permitted to use and redistribute this Software in source and binary+ * forms, with or without modification, provided that redistributions+ * of source code must retain this notice. You may not view, use,+ * disclose, copy or distribute this file or any information contained+ * herein except pursuant to this license grant from Synopsys. If you+ * do not agree with this notice, including the disclaimer below, then+ * you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS+ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL+ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================= */++/** @file+ * This file contains the WUSB cryptographic routines.+ */++#ifdef DWC_CRYPTOLIB++#include "dwc_crypto.h"+#include "usb.h"++#ifdef DEBUG+static inline void dump_bytes(char *name, uint8_t *bytes, int len)+{+	int i;+	DWC_PRINTF("%s: ", name);+	for (i=0; i<len; i++) {+		DWC_PRINTF("%02x ", bytes[i]);+	}+	DWC_PRINTF("\n");+}+#else+#define dump_bytes(x...)+#endif++/* Display a block */+void show_block(const u8 *blk, const char *prefix, const char *suffix, int a)+{+#ifdef DWC_DEBUG_CRYPTO+	int i, blksize = 16;++	DWC_DEBUG("%s", prefix);++	if (suffix == NULL) {+		suffix = "\n";+		blksize = a;+	}++	for (i = 0; i < blksize; i++)+		DWC_PRINT("%02x%s", *blk++, ((i & 3) == 3) ? "  " : " ");+	DWC_PRINT(suffix);+#endif+}++/**+ * Encrypts an array of bytes using the AES encryption engine.+ * If <code>dst</code> == <code>src</code>, then the bytes will be encrypted+ * in-place.+ *+ * @return  0 on success, negative error code on error.+ */+int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst)+{+	u8 block_t[16];+	DWC_MEMSET(block_t, 0, 16);++	return DWC_AES_CBC(src, 16, key, 16, block_t, dst);+}++/**+ * The CCM-MAC-FUNCTION described in section 6.5 of the WUSB spec.+ * This function takes a data string and returns the encrypted CBC+ * Counter-mode MIC.+ *+ * @param key     The 128-bit symmetric key.+ * @param nonce   The CCM nonce.+ * @param label   The unique 14-byte ASCII text label.+ * @param bytes   The byte array to be encrypted.+ * @param len     Length of the byte array.+ * @param result  Byte array to receive the 8-byte encrypted MIC.+ */+void dwc_wusb_cmf(u8 *key, u8 *nonce,+		  char *label, u8 *bytes, int len, u8 *result)+{+	u8 block_m[16];+	u8 block_x[16];+	u8 block_t[8];+	int idx, blkNum;+	u16 la = (u16)(len + 14);++	/* Set the AES-128 key */+	//dwc_aes_setkey(tfm, key, 16);++	/* Fill block B0 from flags = 0x59, N, and l(m) = 0 */+	block_m[0] = 0x59;+	for (idx = 0; idx < 13; idx++)+		block_m[idx + 1] = nonce[idx];+	block_m[14] = 0;+	block_m[15] = 0;++	/* Produce the CBC IV */+	dwc_wusb_aes_encrypt(block_m, key, block_x);+	show_block(block_m, "CBC IV in: ", "\n", 0);+	show_block(block_x, "CBC IV out:", "\n", 0);++	/* Fill block B1 from l(a) = Blen + 14, and A */+	block_x[0] ^= (u8)(la >> 8);+	block_x[1] ^= (u8)la;+	for (idx = 0; idx < 14; idx++)+		block_x[idx + 2] ^= label[idx];+	show_block(block_x, "After xor: ", "b1\n", 16);++	dwc_wusb_aes_encrypt(block_x, key, block_x);+	show_block(block_x, "After AES: ", "b1\n", 16);++	idx = 0;+	blkNum = 0;++	/* Fill remaining blocks with B */+	while (len-- > 0) {+		block_x[idx] ^= *bytes++;+		if (++idx >= 16) {+			idx = 0;+			show_block(block_x, "After xor: ", "\n", blkNum);+			dwc_wusb_aes_encrypt(block_x, key, block_x);+			show_block(block_x, "After AES: ", "\n", blkNum);+			blkNum++;+		}+	}++	/* Handle partial last block */+	if (idx > 0) {+		show_block(block_x, "After xor: ", "\n", blkNum);+		dwc_wusb_aes_encrypt(block_x, key, block_x);+		show_block(block_x, "After AES: ", "\n", blkNum);+	}++	/* Save the MIC tag */+	DWC_MEMCPY(block_t, block_x, 8);+	show_block(block_t, "MIC tag  : ", NULL, 8);++	/* Fill block A0 from flags = 0x01, N, and counter = 0 */+	block_m[0] = 0x01;+	block_m[14] = 0;+	block_m[15] = 0;++	/* Encrypt the counter */+	dwc_wusb_aes_encrypt(block_m, key, block_x);+	show_block(block_x, "CTR[MIC] : ", NULL, 8);++	/* XOR with MIC tag */+	for (idx = 0; idx < 8; idx++) {+		block_t[idx] ^= block_x[idx];+	}++	/* Return result to caller */+	DWC_MEMCPY(result, block_t, 8);+	show_block(result, "CCM-MIC  : ", NULL, 8);++}++/**+ * The PRF function described in section 6.5 of the WUSB spec. This function+ * concatenates MIC values returned from dwc_cmf() to create a value of+ * the requested length.+ *+ * @param prf_len  Length of the PRF function in bits (64, 128, or 256).+ * @param key, nonce, label, bytes, len  Same as for dwc_cmf().+ * @param result   Byte array to receive the result.+ */+void dwc_wusb_prf(int prf_len, u8 *key,+		  u8 *nonce, char *label, u8 *bytes, int len, u8 *result)+{+	int i;++	nonce[0] = 0;+	for (i = 0; i < prf_len >> 6; i++, nonce[0]++) {+		dwc_wusb_cmf(key, nonce, label, bytes, len, result);+		result += 8;+	}+}++/**+ * Fills in CCM Nonce per the WUSB spec.+ *+ * @param[in] haddr Host address.+ * @param[in] daddr Device address.+ * @param[in] tkid Session Key(PTK) identifier.+ * @param[out] nonce Pointer to where the CCM Nonce output is to be written.+ */+void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,+			     uint8_t *nonce)+{++	DWC_DEBUG("%s %x %x\n", __func__, daddr, haddr);++	DWC_MEMSET(&nonce[0], 0, 16);++	DWC_MEMCPY(&nonce[6], tkid, 3);+	nonce[9] = daddr & 0xFF;+	nonce[10] = (daddr >> 8) & 0xFF;+	nonce[11] = haddr & 0xFF;+	nonce[12] = (haddr >> 8) & 0xFF;++	dump_bytes("CCM nonce", nonce, 16);+}++/**+ * Generates a 16-byte cryptographic-grade random number for the Host/Device+ * Nonce.+ */+void dwc_wusb_gen_nonce(uint16_t addr, uint8_t *nonce)+{+	uint8_t inonce[16];+	uint32_t temp[4];++	/* Fill in the Nonce */+	DWC_MEMSET(&inonce[0], 0, sizeof(inonce));+	inonce[9] = addr & 0xFF;+	inonce[10] = (addr >> 8) & 0xFF;+	inonce[11] = inonce[9];+	inonce[12] = inonce[10];++	/* Collect "randomness samples" */+	DWC_RANDOM_BYTES((uint8_t *)temp, 16);++	dwc_wusb_prf_128((uint8_t *)temp, nonce,+			 "Random Numbers", (uint8_t *)temp, sizeof(temp),+			 nonce);+}++/**+ * Generates the Session Key (PTK) and Key Confirmation Key (KCK) per the+ * WUSB spec.+ *+ * @param[in] ccm_nonce Pointer to CCM Nonce.+ * @param[in] mk Master Key to derive the session from+ * @param[in] hnonce Pointer to Host Nonce.+ * @param[in] dnonce Pointer to Device Nonce.+ * @param[out] kck Pointer to where the KCK output is to be written.+ * @param[out] ptk Pointer to where the PTK output is to be written.+ */+void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, uint8_t *hnonce,+		      uint8_t *dnonce, uint8_t *kck, uint8_t *ptk)+{+	uint8_t idata[32];+	uint8_t odata[32];++	dump_bytes("ck", mk, 16);+	dump_bytes("hnonce", hnonce, 16);+	dump_bytes("dnonce", dnonce, 16);++	/* The data is the HNonce and DNonce concatenated */+	DWC_MEMCPY(&idata[0], hnonce, 16);+	DWC_MEMCPY(&idata[16], dnonce, 16);++	dwc_wusb_prf_256(mk, ccm_nonce, "Pair-wise keys", idata, 32, odata);++	/* Low 16 bytes of the result is the KCK, high 16 is the PTK */+	DWC_MEMCPY(kck, &odata[0], 16);+	DWC_MEMCPY(ptk, &odata[16], 16);++	dump_bytes("kck", kck, 16);+	dump_bytes("ptk", ptk, 16);+}++/**+ * Generates the Message Integrity Code over the Handshake data per the+ * WUSB spec.+ *+ * @param ccm_nonce Pointer to CCM Nonce.+ * @param kck   Pointer to Key Confirmation Key.+ * @param data  Pointer to Handshake data to be checked.+ * @param mic   Pointer to where the MIC output is to be written.+ */+void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t *kck,+		      uint8_t *data, uint8_t *mic)+{++	dwc_wusb_prf_64(kck, ccm_nonce, "out-of-bandMIC",+			data, WUSB_HANDSHAKE_LEN_FOR_MIC, mic);+}++#endif	/* DWC_CRYPTOLIB */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_crypto.h linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_crypto.h--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_crypto.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_crypto.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,111 @@+/* =========================================================================+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.h $+ * $Revision: #3 $+ * $Date: 2010/09/28 $+ * $Change: 1596182 $+ *+ * Synopsys Portability Library Software and documentation+ * (hereinafter, "Software") is an Unsupported proprietary work of+ * Synopsys, Inc. unless otherwise expressly agreed to in writing+ * between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product+ * under any End User Software License Agreement or Agreement for+ * Licensed Product with Synopsys or any supplement thereto. You are+ * permitted to use and redistribute this Software in source and binary+ * forms, with or without modification, provided that redistributions+ * of source code must retain this notice. You may not view, use,+ * disclose, copy or distribute this file or any information contained+ * herein except pursuant to this license grant from Synopsys. If you+ * do not agree with this notice, including the disclaimer below, then+ * you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS+ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL+ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================= */++#ifndef _DWC_CRYPTO_H_+#define _DWC_CRYPTO_H_++#ifdef __cplusplus+extern "C" {+#endif++/** @file+ *+ * This file contains declarations for the WUSB Cryptographic routines as+ * defined in the WUSB spec.  They are only to be used internally by the DWC UWB+ * modules.+ */++#include "dwc_os.h"++int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst);++void dwc_wusb_cmf(u8 *key, u8 *nonce,+		  char *label, u8 *bytes, int len, u8 *result);+void dwc_wusb_prf(int prf_len, u8 *key,+		  u8 *nonce, char *label, u8 *bytes, int len, u8 *result);++/**+ * The PRF-64 function described in section 6.5 of the WUSB spec.+ *+ * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().+ */+static inline void dwc_wusb_prf_64(u8 *key, u8 *nonce,+				   char *label, u8 *bytes, int len, u8 *result)+{+	dwc_wusb_prf(64, key, nonce, label, bytes, len, result);+}++/**+ * The PRF-128 function described in section 6.5 of the WUSB spec.+ *+ * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().+ */+static inline void dwc_wusb_prf_128(u8 *key, u8 *nonce,+				    char *label, u8 *bytes, int len, u8 *result)+{+	dwc_wusb_prf(128, key, nonce, label, bytes, len, result);+}++/**+ * The PRF-256 function described in section 6.5 of the WUSB spec.+ *+ * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().+ */+static inline void dwc_wusb_prf_256(u8 *key, u8 *nonce,+				    char *label, u8 *bytes, int len, u8 *result)+{+	dwc_wusb_prf(256, key, nonce, label, bytes, len, result);+}+++void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,+			       uint8_t *nonce);+void dwc_wusb_gen_nonce(uint16_t addr,+			  uint8_t *nonce);++void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk,+			uint8_t *hnonce, uint8_t *dnonce,+			uint8_t *kck, uint8_t *ptk);+++void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t+			*kck, uint8_t *data, uint8_t *mic);++#ifdef __cplusplus+}+#endif++#endif /* _DWC_CRYPTO_H_ */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_dh.c linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_dh.c--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_dh.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_dh.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,291 @@+/* =========================================================================+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.c $+ * $Revision: #3 $+ * $Date: 2010/09/28 $+ * $Change: 1596182 $+ *+ * Synopsys Portability Library Software and documentation+ * (hereinafter, "Software") is an Unsupported proprietary work of+ * Synopsys, Inc. unless otherwise expressly agreed to in writing+ * between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product+ * under any End User Software License Agreement or Agreement for+ * Licensed Product with Synopsys or any supplement thereto. You are+ * permitted to use and redistribute this Software in source and binary+ * forms, with or without modification, provided that redistributions+ * of source code must retain this notice. You may not view, use,+ * disclose, copy or distribute this file or any information contained+ * herein except pursuant to this license grant from Synopsys. If you+ * do not agree with this notice, including the disclaimer below, then+ * you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS+ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL+ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================= */+#ifdef DWC_CRYPTOLIB++#ifndef CONFIG_MACH_IPMATE++#include "dwc_dh.h"+#include "dwc_modpow.h"++#ifdef DEBUG+/* This function prints out a buffer in the format described in the Association+ * Model specification. */+static void dh_dump(char *str, void *_num, int len)+{+	uint8_t *num = _num;+	int i;+	DWC_PRINTF("%s\n", str);+	for (i = 0; i < len; i ++) {+		DWC_PRINTF("%02x", num[i]);+		if (((i + 1) % 2) == 0) DWC_PRINTF(" ");+		if (((i + 1) % 26) == 0) DWC_PRINTF("\n");+	}++	DWC_PRINTF("\n");+}+#else+#define dh_dump(_x...) do {; } while(0)+#endif++/* Constant g value */+static __u32 dh_g[] = {+	0x02000000,+};++/* Constant p value */+static __u32 dh_p[] = {+	0xFFFFFFFF, 0xFFFFFFFF, 0xA2DA0FC9, 0x34C26821, 0x8B62C6C4, 0xD11CDC80, 0x084E0229, 0x74CC678A,+	0xA6BE0B02, 0x229B133B, 0x79084A51, 0xDD04348E, 0xB31995EF, 0x1B433ACD, 0x6D0A2B30, 0x37145FF2,+	0x6D35E14F, 0x45C2516D, 0x76B585E4, 0xC67E5E62, 0xE9424CF4, 0x6BED37A6, 0xB65CFF0B, 0xEDB706F4,+	0xFB6B38EE, 0xA59F895A, 0x11249FAE, 0xE61F4B7C, 0x51662849, 0x3D5BE4EC, 0xB87C00C2, 0x05BF63A1,+	0x3648DA98, 0x9AD3551C, 0xA83F1669, 0x5FCF24FD, 0x235D6583, 0x96ADA3DC, 0x56F3621C, 0xBB528520,+	0x0729D59E, 0x6D969670, 0x4E350C67, 0x0498BC4A, 0x086C74F1, 0x7C2118CA, 0x465E9032, 0x3BCE362E,+	0x2C779EE3, 0x03860E18, 0xA283279B, 0x8FA207EC, 0xF05DC5B5, 0xC9524C6F, 0xF6CB2BDE, 0x18175895,+	0x7C499539, 0xE56A95EA, 0x1826D215, 0x1005FA98, 0x5A8E7215, 0x2DC4AA8A, 0x0D1733AD, 0x337A5004,+	0xAB2155A8, 0x64BA1CDF, 0x0485FBEC, 0x0AEFDB58, 0x5771EA8A, 0x7D0C065D, 0x850F97B3, 0xC7E4E1A6,+	0x8CAEF5AB, 0xD73309DB, 0xE0948C1E, 0x9D61254A, 0x26D2E3CE, 0x6BEED21A, 0x06FA2FF1, 0x64088AD9,+	0x730276D8, 0x646AC83E, 0x182B1F52, 0x0C207B17, 0x5717E1BB, 0x6C5D617A, 0xC0880977, 0xE246D9BA,+	0xA04FE208, 0x31ABE574, 0xFC5BDB43, 0x8E10FDE0, 0x20D1824B, 0xCAD23AA9, 0xFFFFFFFF, 0xFFFFFFFF,+};++static void dh_swap_bytes(void *_in, void *_out, uint32_t len)+{+	uint8_t *in = _in;+	uint8_t *out = _out;+	int i;+	for (i=0; i<len; i++) {+		out[i] = in[len-1-i];+	}+}++/* Computes the modular exponentiation (num^exp % mod).  num, exp, and mod are+ * big endian numbers of size len, in bytes.  Each len value must be a multiple+ * of 4. */+int dwc_dh_modpow(void *mem_ctx, void *num, uint32_t num_len,+		  void *exp, uint32_t exp_len,+		  void *mod, uint32_t mod_len,+		  void *out)+{+	/* modpow() takes little endian numbers.  AM uses big-endian.  This+	 * function swaps bytes of numbers before passing onto modpow. */++	int retval = 0;+	uint32_t *result;++	uint32_t *bignum_num = dwc_alloc(mem_ctx, num_len + 4);+	uint32_t *bignum_exp = dwc_alloc(mem_ctx, exp_len + 4);+	uint32_t *bignum_mod = dwc_alloc(mem_ctx, mod_len + 4);++	dh_swap_bytes(num, &bignum_num[1], num_len);+	bignum_num[0] = num_len / 4;++	dh_swap_bytes(exp, &bignum_exp[1], exp_len);+	bignum_exp[0] = exp_len / 4;++	dh_swap_bytes(mod, &bignum_mod[1], mod_len);+	bignum_mod[0] = mod_len / 4;++	result = dwc_modpow(mem_ctx, bignum_num, bignum_exp, bignum_mod);+	if (!result) {+		retval = -1;+		goto dh_modpow_nomem;+	}++	dh_swap_bytes(&result[1], out, result[0] * 4);+	dwc_free(mem_ctx, result);++ dh_modpow_nomem:+	dwc_free(mem_ctx, bignum_num);+	dwc_free(mem_ctx, bignum_exp);+	dwc_free(mem_ctx, bignum_mod);+	return retval;+}+++int dwc_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pk, uint8_t *hash)+{+	int retval;+	uint8_t m3[385];++#ifndef DH_TEST_VECTORS+	DWC_RANDOM_BYTES(exp, 32);+#endif++	/* Compute the pkd */+	if ((retval = dwc_dh_modpow(mem_ctx, dh_g, 4,+				    exp, 32,+				    dh_p, 384, pk))) {+		return retval;+	}++	m3[384] = nd;+	DWC_MEMCPY(&m3[0], pk, 384);+	DWC_SHA256(m3, 385, hash);++	dh_dump("PK", pk, 384);+	dh_dump("SHA-256(M3)", hash, 32);+	return 0;+}++int dwc_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd,+		       uint8_t *exp, int is_host,+		       char *dd, uint8_t *ck, uint8_t *kdk)+{+	int retval;+	uint8_t mv[784];+	uint8_t sha_result[32];+	uint8_t dhkey[384];+	uint8_t shared_secret[384];+	char *message;+	uint32_t vd;++	uint8_t *pk;++	if (is_host) {+		pk = pkd;+	}+	else {+		pk = pkh;+	}++	if ((retval = dwc_dh_modpow(mem_ctx, pk, 384,+				    exp, 32,+				    dh_p, 384, shared_secret))) {+		return retval;+	}+	dh_dump("Shared Secret", shared_secret, 384);++	DWC_SHA256(shared_secret, 384, dhkey);+	dh_dump("DHKEY", dhkey, 384);++	DWC_MEMCPY(&mv[0], pkd, 384);+	DWC_MEMCPY(&mv[384], pkh, 384);+	DWC_MEMCPY(&mv[768], "displayed digest", 16);+	dh_dump("MV", mv, 784);++	DWC_SHA256(mv, 784, sha_result);+	dh_dump("SHA-256(MV)", sha_result, 32);+	dh_dump("First 32-bits of SHA-256(MV)", sha_result, 4);++	dh_swap_bytes(sha_result, &vd, 4);+#ifdef DEBUG+	DWC_PRINTF("Vd (decimal) = %d\n", vd);+#endif++	switch (nd) {+	case 2:+		vd = vd % 100;+		DWC_SPRINTF(dd, "%02d", vd);+		break;+	case 3:+		vd = vd % 1000;+		DWC_SPRINTF(dd, "%03d", vd);+		break;+	case 4:+		vd = vd % 10000;+		DWC_SPRINTF(dd, "%04d", vd);+		break;+	}+#ifdef DEBUG+	DWC_PRINTF("Display Digits: %s\n", dd);+#endif++	message = "connection key";+	DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);+	dh_dump("HMAC(SHA-256, DHKey, connection key)", sha_result, 32);+	DWC_MEMCPY(ck, sha_result, 16);++	message = "key derivation key";+	DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);+	dh_dump("HMAC(SHA-256, DHKey, key derivation key)", sha_result, 32);+	DWC_MEMCPY(kdk, sha_result, 32);++	return 0;+}+++#ifdef DH_TEST_VECTORS++static __u8 dh_a[] = {+	0x44, 0x00, 0x51, 0xd6,+	0xf0, 0xb5, 0x5e, 0xa9,+	0x67, 0xab, 0x31, 0xc6,+	0x8a, 0x8b, 0x5e, 0x37,+	0xd9, 0x10, 0xda, 0xe0,+	0xe2, 0xd4, 0x59, 0xa4,+	0x86, 0x45, 0x9c, 0xaa,+	0xdf, 0x36, 0x75, 0x16,+};++static __u8 dh_b[] = {+	0x5d, 0xae, 0xc7, 0x86,+	0x79, 0x80, 0xa3, 0x24,+	0x8c, 0xe3, 0x57, 0x8f,+	0xc7, 0x5f, 0x1b, 0x0f,+	0x2d, 0xf8, 0x9d, 0x30,+	0x6f, 0xa4, 0x52, 0xcd,+	0xe0, 0x7a, 0x04, 0x8a,+	0xde, 0xd9, 0x26, 0x56,+};++void dwc_run_dh_test_vectors(void *mem_ctx)+{+	uint8_t pkd[384];+	uint8_t pkh[384];+	uint8_t hashd[32];+	uint8_t hashh[32];+	uint8_t ck[16];+	uint8_t kdk[32];+	char dd[5];++	DWC_PRINTF("\n\n\nDH_TEST_VECTORS\n\n");++	/* compute the PKd and SHA-256(PKd || Nd) */+	DWC_PRINTF("Computing PKd\n");+	dwc_dh_pk(mem_ctx, 2, dh_a, pkd, hashd);++	/* compute the PKd and SHA-256(PKh || Nd) */+	DWC_PRINTF("Computing PKh\n");+	dwc_dh_pk(mem_ctx, 2, dh_b, pkh, hashh);++	/* compute the dhkey */+	dwc_dh_derive_keys(mem_ctx, 2, pkh, pkd, dh_a, 0, dd, ck, kdk);+}+#endif /* DH_TEST_VECTORS */++#endif /* !CONFIG_MACH_IPMATE */++#endif /* DWC_CRYPTOLIB */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_dh.h linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_dh.h--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_dh.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_dh.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,106 @@+/* =========================================================================+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.h $+ * $Revision: #4 $+ * $Date: 2010/09/28 $+ * $Change: 1596182 $+ *+ * Synopsys Portability Library Software and documentation+ * (hereinafter, "Software") is an Unsupported proprietary work of+ * Synopsys, Inc. unless otherwise expressly agreed to in writing+ * between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product+ * under any End User Software License Agreement or Agreement for+ * Licensed Product with Synopsys or any supplement thereto. You are+ * permitted to use and redistribute this Software in source and binary+ * forms, with or without modification, provided that redistributions+ * of source code must retain this notice. You may not view, use,+ * disclose, copy or distribute this file or any information contained+ * herein except pursuant to this license grant from Synopsys. If you+ * do not agree with this notice, including the disclaimer below, then+ * you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS+ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL+ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================= */+#ifndef _DWC_DH_H_+#define _DWC_DH_H_++#ifdef __cplusplus+extern "C" {+#endif++#include "dwc_os.h"++/** @file+ *+ * This file defines the common functions on device and host for performing+ * numeric association as defined in the WUSB spec.  They are only to be+ * used internally by the DWC UWB modules. */++extern int dwc_dh_sha256(uint8_t *message, uint32_t len, uint8_t *out);+extern int dwc_dh_hmac_sha256(uint8_t *message, uint32_t messagelen,+			      uint8_t *key, uint32_t keylen,+			      uint8_t *out);+extern int dwc_dh_modpow(void *mem_ctx, void *num, uint32_t num_len,+			 void *exp, uint32_t exp_len,+			 void *mod, uint32_t mod_len,+			 void *out);++/** Computes PKD or PKH, and SHA-256(PKd || Nd)+ *+ * PK = g^exp mod p.+ *+ * Input:+ * Nd = Number of digits on the device.+ *+ * Output:+ * exp = A 32-byte buffer to be filled with a randomly generated number.+ *       used as either A or B.+ * pk = A 384-byte buffer to be filled with the PKH or PKD.+ * hash = A 32-byte buffer to be filled with SHA-256(PK || ND).+ */+extern int dwc_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pkd, uint8_t *hash);++/** Computes the DHKEY, and VD.+ *+ * If called from host, then it will comput DHKEY=PKD^exp % p.+ * If called from device, then it will comput DHKEY=PKH^exp % p.+ *+ * Input:+ * pkd = The PKD value.+ * pkh = The PKH value.+ * exp = The A value (if device) or B value (if host) generated in dwc_wudev_dh_pk.+ * is_host = Set to non zero if a WUSB host is calling this function.+ *+ * Output:++ * dd = A pointer to an buffer to be set to the displayed digits string to be shown+ *      to the user.  This buffer should be at 5 bytes long to hold 4 digits plus a+ *      null termination character.  This buffer can be used directly for display.+ * ck = A 16-byte buffer to be filled with the CK.+ * kdk = A 32-byte buffer to be filled with the KDK.+ */+extern int dwc_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd,+			      uint8_t *exp, int is_host,+			      char *dd, uint8_t *ck, uint8_t *kdk);++#ifdef DH_TEST_VECTORS+extern void dwc_run_dh_test_vectors(void);+#endif++#ifdef __cplusplus+}+#endif++#endif /* _DWC_DH_H_ */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_list.h linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_list.h--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_list.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_list.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,594 @@+/*	$OpenBSD: queue.h,v 1.26 2004/05/04 16:59:32 grange Exp $	*/+/*	$NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $	*/++/*+ * Copyright (c) 1991, 1993+ *	The Regents of the University of California.  All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. Neither the name of the University nor the names of its contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ *+ *	@(#)queue.h	8.5 (Berkeley) 8/20/94+ */++#ifndef _DWC_LIST_H_+#define _DWC_LIST_H_++#ifdef __cplusplus+extern "C" {+#endif++/** @file+ *+ * This file defines linked list operations.  It is derived from BSD with+ * only the MACRO names being prefixed with DWC_.  This is because a few of+ * these names conflict with those on Linux.  For documentation on use, see the+ * inline comments in the source code.  The original license for this source+ * code applies and is preserved in the dwc_list.h source file.+ */++/*+ * This file defines five types of data structures: singly-linked lists,+ * lists, simple queues, tail queues, and circular queues.+ *+ *+ * A singly-linked list is headed by a single forward pointer. The elements+ * are singly linked for minimum space and pointer manipulation overhead at+ * the expense of O(n) removal for arbitrary elements. New elements can be+ * added to the list after an existing element or at the head of the list.+ * Elements being removed from the head of the list should use the explicit+ * macro for this purpose for optimum efficiency. A singly-linked list may+ * only be traversed in the forward direction.  Singly-linked lists are ideal+ * for applications with large datasets and few or no removals or for+ * implementing a LIFO queue.+ *+ * A list is headed by a single forward pointer (or an array of forward+ * pointers for a hash table header). The elements are doubly linked+ * so that an arbitrary element can be removed without a need to+ * traverse the list. New elements can be added to the list before+ * or after an existing element or at the head of the list. A list+ * may only be traversed in the forward direction.+ *+ * A simple queue is headed by a pair of pointers, one the head of the+ * list and the other to the tail of the list. The elements are singly+ * linked to save space, so elements can only be removed from the+ * head of the list. New elements can be added to the list before or after+ * an existing element, at the head of the list, or at the end of the+ * list. A simple queue may only be traversed in the forward direction.+ *+ * A tail queue is headed by a pair of pointers, one to the head of the+ * list and the other to the tail of the list. The elements are doubly+ * linked so that an arbitrary element can be removed without a need to+ * traverse the list. New elements can be added to the list before or+ * after an existing element, at the head of the list, or at the end of+ * the list. A tail queue may be traversed in either direction.+ *+ * A circle queue is headed by a pair of pointers, one to the head of the+ * list and the other to the tail of the list. The elements are doubly+ * linked so that an arbitrary element can be removed without a need to+ * traverse the list. New elements can be added to the list before or after+ * an existing element, at the head of the list, or at the end of the list.+ * A circle queue may be traversed in either direction, but has a more+ * complex end of list detection.+ *+ * For details on the use of these macros, see the queue(3) manual page.+ */++/*+ * Double-linked List.+ */++typedef struct dwc_list_link {+	struct dwc_list_link *next;+	struct dwc_list_link *prev;+} dwc_list_link_t;++#define DWC_LIST_INIT(link) do {	\+	(link)->next = (link);		\+	(link)->prev = (link);		\+} while (0)++#define DWC_LIST_FIRST(link)	((link)->next)+#define DWC_LIST_LAST(link)	((link)->prev)+#define DWC_LIST_END(link)	(link)+#define DWC_LIST_NEXT(link)	((link)->next)+#define DWC_LIST_PREV(link)	((link)->prev)+#define DWC_LIST_EMPTY(link)	\+	(DWC_LIST_FIRST(link) == DWC_LIST_END(link))+#define DWC_LIST_ENTRY(link, type, field)			\+	(type *)((uint8_t *)(link) - (size_t)(&((type *)0)->field))++#if 0+#define DWC_LIST_INSERT_HEAD(list, link) do {			\+	(link)->next = (list)->next;				\+	(link)->prev = (list);					\+	(list)->next->prev = (link);				\+	(list)->next = (link);					\+} while (0)++#define DWC_LIST_INSERT_TAIL(list, link) do {			\+	(link)->next = (list);					\+	(link)->prev = (list)->prev;				\+	(list)->prev->next = (link);				\+	(list)->prev = (link);					\+} while (0)+#else+#define DWC_LIST_INSERT_HEAD(list, link) do {			\+	dwc_list_link_t *__next__ = (list)->next;		\+	__next__->prev = (link);				\+	(link)->next = __next__;				\+	(link)->prev = (list);					\+	(list)->next = (link);					\+} while (0)++#define DWC_LIST_INSERT_TAIL(list, link) do {			\+	dwc_list_link_t *__prev__ = (list)->prev;		\+	(list)->prev = (link);					\+	(link)->next = (list);					\+	(link)->prev = __prev__;				\+	__prev__->next = (link);				\+} while (0)+#endif++#if 0+static inline void __list_add(struct list_head *new,+                              struct list_head *prev,+                              struct list_head *next)+{+        next->prev = new;+        new->next = next;+        new->prev = prev;+        prev->next = new;+}++static inline void list_add(struct list_head *new, struct list_head *head)+{+        __list_add(new, head, head->next);+}++static inline void list_add_tail(struct list_head *new, struct list_head *head)+{+        __list_add(new, head->prev, head);+}++static inline void __list_del(struct list_head * prev, struct list_head * next)+{+        next->prev = prev;+        prev->next = next;+}++static inline void list_del(struct list_head *entry)+{+        __list_del(entry->prev, entry->next);+        entry->next = LIST_POISON1;+        entry->prev = LIST_POISON2;+}+#endif++#define DWC_LIST_REMOVE(link) do {				\+	(link)->next->prev = (link)->prev;			\+	(link)->prev->next = (link)->next;			\+} while (0)++#define DWC_LIST_REMOVE_INIT(link) do {				\+	DWC_LIST_REMOVE(link);					\+	DWC_LIST_INIT(link);					\+} while (0)++#define DWC_LIST_MOVE_HEAD(list, link) do {			\+	DWC_LIST_REMOVE(link);					\+	DWC_LIST_INSERT_HEAD(list, link);			\+} while (0)++#define DWC_LIST_MOVE_TAIL(list, link) do {			\+	DWC_LIST_REMOVE(link);					\+	DWC_LIST_INSERT_TAIL(list, link);			\+} while (0)++#define DWC_LIST_FOREACH(var, list)				\+	for((var) = DWC_LIST_FIRST(list);			\+	    (var) != DWC_LIST_END(list);			\+	    (var) = DWC_LIST_NEXT(var))++#define DWC_LIST_FOREACH_SAFE(var, var2, list)			\+	for((var) = DWC_LIST_FIRST(list), (var2) = DWC_LIST_NEXT(var);	\+	    (var) != DWC_LIST_END(list);			\+	    (var) = (var2), (var2) = DWC_LIST_NEXT(var2))++#define DWC_LIST_FOREACH_REVERSE(var, list)			\+	for((var) = DWC_LIST_LAST(list);			\+	    (var) != DWC_LIST_END(list);			\+	    (var) = DWC_LIST_PREV(var))++/*+ * Singly-linked List definitions.+ */+#define DWC_SLIST_HEAD(name, type)					\+struct name {								\+	struct type *slh_first;	/* first element */			\+}++#define DWC_SLIST_HEAD_INITIALIZER(head)				\+	{ NULL }++#define DWC_SLIST_ENTRY(type)						\+struct {								\+	struct type *sle_next;	/* next element */			\+}++/*+ * Singly-linked List access methods.+ */+#define DWC_SLIST_FIRST(head)	((head)->slh_first)+#define DWC_SLIST_END(head)		NULL+#define DWC_SLIST_EMPTY(head)	(SLIST_FIRST(head) == SLIST_END(head))+#define DWC_SLIST_NEXT(elm, field)	((elm)->field.sle_next)++#define DWC_SLIST_FOREACH(var, head, field)				\+	for((var) = SLIST_FIRST(head);					\+	    (var) != SLIST_END(head);					\+	    (var) = SLIST_NEXT(var, field))++#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field)		\+	for((varp) = &SLIST_FIRST((head));				\+	    ((var) = *(varp)) != SLIST_END(head);			\+	    (varp) = &SLIST_NEXT((var), field))++/*+ * Singly-linked List functions.+ */+#define DWC_SLIST_INIT(head) {						\+	SLIST_FIRST(head) = SLIST_END(head);				\+}++#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do {		\+	(elm)->field.sle_next = (slistelm)->field.sle_next;		\+	(slistelm)->field.sle_next = (elm);				\+} while (0)++#define DWC_SLIST_INSERT_HEAD(head, elm, field) do {			\+	(elm)->field.sle_next = (head)->slh_first;			\+	(head)->slh_first = (elm);					\+} while (0)++#define DWC_SLIST_REMOVE_NEXT(head, elm, field) do {			\+	(elm)->field.sle_next = (elm)->field.sle_next->field.sle_next;	\+} while (0)++#define DWC_SLIST_REMOVE_HEAD(head, field) do {				\+	(head)->slh_first = (head)->slh_first->field.sle_next;		\+} while (0)++#define DWC_SLIST_REMOVE(head, elm, type, field) do {			\+	if ((head)->slh_first == (elm)) {				\+		SLIST_REMOVE_HEAD((head), field);			\+	}								\+	else {								\+		struct type *curelm = (head)->slh_first;		\+		while( curelm->field.sle_next != (elm) )		\+			curelm = curelm->field.sle_next;		\+		curelm->field.sle_next =				\+		    curelm->field.sle_next->field.sle_next;		\+	}								\+} while (0)++/*+ * Simple queue definitions.+ */+#define DWC_SIMPLEQ_HEAD(name, type)					\+struct name {								\+	struct type *sqh_first;	/* first element */			\+	struct type **sqh_last;	/* addr of last next element */		\+}++#define DWC_SIMPLEQ_HEAD_INITIALIZER(head)				\+	{ NULL, &(head).sqh_first }++#define DWC_SIMPLEQ_ENTRY(type)						\+struct {								\+	struct type *sqe_next;	/* next element */			\+}++/*+ * Simple queue access methods.+ */+#define DWC_SIMPLEQ_FIRST(head)	    ((head)->sqh_first)+#define DWC_SIMPLEQ_END(head)	    NULL+#define DWC_SIMPLEQ_EMPTY(head)	    (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))+#define DWC_SIMPLEQ_NEXT(elm, field)    ((elm)->field.sqe_next)++#define DWC_SIMPLEQ_FOREACH(var, head, field)				\+	for((var) = SIMPLEQ_FIRST(head);				\+	    (var) != SIMPLEQ_END(head);					\+	    (var) = SIMPLEQ_NEXT(var, field))++/*+ * Simple queue functions.+ */+#define DWC_SIMPLEQ_INIT(head) do {					\+	(head)->sqh_first = NULL;					\+	(head)->sqh_last = &(head)->sqh_first;				\+} while (0)++#define DWC_SIMPLEQ_INSERT_HEAD(head, elm, field) do {			\+	if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)	\+		(head)->sqh_last = &(elm)->field.sqe_next;		\+	(head)->sqh_first = (elm);					\+} while (0)++#define DWC_SIMPLEQ_INSERT_TAIL(head, elm, field) do {			\+	(elm)->field.sqe_next = NULL;					\+	*(head)->sqh_last = (elm);					\+	(head)->sqh_last = &(elm)->field.sqe_next;			\+} while (0)++#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {	\+	if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\+		(head)->sqh_last = &(elm)->field.sqe_next;		\+	(listelm)->field.sqe_next = (elm);				\+} while (0)++#define DWC_SIMPLEQ_REMOVE_HEAD(head, field) do {			\+	if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \+		(head)->sqh_last = &(head)->sqh_first;			\+} while (0)++/*+ * Tail queue definitions.+ */+#define DWC_TAILQ_HEAD(name, type)					\+struct name {								\+	struct type *tqh_first;	/* first element */			\+	struct type **tqh_last;	/* addr of last next element */		\+}++#define DWC_TAILQ_HEAD_INITIALIZER(head)				\+	{ NULL, &(head).tqh_first }++#define DWC_TAILQ_ENTRY(type)						\+struct {								\+	struct type *tqe_next;	/* next element */			\+	struct type **tqe_prev;	/* address of previous next element */	\+}++/*+ * tail queue access methods+ */+#define DWC_TAILQ_FIRST(head)		((head)->tqh_first)+#define DWC_TAILQ_END(head)		NULL+#define DWC_TAILQ_NEXT(elm, field)	((elm)->field.tqe_next)+#define DWC_TAILQ_LAST(head, headname)					\+	(*(((struct headname *)((head)->tqh_last))->tqh_last))+/* XXX */+#define DWC_TAILQ_PREV(elm, headname, field)				\+	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))+#define DWC_TAILQ_EMPTY(head)						\+	(DWC_TAILQ_FIRST(head) == DWC_TAILQ_END(head))++#define DWC_TAILQ_FOREACH(var, head, field)				\+	for ((var) = DWC_TAILQ_FIRST(head);				\+	    (var) != DWC_TAILQ_END(head);				\+	    (var) = DWC_TAILQ_NEXT(var, field))++#define DWC_TAILQ_FOREACH_REVERSE(var, head, headname, field)		\+	for ((var) = DWC_TAILQ_LAST(head, headname);			\+	    (var) != DWC_TAILQ_END(head);				\+	    (var) = DWC_TAILQ_PREV(var, headname, field))++/*+ * Tail queue functions.+ */+#define DWC_TAILQ_INIT(head) do {					\+	(head)->tqh_first = NULL;					\+	(head)->tqh_last = &(head)->tqh_first;				\+} while (0)++#define DWC_TAILQ_INSERT_HEAD(head, elm, field) do {			\+	if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)	\+		(head)->tqh_first->field.tqe_prev =			\+		    &(elm)->field.tqe_next;				\+	else								\+		(head)->tqh_last = &(elm)->field.tqe_next;		\+	(head)->tqh_first = (elm);					\+	(elm)->field.tqe_prev = &(head)->tqh_first;			\+} while (0)++#define DWC_TAILQ_INSERT_TAIL(head, elm, field) do {			\+	(elm)->field.tqe_next = NULL;					\+	(elm)->field.tqe_prev = (head)->tqh_last;			\+	*(head)->tqh_last = (elm);					\+	(head)->tqh_last = &(elm)->field.tqe_next;			\+} while (0)++#define DWC_TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\+	if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\+		(elm)->field.tqe_next->field.tqe_prev =			\+		    &(elm)->field.tqe_next;				\+	else								\+		(head)->tqh_last = &(elm)->field.tqe_next;		\+	(listelm)->field.tqe_next = (elm);				\+	(elm)->field.tqe_prev = &(listelm)->field.tqe_next;		\+} while (0)++#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do {		\+	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\+	(elm)->field.tqe_next = (listelm);				\+	*(listelm)->field.tqe_prev = (elm);				\+	(listelm)->field.tqe_prev = &(elm)->field.tqe_next;		\+} while (0)++#define DWC_TAILQ_REMOVE(head, elm, field) do {				\+	if (((elm)->field.tqe_next) != NULL)				\+		(elm)->field.tqe_next->field.tqe_prev =			\+		    (elm)->field.tqe_prev;				\+	else								\+		(head)->tqh_last = (elm)->field.tqe_prev;		\+	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\+} while (0)++#define DWC_TAILQ_REPLACE(head, elm, elm2, field) do {			\+	if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL)	\+		(elm2)->field.tqe_next->field.tqe_prev =		\+		    &(elm2)->field.tqe_next;				\+	else								\+		(head)->tqh_last = &(elm2)->field.tqe_next;		\+	(elm2)->field.tqe_prev = (elm)->field.tqe_prev;			\+	*(elm2)->field.tqe_prev = (elm2);				\+} while (0)++/*+ * Circular queue definitions.+ */+#define DWC_CIRCLEQ_HEAD(name, type)					\+struct name {								\+	struct type *cqh_first;		/* first element */		\+	struct type *cqh_last;		/* last element */		\+}++#define DWC_CIRCLEQ_HEAD_INITIALIZER(head)				\+	{ DWC_CIRCLEQ_END(&head), DWC_CIRCLEQ_END(&head) }++#define DWC_CIRCLEQ_ENTRY(type)						\+struct {								\+	struct type *cqe_next;		/* next element */		\+	struct type *cqe_prev;		/* previous element */		\+}++/*+ * Circular queue access methods+ */+#define DWC_CIRCLEQ_FIRST(head)		((head)->cqh_first)+#define DWC_CIRCLEQ_LAST(head)		((head)->cqh_last)+#define DWC_CIRCLEQ_END(head)		((void *)(head))+#define DWC_CIRCLEQ_NEXT(elm, field)	((elm)->field.cqe_next)+#define DWC_CIRCLEQ_PREV(elm, field)	((elm)->field.cqe_prev)+#define DWC_CIRCLEQ_EMPTY(head)						\+	(DWC_CIRCLEQ_FIRST(head) == DWC_CIRCLEQ_END(head))++#define DWC_CIRCLEQ_EMPTY_ENTRY(elm, field) (((elm)->field.cqe_next == NULL) && ((elm)->field.cqe_prev == NULL))++#define DWC_CIRCLEQ_FOREACH(var, head, field)				\+	for((var) = DWC_CIRCLEQ_FIRST(head);				\+	    (var) != DWC_CIRCLEQ_END(head);				\+	    (var) = DWC_CIRCLEQ_NEXT(var, field))++#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field)			\+	for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field); \+	    (var) != DWC_CIRCLEQ_END(head);					\+	    (var) = var2, var2 = DWC_CIRCLEQ_NEXT(var, field))++#define DWC_CIRCLEQ_FOREACH_REVERSE(var, head, field)			\+	for((var) = DWC_CIRCLEQ_LAST(head);				\+	    (var) != DWC_CIRCLEQ_END(head);				\+	    (var) = DWC_CIRCLEQ_PREV(var, field))++/*+ * Circular queue functions.+ */+#define DWC_CIRCLEQ_INIT(head) do {					\+	(head)->cqh_first = DWC_CIRCLEQ_END(head);			\+	(head)->cqh_last = DWC_CIRCLEQ_END(head);			\+} while (0)++#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do {				\+	(elm)->field.cqe_next = NULL;					\+	(elm)->field.cqe_prev = NULL;					\+} while (0)++#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {	\+	(elm)->field.cqe_next = (listelm)->field.cqe_next;		\+	(elm)->field.cqe_prev = (listelm);				\+	if ((listelm)->field.cqe_next == DWC_CIRCLEQ_END(head))		\+		(head)->cqh_last = (elm);				\+	else								\+		(listelm)->field.cqe_next->field.cqe_prev = (elm);	\+	(listelm)->field.cqe_next = (elm);				\+} while (0)++#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {	\+	(elm)->field.cqe_next = (listelm);				\+	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;		\+	if ((listelm)->field.cqe_prev == DWC_CIRCLEQ_END(head))		\+		(head)->cqh_first = (elm);				\+	else								\+		(listelm)->field.cqe_prev->field.cqe_next = (elm);	\+	(listelm)->field.cqe_prev = (elm);				\+} while (0)++#define DWC_CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\+	(elm)->field.cqe_next = (head)->cqh_first;			\+	(elm)->field.cqe_prev = DWC_CIRCLEQ_END(head);			\+	if ((head)->cqh_last == DWC_CIRCLEQ_END(head))			\+		(head)->cqh_last = (elm);				\+	else								\+		(head)->cqh_first->field.cqe_prev = (elm);		\+	(head)->cqh_first = (elm);					\+} while (0)++#define DWC_CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\+	(elm)->field.cqe_next = DWC_CIRCLEQ_END(head);			\+	(elm)->field.cqe_prev = (head)->cqh_last;			\+	if ((head)->cqh_first == DWC_CIRCLEQ_END(head))			\+		(head)->cqh_first = (elm);				\+	else								\+		(head)->cqh_last->field.cqe_next = (elm);		\+	(head)->cqh_last = (elm);					\+} while (0)++#define DWC_CIRCLEQ_REMOVE(head, elm, field) do {			\+	if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head))		\+		(head)->cqh_last = (elm)->field.cqe_prev;		\+	else								\+		(elm)->field.cqe_next->field.cqe_prev =			\+		    (elm)->field.cqe_prev;				\+	if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head))		\+		(head)->cqh_first = (elm)->field.cqe_next;		\+	else								\+		(elm)->field.cqe_prev->field.cqe_next =			\+		    (elm)->field.cqe_next;				\+} while (0)++#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do {			\+	DWC_CIRCLEQ_REMOVE(head, elm, field);				\+	DWC_CIRCLEQ_INIT_ENTRY(elm, field);				\+} while (0)++#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do {		\+	if (((elm2)->field.cqe_next = (elm)->field.cqe_next) ==		\+	    DWC_CIRCLEQ_END(head))					\+		(head).cqh_last = (elm2);				\+	else								\+		(elm2)->field.cqe_next->field.cqe_prev = (elm2);	\+	if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) ==		\+	    DWC_CIRCLEQ_END(head))					\+		(head).cqh_first = (elm2);				\+	else								\+		(elm2)->field.cqe_prev->field.cqe_next = (elm2);	\+} while (0)++#ifdef __cplusplus+}+#endif++#endif /* _DWC_LIST_H_ */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_mem.c linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_mem.c--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_mem.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_mem.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,245 @@+/* Memory Debugging */+#ifdef DWC_DEBUG_MEMORY++#include "dwc_os.h"+#include "dwc_list.h"++struct allocation {+	void *addr;+	void *ctx;+	char *func;+	int line;+	uint32_t size;+	int dma;+	DWC_CIRCLEQ_ENTRY(allocation) entry;+};++DWC_CIRCLEQ_HEAD(allocation_queue, allocation);++struct allocation_manager {+	void *mem_ctx;+	struct allocation_queue allocations;++	/* statistics */+	int num;+	int num_freed;+	int num_active;+	uint32_t total;+	uint32_t cur;+	uint32_t max;+};++static struct allocation_manager *manager = NULL;++static int add_allocation(void *ctx, uint32_t size, char const *func, int line, void *addr,+			  int dma)+{+	struct allocation *a;++	DWC_ASSERT(manager != NULL, "manager not allocated");++	a = __DWC_ALLOC_ATOMIC(manager->mem_ctx, sizeof(*a));+	if (!a) {+		return -DWC_E_NO_MEMORY;+	}++	a->func = __DWC_ALLOC_ATOMIC(manager->mem_ctx, DWC_STRLEN(func) + 1);+	if (!a->func) {+		__DWC_FREE(manager->mem_ctx, a);+		return -DWC_E_NO_MEMORY;+	}++	DWC_MEMCPY(a->func, func, DWC_STRLEN(func) + 1);+	a->addr = addr;+	a->ctx = ctx;+	a->line = line;+	a->size = size;+	a->dma = dma;+	DWC_CIRCLEQ_INSERT_TAIL(&manager->allocations, a, entry);++	/* Update stats */+	manager->num++;+	manager->num_active++;+	manager->total += size;+	manager->cur += size;++	if (manager->max < manager->cur) {+		manager->max = manager->cur;+	}++	return 0;+}++static struct allocation *find_allocation(void *ctx, void *addr)+{+	struct allocation *a;++	DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {+		if (a->ctx == ctx && a->addr == addr) {+			return a;+		}+	}++	return NULL;+}++static void free_allocation(void *ctx, void *addr, char const *func, int line)+{+	struct allocation *a = find_allocation(ctx, addr);++	if (!a) {+		DWC_ASSERT(0,+			   "Free of address %p that was never allocated or already freed %s:%d",+			   addr, func, line);+		return;+	}++	DWC_CIRCLEQ_REMOVE(&manager->allocations, a, entry);++	manager->num_active--;+	manager->num_freed++;+	manager->cur -= a->size;+	__DWC_FREE(manager->mem_ctx, a->func);+	__DWC_FREE(manager->mem_ctx, a);+}++int dwc_memory_debug_start(void *mem_ctx)+{+	DWC_ASSERT(manager == NULL, "Memory debugging has already started\n");++	if (manager) {+		return -DWC_E_BUSY;+	}++	manager = __DWC_ALLOC(mem_ctx, sizeof(*manager));+	if (!manager) {+		return -DWC_E_NO_MEMORY;+	}++	DWC_CIRCLEQ_INIT(&manager->allocations);+	manager->mem_ctx = mem_ctx;+	manager->num = 0;+	manager->num_freed = 0;+	manager->num_active = 0;+	manager->total = 0;+	manager->cur = 0;+	manager->max = 0;++	return 0;+}++void dwc_memory_debug_stop(void)+{+	struct allocation *a;++	dwc_memory_debug_report();++	DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {+		DWC_ERROR("Memory leaked from %s:%d\n", a->func, a->line);+		free_allocation(a->ctx, a->addr, NULL, -1);+	}++	__DWC_FREE(manager->mem_ctx, manager);+}++void dwc_memory_debug_report(void)+{+	struct allocation *a;++	DWC_PRINTF("\n\n\n----------------- Memory Debugging Report -----------------\n\n");+	DWC_PRINTF("Num Allocations = %d\n", manager->num);+	DWC_PRINTF("Freed = %d\n", manager->num_freed);+	DWC_PRINTF("Active = %d\n", manager->num_active);+	DWC_PRINTF("Current Memory Used = %d\n", manager->cur);+	DWC_PRINTF("Total Memory Used = %d\n", manager->total);+	DWC_PRINTF("Maximum Memory Used at Once = %d\n", manager->max);+	DWC_PRINTF("Unfreed allocations:\n");++	DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {+		DWC_PRINTF("    addr=%p, size=%d from %s:%d, DMA=%d\n",+			   a->addr, a->size, a->func, a->line, a->dma);+	}+}++/* The replacement functions */+void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line)+{+	void *addr = __DWC_ALLOC(mem_ctx, size);++	if (!addr) {+		return NULL;+	}++	if (add_allocation(mem_ctx, size, func, line, addr, 0)) {+		__DWC_FREE(mem_ctx, addr);+		return NULL;+	}++	return addr;+}++void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func,+			     int line)+{+	void *addr = __DWC_ALLOC_ATOMIC(mem_ctx, size);++	if (!addr) {+		return NULL;+	}++	if (add_allocation(mem_ctx, size, func, line, addr, 0)) {+		__DWC_FREE(mem_ctx, addr);+		return NULL;+	}++	return addr;+}++void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line)+{+	free_allocation(mem_ctx, addr, func, line);+	__DWC_FREE(mem_ctx, addr);+}++void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,+			  char const *func, int line)+{+	void *addr = __DWC_DMA_ALLOC(dma_ctx, size, dma_addr);++	if (!addr) {+		return NULL;+	}++	if (add_allocation(dma_ctx, size, func, line, addr, 1)) {+		__DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr);+		return NULL;+	}++	return addr;+}++void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size,+				 dwc_dma_t *dma_addr, char const *func, int line)+{+	void *addr = __DWC_DMA_ALLOC_ATOMIC(dma_ctx, size, dma_addr);++	if (!addr) {+		return NULL;+	}++	if (add_allocation(dma_ctx, size, func, line, addr, 1)) {+		__DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr);+		return NULL;+	}++	return addr;+}++void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr,+			dwc_dma_t dma_addr, char const *func, int line)+{+	free_allocation(dma_ctx, virt_addr, func, line);+	__DWC_DMA_FREE(dma_ctx, size, virt_addr, dma_addr);+}++#endif /* DWC_DEBUG_MEMORY */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_modpow.c linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_modpow.c--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_modpow.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_modpow.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,636 @@+/* Bignum routines adapted from PUTTY sources.  PuTTY copyright notice follows.+ *+ * PuTTY is copyright 1997-2007 Simon Tatham.+ *+ * Portions copyright Robert de Bath, Joris van Rantwijk, Delian+ * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,+ * Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus+ * Kuhn, and CORE SDI S.A.+ *+ * Permission is hereby granted, free of charge, to any person+ * obtaining a copy of this software and associated documentation files+ * (the "Software"), to deal in the Software without restriction,+ * including without limitation the rights to use, copy, modify, merge,+ * publish, distribute, sublicense, and/or sell copies of the Software,+ * and to permit persons to whom the Software is furnished to do so,+ * subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be+ * included in all copies or substantial portions of the Software.++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.+ *+ */+#ifdef DWC_CRYPTOLIB++#ifndef CONFIG_MACH_IPMATE++#include "dwc_modpow.h"++#define BIGNUM_INT_MASK  0xFFFFFFFFUL+#define BIGNUM_TOP_BIT   0x80000000UL+#define BIGNUM_INT_BITS  32+++static void *snmalloc(void *mem_ctx, size_t n, size_t size)+{+    void *p;+    size *= n;+    if (size == 0) size = 1;+    p = dwc_alloc(mem_ctx, size);+    return p;+}++#define snewn(ctx, n, type) ((type *)snmalloc((ctx), (n), sizeof(type)))+#define sfree dwc_free++/*+ * Usage notes:+ *  * Do not call the DIVMOD_WORD macro with expressions such as array+ *    subscripts, as some implementations object to this (see below).+ *  * Note that none of the division methods below will cope if the+ *    quotient won't fit into BIGNUM_INT_BITS. Callers should be careful+ *    to avoid this case.+ *    If this condition occurs, in the case of the x86 DIV instruction,+ *    an overflow exception will occur, which (according to a correspondent)+ *    will manifest on Windows as something like+ *      0xC0000095: Integer overflow+ *    The C variant won't give the right answer, either.+ */++#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)++#if defined __GNUC__ && defined __i386__+#define DIVMOD_WORD(q, r, hi, lo, w) \+    __asm__("div %2" : \+	    "=d" (r), "=a" (q) : \+	    "r" (w), "d" (hi), "a" (lo))+#else+#define DIVMOD_WORD(q, r, hi, lo, w) do { \+    BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \+    q = n / w; \+    r = n % w; \+} while (0)+#endif++//    q = n / w;+//    r = n % w;++#define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8)++#define BIGNUM_INTERNAL++static Bignum newbn(void *mem_ctx, int length)+{+    Bignum b = snewn(mem_ctx, length + 1, BignumInt);+    //if (!b)+    //abort();		       /* FIXME */+    DWC_MEMSET(b, 0, (length + 1) * sizeof(*b));+    b[0] = length;+    return b;+}++void freebn(void *mem_ctx, Bignum b)+{+    /*+     * Burn the evidence, just in case.+     */+    DWC_MEMSET(b, 0, sizeof(b[0]) * (b[0] + 1));+    sfree(mem_ctx, b);+}++/*+ * Compute c = a * b.+ * Input is in the first len words of a and b.+ * Result is returned in the first 2*len words of c.+ */+static void internal_mul(BignumInt *a, BignumInt *b,+			 BignumInt *c, int len)+{+    int i, j;+    BignumDblInt t;++    for (j = 0; j < 2 * len; j++)+	c[j] = 0;++    for (i = len - 1; i >= 0; i--) {+	t = 0;+	for (j = len - 1; j >= 0; j--) {+	    t += MUL_WORD(a[i], (BignumDblInt) b[j]);+	    t += (BignumDblInt) c[i + j + 1];+	    c[i + j + 1] = (BignumInt) t;+	    t = t >> BIGNUM_INT_BITS;+	}+	c[i] = (BignumInt) t;+    }+}++static void internal_add_shifted(BignumInt *number,+				 unsigned n, int shift)+{+    int word = 1 + (shift / BIGNUM_INT_BITS);+    int bshift = shift % BIGNUM_INT_BITS;+    BignumDblInt addend;++    addend = (BignumDblInt)n << bshift;++    while (addend) {+	addend += number[word];+	number[word] = (BignumInt) addend & BIGNUM_INT_MASK;+	addend >>= BIGNUM_INT_BITS;+	word++;+    }+}++/*+ * Compute a = a % m.+ * Input in first alen words of a and first mlen words of m.+ * Output in first alen words of a+ * (of which first alen-mlen words will be zero).+ * The MSW of m MUST have its high bit set.+ * Quotient is accumulated in the `quotient' array, which is a Bignum+ * rather than the internal bigendian format. Quotient parts are shifted+ * left by `qshift' before adding into quot.+ */+static void internal_mod(BignumInt *a, int alen,+			 BignumInt *m, int mlen,+			 BignumInt *quot, int qshift)+{+    BignumInt m0, m1;+    unsigned int h;+    int i, k;++    m0 = m[0];+    if (mlen > 1)+	m1 = m[1];+    else+	m1 = 0;++    for (i = 0; i <= alen - mlen; i++) {+	BignumDblInt t;+	unsigned int q, r, c, ai1;++	if (i == 0) {+	    h = 0;+	} else {+	    h = a[i - 1];+	    a[i - 1] = 0;+	}++	if (i == alen - 1)+	    ai1 = 0;+	else+	    ai1 = a[i + 1];++	/* Find q = h:a[i] / m0 */+	if (h >= m0) {+	    /*+	     * Special case.+	     *+	     * To illustrate it, suppose a BignumInt is 8 bits, and+	     * we are dividing (say) A1:23:45:67 by A1:B2:C3. Then+	     * our initial division will be 0xA123 / 0xA1, which+	     * will give a quotient of 0x100 and a divide overflow.+	     * However, the invariants in this division algorithm+	     * are not violated, since the full number A1:23:... is+	     * _less_ than the quotient prefix A1:B2:... and so the+	     * following correction loop would have sorted it out.+	     *+	     * In this situation we set q to be the largest+	     * quotient we _can_ stomach (0xFF, of course).+	     */+	    q = BIGNUM_INT_MASK;+	} else {+	    /* Macro doesn't want an array subscript expression passed+	     * into it (see definition), so use a temporary. */+	    BignumInt tmplo = a[i];+	    DIVMOD_WORD(q, r, h, tmplo, m0);++	    /* Refine our estimate of q by looking at+	     h:a[i]:a[i+1] / m0:m1 */+	    t = MUL_WORD(m1, q);+	    if (t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) {+		q--;+		t -= m1;+		r = (r + m0) & BIGNUM_INT_MASK;     /* overflow? */+		if (r >= (BignumDblInt) m0 &&+		    t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) q--;+	    }+	}++	/* Subtract q * m from a[i...] */+	c = 0;+	for (k = mlen - 1; k >= 0; k--) {+	    t = MUL_WORD(q, m[k]);+	    t += c;+	    c = (unsigned)(t >> BIGNUM_INT_BITS);+	    if ((BignumInt) t > a[i + k])+		c++;+	    a[i + k] -= (BignumInt) t;+	}++	/* Add back m in case of borrow */+	if (c != h) {+	    t = 0;+	    for (k = mlen - 1; k >= 0; k--) {+		t += m[k];+		t += a[i + k];+		a[i + k] = (BignumInt) t;+		t = t >> BIGNUM_INT_BITS;+	    }+	    q--;+	}+	if (quot)+	    internal_add_shifted(quot, q, qshift + BIGNUM_INT_BITS * (alen - mlen - i));+    }+}++/*+ * Compute p % mod.+ * The most significant word of mod MUST be non-zero.+ * We assume that the result array is the same size as the mod array.+ * We optionally write out a quotient if `quotient' is non-NULL.+ * We can avoid writing out the result if `result' is NULL.+ */+void bigdivmod(void *mem_ctx, Bignum p, Bignum mod, Bignum result, Bignum quotient)+{+    BignumInt *n, *m;+    int mshift;+    int plen, mlen, i, j;++    /* Allocate m of size mlen, copy mod to m */+    /* We use big endian internally */+    mlen = mod[0];+    m = snewn(mem_ctx, mlen, BignumInt);+    //if (!m)+    //abort();		       /* FIXME */+    for (j = 0; j < mlen; j++)+	m[j] = mod[mod[0] - j];++    /* Shift m left to make msb bit set */+    for (mshift = 0; mshift < BIGNUM_INT_BITS-1; mshift++)+	if ((m[0] << mshift) & BIGNUM_TOP_BIT)+	    break;+    if (mshift) {+	for (i = 0; i < mlen - 1; i++)+	    m[i] = (m[i] << mshift) | (m[i + 1] >> (BIGNUM_INT_BITS - mshift));+	m[mlen - 1] = m[mlen - 1] << mshift;+    }++    plen = p[0];+    /* Ensure plen > mlen */+    if (plen <= mlen)+	plen = mlen + 1;++    /* Allocate n of size plen, copy p to n */+    n = snewn(mem_ctx, plen, BignumInt);+    //if (!n)+    //abort();		       /* FIXME */+    for (j = 0; j < plen; j++)+	n[j] = 0;+    for (j = 1; j <= (int)p[0]; j++)+	n[plen - j] = p[j];++    /* Main computation */+    internal_mod(n, plen, m, mlen, quotient, mshift);++    /* Fixup result in case the modulus was shifted */+    if (mshift) {+	for (i = plen - mlen - 1; i < plen - 1; i++)+	    n[i] = (n[i] << mshift) | (n[i + 1] >> (BIGNUM_INT_BITS - mshift));+	n[plen - 1] = n[plen - 1] << mshift;+	internal_mod(n, plen, m, mlen, quotient, 0);+	for (i = plen - 1; i >= plen - mlen; i--)+	    n[i] = (n[i] >> mshift) | (n[i - 1] << (BIGNUM_INT_BITS - mshift));+    }++    /* Copy result to buffer */+    if (result) {+	for (i = 1; i <= (int)result[0]; i++) {+	    int j = plen - i;+	    result[i] = j >= 0 ? n[j] : 0;+	}+    }++    /* Free temporary arrays */+    for (i = 0; i < mlen; i++)+	m[i] = 0;+    sfree(mem_ctx, m);+    for (i = 0; i < plen; i++)+	n[i] = 0;+    sfree(mem_ctx, n);+}++/*+ * Simple remainder.+ */+Bignum bigmod(void *mem_ctx, Bignum a, Bignum b)+{+    Bignum r = newbn(mem_ctx, b[0]);+    bigdivmod(mem_ctx, a, b, r, NULL);+    return r;+}++/*+ * Compute (base ^ exp) % mod.+ */+Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod)+{+    BignumInt *a, *b, *n, *m;+    int mshift;+    int mlen, i, j;+    Bignum base, result;++    /*+     * The most significant word of mod needs to be non-zero. It+     * should already be, but let's make sure.+     */+    //assert(mod[mod[0]] != 0);++    /*+     * Make sure the base is smaller than the modulus, by reducing+     * it modulo the modulus if not.+     */+    base = bigmod(mem_ctx, base_in, mod);++    /* Allocate m of size mlen, copy mod to m */+    /* We use big endian internally */+    mlen = mod[0];+    m = snewn(mem_ctx, mlen, BignumInt);+    //if (!m)+    //abort();		       /* FIXME */+    for (j = 0; j < mlen; j++)+	m[j] = mod[mod[0] - j];++    /* Shift m left to make msb bit set */+    for (mshift = 0; mshift < BIGNUM_INT_BITS - 1; mshift++)+	if ((m[0] << mshift) & BIGNUM_TOP_BIT)+	    break;+    if (mshift) {+	for (i = 0; i < mlen - 1; i++)+	    m[i] =+		(m[i] << mshift) | (m[i + 1] >>+				    (BIGNUM_INT_BITS - mshift));+	m[mlen - 1] = m[mlen - 1] << mshift;+    }++    /* Allocate n of size mlen, copy base to n */+    n = snewn(mem_ctx, mlen, BignumInt);+    //if (!n)+    //abort();		       /* FIXME */+    i = mlen - base[0];+    for (j = 0; j < i; j++)+	n[j] = 0;+    for (j = 0; j < base[0]; j++)+	n[i + j] = base[base[0] - j];++    /* Allocate a and b of size 2*mlen. Set a = 1 */+    a = snewn(mem_ctx, 2 * mlen, BignumInt);+    //if (!a)+    //abort();		       /* FIXME */+    b = snewn(mem_ctx, 2 * mlen, BignumInt);+    //if (!b)+    //abort();		       /* FIXME */+    for (i = 0; i < 2 * mlen; i++)+	a[i] = 0;+    a[2 * mlen - 1] = 1;++    /* Skip leading zero bits of exp. */+    i = 0;+    j = BIGNUM_INT_BITS - 1;+    while (i < exp[0] && (exp[exp[0] - i] & (1 << j)) == 0) {+	j--;+	if (j < 0) {+	    i++;+	    j = BIGNUM_INT_BITS - 1;+	}+    }++    /* Main computation */+    while (i < exp[0]) {+	while (j >= 0) {+	    internal_mul(a + mlen, a + mlen, b, mlen);+	    internal_mod(b, mlen * 2, m, mlen, NULL, 0);+	    if ((exp[exp[0] - i] & (1 << j)) != 0) {+		internal_mul(b + mlen, n, a, mlen);+		internal_mod(a, mlen * 2, m, mlen, NULL, 0);+	    } else {+		BignumInt *t;+		t = a;+		a = b;+		b = t;+	    }+	    j--;+	}+	i++;+	j = BIGNUM_INT_BITS - 1;+    }++    /* Fixup result in case the modulus was shifted */+    if (mshift) {+	for (i = mlen - 1; i < 2 * mlen - 1; i++)+	    a[i] =+		(a[i] << mshift) | (a[i + 1] >>+				    (BIGNUM_INT_BITS - mshift));+	a[2 * mlen - 1] = a[2 * mlen - 1] << mshift;+	internal_mod(a, mlen * 2, m, mlen, NULL, 0);+	for (i = 2 * mlen - 1; i >= mlen; i--)+	    a[i] =+		(a[i] >> mshift) | (a[i - 1] <<+				    (BIGNUM_INT_BITS - mshift));+    }++    /* Copy result to buffer */+    result = newbn(mem_ctx, mod[0]);+    for (i = 0; i < mlen; i++)+	result[result[0] - i] = a[i + mlen];+    while (result[0] > 1 && result[result[0]] == 0)+	result[0]--;++    /* Free temporary arrays */+    for (i = 0; i < 2 * mlen; i++)+	a[i] = 0;+    sfree(mem_ctx, a);+    for (i = 0; i < 2 * mlen; i++)+	b[i] = 0;+    sfree(mem_ctx, b);+    for (i = 0; i < mlen; i++)+	m[i] = 0;+    sfree(mem_ctx, m);+    for (i = 0; i < mlen; i++)+	n[i] = 0;+    sfree(mem_ctx, n);++    freebn(mem_ctx, base);++    return result;+}+++#ifdef UNITTEST++static __u32 dh_p[] = {+	96,+	0xFFFFFFFF,+	0xFFFFFFFF,+	0xA93AD2CA,+	0x4B82D120,+	0xE0FD108E,+	0x43DB5BFC,+	0x74E5AB31,+	0x08E24FA0,+	0xBAD946E2,+	0x770988C0,+	0x7A615D6C,+	0xBBE11757,+	0x177B200C,+	0x521F2B18,+	0x3EC86A64,+	0xD8760273,+	0xD98A0864,+	0xF12FFA06,+	0x1AD2EE6B,+	0xCEE3D226,+	0x4A25619D,+	0x1E8C94E0,+	0xDB0933D7,+	0xABF5AE8C,+	0xA6E1E4C7,+	0xB3970F85,+	0x5D060C7D,+	0x8AEA7157,+	0x58DBEF0A,+	0xECFB8504,+	0xDF1CBA64,+	0xA85521AB,+	0x04507A33,+	0xAD33170D,+	0x8AAAC42D,+	0x15728E5A,+	0x98FA0510,+	0x15D22618,+	0xEA956AE5,+	0x3995497C,+	0x95581718,+	0xDE2BCBF6,+	0x6F4C52C9,+	0xB5C55DF0,+	0xEC07A28F,+	0x9B2783A2,+	0x180E8603,+	0xE39E772C,+	0x2E36CE3B,+	0x32905E46,+	0xCA18217C,+	0xF1746C08,+	0x4ABC9804,+	0x670C354E,+	0x7096966D,+	0x9ED52907,+	0x208552BB,+	0x1C62F356,+	0xDCA3AD96,+	0x83655D23,+	0xFD24CF5F,+	0x69163FA8,+	0x1C55D39A,+	0x98DA4836,+	0xA163BF05,+	0xC2007CB8,+	0xECE45B3D,+	0x49286651,+	0x7C4B1FE6,+	0xAE9F2411,+	0x5A899FA5,+	0xEE386BFB,+	0xF406B7ED,+	0x0BFF5CB6,+	0xA637ED6B,+	0xF44C42E9,+	0x625E7EC6,+	0xE485B576,+	0x6D51C245,+	0x4FE1356D,+	0xF25F1437,+	0x302B0A6D,+	0xCD3A431B,+	0xEF9519B3,+	0x8E3404DD,+	0x514A0879,+	0x3B139B22,+	0x020BBEA6,+	0x8A67CC74,+	0x29024E08,+	0x80DC1CD1,+	0xC4C6628B,+	0x2168C234,+	0xC90FDAA2,+	0xFFFFFFFF,+	0xFFFFFFFF,+};++static __u32 dh_a[] = {+	8,+	0xdf367516,+	0x86459caa,+	0xe2d459a4,+	0xd910dae0,+	0x8a8b5e37,+	0x67ab31c6,+	0xf0b55ea9,+	0x440051d6,+};++static __u32 dh_b[] = {+	8,+	0xded92656,+	0xe07a048a,+	0x6fa452cd,+	0x2df89d30,+	0xc75f1b0f,+	0x8ce3578f,+	0x7980a324,+	0x5daec786,+};++static __u32 dh_g[] = {+	1,+	2,+};++int main(void)+{+	int i;+	__u32 *k;+	k = dwc_modpow(NULL, dh_g, dh_a, dh_p);++	printf("\n\n");+	for (i=0; i<k[0]; i++) {+		__u32 word32 = k[k[0] - i];+		__u16 l = word32 & 0xffff;+		__u16 m = (word32 & 0xffff0000) >> 16;+		printf("%04x %04x ", m, l);+		if (!((i + 1)%13)) printf("\n");+	}+	printf("\n\n");++	if ((k[0] == 0x60) && (k[1] == 0x28e490e5) && (k[0x60] == 0x5a0d3d4e)) {+		printf("PASS\n\n");+	}+	else {+		printf("FAIL\n\n");+	}++}++#endif /* UNITTEST */++#endif /* CONFIG_MACH_IPMATE */++#endif /*DWC_CRYPTOLIB */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_modpow.h linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_modpow.h--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_modpow.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_modpow.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,34 @@+/*+ * dwc_modpow.h+ * See dwc_modpow.c for license and changes+ */+#ifndef _DWC_MODPOW_H+#define _DWC_MODPOW_H++#ifdef __cplusplus+extern "C" {+#endif++#include "dwc_os.h"++/** @file+ *+ * This file defines the module exponentiation function which is only used+ * internally by the DWC UWB modules for calculation of PKs during numeric+ * association.  The routine is taken from the PUTTY, an open source terminal+ * emulator.  The PUTTY License is preserved in the dwc_modpow.c file.+ *+ */++typedef uint32_t BignumInt;+typedef uint64_t BignumDblInt;+typedef BignumInt *Bignum;++/* Compute modular exponentiaion */+extern Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod);++#ifdef __cplusplus+}+#endif++#endif /* _LINUX_BIGNUM_H */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_notifier.c--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_notifier.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_notifier.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,319 @@+#ifdef DWC_NOTIFYLIB++#include "dwc_notifier.h"+#include "dwc_list.h"++typedef struct dwc_observer {+	void *observer;+	dwc_notifier_callback_t callback;+	void *data;+	char *notification;+	DWC_CIRCLEQ_ENTRY(dwc_observer) list_entry;+} observer_t;++DWC_CIRCLEQ_HEAD(observer_queue, dwc_observer);++typedef struct dwc_notifier {+	void *mem_ctx;+	void *object;+	struct observer_queue observers;+	DWC_CIRCLEQ_ENTRY(dwc_notifier) list_entry;+} notifier_t;++DWC_CIRCLEQ_HEAD(notifier_queue, dwc_notifier);++typedef struct manager {+	void *mem_ctx;+	void *wkq_ctx;+	dwc_workq_t *wq;+//	dwc_mutex_t *mutex;+	struct notifier_queue notifiers;+} manager_t;++static manager_t *manager = NULL;++static int create_manager(void *mem_ctx, void *wkq_ctx)+{+	manager = dwc_alloc(mem_ctx, sizeof(manager_t));+	if (!manager) {+		return -DWC_E_NO_MEMORY;+	}++	DWC_CIRCLEQ_INIT(&manager->notifiers);++	manager->wq = dwc_workq_alloc(wkq_ctx, "DWC Notification WorkQ");+	if (!manager->wq) {+		return -DWC_E_NO_MEMORY;+	}++	return 0;+}++static void free_manager(void)+{+	dwc_workq_free(manager->wq);++	/* All notifiers must have unregistered themselves before this module+	 * can be removed.  Hitting this assertion indicates a programmer+	 * error. */+	DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&manager->notifiers),+		   "Notification manager being freed before all notifiers have been removed");+	dwc_free(manager->mem_ctx, manager);+}++#ifdef DEBUG+static void dump_manager(void)+{+	notifier_t *n;+	observer_t *o;++	DWC_ASSERT(manager, "Notification manager not found");++	DWC_DEBUG("List of all notifiers and observers:\n");+	DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {+		DWC_DEBUG("Notifier %p has observers:\n", n->object);+		DWC_CIRCLEQ_FOREACH(o, &n->observers, list_entry) {+			DWC_DEBUG("    %p watching %s\n", o->observer, o->notification);+		}+	}+}+#else+#define dump_manager(...)+#endif++static observer_t *alloc_observer(void *mem_ctx, void *observer, char *notification,+				  dwc_notifier_callback_t callback, void *data)+{+	observer_t *new_observer = dwc_alloc(mem_ctx, sizeof(observer_t));++	if (!new_observer) {+		return NULL;+	}++	DWC_CIRCLEQ_INIT_ENTRY(new_observer, list_entry);+	new_observer->observer = observer;+	new_observer->notification = notification;+	new_observer->callback = callback;+	new_observer->data = data;+	return new_observer;+}++static void free_observer(void *mem_ctx, observer_t *observer)+{+	dwc_free(mem_ctx, observer);+}++static notifier_t *alloc_notifier(void *mem_ctx, void *object)+{+	notifier_t *notifier;++	if (!object) {+		return NULL;+	}++	notifier = dwc_alloc(mem_ctx, sizeof(notifier_t));+	if (!notifier) {+		return NULL;+	}++	DWC_CIRCLEQ_INIT(¬ifier->observers);+	DWC_CIRCLEQ_INIT_ENTRY(notifier, list_entry);++	notifier->mem_ctx = mem_ctx;+	notifier->object = object;+	return notifier;+}++static void free_notifier(notifier_t *notifier)+{+	observer_t *observer;++	DWC_CIRCLEQ_FOREACH(observer, ¬ifier->observers, list_entry) {+		free_observer(notifier->mem_ctx, observer);+	}++	dwc_free(notifier->mem_ctx, notifier);+}++static notifier_t *find_notifier(void *object)+{+	notifier_t *notifier;++	DWC_ASSERT(manager, "Notification manager not found");++	if (!object) {+		return NULL;+	}++	DWC_CIRCLEQ_FOREACH(notifier, &manager->notifiers, list_entry) {+		if (notifier->object == object) {+			return notifier;+		}+	}++	return NULL;+}++int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx)+{+	return create_manager(mem_ctx, wkq_ctx);+}++void dwc_free_notification_manager(void)+{+	free_manager();+}++dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object)+{+	notifier_t *notifier;++	DWC_ASSERT(manager, "Notification manager not found");++	notifier = find_notifier(object);+	if (notifier) {+		DWC_ERROR("Notifier %p is already registered\n", object);+		return NULL;+	}++	notifier = alloc_notifier(mem_ctx, object);+	if (!notifier) {+		return NULL;+	}++	DWC_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry);++	DWC_INFO("Notifier %p registered", object);+	dump_manager();++	return notifier;+}++void dwc_unregister_notifier(dwc_notifier_t *notifier)+{+	DWC_ASSERT(manager, "Notification manager not found");++	if (!DWC_CIRCLEQ_EMPTY(¬ifier->observers)) {+		observer_t *o;++		DWC_ERROR("Notifier %p has active observers when removing\n", notifier->object);+		DWC_CIRCLEQ_FOREACH(o, ¬ifier->observers, list_entry) {+			DWC_DEBUGC("    %p watching %s\n", o->observer, o->notification);+		}++		DWC_ASSERT(DWC_CIRCLEQ_EMPTY(¬ifier->observers),+			   "Notifier %p has active observers when removing", notifier);+	}++	DWC_CIRCLEQ_REMOVE_INIT(&manager->notifiers, notifier, list_entry);+	free_notifier(notifier);++	DWC_INFO("Notifier unregistered");+	dump_manager();+}++/* Add an observer to observe the notifier for a particular state, event, or notification. */+int dwc_add_observer(void *observer, void *object, char *notification,+		     dwc_notifier_callback_t callback, void *data)+{+	notifier_t *notifier = find_notifier(object);+	observer_t *new_observer;++	if (!notifier) {+		DWC_ERROR("Notifier %p is not found when adding observer\n", object);+		return -DWC_E_INVALID;+	}++	new_observer = alloc_observer(notifier->mem_ctx, observer, notification, callback, data);+	if (!new_observer) {+		return -DWC_E_NO_MEMORY;+	}++	DWC_CIRCLEQ_INSERT_TAIL(¬ifier->observers, new_observer, list_entry);++	DWC_INFO("Added observer %p to notifier %p observing notification %s, callback=%p, data=%p",+		 observer, object, notification, callback, data);++	dump_manager();+	return 0;+}++int dwc_remove_observer(void *observer)+{+	notifier_t *n;++	DWC_ASSERT(manager, "Notification manager not found");++	DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {+		observer_t *o;+		observer_t *o2;++		DWC_CIRCLEQ_FOREACH_SAFE(o, o2, &n->observers, list_entry) {+			if (o->observer == observer) {+				DWC_CIRCLEQ_REMOVE_INIT(&n->observers, o, list_entry);+				DWC_INFO("Removing observer %p from notifier %p watching notification %s:",+					 o->observer, n->object, o->notification);+				free_observer(n->mem_ctx, o);+			}+		}+	}++	dump_manager();+	return 0;+}++typedef struct callback_data {+	void *mem_ctx;+	dwc_notifier_callback_t cb;+	void *observer;+	void *data;+	void *object;+	char *notification;+	void *notification_data;+} cb_data_t;++static void cb_task(void *data)+{+	cb_data_t *cb = (cb_data_t *)data;++	cb->cb(cb->object, cb->notification, cb->observer, cb->notification_data, cb->data);+	dwc_free(cb->mem_ctx, cb);+}++void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data)+{+	observer_t *o;++	DWC_ASSERT(manager, "Notification manager not found");++	DWC_CIRCLEQ_FOREACH(o, ¬ifier->observers, list_entry) {+		int len = DWC_STRLEN(notification);++		if (DWC_STRLEN(o->notification) != len) {+			continue;+		}++		if (DWC_STRNCMP(o->notification, notification, len) == 0) {+			cb_data_t *cb_data = dwc_alloc(notifier->mem_ctx, sizeof(cb_data_t));++			if (!cb_data) {+				DWC_ERROR("Failed to allocate callback data\n");+				return;+			}++			cb_data->mem_ctx = notifier->mem_ctx;+			cb_data->cb = o->callback;+			cb_data->observer = o->observer;+			cb_data->data = o->data;+			cb_data->object = notifier->object;+			cb_data->notification = notification;+			cb_data->notification_data = notification_data;+			DWC_DEBUGC("Observer found %p for notification %s\n", o->observer, notification);+			DWC_WORKQ_SCHEDULE(manager->wq, cb_task, cb_data,+					   "Notify callback from %p for Notification %s, to observer %p",+					   cb_data->object, notification, cb_data->observer);+		}+	}+}++#endif	/* DWC_NOTIFYLIB */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_notifier.h linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_notifier.h--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_notifier.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_notifier.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,122 @@++#ifndef __DWC_NOTIFIER_H__+#define __DWC_NOTIFIER_H__++#ifdef __cplusplus+extern "C" {+#endif++#include "dwc_os.h"++/** @file+ *+ * A simple implementation of the Observer pattern.  Any "module" can+ * register as an observer or notifier.  The notion of "module" is abstract and+ * can mean anything used to identify either an observer or notifier.  Usually+ * it will be a pointer to a data structure which contains some state, ie an+ * object.+ *+ * Before any notifiers can be added, the global notification manager must be+ * brought up with dwc_alloc_notification_manager().+ * dwc_free_notification_manager() will bring it down and free all resources.+ * These would typically be called upon module load and unload.  The+ * notification manager is a single global instance that handles all registered+ * observable modules and observers so this should be done only once.+ *+ * A module can be observable by using Notifications to publicize some general+ * information about it's state or operation.  It does not care who listens, or+ * even if anyone listens, or what they do with the information.  The observable+ * modules do not need to know any information about it's observers or their+ * interface, or their state or data.+ *+ * Any module can register to emit Notifications.  It should publish a list of+ * notifications that it can emit and their behavior, such as when they will get+ * triggered, and what information will be provided to the observer.  Then it+ * should register itself as an observable module. See dwc_register_notifier().+ *+ * Any module can observe any observable, registered module, provided it has a+ * handle to the other module and knows what notifications to observe.  See+ * dwc_add_observer().+ *+ * A function of type dwc_notifier_callback_t is called whenever a notification+ * is triggered with one or more observers observing it.  This function is+ * called in it's own process so it may sleep or block if needed.  It is+ * guaranteed to be called sometime after the notification has occurred and will+ * be called once per each time the notification is triggered.  It will NOT be+ * called in the same process context used to trigger the notification.+ *+ * @section Limitiations+ *+ * Keep in mind that Notifications that can be triggered in rapid sucession may+ * schedule too many processes too handle.  Be aware of this limitation when+ * designing to use notifications, and only add notifications for appropriate+ * observable information.+ *+ * Also Notification callbacks are not synchronous.  If you need to synchronize+ * the behavior between module/observer you must use other means.  And perhaps+ * that will mean Notifications are not the proper solution.+ */++struct dwc_notifier;+typedef struct dwc_notifier dwc_notifier_t;++/** The callback function must be of this type.+ *+ * @param object This is the object that is being observed.+ * @param notification This is the notification that was triggered.+ * @param observer This is the observer+ * @param notification_data This is notification-specific data that the notifier+ * has included in this notification.  The value of this should be published in+ * the documentation of the observable module with the notifications.+ * @param user_data This is any custom data that the observer provided when+ * adding itself as an observer to the notification. */+typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer,+					void *notification_data, void *user_data);++/** Brings up the notification manager. */+extern int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx);+/** Brings down the notification manager. */+extern void dwc_free_notification_manager(void);++/** This function registers an observable module.  A dwc_notifier_t object is+ * returned to the observable module.  This is an opaque object that is used by+ * the observable module to trigger notifications.  This object should only be+ * accessible to functions that are authorized to trigger notifications for this+ * module.  Observers do not need this object. */+extern dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object);++/** This function unregisters an observable module.  All observers have to be+ * removed prior to unregistration. */+extern void dwc_unregister_notifier(dwc_notifier_t *notifier);++/** Add a module as an observer to the observable module.  The observable module+ * needs to have previously registered with the notification manager.+ *+ * @param observer The observer module+ * @param object The module to observe+ * @param notification The notification to observe+ * @param callback The callback function to call+ * @param user_data Any additional user data to pass into the callback function */+extern int dwc_add_observer(void *observer, void *object, char *notification,+			    dwc_notifier_callback_t callback, void *user_data);++/** Removes the specified observer from all notifications that it is currently+ * observing. */+extern int dwc_remove_observer(void *observer);++/** This function triggers a Notification.  It should be called by the+ * observable module, or any module or library which the observable module+ * allows to trigger notification on it's behalf.  Such as the dwc_cc_t.+ *+ * dwc_notify is a non-blocking function.  Callbacks are scheduled called in+ * their own process context for each trigger.  Callbacks can be blocking.+ * dwc_notify can be called from interrupt context if needed.+ *+ */+void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data);++#ifdef __cplusplus+}+#endif++#endif /* __DWC_NOTIFIER_H__ */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_os.h linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_os.h--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/dwc_os.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/dwc_os.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,1262 @@+/* =========================================================================+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_os.h $+ * $Revision: #14 $+ * $Date: 2010/11/04 $+ * $Change: 1621695 $+ *+ * Synopsys Portability Library Software and documentation+ * (hereinafter, "Software") is an Unsupported proprietary work of+ * Synopsys, Inc. unless otherwise expressly agreed to in writing+ * between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product+ * under any End User Software License Agreement or Agreement for+ * Licensed Product with Synopsys or any supplement thereto. You are+ * permitted to use and redistribute this Software in source and binary+ * forms, with or without modification, provided that redistributions+ * of source code must retain this notice. You may not view, use,+ * disclose, copy or distribute this file or any information contained+ * herein except pursuant to this license grant from Synopsys. If you+ * do not agree with this notice, including the disclaimer below, then+ * you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS+ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL+ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================= */+#ifndef _DWC_OS_H_+#define _DWC_OS_H_++#ifdef __cplusplus+extern "C" {+#endif++/** @file+ *+ * DWC portability library, low level os-wrapper functions+ *+ */++/* These basic types need to be defined by some OS header file or custom header+ * file for your specific target architecture.+ *+ * uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t+ *+ * Any custom or alternate header file must be added and enabled here.+ */++#ifdef DWC_LINUX+# include <linux/types.h>+# ifdef CONFIG_DEBUG_MUTEXES+#  include <linux/mutex.h>+# endif+# include <linux/errno.h>+# include <stdarg.h>+#endif++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)+# include <os_dep.h>+#endif+++/** @name Primitive Types and Values */++/** We define a boolean type for consistency.  Can be either YES or NO */+typedef uint8_t dwc_bool_t;+#define YES  1+#define NO   0++#ifdef DWC_LINUX++/** @name Error Codes */+#define DWC_E_INVALID		EINVAL+#define DWC_E_NO_MEMORY		ENOMEM+#define DWC_E_NO_DEVICE		ENODEV+#define DWC_E_NOT_SUPPORTED	EOPNOTSUPP+#define DWC_E_TIMEOUT		ETIMEDOUT+#define DWC_E_BUSY		EBUSY+#define DWC_E_AGAIN		EAGAIN+#define DWC_E_RESTART		ERESTART+#define DWC_E_ABORT		ECONNABORTED+#define DWC_E_SHUTDOWN		ESHUTDOWN+#define DWC_E_NO_DATA		ENODATA+#define DWC_E_DISCONNECT	ECONNRESET+#define DWC_E_UNKNOWN		EINVAL+#define DWC_E_NO_STREAM_RES	ENOSR+#define DWC_E_COMMUNICATION	ECOMM+#define DWC_E_OVERFLOW		EOVERFLOW+#define DWC_E_PROTOCOL		EPROTO+#define DWC_E_IN_PROGRESS	EINPROGRESS+#define DWC_E_PIPE		EPIPE+#define DWC_E_IO		EIO+#define DWC_E_NO_SPACE		ENOSPC++#else++/** @name Error Codes */+#define DWC_E_INVALID		1001+#define DWC_E_NO_MEMORY		1002+#define DWC_E_NO_DEVICE		1003+#define DWC_E_NOT_SUPPORTED	1004+#define DWC_E_TIMEOUT		1005+#define DWC_E_BUSY		1006+#define DWC_E_AGAIN		1007+#define DWC_E_RESTART		1008+#define DWC_E_ABORT		1009+#define DWC_E_SHUTDOWN		1010+#define DWC_E_NO_DATA		1011+#define DWC_E_DISCONNECT	2000+#define DWC_E_UNKNOWN		3000+#define DWC_E_NO_STREAM_RES	4001+#define DWC_E_COMMUNICATION	4002+#define DWC_E_OVERFLOW		4003+#define DWC_E_PROTOCOL		4004+#define DWC_E_IN_PROGRESS	4005+#define DWC_E_PIPE		4006+#define DWC_E_IO		4007+#define DWC_E_NO_SPACE		4008++#endif+++/** @name Tracing/Logging Functions+ *+ * These function provide the capability to add tracing, debugging, and error+ * messages, as well exceptions as assertions.  The WUDEV uses these+ * extensively.  These could be logged to the main console, the serial port, an+ * internal buffer, etc.  These functions could also be no-op if they are too+ * expensive on your system.  By default undefining the DEBUG macro already+ * no-ops some of these functions. */++/** Returns non-zero if in interrupt context. */+extern dwc_bool_t DWC_IN_IRQ(void);+#define dwc_in_irq DWC_IN_IRQ++/** Returns "IRQ" if DWC_IN_IRQ is true. */+static inline char *dwc_irq(void) {+	return DWC_IN_IRQ() ? "IRQ" : "";+}++/** Returns non-zero if in bottom-half context. */+extern dwc_bool_t DWC_IN_BH(void);+#define dwc_in_bh DWC_IN_BH++/** Returns "BH" if DWC_IN_BH is true. */+static inline char *dwc_bh(void) {+	return DWC_IN_BH() ? "BH" : "";+}++/**+ * A vprintf() clone.  Just call vprintf if you've got it.+ */+extern void DWC_VPRINTF(char *format, va_list args);+#define dwc_vprintf DWC_VPRINTF++/**+ * A vsnprintf() clone.  Just call vprintf if you've got it.+ */+extern int DWC_VSNPRINTF(char *str, int size, char *format, va_list args);+#define dwc_vsnprintf DWC_VSNPRINTF++/**+ * printf() clone.  Just call printf if you've go it.+ */+extern void DWC_PRINTF(char *format, ...)+/* This provides compiler level static checking of the parameters if you're+ * using GCC. */+#ifdef __GNUC__+	__attribute__ ((format(printf, 1, 2)));+#else+	;+#endif+#define dwc_printf DWC_PRINTF++/**+ * sprintf() clone.  Just call sprintf if you've got it.+ */+extern int DWC_SPRINTF(char *string, char *format, ...)+#ifdef __GNUC__+	__attribute__ ((format(printf, 2, 3)));+#else+	;+#endif+#define dwc_sprintf DWC_SPRINTF++/**+ * snprintf() clone.  Just call snprintf if you've got it.+ */+extern int DWC_SNPRINTF(char *string, int size, char *format, ...)+#ifdef __GNUC__+	__attribute__ ((format(printf, 3, 4)));+#else+	;+#endif+#define dwc_snprintf DWC_SNPRINTF++/**+ * Prints a WARNING message.  On systems that don't differentiate between+ * warnings and regular log messages, just print it.  Indicates that something+ * may be wrong with the driver.  Works like printf().+ *+ * Use the DWC_WARN macro to call this function.+ */+extern void __DWC_WARN(char *format, ...)+#ifdef __GNUC__+	__attribute__ ((format(printf, 1, 2)));+#else+	;+#endif++/**+ * Prints an error message.  On systems that don't differentiate between errors+ * and regular log messages, just print it.  Indicates that something went wrong+ * with the driver.  Works like printf().+ *+ * Use the DWC_ERROR macro to call this function.+ */+extern void __DWC_ERROR(char *format, ...)+#ifdef __GNUC__+	__attribute__ ((format(printf, 1, 2)));+#else+	;+#endif++/**+ * Prints an exception error message and takes some user-defined action such as+ * print out a backtrace or trigger a breakpoint.  Indicates that something went+ * abnormally wrong with the driver such as programmer error, or other+ * exceptional condition.  It should not be ignored so even on systems without+ * printing capability, some action should be taken to notify the developer of+ * it.  Works like printf().+ */+extern void DWC_EXCEPTION(char *format, ...)+#ifdef __GNUC__+	__attribute__ ((format(printf, 1, 2)));+#else+	;+#endif+#define dwc_exception DWC_EXCEPTION++#ifndef DWC_OTG_DEBUG_LEV+#define DWC_OTG_DEBUG_LEV 0+#endif++#ifdef DEBUG+/**+ * Prints out a debug message.  Used for logging/trace messages.+ *+ * Use the DWC_DEBUG macro to call this function+ */+extern void __DWC_DEBUG(char *format, ...)+#ifdef __GNUC__+	__attribute__ ((format(printf, 1, 2)));+#else+	;+#endif+#else+#define __DWC_DEBUG printk+#endif++/**+ * Prints out a Debug message.+ */+#define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", \+						 __func__, dwc_irq(), ## _args)+#define dwc_debug DWC_DEBUG+/**+ * Prints out a Debug message if enabled at compile time.+ */+#if DWC_OTG_DEBUG_LEV > 0+#define DWC_DEBUGC(_format, _args...) DWC_DEBUG(_format, ##_args )+#else+#define DWC_DEBUGC(_format, _args...)+#endif+#define dwc_debugc DWC_DEBUGC+/**+ * Prints out an informative message.+ */+#define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", \+					       dwc_irq(), ## _args)+#define dwc_info DWC_INFO+/**+ * Prints out an informative message if enabled at compile time.+ */+#if DWC_OTG_DEBUG_LEV > 1+#define DWC_INFOC(_format, _args...) DWC_INFO(_format, ##_args )+#else+#define DWC_INFOC(_format, _args...)+#endif+#define dwc_infoc DWC_INFOC+/**+ * Prints out a warning message.+ */+#define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", \+					dwc_irq(), __func__, __LINE__, ## _args)+#define dwc_warn DWC_WARN+/**+ * Prints out an error message.+ */+#define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", \+					dwc_irq(), __func__, __LINE__, ## _args)+#define dwc_error DWC_ERROR++#define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", \+						dwc_irq(), __func__, __LINE__, ## _args)+#define dwc_proto_error DWC_PROTO_ERROR++#ifdef DEBUG+/** Prints out a exception error message if the _expr expression fails.  Disabled+ * if DEBUG is not enabled. */+#define DWC_ASSERT(_expr, _format, _args...) do { \+	if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), \+				      __FILE__, __LINE__, ## _args); } \+	} while (0)+#else+#define DWC_ASSERT(_x...)+#endif+#define dwc_assert DWC_ASSERT+++/** @name Byte Ordering+ * The following functions are for conversions between processor's byte ordering+ * and specific ordering you want.+ */++/** Converts 32 bit data in CPU byte ordering to little endian. */+extern uint32_t DWC_CPU_TO_LE32(uint32_t *p);+#define dwc_cpu_to_le32 DWC_CPU_TO_LE32++/** Converts 32 bit data in CPU byte orderint to big endian. */+extern uint32_t DWC_CPU_TO_BE32(uint32_t *p);+#define dwc_cpu_to_be32 DWC_CPU_TO_BE32++/** Converts 32 bit little endian data to CPU byte ordering. */+extern uint32_t DWC_LE32_TO_CPU(uint32_t *p);+#define dwc_le32_to_cpu DWC_LE32_TO_CPU++/** Converts 32 bit big endian data to CPU byte ordering. */+extern uint32_t DWC_BE32_TO_CPU(uint32_t *p);+#define dwc_be32_to_cpu DWC_BE32_TO_CPU++/** Converts 16 bit data in CPU byte ordering to little endian. */+extern uint16_t DWC_CPU_TO_LE16(uint16_t *p);+#define dwc_cpu_to_le16 DWC_CPU_TO_LE16++/** Converts 16 bit data in CPU byte orderint to big endian. */+extern uint16_t DWC_CPU_TO_BE16(uint16_t *p);+#define dwc_cpu_to_be16 DWC_CPU_TO_BE16++/** Converts 16 bit little endian data to CPU byte ordering. */+extern uint16_t DWC_LE16_TO_CPU(uint16_t *p);+#define dwc_le16_to_cpu DWC_LE16_TO_CPU++/** Converts 16 bit bi endian data to CPU byte ordering. */+extern uint16_t DWC_BE16_TO_CPU(uint16_t *p);+#define dwc_be16_to_cpu DWC_BE16_TO_CPU+++/** @name Register Read/Write+ *+ * The following six functions should be implemented to read/write registers of+ * 32-bit and 64-bit sizes.  All modules use this to read/write register values.+ * The reg value is a pointer to the register calculated from the void *base+ * variable passed into the driver when it is started.  */++#ifdef DWC_LINUX+/* Linux doesn't need any extra parameters for register read/write, so we+ * just throw away the IO context parameter.+ */+/** Reads the content of a 32-bit register. */+extern uint32_t DWC_READ_REG32(uint32_t volatile *reg);+#define dwc_read_reg32(_ctx_,_reg_) DWC_READ_REG32(_reg_)++/** Reads the content of a 64-bit register. */+extern uint64_t DWC_READ_REG64(uint64_t volatile *reg);+#define dwc_read_reg64(_ctx_,_reg_) DWC_READ_REG64(_reg_)++/** Writes to a 32-bit register. */+extern void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value);+#define dwc_write_reg32(_ctx_,_reg_,_val_) DWC_WRITE_REG32(_reg_, _val_)++/** Writes to a 64-bit register. */+extern void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value);+#define dwc_write_reg64(_ctx_,_reg_,_val_) DWC_WRITE_REG64(_reg_, _val_)++/**+ * Modify bit values in a register.  Using the+ * algorithm: (reg_contents & ~clear_mask) | set_mask.+ */+extern void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);+#define dwc_modify_reg32(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG32(_reg_,_cmsk_,_smsk_)+extern void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask);+#define dwc_modify_reg64(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG64(_reg_,_cmsk_,_smsk_)++#endif	/* DWC_LINUX */++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)+typedef struct dwc_ioctx {+	struct device *dev;+	bus_space_tag_t iot;+	bus_space_handle_t ioh;+} dwc_ioctx_t;++/** BSD needs two extra parameters for register read/write, so we pass+ * them in using the IO context parameter.+ */+/** Reads the content of a 32-bit register. */+extern uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg);+#define dwc_read_reg32 DWC_READ_REG32++/** Reads the content of a 64-bit register. */+extern uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg);+#define dwc_read_reg64 DWC_READ_REG64++/** Writes to a 32-bit register. */+extern void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value);+#define dwc_write_reg32 DWC_WRITE_REG32++/** Writes to a 64-bit register. */+extern void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value);+#define dwc_write_reg64 DWC_WRITE_REG64++/**+ * Modify bit values in a register.  Using the+ * algorithm: (reg_contents & ~clear_mask) | set_mask.+ */+extern void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);+#define dwc_modify_reg32 DWC_MODIFY_REG32+extern void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask);+#define dwc_modify_reg64 DWC_MODIFY_REG64++#endif	/* DWC_FREEBSD || DWC_NETBSD */++/** @cond */++/** @name Some convenience MACROS used internally.  Define DWC_DEBUG_REGS to log the+ * register writes. */++#ifdef DWC_LINUX++# ifdef DWC_DEBUG_REGS++#define dwc_define_read_write_reg_n(_reg,_container_type) \+static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \+	return DWC_READ_REG32(&container->regs->_reg[num]); \+} \+static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \+	DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \+		  &(((uint32_t*)container->regs->_reg)[num]), data); \+	DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \+}++#define dwc_define_read_write_reg(_reg,_container_type) \+static inline uint32_t dwc_read_##_reg(_container_type *container) { \+	return DWC_READ_REG32(&container->regs->_reg); \+} \+static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \+	DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \+	DWC_WRITE_REG32(&container->regs->_reg, data); \+}++# else	/* DWC_DEBUG_REGS */++#define dwc_define_read_write_reg_n(_reg,_container_type) \+static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \+	return DWC_READ_REG32(&container->regs->_reg[num]); \+} \+static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \+	DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \+}++#define dwc_define_read_write_reg(_reg,_container_type) \+static inline uint32_t dwc_read_##_reg(_container_type *container) { \+	return DWC_READ_REG32(&container->regs->_reg); \+} \+static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \+	DWC_WRITE_REG32(&container->regs->_reg, data); \+}++# endif	/* DWC_DEBUG_REGS */++#endif	/* DWC_LINUX */++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)++# ifdef DWC_DEBUG_REGS++#define dwc_define_read_write_reg_n(_reg,_container_type) \+static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \+	return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \+} \+static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \+	DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \+		  &(((uint32_t*)container->regs->_reg)[num]), data); \+	DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \+}++#define dwc_define_read_write_reg(_reg,_container_type) \+static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \+	return DWC_READ_REG32(io_ctx, &container->regs->_reg); \+} \+static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \+	DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \+	DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \+}++# else	/* DWC_DEBUG_REGS */++#define dwc_define_read_write_reg_n(_reg,_container_type) \+static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \+	return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \+} \+static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \+	DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \+}++#define dwc_define_read_write_reg(_reg,_container_type) \+static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \+	return DWC_READ_REG32(io_ctx, &container->regs->_reg); \+} \+static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \+	DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \+}++# endif	/* DWC_DEBUG_REGS */++#endif	/* DWC_FREEBSD || DWC_NETBSD */++/** @endcond */+++#ifdef DWC_CRYPTOLIB+/** @name Crypto Functions+ *+ * These are the low-level cryptographic functions used by the driver. */++/** Perform AES CBC */+extern int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out);+#define dwc_aes_cbc DWC_AES_CBC++/** Fill the provided buffer with random bytes.  These should be cryptographic grade random numbers. */+extern void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length);+#define dwc_random_bytes DWC_RANDOM_BYTES++/** Perform the SHA-256 hash function */+extern int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out);+#define dwc_sha256 DWC_SHA256++/** Calculated the HMAC-SHA256 */+extern int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t *out);+#define dwc_hmac_sha256 DWC_HMAC_SHA256++#endif	/* DWC_CRYPTOLIB */+++/** @name Memory Allocation+ *+ * These function provide access to memory allocation.  There are only 2 DMA+ * functions and 3 Regular memory functions that need to be implemented.  None+ * of the memory debugging routines need to be implemented.  The allocation+ * routines all ZERO the contents of the memory.+ *+ * Defining DWC_DEBUG_MEMORY turns on memory debugging and statistic gathering.+ * This checks for memory leaks, keeping track of alloc/free pairs.  It also+ * keeps track of how much memory the driver is using at any given time. */++#define DWC_PAGE_SIZE 4096+#define DWC_PAGE_OFFSET(addr) (((uint32_t)addr) & 0xfff)+#define DWC_PAGE_ALIGNED(addr) ((((uint32_t)addr) & 0xfff) == 0)++#define DWC_INVALID_DMA_ADDR 0x0++#ifdef DWC_LINUX+/** Type for a DMA address */+typedef dma_addr_t dwc_dma_t;+#endif++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)+typedef bus_addr_t dwc_dma_t;+#endif++#ifdef DWC_FREEBSD+typedef struct dwc_dmactx {+	struct device *dev;+	bus_dma_tag_t dma_tag;+	bus_dmamap_t dma_map;+	bus_addr_t dma_paddr;+	void *dma_vaddr;+} dwc_dmactx_t;+#endif++#ifdef DWC_NETBSD+typedef struct dwc_dmactx {+	struct device *dev;+	bus_dma_tag_t dma_tag;+	bus_dmamap_t dma_map;+	bus_dma_segment_t segs[1];+	int nsegs;+	bus_addr_t dma_paddr;+	void *dma_vaddr;+} dwc_dmactx_t;+#endif++/* @todo these functions will be added in the future */+#if 0+/**+ * Creates a DMA pool from which you can allocate DMA buffers.  Buffers+ * allocated from this pool will be guaranteed to meet the size, alignment, and+ * boundary requirements specified.+ *+ * @param[in] size Specifies the size of the buffers that will be allocated from+ * this pool.+ * @param[in] align Specifies the byte alignment requirements of the buffers+ * allocated from this pool.  Must be a power of 2.+ * @param[in] boundary Specifies the N-byte boundary that buffers allocated from+ * this pool must not cross.+ *+ * @returns A pointer to an internal opaque structure which is not to be+ * accessed outside of these library functions.  Use this handle to specify+ * which pools to allocate/free DMA buffers from and also to destroy the pool,+ * when you are done with it.+ */+extern dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, uint32_t align, uint32_t boundary);++/**+ * Destroy a DMA pool.  All buffers allocated from that pool must be freed first.+ */+extern void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool);++/**+ * Allocate a buffer from the specified DMA pool and zeros its contents.+ */+extern void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr);++/**+ * Free a previously allocated buffer from the DMA pool.+ */+extern void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr);+#endif++/** Allocates a DMA capable buffer and zeroes its contents. */+extern void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr);++/** Allocates a DMA capable buffer and zeroes its contents in atomic contest */+extern void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr);++/** Frees a previously allocated buffer. */+extern void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr);++/** Allocates a block of memory and zeroes its contents. */+extern void *__DWC_ALLOC(void *mem_ctx, uint32_t size);++/** Allocates a block of memory and zeroes its contents, in an atomic manner+ * which can be used inside interrupt context.  The size should be sufficiently+ * small, a few KB at most, such that failures are not likely to occur.  Can just call+ * __DWC_ALLOC if it is atomic. */+extern void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size);++/** Frees a previously allocated buffer. */+extern void __DWC_FREE(void *mem_ctx, void *addr);++#ifndef DWC_DEBUG_MEMORY++#define DWC_ALLOC(_size_) __DWC_ALLOC(NULL, _size_)+#define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(NULL, _size_)+#define DWC_FREE(_addr_) __DWC_FREE(NULL, _addr_)++# ifdef DWC_LINUX+#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(NULL, _size_, _dma_)+#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(NULL, _size_,_dma_)+#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(NULL, _size_, _virt_, _dma_)+# endif++# if defined(DWC_FREEBSD) || defined(DWC_NETBSD)+#define DWC_DMA_ALLOC __DWC_DMA_ALLOC+#define DWC_DMA_FREE __DWC_DMA_FREE+# endif+extern void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line);++#else	/* DWC_DEBUG_MEMORY */++extern void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line);+extern void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, int line);+extern void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line);+extern void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,+				 char const *func, int line);+extern void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,+				char const *func, int line);+extern void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr,+			       dwc_dma_t dma_addr, char const *func, int line);++extern int dwc_memory_debug_start(void *mem_ctx);+extern void dwc_memory_debug_stop(void);+extern void dwc_memory_debug_report(void);++#define DWC_ALLOC(_size_) dwc_alloc_debug(NULL, _size_, __func__, __LINE__)+#define DWC_ALLOC_ATOMIC(_size_) dwc_alloc_atomic_debug(NULL, _size_, \+							__func__, __LINE__)+#define DWC_FREE(_addr_) dwc_free_debug(NULL, _addr_, __func__, __LINE__)++# ifdef DWC_LINUX+#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(NULL, _size_, \+						_dma_, __func__, __LINE__)+#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(NULL, _size_, \+						_dma_, __func__, __LINE__)+#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(NULL, _size_, \+						_virt_, _dma_, __func__, __LINE__)+# endif++# if defined(DWC_FREEBSD) || defined(DWC_NETBSD)+#define DWC_DMA_ALLOC(_ctx_,_size_,_dma_) dwc_dma_alloc_debug(_ctx_, _size_, \+						_dma_, __func__, __LINE__)+#define DWC_DMA_FREE(_ctx_,_size_,_virt_,_dma_) dwc_dma_free_debug(_ctx_, _size_, \+						 _virt_, _dma_, __func__, __LINE__)+# endif++#endif /* DWC_DEBUG_MEMORY */++#define dwc_alloc(_ctx_,_size_) DWC_ALLOC(_size_)+#define dwc_alloc_atomic(_ctx_,_size_) DWC_ALLOC_ATOMIC(_size_)+#define dwc_free(_ctx_,_addr_) DWC_FREE(_addr_)++#ifdef DWC_LINUX+/* Linux doesn't need any extra parameters for DMA buffer allocation, so we+ * just throw away the DMA context parameter.+ */+#define dwc_dma_alloc(_ctx_,_size_,_dma_) DWC_DMA_ALLOC(_size_, _dma_)+#define dwc_dma_alloc_atomic(_ctx_,_size_,_dma_) DWC_DMA_ALLOC_ATOMIC(_size_, _dma_)+#define dwc_dma_free(_ctx_,_size_,_virt_,_dma_) DWC_DMA_FREE(_size_, _virt_, _dma_)+#endif++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)+/** BSD needs several extra parameters for DMA buffer allocation, so we pass+ * them in using the DMA context parameter.+ */+#define dwc_dma_alloc DWC_DMA_ALLOC+#define dwc_dma_free DWC_DMA_FREE+#endif+++/** @name Memory and String Processing */++/** memset() clone */+extern void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size);+#define dwc_memset DWC_MEMSET++/** memcpy() clone */+extern void *DWC_MEMCPY(void *dest, void const *src, uint32_t size);+#define dwc_memcpy DWC_MEMCPY++/** memmove() clone */+extern void *DWC_MEMMOVE(void *dest, void *src, uint32_t size);+#define dwc_memmove DWC_MEMMOVE++/** memcmp() clone */+extern int DWC_MEMCMP(void *m1, void *m2, uint32_t size);+#define dwc_memcmp DWC_MEMCMP++/** strcmp() clone */+extern int DWC_STRCMP(void *s1, void *s2);+#define dwc_strcmp DWC_STRCMP++/** strncmp() clone */+extern int DWC_STRNCMP(void *s1, void *s2, uint32_t size);+#define dwc_strncmp DWC_STRNCMP++/** strlen() clone, for NULL terminated ASCII strings */+extern int DWC_STRLEN(char const *str);+#define dwc_strlen DWC_STRLEN++/** strcpy() clone, for NULL terminated ASCII strings */+extern char *DWC_STRCPY(char *to, const char *from);+#define dwc_strcpy DWC_STRCPY++/** strdup() clone.  If you wish to use memory allocation debugging, this+ * implementation of strdup should use the DWC_* memory routines instead of+ * calling a predefined strdup.  Otherwise the memory allocated by this routine+ * will not be seen by the debugging routines. */+extern char *DWC_STRDUP(char const *str);+#define dwc_strdup(_ctx_,_str_) DWC_STRDUP(_str_)++/** NOT an atoi() clone.  Read the description carefully.  Returns an integer+ * converted from the string str in base 10 unless the string begins with a "0x"+ * in which case it is base 16.  String must be a NULL terminated sequence of+ * ASCII characters and may optionally begin with whitespace, a + or -, and a+ * "0x" prefix if base 16.  The remaining characters must be valid digits for+ * the number and end with a NULL character.  If any invalid characters are+ * encountered or it returns with a negative error code and the results of the+ * conversion are undefined.  On sucess it returns 0.  Overflow conditions are+ * undefined.  An example implementation using atoi() can be referenced from the+ * Linux implementation. */+extern int DWC_ATOI(const char *str, int32_t *value);+#define dwc_atoi DWC_ATOI++/** Same as above but for unsigned. */+extern int DWC_ATOUI(const char *str, uint32_t *value);+#define dwc_atoui DWC_ATOUI++#ifdef DWC_UTFLIB+/** This routine returns a UTF16LE unicode encoded string from a UTF8 string. */+extern int DWC_UTF8_TO_UTF16LE(uint8_t const *utf8string, uint16_t *utf16string, unsigned len);+#define dwc_utf8_to_utf16le DWC_UTF8_TO_UTF16LE+#endif+++/** @name Wait queues+ *+ * Wait queues provide a means of synchronizing between threads or processes.  A+ * process can block on a waitq if some condition is not true, waiting for it to+ * become true.  When the waitq is triggered all waiting process will get+ * unblocked and the condition will be check again.  Waitqs should be triggered+ * every time a condition can potentially change.*/+struct dwc_waitq;++/** Type for a waitq */+typedef struct dwc_waitq dwc_waitq_t;++/** The type of waitq condition callback function.  This is called every time+ * condition is evaluated. */+typedef int (*dwc_waitq_condition_t)(void *data);++/** Allocate a waitq */+extern dwc_waitq_t *DWC_WAITQ_ALLOC(void);+#define dwc_waitq_alloc(_ctx_) DWC_WAITQ_ALLOC()++/** Free a waitq */+extern void DWC_WAITQ_FREE(dwc_waitq_t *wq);+#define dwc_waitq_free DWC_WAITQ_FREE++/** Check the condition and if it is false, block on the waitq.  When unblocked, check the+ * condition again.  The function returns when the condition becomes true.  The return value+ * is 0 on condition true, DWC_WAITQ_ABORTED on abort or killed, or DWC_WAITQ_UNKNOWN on error. */+extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data);+#define dwc_waitq_wait DWC_WAITQ_WAIT++/** Check the condition and if it is false, block on the waitq.  When unblocked,+ * check the condition again.  The function returns when the condition become+ * true or the timeout has passed.  The return value is 0 on condition true or+ * DWC_TIMED_OUT on timeout, or DWC_WAITQ_ABORTED, or DWC_WAITQ_UNKNOWN on+ * error. */+extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,+				      void *data, int32_t msecs);+#define dwc_waitq_wait_timeout DWC_WAITQ_WAIT_TIMEOUT++/** Trigger a waitq, unblocking all processes.  This should be called whenever a condition+ * has potentially changed. */+extern void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq);+#define dwc_waitq_trigger DWC_WAITQ_TRIGGER++/** Unblock all processes waiting on the waitq with an ABORTED result. */+extern void DWC_WAITQ_ABORT(dwc_waitq_t *wq);+#define dwc_waitq_abort DWC_WAITQ_ABORT+++/** @name Threads+ *+ * A thread must be explicitly stopped.  It must check DWC_THREAD_SHOULD_STOP+ * whenever it is woken up, and then return.  The DWC_THREAD_STOP function+ * returns the value from the thread.+ */++struct dwc_thread;++/** Type for a thread */+typedef struct dwc_thread dwc_thread_t;++/** The thread function */+typedef int (*dwc_thread_function_t)(void *data);++/** Create a thread and start it running the thread_function.  Returns a handle+ * to the thread */+extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data);+#define dwc_thread_run(_ctx_,_func_,_name_,_data_) DWC_THREAD_RUN(_func_, _name_, _data_)++/** Stops a thread.  Return the value returned by the thread.  Or will return+ * DWC_ABORT if the thread never started. */+extern int DWC_THREAD_STOP(dwc_thread_t *thread);+#define dwc_thread_stop DWC_THREAD_STOP++/** Signifies to the thread that it must stop. */+#ifdef DWC_LINUX+/* Linux doesn't need any parameters for kthread_should_stop() */+extern dwc_bool_t DWC_THREAD_SHOULD_STOP(void);+#define dwc_thread_should_stop(_thrd_) DWC_THREAD_SHOULD_STOP()++/* No thread_exit function in Linux */+#define dwc_thread_exit(_thrd_)+#endif++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)+/** BSD needs the thread pointer for kthread_suspend_check() */+extern dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread);+#define dwc_thread_should_stop DWC_THREAD_SHOULD_STOP++/** The thread must call this to exit. */+extern void DWC_THREAD_EXIT(dwc_thread_t *thread);+#define dwc_thread_exit DWC_THREAD_EXIT+#endif+++/** @name Work queues+ *+ * Workqs are used to queue a callback function to be called at some later time,+ * in another thread. */+struct dwc_workq;++/** Type for a workq */+typedef struct dwc_workq dwc_workq_t;++/** The type of the callback function to be called. */+typedef void (*dwc_work_callback_t)(void *data);++/** Allocate a workq */+extern dwc_workq_t *DWC_WORKQ_ALLOC(char *name);+#define dwc_workq_alloc(_ctx_,_name_) DWC_WORKQ_ALLOC(_name_)++/** Free a workq.  All work must be completed before being freed. */+extern void DWC_WORKQ_FREE(dwc_workq_t *workq);+#define dwc_workq_free DWC_WORKQ_FREE++/** Schedule a callback on the workq, passing in data.  The function will be+ * scheduled at some later time. */+extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t cb,+			       void *data, char *format, ...)+#ifdef __GNUC__+	__attribute__ ((format(printf, 4, 5)));+#else+	;+#endif+#define dwc_workq_schedule DWC_WORKQ_SCHEDULE++/** Schedule a callback on the workq, that will be called until at least+ * given number miliseconds have passed. */+extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t cb,+				       void *data, uint32_t time, char *format, ...)+#ifdef __GNUC__+	__attribute__ ((format(printf, 5, 6)));+#else+	;+#endif+#define dwc_workq_schedule_delayed DWC_WORKQ_SCHEDULE_DELAYED++/** The number of processes in the workq */+extern int DWC_WORKQ_PENDING(dwc_workq_t *workq);+#define dwc_workq_pending DWC_WORKQ_PENDING++/** Blocks until all the work in the workq is complete or timed out.  Returns <+ * 0 on timeout. */+extern int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout);+#define dwc_workq_wait_work_done DWC_WORKQ_WAIT_WORK_DONE+++/** @name Tasklets+ *+ */+struct dwc_tasklet;++/** Type for a tasklet */+typedef struct dwc_tasklet dwc_tasklet_t;++/** The type of the callback function to be called */+typedef void (*dwc_tasklet_callback_t)(void *data);++/** Allocates a tasklet */+extern dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data);+#define dwc_task_alloc(_ctx_,_name_,_cb_,_data_) DWC_TASK_ALLOC(_name_, _cb_, _data_)++/** Frees a tasklet */+extern void DWC_TASK_FREE(dwc_tasklet_t *task);+#define dwc_task_free DWC_TASK_FREE++/** Schedules a tasklet to run */+extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task);+#define dwc_task_schedule DWC_TASK_SCHEDULE++extern void DWC_TASK_HI_SCHEDULE(dwc_tasklet_t *task);+#define dwc_task_hi_schedule DWC_TASK_HI_SCHEDULE++/** @name Timer+ *+ * Callbacks must be small and atomic.+ */+struct dwc_timer;++/** Type for a timer */+typedef struct dwc_timer dwc_timer_t;++/** The type of the callback function to be called */+typedef void (*dwc_timer_callback_t)(void *data);++/** Allocates a timer */+extern dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data);+#define dwc_timer_alloc(_ctx_,_name_,_cb_,_data_) DWC_TIMER_ALLOC(_name_,_cb_,_data_)++/** Frees a timer */+extern void DWC_TIMER_FREE(dwc_timer_t *timer);+#define dwc_timer_free DWC_TIMER_FREE++/** Schedules the timer to run at time ms from now.  And will repeat at every+ * repeat_interval msec therafter+ *+ * Modifies a timer that is still awaiting execution to a new expiration time.+ * The mod_time is added to the old time.  */+extern void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time);+#define dwc_timer_schedule DWC_TIMER_SCHEDULE++/** Disables the timer from execution. */+extern void DWC_TIMER_CANCEL(dwc_timer_t *timer);+#define dwc_timer_cancel DWC_TIMER_CANCEL+++/** @name Spinlocks+ *+ * These locks are used when the work between the lock/unlock is atomic and+ * short.  Interrupts are also disabled during the lock/unlock and thus they are+ * suitable to lock between interrupt/non-interrupt context.  They also lock+ * between processes if you have multiple CPUs or Preemption.  If you don't have+ * multiple CPUS or Preemption, then the you can simply implement the+ * DWC_SPINLOCK and DWC_SPINUNLOCK to disable and enable interrupts.  Because+ * the work between the lock/unlock is atomic, the process context will never+ * change, and so you never have to lock between processes.  */++struct dwc_spinlock;++/** Type for a spinlock */+typedef struct dwc_spinlock dwc_spinlock_t;++/** Type for the 'flags' argument to spinlock funtions */+typedef unsigned long dwc_irqflags_t;++/** Returns an initialized lock variable.  This function should allocate and+ * initialize the OS-specific data structure used for locking.  This data+ * structure is to be used for the DWC_LOCK and DWC_UNLOCK functions and should+ * be freed by the DWC_FREE_LOCK when it is no longer used. */+extern dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void);+#define dwc_spinlock_alloc(_ctx_) DWC_SPINLOCK_ALLOC()++/** Frees an initialized lock variable. */+extern void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock);+#define dwc_spinlock_free(_ctx_,_lock_) DWC_SPINLOCK_FREE(_lock_)++/** Disables interrupts and blocks until it acquires the lock.+ *+ * @param lock Pointer to the spinlock.+ * @param flags Unsigned long for irq flags storage.+ */+extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags);+#define dwc_spinlock_irqsave DWC_SPINLOCK_IRQSAVE++/** Re-enables the interrupt and releases the lock.+ *+ * @param lock Pointer to the spinlock.+ * @param flags Unsigned long for irq flags storage.  Must be the same as was+ * passed into DWC_LOCK.+ */+extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags);+#define dwc_spinunlock_irqrestore DWC_SPINUNLOCK_IRQRESTORE++/** Blocks until it acquires the lock.+ *+ * @param lock Pointer to the spinlock.+ */+extern void DWC_SPINLOCK(dwc_spinlock_t *lock);+#define dwc_spinlock DWC_SPINLOCK++/** Releases the lock.+ *+ * @param lock Pointer to the spinlock.+ */+extern void DWC_SPINUNLOCK(dwc_spinlock_t *lock);+#define dwc_spinunlock DWC_SPINUNLOCK+++/** @name Mutexes+ *+ * Unlike spinlocks Mutexes lock only between processes and the work between the+ * lock/unlock CAN block, therefore it CANNOT be called from interrupt context.+ */++struct dwc_mutex;++/** Type for a mutex */+typedef struct dwc_mutex dwc_mutex_t;++/* For Linux Mutex Debugging make it inline because the debugging routines use+ * the symbol to determine recursive locking.  This makes it falsely think+ * recursive locking occurs. */+#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)+#define DWC_MUTEX_ALLOC_LINUX_DEBUG(__mutexp) ({ \+	__mutexp = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); \+	mutex_init((struct mutex *)__mutexp); \+})+#endif++/** Allocate a mutex */+extern dwc_mutex_t *DWC_MUTEX_ALLOC(void);+#define dwc_mutex_alloc(_ctx_) DWC_MUTEX_ALLOC()++/* For memory leak debugging when using Linux Mutex Debugging */+#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)+#define DWC_MUTEX_FREE(__mutexp) do { \+	mutex_destroy((struct mutex *)__mutexp); \+	DWC_FREE(__mutexp); \+} while(0)+#else+/** Free a mutex */+extern void DWC_MUTEX_FREE(dwc_mutex_t *mutex);+#define dwc_mutex_free(_ctx_,_mutex_) DWC_MUTEX_FREE(_mutex_)+#endif++/** Lock a mutex */+extern void DWC_MUTEX_LOCK(dwc_mutex_t *mutex);+#define dwc_mutex_lock DWC_MUTEX_LOCK++/** Non-blocking lock returns 1 on successful lock. */+extern int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex);+#define dwc_mutex_trylock DWC_MUTEX_TRYLOCK++/** Unlock a mutex */+extern void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex);+#define dwc_mutex_unlock DWC_MUTEX_UNLOCK+++/** @name Time */++/** Microsecond delay.+ *+ * @param usecs  Microseconds to delay.+ */+extern void DWC_UDELAY(uint32_t usecs);+#define dwc_udelay DWC_UDELAY++/** Millisecond delay.+ *+ * @param msecs  Milliseconds to delay.+ */+extern void DWC_MDELAY(uint32_t msecs);+#define dwc_mdelay DWC_MDELAY++/** Non-busy waiting.+ * Sleeps for specified number of milliseconds.+ *+ * @param msecs Milliseconds to sleep.+ */+extern void DWC_MSLEEP(uint32_t msecs);+#define dwc_msleep DWC_MSLEEP++/**+ * Returns number of milliseconds since boot.+ */+extern uint32_t DWC_TIME(void);+#define dwc_time DWC_TIME+++++/* @mainpage DWC Portability and Common Library+ *+ * This is the documentation for the DWC Portability and Common Library.+ *+ * @section intro Introduction+ *+ * The DWC Portability library consists of wrapper calls and data structures to+ * all low-level functions which are typically provided by the OS.  The WUDEV+ * driver uses only these functions.  In order to port the WUDEV driver, only+ * the functions in this library need to be re-implemented, with the same+ * behavior as documented here.+ *+ * The Common library consists of higher level functions, which rely only on+ * calling the functions from the DWC Portability library.  These common+ * routines are shared across modules.  Some of the common libraries need to be+ * used directly by the driver programmer when porting WUDEV.  Such as the+ * parameter and notification libraries.+ *+ * @section low Portability Library OS Wrapper Functions+ *+ * Any function starting with DWC and in all CAPS is a low-level OS-wrapper that+ * needs to be implemented when porting, for example DWC_MUTEX_ALLOC().  All of+ * these functions are included in the dwc_os.h file.+ *+ * There are many functions here covering a wide array of OS services.  Please+ * see dwc_os.h for details, and implementation notes for each function.+ *+ * @section common Common Library Functions+ *+ * Any function starting with dwc and in all lowercase is a common library+ * routine.  These functions have a portable implementation and do not need to+ * be reimplemented when porting.  The common routines can be used by any+ * driver, and some must be used by the end user to control the drivers.  For+ * example, you must use the Parameter common library in order to set the+ * parameters in the WUDEV module.+ *+ * The common libraries consist of the following:+ *+ * - Connection Contexts - Used internally and can be used by end-user.  See dwc_cc.h+ * - Parameters - Used internally and can be used by end-user.  See dwc_params.h+ * - Notifications - Used internally and can be used by end-user.  See dwc_notifier.h+ * - Lists - Used internally and can be used by end-user.  See dwc_list.h+ * - Memory Debugging - Used internally and can be used by end-user.  See dwc_os.h+ * - Modpow - Used internally only.  See dwc_modpow.h+ * - DH - Used internally only.  See dwc_dh.h+ * - Crypto - Used internally only.  See dwc_crypto.h+ *+ *+ * @section prereq Prerequistes For dwc_os.h+ * @subsection types Data Types+ *+ * The dwc_os.h file assumes that several low-level data types are pre defined for the+ * compilation environment.  These data types are:+ *+ * - uint8_t - unsigned 8-bit data type+ * - int8_t - signed 8-bit data type+ * - uint16_t - unsigned 16-bit data type+ * - int16_t - signed 16-bit data type+ * - uint32_t - unsigned 32-bit data type+ * - int32_t - signed 32-bit data type+ * - uint64_t - unsigned 64-bit data type+ * - int64_t - signed 64-bit data type+ *+ * Ensure that these are defined before using dwc_os.h.  The easiest way to do+ * that is to modify the top of the file to include the appropriate header.+ * This is already done for the Linux environment.  If the DWC_LINUX macro is+ * defined, the correct header will be added.  A standard header <stdint.h> is+ * also used for environments where standard C headers are available.+ *+ * @subsection stdarg Variable Arguments+ *+ * Variable arguments are provided by a standard C header <stdarg.h>.  it is+ * available in Both the Linux and ANSI C enviornment.  An equivalent must be+ * provided in your enviornment in order to use dwc_os.h with the debug and+ * tracing message functionality.+ *+ * @subsection thread Threading+ *+ * WUDEV Core must be run on an operating system that provides for multiple+ * threads/processes.  Threading can be implemented in many ways, even in+ * embedded systems without an operating system.  At the bare minimum, the+ * system should be able to start any number of processes at any time to handle+ * special work.  It need not be a pre-emptive system.  Process context can+ * change upon a call to a blocking function.  The hardware interrupt context+ * that calls the module's ISR() function must be differentiable from process+ * context, even if your processes are impemented via a hardware interrupt.+ * Further locking mechanism between process must exist (or be implemented), and+ * process context must have a way to disable interrupts for a period of time to+ * lock them out.  If all of this exists, the functions in dwc_os.h related to+ * threading should be able to be implemented with the defined behavior.+ *+ */++#ifdef __cplusplus+}+#endif++#endif /* _DWC_OS_H_ */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/Makefile linux-3.11.10/drivers/usb/host/dwc_common_port/Makefile--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/Makefile	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/Makefile	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,58 @@+#+# Makefile for DWC_common library+#++ifneq ($(KERNELRELEASE),)++EXTRA_CFLAGS	+= -DDWC_LINUX+#EXTRA_CFLAGS	+= -DDEBUG+#EXTRA_CFLAGS	+= -DDWC_DEBUG_REGS+#EXTRA_CFLAGS	+= -DDWC_DEBUG_MEMORY++EXTRA_CFLAGS	+= -DDWC_LIBMODULE+EXTRA_CFLAGS	+= -DDWC_CCLIB+#EXTRA_CFLAGS	+= -DDWC_CRYPTOLIB+EXTRA_CFLAGS	+= -DDWC_NOTIFYLIB+EXTRA_CFLAGS	+= -DDWC_UTFLIB++obj-$(CONFIG_USB_DWCOTG)	+= dwc_common_port_lib.o+dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \+			    dwc_crypto.o dwc_notifier.o \+			    dwc_common_linux.o dwc_mem.o++kernrelwd := $(subst ., ,$(KERNELRELEASE))+kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))++ifneq ($(kernrel3),2.6.20)+# grayg - I only know that we use EXTRA_CFLAGS in 2.6.31 actually+EXTRA_CFLAGS += $(CPPFLAGS)+endif++else++#ifeq ($(KDIR),)+#$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment)+#endif++ifeq ($(ARCH),)+$(error Must give "ARCH=<arch>" on command line or in environment. Also, if \+ cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-")+endif++ifeq ($(DOXYGEN),)+DOXYGEN		:= doxygen+endif++default:+	$(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules++docs:	$(wildcard *.[hc]) doc/doxygen.cfg+	$(DOXYGEN) doc/doxygen.cfg++tags:	$(wildcard *.[hc])+	$(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)++endif++clean:+	rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/Makefile.fbsd linux-3.11.10/drivers/usb/host/dwc_common_port/Makefile.fbsd--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/Makefile.fbsd	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/Makefile.fbsd	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,17 @@+CFLAGS	+= -I/sys/i386/compile/GENERIC -I/sys/i386/include -I/usr/include+CFLAGS	+= -DDWC_FREEBSD+CFLAGS	+= -DDEBUG+#CFLAGS	+= -DDWC_DEBUG_REGS+#CFLAGS	+= -DDWC_DEBUG_MEMORY++#CFLAGS	+= -DDWC_LIBMODULE+#CFLAGS	+= -DDWC_CCLIB+#CFLAGS	+= -DDWC_CRYPTOLIB+#CFLAGS	+= -DDWC_NOTIFYLIB+#CFLAGS	+= -DDWC_UTFLIB++KMOD = dwc_common_port_lib+SRCS = dwc_cc.c dwc_modpow.c dwc_dh.c dwc_crypto.c dwc_notifier.c \+       dwc_common_fbsd.c dwc_mem.c++.include <bsd.kmod.mk>diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/Makefile.linux linux-3.11.10/drivers/usb/host/dwc_common_port/Makefile.linux--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/Makefile.linux	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/Makefile.linux	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,49 @@+#+# Makefile for DWC_common library+#+ifneq ($(KERNELRELEASE),)++EXTRA_CFLAGS	+= -DDWC_LINUX+#EXTRA_CFLAGS	+= -DDEBUG+#EXTRA_CFLAGS	+= -DDWC_DEBUG_REGS+#EXTRA_CFLAGS	+= -DDWC_DEBUG_MEMORY++EXTRA_CFLAGS	+= -DDWC_LIBMODULE+EXTRA_CFLAGS	+= -DDWC_CCLIB+EXTRA_CFLAGS	+= -DDWC_CRYPTOLIB+EXTRA_CFLAGS	+= -DDWC_NOTIFYLIB+EXTRA_CFLAGS	+= -DDWC_UTFLIB++obj-m			 := dwc_common_port_lib.o+dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \+			    dwc_crypto.o dwc_notifier.o \+			    dwc_common_linux.o dwc_mem.o++else++ifeq ($(KDIR),)+$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment)+endif++ifeq ($(ARCH),)+$(error Must give "ARCH=<arch>" on command line or in environment. Also, if \+ cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-")+endif++ifeq ($(DOXYGEN),)+DOXYGEN		:= doxygen+endif++default:+	$(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules++docs:	$(wildcard *.[hc]) doc/doxygen.cfg+	$(DOXYGEN) doc/doxygen.cfg++tags:	$(wildcard *.[hc])+	$(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)++endif++clean:+	rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_common_port/usb.h linux-3.11.10/drivers/usb/host/dwc_common_port/usb.h--- linux-3.11.10.orig/drivers/usb/host/dwc_common_port/usb.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_common_port/usb.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,946 @@+/*+ * Copyright (c) 1998 The NetBSD Foundation, Inc.+ * All rights reserved.+ *+ * This code is derived from software contributed to The NetBSD Foundation+ * by Lennart Augustsson (lennart@augustsson.net) at+ * Carlstedt Research & Technology.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. All advertising materials mentioning features or use of this software+ *    must display the following acknowledgement:+ *        This product includes software developed by the NetBSD+ *        Foundation, Inc. and its contributors.+ * 4. Neither the name of The NetBSD Foundation nor the names of its+ *    contributors may be used to endorse or promote products derived+ *    from this software without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+ * POSSIBILITY OF SUCH DAMAGE.+ */++/* Modified by Synopsys, Inc, 12/12/2007 */+++#ifndef _USB_H_+#define _USB_H_++#ifdef __cplusplus+extern "C" {+#endif++/*+ * The USB records contain some unaligned little-endian word+ * components.  The U[SG]ETW macros take care of both the alignment+ * and endian problem and should always be used to access non-byte+ * values.+ */+typedef u_int8_t uByte;+typedef u_int8_t uWord[2];+typedef u_int8_t uDWord[4];++#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h))+#define UCONSTW(x)	{ (x) & 0xff, ((x) >> 8) & 0xff }+#define UCONSTDW(x)	{ (x) & 0xff, ((x) >> 8) & 0xff, \+			  ((x) >> 16) & 0xff, ((x) >> 24) & 0xff }++#if 1+#define UGETW(w) ((w)[0] | ((w)[1] << 8))+#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8))+#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24))+#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \+		     (w)[1] = (u_int8_t)((v) >> 8), \+		     (w)[2] = (u_int8_t)((v) >> 16), \+		     (w)[3] = (u_int8_t)((v) >> 24))+#else+/*+ * On little-endian machines that can handle unanliged accesses+ * (e.g. i386) these macros can be replaced by the following.+ */+#define UGETW(w) (*(u_int16_t *)(w))+#define USETW(w,v) (*(u_int16_t *)(w) = (v))+#define UGETDW(w) (*(u_int32_t *)(w))+#define USETDW(w,v) (*(u_int32_t *)(w) = (v))+#endif++/*+ * Macros for accessing UAS IU fields, which are big-endian+ */+#define IUSETW2(w,h,l) ((w)[0] = (u_int8_t)(h), (w)[1] = (u_int8_t)(l))+#define IUCONSTW(x)	{ ((x) >> 8) & 0xff, (x) & 0xff }+#define IUCONSTDW(x)	{ ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \+			((x) >> 8) & 0xff, (x) & 0xff }+#define IUGETW(w) (((w)[0] << 8) | (w)[1])+#define IUSETW(w,v) ((w)[0] = (u_int8_t)((v) >> 8), (w)[1] = (u_int8_t)(v))+#define IUGETDW(w) (((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3])+#define IUSETDW(w,v) ((w)[0] = (u_int8_t)((v) >> 24), \+		      (w)[1] = (u_int8_t)((v) >> 16), \+		      (w)[2] = (u_int8_t)((v) >> 8), \+		      (w)[3] = (u_int8_t)(v))++#define UPACKED __attribute__((__packed__))++typedef struct {+	uByte		bmRequestType;+	uByte		bRequest;+	uWord		wValue;+	uWord		wIndex;+	uWord		wLength;+} UPACKED usb_device_request_t;++#define UT_GET_DIR(a) ((a) & 0x80)+#define UT_WRITE		0x00+#define UT_READ			0x80++#define UT_GET_TYPE(a) ((a) & 0x60)+#define UT_STANDARD		0x00+#define UT_CLASS		0x20+#define UT_VENDOR		0x40++#define UT_GET_RECIPIENT(a) ((a) & 0x1f)+#define UT_DEVICE		0x00+#define UT_INTERFACE		0x01+#define UT_ENDPOINT		0x02+#define UT_OTHER		0x03++#define UT_READ_DEVICE		(UT_READ  | UT_STANDARD | UT_DEVICE)+#define UT_READ_INTERFACE	(UT_READ  | UT_STANDARD | UT_INTERFACE)+#define UT_READ_ENDPOINT	(UT_READ  | UT_STANDARD | UT_ENDPOINT)+#define UT_WRITE_DEVICE		(UT_WRITE | UT_STANDARD | UT_DEVICE)+#define UT_WRITE_INTERFACE	(UT_WRITE | UT_STANDARD | UT_INTERFACE)+#define UT_WRITE_ENDPOINT	(UT_WRITE | UT_STANDARD | UT_ENDPOINT)+#define UT_READ_CLASS_DEVICE	(UT_READ  | UT_CLASS | UT_DEVICE)+#define UT_READ_CLASS_INTERFACE	(UT_READ  | UT_CLASS | UT_INTERFACE)+#define UT_READ_CLASS_OTHER	(UT_READ  | UT_CLASS | UT_OTHER)+#define UT_READ_CLASS_ENDPOINT	(UT_READ  | UT_CLASS | UT_ENDPOINT)+#define UT_WRITE_CLASS_DEVICE	(UT_WRITE | UT_CLASS | UT_DEVICE)+#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE)+#define UT_WRITE_CLASS_OTHER	(UT_WRITE | UT_CLASS | UT_OTHER)+#define UT_WRITE_CLASS_ENDPOINT	(UT_WRITE | UT_CLASS | UT_ENDPOINT)+#define UT_READ_VENDOR_DEVICE	(UT_READ  | UT_VENDOR | UT_DEVICE)+#define UT_READ_VENDOR_INTERFACE (UT_READ  | UT_VENDOR | UT_INTERFACE)+#define UT_READ_VENDOR_OTHER	(UT_READ  | UT_VENDOR | UT_OTHER)+#define UT_READ_VENDOR_ENDPOINT	(UT_READ  | UT_VENDOR | UT_ENDPOINT)+#define UT_WRITE_VENDOR_DEVICE	(UT_WRITE | UT_VENDOR | UT_DEVICE)+#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE)+#define UT_WRITE_VENDOR_OTHER	(UT_WRITE | UT_VENDOR | UT_OTHER)+#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT)++/* Requests */+#define UR_GET_STATUS		0x00+#define  USTAT_STANDARD_STATUS  0x00+#define  WUSTAT_WUSB_FEATURE    0x01+#define  WUSTAT_CHANNEL_INFO    0x02+#define  WUSTAT_RECEIVED_DATA   0x03+#define  WUSTAT_MAS_AVAILABILITY 0x04+#define  WUSTAT_CURRENT_TRANSMIT_POWER 0x05+#define UR_CLEAR_FEATURE	0x01+#define UR_SET_FEATURE		0x03+#define UR_SET_AND_TEST_FEATURE 0x0c+#define UR_SET_ADDRESS		0x05+#define UR_GET_DESCRIPTOR	0x06+#define  UDESC_DEVICE		0x01+#define  UDESC_CONFIG		0x02+#define  UDESC_STRING		0x03+#define  UDESC_INTERFACE	0x04+#define  UDESC_ENDPOINT		0x05+#define  UDESC_SS_USB_COMPANION	0x30+#define  UDESC_DEVICE_QUALIFIER	0x06+#define  UDESC_OTHER_SPEED_CONFIGURATION 0x07+#define  UDESC_INTERFACE_POWER	0x08+#define  UDESC_OTG		0x09+#define  WUDESC_SECURITY	0x0c+#define  WUDESC_KEY		0x0d+#define   WUD_GET_KEY_INDEX(_wValue_) ((_wValue_) & 0xf)+#define   WUD_GET_KEY_TYPE(_wValue_) (((_wValue_) & 0x30) >> 4)+#define    WUD_KEY_TYPE_ASSOC    0x01+#define    WUD_KEY_TYPE_GTK      0x02+#define   WUD_GET_KEY_ORIGIN(_wValue_) (((_wValue_) & 0x40) >> 6)+#define    WUD_KEY_ORIGIN_HOST   0x00+#define    WUD_KEY_ORIGIN_DEVICE 0x01+#define  WUDESC_ENCRYPTION_TYPE	0x0e+#define  WUDESC_BOS		0x0f+#define  WUDESC_DEVICE_CAPABILITY 0x10+#define  WUDESC_WIRELESS_ENDPOINT_COMPANION 0x11+#define  UDESC_BOS		0x0f+#define  UDESC_DEVICE_CAPABILITY 0x10+#define  UDESC_CS_DEVICE	0x21	/* class specific */+#define  UDESC_CS_CONFIG	0x22+#define  UDESC_CS_STRING	0x23+#define  UDESC_CS_INTERFACE	0x24+#define  UDESC_CS_ENDPOINT	0x25+#define  UDESC_HUB		0x29+#define UR_SET_DESCRIPTOR	0x07+#define UR_GET_CONFIG		0x08+#define UR_SET_CONFIG		0x09+#define UR_GET_INTERFACE	0x0a+#define UR_SET_INTERFACE	0x0b+#define UR_SYNCH_FRAME		0x0c+#define WUR_SET_ENCRYPTION      0x0d+#define WUR_GET_ENCRYPTION	0x0e+#define WUR_SET_HANDSHAKE	0x0f+#define WUR_GET_HANDSHAKE	0x10+#define WUR_SET_CONNECTION	0x11+#define WUR_SET_SECURITY_DATA	0x12+#define WUR_GET_SECURITY_DATA	0x13+#define WUR_SET_WUSB_DATA	0x14+#define  WUDATA_DRPIE_INFO	0x01+#define  WUDATA_TRANSMIT_DATA	0x02+#define  WUDATA_TRANSMIT_PARAMS	0x03+#define  WUDATA_RECEIVE_PARAMS	0x04+#define  WUDATA_TRANSMIT_POWER	0x05+#define WUR_LOOPBACK_DATA_WRITE	0x15+#define WUR_LOOPBACK_DATA_READ	0x16+#define WUR_SET_INTERFACE_DS	0x17++/* Feature numbers */+#define UF_ENDPOINT_HALT	0+#define UF_DEVICE_REMOTE_WAKEUP	1+#define UF_TEST_MODE		2+#define UF_DEVICE_B_HNP_ENABLE	3+#define UF_DEVICE_A_HNP_SUPPORT	4+#define UF_DEVICE_A_ALT_HNP_SUPPORT 5+#define WUF_WUSB		3+#define  WUF_TX_DRPIE		0x0+#define  WUF_DEV_XMIT_PACKET	0x1+#define  WUF_COUNT_PACKETS	0x2+#define  WUF_CAPTURE_PACKETS	0x3+#define UF_FUNCTION_SUSPEND	0+#define UF_U1_ENABLE		48+#define UF_U2_ENABLE		49+#define UF_LTM_ENABLE		50++/* Class requests from the USB 2.0 hub spec, table 11-15 */+#define UCR_CLEAR_HUB_FEATURE		(0x2000 | UR_CLEAR_FEATURE)+#define UCR_CLEAR_PORT_FEATURE		(0x2300 | UR_CLEAR_FEATURE)+#define UCR_GET_HUB_DESCRIPTOR		(0xa000 | UR_GET_DESCRIPTOR)+#define UCR_GET_HUB_STATUS		(0xa000 | UR_GET_STATUS)+#define UCR_GET_PORT_STATUS		(0xa300 | UR_GET_STATUS)+#define UCR_SET_HUB_FEATURE		(0x2000 | UR_SET_FEATURE)+#define UCR_SET_PORT_FEATURE		(0x2300 | UR_SET_FEATURE)+#define UCR_SET_AND_TEST_PORT_FEATURE	(0xa300 | UR_SET_AND_TEST_FEATURE)++#ifdef _MSC_VER+#include <pshpack1.h>+#endif++typedef struct {+	uByte		bLength;+	uByte		bDescriptorType;+	uByte		bDescriptorSubtype;+} UPACKED usb_descriptor_t;++typedef struct {+	uByte		bLength;+	uByte		bDescriptorType;+} UPACKED usb_descriptor_header_t;++typedef struct {+	uByte		bLength;+	uByte		bDescriptorType;+	uWord		bcdUSB;+#define UD_USB_2_0		0x0200+#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0)+	uByte		bDeviceClass;+	uByte		bDeviceSubClass;+	uByte		bDeviceProtocol;+	uByte		bMaxPacketSize;+	/* The fields below are not part of the initial descriptor. */+	uWord		idVendor;+	uWord		idProduct;+	uWord		bcdDevice;+	uByte		iManufacturer;+	uByte		iProduct;+	uByte		iSerialNumber;+	uByte		bNumConfigurations;+} UPACKED usb_device_descriptor_t;+#define USB_DEVICE_DESCRIPTOR_SIZE 18++typedef struct {+	uByte		bLength;+	uByte		bDescriptorType;+	uWord		wTotalLength;+	uByte		bNumInterface;+	uByte		bConfigurationValue;+	uByte		iConfiguration;+#define UC_ATT_ONE		(1 << 7)	/* must be set */+#define UC_ATT_SELFPOWER	(1 << 6)	/* self powered */+#define UC_ATT_WAKEUP		(1 << 5)	/* can wakeup */+#define UC_ATT_BATTERY		(1 << 4)	/* battery powered */+	uByte		bmAttributes;+#define UC_BUS_POWERED		0x80+#define UC_SELF_POWERED		0x40+#define UC_REMOTE_WAKEUP	0x20+	uByte		bMaxPower; /* max current in 2 mA units */+#define UC_POWER_FACTOR 2+} UPACKED usb_config_descriptor_t;+#define USB_CONFIG_DESCRIPTOR_SIZE 9++typedef struct {+	uByte		bLength;+	uByte		bDescriptorType;+	uByte		bInterfaceNumber;+	uByte		bAlternateSetting;+	uByte		bNumEndpoints;+	uByte		bInterfaceClass;+	uByte		bInterfaceSubClass;+	uByte		bInterfaceProtocol;+	uByte		iInterface;+} UPACKED usb_interface_descriptor_t;+#define USB_INTERFACE_DESCRIPTOR_SIZE 9++typedef struct {+	uByte		bLength;+	uByte		bDescriptorType;+	uByte		bEndpointAddress;+#define UE_GET_DIR(a)	((a) & 0x80)+#define UE_SET_DIR(a,d)	((a) | (((d)&1) << 7))+#define UE_DIR_IN	0x80+#define UE_DIR_OUT	0x00+#define UE_ADDR		0x0f+#define UE_GET_ADDR(a)	((a) & UE_ADDR)+	uByte		bmAttributes;+#define UE_XFERTYPE	0x03+#define  UE_CONTROL	0x00+#define  UE_ISOCHRONOUS	0x01+#define  UE_BULK	0x02+#define  UE_INTERRUPT	0x03+#define UE_GET_XFERTYPE(a)	((a) & UE_XFERTYPE)+#define UE_ISO_TYPE	0x0c+#define  UE_ISO_ASYNC	0x04+#define  UE_ISO_ADAPT	0x08+#define  UE_ISO_SYNC	0x0c+#define UE_GET_ISO_TYPE(a)	((a) & UE_ISO_TYPE)+	uWord		wMaxPacketSize;+	uByte		bInterval;+} UPACKED usb_endpoint_descriptor_t;+#define USB_ENDPOINT_DESCRIPTOR_SIZE 7++typedef struct ss_endpoint_companion_descriptor {+	uByte bLength;+	uByte bDescriptorType;+	uByte bMaxBurst;+#define USSE_GET_MAX_STREAMS(a)		((a) & 0x1f)+#define USSE_SET_MAX_STREAMS(a, b)	((a) | ((b) & 0x1f))+#define USSE_GET_MAX_PACKET_NUM(a)	((a) & 0x03)+#define USSE_SET_MAX_PACKET_NUM(a, b)	((a) | ((b) & 0x03))+	uByte bmAttributes;+	uWord wBytesPerInterval;+} UPACKED ss_endpoint_companion_descriptor_t;+#define USB_SS_ENDPOINT_COMPANION_DESCRIPTOR_SIZE 6++typedef struct {+	uByte		bLength;+	uByte		bDescriptorType;+	uWord		bString[127];+} UPACKED usb_string_descriptor_t;+#define USB_MAX_STRING_LEN 128+#define USB_LANGUAGE_TABLE 0	/* # of the string language id table */++/* Hub specific request */+#define UR_GET_BUS_STATE	0x02+#define UR_CLEAR_TT_BUFFER	0x08+#define UR_RESET_TT		0x09+#define UR_GET_TT_STATE		0x0a+#define UR_STOP_TT		0x0b++/* Hub features */+#define UHF_C_HUB_LOCAL_POWER	0+#define UHF_C_HUB_OVER_CURRENT	1+#define UHF_PORT_CONNECTION	0+#define UHF_PORT_ENABLE		1+#define UHF_PORT_SUSPEND	2+#define UHF_PORT_OVER_CURRENT	3+#define UHF_PORT_RESET		4+#define UHF_PORT_L1		5+#define UHF_PORT_POWER		8+#define UHF_PORT_LOW_SPEED	9+#define UHF_PORT_HIGH_SPEED	10+#define UHF_C_PORT_CONNECTION	16+#define UHF_C_PORT_ENABLE	17+#define UHF_C_PORT_SUSPEND	18+#define UHF_C_PORT_OVER_CURRENT	19+#define UHF_C_PORT_RESET	20+#define UHF_C_PORT_L1		23+#define UHF_PORT_TEST		21+#define UHF_PORT_INDICATOR	22++typedef struct {+	uByte		bDescLength;+	uByte		bDescriptorType;+	uByte		bNbrPorts;+	uWord		wHubCharacteristics;+#define UHD_PWR			0x0003+#define  UHD_PWR_GANGED		0x0000+#define  UHD_PWR_INDIVIDUAL	0x0001+#define  UHD_PWR_NO_SWITCH	0x0002+#define UHD_COMPOUND		0x0004+#define UHD_OC			0x0018+#define  UHD_OC_GLOBAL		0x0000+#define  UHD_OC_INDIVIDUAL	0x0008+#define  UHD_OC_NONE		0x0010+#define UHD_TT_THINK		0x0060+#define  UHD_TT_THINK_8		0x0000+#define  UHD_TT_THINK_16	0x0020+#define  UHD_TT_THINK_24	0x0040+#define  UHD_TT_THINK_32	0x0060+#define UHD_PORT_IND		0x0080+	uByte		bPwrOn2PwrGood;	/* delay in 2 ms units */+#define UHD_PWRON_FACTOR 2+	uByte		bHubContrCurrent;+	uByte		DeviceRemovable[32]; /* max 255 ports */+#define UHD_NOT_REMOV(desc, i) \+    (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1)+	/* deprecated */ uByte		PortPowerCtrlMask[1];+} UPACKED usb_hub_descriptor_t;+#define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */++typedef struct {+	uByte		bLength;+	uByte		bDescriptorType;+	uWord		bcdUSB;+	uByte		bDeviceClass;+	uByte		bDeviceSubClass;+	uByte		bDeviceProtocol;+	uByte		bMaxPacketSize0;+	uByte		bNumConfigurations;+	uByte		bReserved;+} UPACKED usb_device_qualifier_t;+#define USB_DEVICE_QUALIFIER_SIZE 10++typedef struct {+	uByte		bLength;+	uByte		bDescriptorType;+	uByte		bmAttributes;+#define UOTG_SRP	0x01+#define UOTG_HNP	0x02+} UPACKED usb_otg_descriptor_t;++/* OTG feature selectors */+#define UOTG_B_HNP_ENABLE	3+#define UOTG_A_HNP_SUPPORT	4+#define UOTG_A_ALT_HNP_SUPPORT	5++typedef struct {+	uWord		wStatus;+/* Device status flags */+#define UDS_SELF_POWERED		0x0001+#define UDS_REMOTE_WAKEUP		0x0002+/* Endpoint status flags */+#define UES_HALT			0x0001+} UPACKED usb_status_t;++typedef struct {+	uWord		wHubStatus;+#define UHS_LOCAL_POWER			0x0001+#define UHS_OVER_CURRENT		0x0002+	uWord		wHubChange;+} UPACKED usb_hub_status_t;++typedef struct {+	uWord		wPortStatus;+#define UPS_CURRENT_CONNECT_STATUS	0x0001+#define UPS_PORT_ENABLED		0x0002+#define UPS_SUSPEND			0x0004+#define UPS_OVERCURRENT_INDICATOR	0x0008+#define UPS_RESET			0x0010+#define UPS_PORT_POWER			0x0100+#define UPS_LOW_SPEED			0x0200+#define UPS_HIGH_SPEED			0x0400+#define UPS_PORT_TEST			0x0800+#define UPS_PORT_INDICATOR		0x1000+	uWord		wPortChange;+#define UPS_C_CONNECT_STATUS		0x0001+#define UPS_C_PORT_ENABLED		0x0002+#define UPS_C_SUSPEND			0x0004+#define UPS_C_OVERCURRENT_INDICATOR	0x0008+#define UPS_C_PORT_RESET		0x0010+} UPACKED usb_port_status_t;++#ifdef _MSC_VER+#include <poppack.h>+#endif++/* Device class codes */+#define UDCLASS_IN_INTERFACE	0x00+#define UDCLASS_COMM		0x02+#define UDCLASS_HUB		0x09+#define  UDSUBCLASS_HUB		0x00+#define  UDPROTO_FSHUB		0x00+#define  UDPROTO_HSHUBSTT	0x01+#define  UDPROTO_HSHUBMTT	0x02+#define UDCLASS_DIAGNOSTIC	0xdc+#define UDCLASS_WIRELESS	0xe0+#define  UDSUBCLASS_RF		0x01+#define   UDPROTO_BLUETOOTH	0x01+#define UDCLASS_VENDOR		0xff++/* Interface class codes */+#define UICLASS_UNSPEC		0x00++#define UICLASS_AUDIO		0x01+#define  UISUBCLASS_AUDIOCONTROL	1+#define  UISUBCLASS_AUDIOSTREAM		2+#define  UISUBCLASS_MIDISTREAM		3++#define UICLASS_CDC		0x02 /* communication */+#define  UISUBCLASS_DIRECT_LINE_CONTROL_MODEL	1+#define  UISUBCLASS_ABSTRACT_CONTROL_MODEL	2+#define  UISUBCLASS_TELEPHONE_CONTROL_MODEL	3+#define  UISUBCLASS_MULTICHANNEL_CONTROL_MODEL	4+#define  UISUBCLASS_CAPI_CONTROLMODEL		5+#define  UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6+#define  UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7+#define   UIPROTO_CDC_AT			1++#define UICLASS_HID		0x03+#define  UISUBCLASS_BOOT	1+#define  UIPROTO_BOOT_KEYBOARD	1++#define UICLASS_PHYSICAL	0x05++#define UICLASS_IMAGE		0x06++#define UICLASS_PRINTER		0x07+#define  UISUBCLASS_PRINTER	1+#define  UIPROTO_PRINTER_UNI	1+#define  UIPROTO_PRINTER_BI	2+#define  UIPROTO_PRINTER_1284	3++#define UICLASS_MASS		0x08+#define  UISUBCLASS_RBC		1+#define  UISUBCLASS_SFF8020I	2+#define  UISUBCLASS_QIC157	3+#define  UISUBCLASS_UFI		4+#define  UISUBCLASS_SFF8070I	5+#define  UISUBCLASS_SCSI	6+#define  UIPROTO_MASS_CBI_I	0+#define  UIPROTO_MASS_CBI	1+#define  UIPROTO_MASS_BBB_OLD	2	/* Not in the spec anymore */+#define  UIPROTO_MASS_BBB	80	/* 'P' for the Iomega Zip drive */++#define UICLASS_HUB		0x09+#define  UISUBCLASS_HUB		0+#define  UIPROTO_FSHUB		0+#define  UIPROTO_HSHUBSTT	0 /* Yes, same as previous */+#define  UIPROTO_HSHUBMTT	1++#define UICLASS_CDC_DATA	0x0a+#define  UISUBCLASS_DATA		0+#define   UIPROTO_DATA_ISDNBRI		0x30    /* Physical iface */+#define   UIPROTO_DATA_HDLC		0x31    /* HDLC */+#define   UIPROTO_DATA_TRANSPARENT	0x32    /* Transparent */+#define   UIPROTO_DATA_Q921M		0x50    /* Management for Q921 */+#define   UIPROTO_DATA_Q921		0x51    /* Data for Q921 */+#define   UIPROTO_DATA_Q921TM		0x52    /* TEI multiplexer for Q921 */+#define   UIPROTO_DATA_V42BIS		0x90    /* Data compression */+#define   UIPROTO_DATA_Q931		0x91    /* Euro-ISDN */+#define   UIPROTO_DATA_V120		0x92    /* V.24 rate adaption */+#define   UIPROTO_DATA_CAPI		0x93    /* CAPI 2.0 commands */+#define   UIPROTO_DATA_HOST_BASED	0xfd    /* Host based driver */+#define   UIPROTO_DATA_PUF		0xfe    /* see Prot. Unit Func. Desc.*/+#define   UIPROTO_DATA_VENDOR		0xff    /* Vendor specific */++#define UICLASS_SMARTCARD	0x0b++/*#define UICLASS_FIRM_UPD	0x0c*/++#define UICLASS_SECURITY	0x0d++#define UICLASS_DIAGNOSTIC	0xdc++#define UICLASS_WIRELESS	0xe0+#define  UISUBCLASS_RF			0x01+#define   UIPROTO_BLUETOOTH		0x01++#define UICLASS_APPL_SPEC	0xfe+#define  UISUBCLASS_FIRMWARE_DOWNLOAD	1+#define  UISUBCLASS_IRDA		2+#define  UIPROTO_IRDA			0++#define UICLASS_VENDOR		0xff++#define USB_HUB_MAX_DEPTH 5++/*+ * Minimum time a device needs to be powered down to go through+ * a power cycle.  XXX Are these time in the spec?+ */+#define USB_POWER_DOWN_TIME	200 /* ms */+#define USB_PORT_POWER_DOWN_TIME	100 /* ms */++#if 0+/* These are the values from the spec. */+#define USB_PORT_RESET_DELAY	10  /* ms */+#define USB_PORT_ROOT_RESET_DELAY 50  /* ms */+#define USB_PORT_RESET_RECOVERY	10  /* ms */+#define USB_PORT_POWERUP_DELAY	100 /* ms */+#define USB_SET_ADDRESS_SETTLE	2   /* ms */+#define USB_RESUME_DELAY	(20*5)  /* ms */+#define USB_RESUME_WAIT		10  /* ms */+#define USB_RESUME_RECOVERY	10  /* ms */+#define USB_EXTRA_POWER_UP_TIME	0   /* ms */+#else+/* Allow for marginal (i.e. non-conforming) devices. */+#define USB_PORT_RESET_DELAY	50  /* ms */+#define USB_PORT_ROOT_RESET_DELAY 250  /* ms */+#define USB_PORT_RESET_RECOVERY	250  /* ms */+#define USB_PORT_POWERUP_DELAY	300 /* ms */+#define USB_SET_ADDRESS_SETTLE	10  /* ms */+#define USB_RESUME_DELAY	(50*5)  /* ms */+#define USB_RESUME_WAIT		50  /* ms */+#define USB_RESUME_RECOVERY	50  /* ms */+#define USB_EXTRA_POWER_UP_TIME	20  /* ms */+#endif++#define USB_MIN_POWER		100 /* mA */+#define USB_MAX_POWER		500 /* mA */++#define USB_BUS_RESET_DELAY	100 /* ms XXX?*/++#define USB_UNCONFIG_NO 0+#define USB_UNCONFIG_INDEX (-1)++/*** ioctl() related stuff ***/++struct usb_ctl_request {+	int	ucr_addr;+	usb_device_request_t ucr_request;+	void	*ucr_data;+	int	ucr_flags;+#define USBD_SHORT_XFER_OK	0x04	/* allow short reads */+	int	ucr_actlen;		/* actual length transferred */+};++struct usb_alt_interface {+	int	uai_config_index;+	int	uai_interface_index;+	int	uai_alt_no;+};++#define USB_CURRENT_CONFIG_INDEX (-1)+#define USB_CURRENT_ALT_INDEX (-1)++struct usb_config_desc {+	int	ucd_config_index;+	usb_config_descriptor_t ucd_desc;+};++struct usb_interface_desc {+	int	uid_config_index;+	int	uid_interface_index;+	int	uid_alt_index;+	usb_interface_descriptor_t uid_desc;+};++struct usb_endpoint_desc {+	int	ued_config_index;+	int	ued_interface_index;+	int	ued_alt_index;+	int	ued_endpoint_index;+	usb_endpoint_descriptor_t ued_desc;+};++struct usb_full_desc {+	int	ufd_config_index;+	u_int	ufd_size;+	u_char	*ufd_data;+};++struct usb_string_desc {+	int	usd_string_index;+	int	usd_language_id;+	usb_string_descriptor_t usd_desc;+};++struct usb_ctl_report_desc {+	int	ucrd_size;+	u_char	ucrd_data[1024];	/* filled data size will vary */+};++typedef struct { u_int32_t cookie; } usb_event_cookie_t;++#define USB_MAX_DEVNAMES 4+#define USB_MAX_DEVNAMELEN 16+struct usb_device_info {+	u_int8_t	udi_bus;+	u_int8_t	udi_addr;	/* device address */+	usb_event_cookie_t udi_cookie;+	char		udi_product[USB_MAX_STRING_LEN];+	char		udi_vendor[USB_MAX_STRING_LEN];+	char		udi_release[8];+	u_int16_t	udi_productNo;+	u_int16_t	udi_vendorNo;+	u_int16_t	udi_releaseNo;+	u_int8_t	udi_class;+	u_int8_t	udi_subclass;+	u_int8_t	udi_protocol;+	u_int8_t	udi_config;+	u_int8_t	udi_speed;+#define USB_SPEED_UNKNOWN	0+#define USB_SPEED_LOW		1+#define USB_SPEED_FULL		2+#define USB_SPEED_HIGH		3+#define USB_SPEED_VARIABLE	4+#define USB_SPEED_SUPER		5+	int		udi_power;	/* power consumption in mA, 0 if selfpowered */+	int		udi_nports;+	char		udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN];+	u_int8_t	udi_ports[16];/* hub only: addresses of devices on ports */+#define USB_PORT_ENABLED 0xff+#define USB_PORT_SUSPENDED 0xfe+#define USB_PORT_POWERED 0xfd+#define USB_PORT_DISABLED 0xfc+};++struct usb_ctl_report {+	int	ucr_report;+	u_char	ucr_data[1024];	/* filled data size will vary */+};++struct usb_device_stats {+	u_long	uds_requests[4];	/* indexed by transfer type UE_* */+};++#define WUSB_MIN_IE			0x80+#define WUSB_WCTA_IE			0x80+#define WUSB_WCONNECTACK_IE		0x81+#define WUSB_WHOSTINFO_IE		0x82+#define  WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3)+#define   WUHI_CA_RECONN		0x00+#define   WUHI_CA_LIMITED		0x01+#define   WUHI_CA_ALL			0x03+#define  WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3)+#define WUSB_WCHCHANGEANNOUNCE_IE	0x83+#define WUSB_WDEV_DISCONNECT_IE		0x84+#define WUSB_WHOST_DISCONNECT_IE	0x85+#define WUSB_WRELEASE_CHANNEL_IE	0x86+#define WUSB_WWORK_IE			0x87+#define WUSB_WCHANNEL_STOP_IE		0x88+#define WUSB_WDEV_KEEPALIVE_IE		0x89+#define WUSB_WISOCH_DISCARD_IE		0x8A+#define WUSB_WRESETDEVICE_IE		0x8B+#define WUSB_WXMIT_PACKET_ADJUST_IE	0x8C+#define WUSB_MAX_IE			0x8C++/* Device Notification Types */++#define WUSB_DN_MIN			0x01+#define WUSB_DN_CONNECT			0x01+# define WUSB_DA_OLDCONN	0x00+# define WUSB_DA_NEWCONN	0x01+# define WUSB_DA_SELF_BEACON	0x02+# define WUSB_DA_DIR_BEACON	0x04+# define WUSB_DA_NO_BEACON	0x06+#define WUSB_DN_DISCONNECT		0x02+#define WUSB_DN_EPRDY			0x03+#define WUSB_DN_MASAVAILCHANGED		0x04+#define WUSB_DN_REMOTEWAKEUP		0x05+#define WUSB_DN_SLEEP			0x06+#define WUSB_DN_ALIVE			0x07+#define WUSB_DN_MAX			0x07++#ifdef _MSC_VER+#include <pshpack1.h>+#endif++/* WUSB Handshake Data.  Used during the SET/GET HANDSHAKE requests */+typedef struct wusb_hndshk_data {+	uByte bMessageNumber;+	uByte bStatus;+	uByte tTKID[3];+	uByte bReserved;+	uByte CDID[16];+	uByte Nonce[16];+	uByte MIC[8];+} UPACKED wusb_hndshk_data_t;+#define WUSB_HANDSHAKE_LEN_FOR_MIC	38++/* WUSB Connection Context */+typedef struct wusb_conn_context {+	uByte CHID [16];+	uByte CDID [16];+	uByte CK [16];+} UPACKED wusb_conn_context_t;++/* WUSB Security Descriptor */+typedef struct wusb_security_desc {+	uByte bLength;+	uByte bDescriptorType;+	uWord wTotalLength;+	uByte bNumEncryptionTypes;+} UPACKED wusb_security_desc_t;++/* WUSB Encryption Type Descriptor */+typedef struct wusb_encrypt_type_desc {+	uByte bLength;+	uByte bDescriptorType;++	uByte bEncryptionType;+#define WUETD_UNSECURE		0+#define WUETD_WIRED		1+#define WUETD_CCM_1		2+#define WUETD_RSA_1		3++	uByte bEncryptionValue;+	uByte bAuthKeyIndex;+} UPACKED wusb_encrypt_type_desc_t;++/* WUSB Key Descriptor */+typedef struct wusb_key_desc {+	uByte bLength;+	uByte bDescriptorType;+	uByte tTKID[3];+	uByte bReserved;+	uByte KeyData[1];	/* variable length */+} UPACKED wusb_key_desc_t;++/* WUSB BOS Descriptor (Binary device Object Store) */+typedef struct wusb_bos_desc {+	uByte bLength;+	uByte bDescriptorType;+	uWord wTotalLength;+	uByte bNumDeviceCaps;+} UPACKED wusb_bos_desc_t;++#define USB_DEVICE_CAPABILITY_20_EXTENSION	0x02+typedef struct usb_dev_cap_20_ext_desc {+	uByte bLength;+	uByte bDescriptorType;+	uByte bDevCapabilityType;+#define USB_20_EXT_LPM				0x02+	uDWord bmAttributes;+} UPACKED usb_dev_cap_20_ext_desc_t;++#define USB_DEVICE_CAPABILITY_SS_USB		0x03+typedef struct usb_dev_cap_ss_usb {+	uByte bLength;+	uByte bDescriptorType;+	uByte bDevCapabilityType;+#define USB_DC_SS_USB_LTM_CAPABLE		0x02+	uByte bmAttributes;+#define USB_DC_SS_USB_SPEED_SUPPORT_LOW		0x01+#define USB_DC_SS_USB_SPEED_SUPPORT_FULL	0x02+#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH	0x04+#define USB_DC_SS_USB_SPEED_SUPPORT_SS		0x08+	uWord wSpeedsSupported;+	uByte bFunctionalitySupport;+	uByte bU1DevExitLat;+	uWord wU2DevExitLat;+} UPACKED usb_dev_cap_ss_usb_t;++#define USB_DEVICE_CAPABILITY_CONTAINER_ID	0x04+typedef struct usb_dev_cap_container_id {+	uByte bLength;+	uByte bDescriptorType;+	uByte bDevCapabilityType;+	uByte bReserved;+	uByte containerID[16];+} UPACKED usb_dev_cap_container_id_t;++/* Device Capability Type Codes */+#define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01++/* Device Capability Descriptor */+typedef struct wusb_dev_cap_desc {+	uByte bLength;+	uByte bDescriptorType;+	uByte bDevCapabilityType;+	uByte caps[1];	/* Variable length */+} UPACKED wusb_dev_cap_desc_t;++/* Device Capability Descriptor */+typedef struct wusb_dev_cap_uwb_desc {+	uByte bLength;+	uByte bDescriptorType;+	uByte bDevCapabilityType;+	uByte bmAttributes;+	uWord wPHYRates;	/* Bitmap */+	uByte bmTFITXPowerInfo;+	uByte bmFFITXPowerInfo;+	uWord bmBandGroup;+	uByte bReserved;+} UPACKED wusb_dev_cap_uwb_desc_t;++/* Wireless USB Endpoint Companion Descriptor */+typedef struct wusb_endpoint_companion_desc {+	uByte bLength;+	uByte bDescriptorType;+	uByte bMaxBurst;+	uByte bMaxSequence;+	uWord wMaxStreamDelay;+	uWord wOverTheAirPacketSize;+	uByte bOverTheAirInterval;+	uByte bmCompAttributes;+} UPACKED wusb_endpoint_companion_desc_t;++/* Wireless USB Numeric Association M1 Data Structure */+typedef struct wusb_m1_data {+	uByte version;+	uWord langId;+	uByte deviceFriendlyNameLength;+	uByte sha_256_m3[32];+	uByte deviceFriendlyName[256];+} UPACKED wusb_m1_data_t;++typedef struct wusb_m2_data {+	uByte version;+	uWord langId;+	uByte hostFriendlyNameLength;+	uByte pkh[384];+	uByte hostFriendlyName[256];+} UPACKED wusb_m2_data_t;++typedef struct wusb_m3_data {+	uByte pkd[384];+	uByte nd;+} UPACKED wusb_m3_data_t;++typedef struct wusb_m4_data {+	uDWord _attributeTypeIdAndLength_1;+	uWord  associationTypeId;++	uDWord _attributeTypeIdAndLength_2;+	uWord  associationSubTypeId;++	uDWord _attributeTypeIdAndLength_3;+	uDWord length;++	uDWord _attributeTypeIdAndLength_4;+	uDWord associationStatus;++	uDWord _attributeTypeIdAndLength_5;+	uByte  chid[16];++	uDWord _attributeTypeIdAndLength_6;+	uByte  cdid[16];++	uDWord _attributeTypeIdAndLength_7;+	uByte  bandGroups[2];+} UPACKED wusb_m4_data_t;++#ifdef _MSC_VER+#include <poppack.h>+#endif++#ifdef __cplusplus+}+#endif++#endif /* _USB_H_ */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/doc/doxygen.cfg linux-3.11.10/drivers/usb/host/dwc_otg/doc/doxygen.cfg--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/doc/doxygen.cfg	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/doc/doxygen.cfg	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,224 @@+# Doxyfile 1.3.9.1++#---------------------------------------------------------------------------+# Project related configuration options+#---------------------------------------------------------------------------+PROJECT_NAME           = "DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver"+PROJECT_NUMBER         = v3.00a+OUTPUT_DIRECTORY       = ./doc/+CREATE_SUBDIRS         = NO+OUTPUT_LANGUAGE        = English+BRIEF_MEMBER_DESC      = YES+REPEAT_BRIEF           = YES+ABBREVIATE_BRIEF       = "The $name class" \+                         "The $name widget" \+                         "The $name file" \+                         is \+                         provides \+                         specifies \+                         contains \+                         represents \+                         a \+                         an \+                         the+ALWAYS_DETAILED_SEC    = NO+INLINE_INHERITED_MEMB  = NO+FULL_PATH_NAMES        = NO+STRIP_FROM_PATH        =+STRIP_FROM_INC_PATH    =+SHORT_NAMES            = NO+JAVADOC_AUTOBRIEF      = YES+MULTILINE_CPP_IS_BRIEF = NO+INHERIT_DOCS           = YES+DISTRIBUTE_GROUP_DOC   = NO+TAB_SIZE               = 8+ALIASES                =+OPTIMIZE_OUTPUT_FOR_C  = YES+OPTIMIZE_OUTPUT_JAVA   = NO+SUBGROUPING            = YES+#---------------------------------------------------------------------------+# Build related configuration options+#---------------------------------------------------------------------------+EXTRACT_ALL            = NO+EXTRACT_PRIVATE        = YES+EXTRACT_STATIC         = YES+EXTRACT_LOCAL_CLASSES  = YES+EXTRACT_LOCAL_METHODS  = NO+HIDE_UNDOC_MEMBERS     = NO+HIDE_UNDOC_CLASSES     = NO+HIDE_FRIEND_COMPOUNDS  = NO+HIDE_IN_BODY_DOCS      = NO+INTERNAL_DOCS          = NO+CASE_SENSE_NAMES       = NO+HIDE_SCOPE_NAMES       = NO+SHOW_INCLUDE_FILES     = YES+INLINE_INFO            = YES+SORT_MEMBER_DOCS       = NO+SORT_BRIEF_DOCS        = NO+SORT_BY_SCOPE_NAME     = NO+GENERATE_TODOLIST      = YES+GENERATE_TESTLIST      = YES+GENERATE_BUGLIST       = YES+GENERATE_DEPRECATEDLIST= YES+ENABLED_SECTIONS       =+MAX_INITIALIZER_LINES  = 30+SHOW_USED_FILES        = YES+SHOW_DIRECTORIES       = YES+#---------------------------------------------------------------------------+# configuration options related to warning and progress messages+#---------------------------------------------------------------------------+QUIET                  = YES+WARNINGS               = YES+WARN_IF_UNDOCUMENTED   = NO+WARN_IF_DOC_ERROR      = YES+WARN_FORMAT            = "$file:$line: $text"+WARN_LOGFILE           =+#---------------------------------------------------------------------------+# configuration options related to the input files+#---------------------------------------------------------------------------+INPUT                  = .+FILE_PATTERNS          = *.c \+                         *.h \+                         ./linux/*.c \+                         ./linux/*.h+RECURSIVE              = NO+EXCLUDE                = ./test/ \+                         ./dwc_otg/.AppleDouble/+EXCLUDE_SYMLINKS       = YES+EXCLUDE_PATTERNS       = *.mod.*+EXAMPLE_PATH           =+EXAMPLE_PATTERNS       = *+EXAMPLE_RECURSIVE      = NO+IMAGE_PATH             =+INPUT_FILTER           =+FILTER_PATTERNS        =+FILTER_SOURCE_FILES    = NO+#---------------------------------------------------------------------------+# configuration options related to source browsing+#---------------------------------------------------------------------------+SOURCE_BROWSER         = YES+INLINE_SOURCES         = NO+STRIP_CODE_COMMENTS    = YES+REFERENCED_BY_RELATION = NO+REFERENCES_RELATION    = NO+VERBATIM_HEADERS       = NO+#---------------------------------------------------------------------------+# configuration options related to the alphabetical class index+#---------------------------------------------------------------------------+ALPHABETICAL_INDEX     = NO+COLS_IN_ALPHA_INDEX    = 5+IGNORE_PREFIX          =+#---------------------------------------------------------------------------+# configuration options related to the HTML output+#---------------------------------------------------------------------------+GENERATE_HTML          = YES+HTML_OUTPUT            = html+HTML_FILE_EXTENSION    = .html+HTML_HEADER            =+HTML_FOOTER            =+HTML_STYLESHEET        =+HTML_ALIGN_MEMBERS     = YES+GENERATE_HTMLHELP      = NO+CHM_FILE               =+HHC_LOCATION           =+GENERATE_CHI           = NO+BINARY_TOC             = NO+TOC_EXPAND             = NO+DISABLE_INDEX          = NO+ENUM_VALUES_PER_LINE   = 4+GENERATE_TREEVIEW      = YES+TREEVIEW_WIDTH         = 250+#---------------------------------------------------------------------------+# configuration options related to the LaTeX output+#---------------------------------------------------------------------------+GENERATE_LATEX         = NO+LATEX_OUTPUT           = latex+LATEX_CMD_NAME         = latex+MAKEINDEX_CMD_NAME     = makeindex+COMPACT_LATEX          = NO+PAPER_TYPE             = a4wide+EXTRA_PACKAGES         =+LATEX_HEADER           =+PDF_HYPERLINKS         = NO+USE_PDFLATEX           = NO+LATEX_BATCHMODE        = NO+LATEX_HIDE_INDICES     = NO+#---------------------------------------------------------------------------+# configuration options related to the RTF output+#---------------------------------------------------------------------------+GENERATE_RTF           = NO+RTF_OUTPUT             = rtf+COMPACT_RTF            = NO+RTF_HYPERLINKS         = NO+RTF_STYLESHEET_FILE    =+RTF_EXTENSIONS_FILE    =+#---------------------------------------------------------------------------+# configuration options related to the man page output+#---------------------------------------------------------------------------+GENERATE_MAN           = NO+MAN_OUTPUT             = man+MAN_EXTENSION          = .3+MAN_LINKS              = NO+#---------------------------------------------------------------------------+# configuration options related to the XML output+#---------------------------------------------------------------------------+GENERATE_XML           = NO+XML_OUTPUT             = xml+XML_SCHEMA             =+XML_DTD                =+XML_PROGRAMLISTING     = YES+#---------------------------------------------------------------------------+# configuration options for the AutoGen Definitions output+#---------------------------------------------------------------------------+GENERATE_AUTOGEN_DEF   = NO+#---------------------------------------------------------------------------+# configuration options related to the Perl module output+#---------------------------------------------------------------------------+GENERATE_PERLMOD       = NO+PERLMOD_LATEX          = NO+PERLMOD_PRETTY         = YES+PERLMOD_MAKEVAR_PREFIX =+#---------------------------------------------------------------------------+# Configuration options related to the preprocessor+#---------------------------------------------------------------------------+ENABLE_PREPROCESSING   = YES+MACRO_EXPANSION        = YES+EXPAND_ONLY_PREDEF     = YES+SEARCH_INCLUDES        = YES+INCLUDE_PATH           =+INCLUDE_FILE_PATTERNS  =+PREDEFINED             = DEVICE_ATTR DWC_EN_ISOC+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+SKIP_FUNCTION_MACROS   = NO+#---------------------------------------------------------------------------+# Configuration::additions related to external references+#---------------------------------------------------------------------------+TAGFILES               =+GENERATE_TAGFILE       =+ALLEXTERNALS           = NO+EXTERNAL_GROUPS        = YES+PERL_PATH              = /usr/bin/perl+#---------------------------------------------------------------------------+# Configuration options related to the dot tool+#---------------------------------------------------------------------------+CLASS_DIAGRAMS         = YES+HIDE_UNDOC_RELATIONS   = YES+HAVE_DOT               = NO+CLASS_GRAPH            = YES+COLLABORATION_GRAPH    = YES+UML_LOOK               = NO+TEMPLATE_RELATIONS     = NO+INCLUDE_GRAPH          = YES+INCLUDED_BY_GRAPH      = YES+CALL_GRAPH             = NO+GRAPHICAL_HIERARCHY    = YES+DOT_IMAGE_FORMAT       = png+DOT_PATH               =+DOTFILE_DIRS           =+MAX_DOT_GRAPH_DEPTH    = 1000+GENERATE_LEGEND        = YES+DOT_CLEANUP            = YES+#---------------------------------------------------------------------------+# Configuration::additions related to the search engine+#---------------------------------------------------------------------------+SEARCHENGINE           = NOdiff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dummy_audio.c linux-3.11.10/drivers/usb/host/dwc_otg/dummy_audio.c--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dummy_audio.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dummy_audio.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,1575 @@+/*+ * zero.c -- Gadget Zero, for USB development+ *+ * Copyright (C) 2003-2004 David Brownell+ * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions, and the following disclaimer,+ *    without modification.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. The names of the above-listed copyright holders may not be used+ *    to endorse or promote products derived from this software without+ *    specific prior written permission.+ *+ * ALTERNATIVELY, this software may be distributed under the terms of the+ * GNU General Public License ("GPL") as published by the Free Software+ * Foundation, either version 2 of that License or (at your option) any+ * later version.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */+++/*+ * Gadget Zero only needs two bulk endpoints, and is an example of how you+ * can write a hardware-agnostic gadget driver running inside a USB device.+ *+ * Hardware details are visible (see CONFIG_USB_ZERO_* below) but don't+ * affect most of the driver.+ *+ * Use it with the Linux host/master side "usbtest" driver to get a basic+ * functional test of your device-side usb stack, or with "usb-skeleton".+ *+ * It supports two similar configurations.  One sinks whatever the usb host+ * writes, and in return sources zeroes.  The other loops whatever the host+ * writes back, so the host can read it.  Module options include:+ *+ *   buflen=N		default N=4096, buffer size used+ *   qlen=N		default N=32, how many buffers in the loopback queue+ *   loopdefault	default false, list loopback config first+ *+ * Many drivers will only have one configuration, letting them be much+ * simpler if they also don't support high speed operation (like this+ * driver does).+ */++#include <linux/config.h>+#include <linux/module.h>+#include <linux/kernel.h>+#include <linux/delay.h>+#include <linux/ioport.h>+#include <linux/sched.h>+#include <linux/slab.h>+#include <linux/smp_lock.h>+#include <linux/errno.h>+#include <linux/init.h>+#include <linux/timer.h>+#include <linux/list.h>+#include <linux/interrupt.h>+#include <linux/uts.h>+#include <linux/version.h>+#include <linux/device.h>+#include <linux/moduleparam.h>+#include <linux/proc_fs.h>++#include <asm/byteorder.h>+#include <asm/io.h>+#include <asm/irq.h>+#include <asm/system.h>+#include <asm/unaligned.h>++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)+# include <linux/usb/ch9.h>+#else+# include <linux/usb_ch9.h>+#endif++#include <linux/usb_gadget.h>+++/*-------------------------------------------------------------------------*/+/*-------------------------------------------------------------------------*/+++static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len)+{+	int	count = 0;+	u8	c;+	u16	uchar;++	/* this insists on correct encodings, though not minimal ones.+	 * BUT it currently rejects legit 4-byte UTF-8 code points,+	 * which need surrogate pairs.  (Unicode 3.1 can use them.)+	 */+	while (len != 0 && (c = (u8) *s++) != 0) {+		if (unlikely(c & 0x80)) {+			// 2-byte sequence:+			// 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx+			if ((c & 0xe0) == 0xc0) {+				uchar = (c & 0x1f) << 6;++				c = (u8) *s++;+				if ((c & 0xc0) != 0xc0)+					goto fail;+				c &= 0x3f;+				uchar |= c;++			// 3-byte sequence (most CJKV characters):+			// zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx+			} else if ((c & 0xf0) == 0xe0) {+				uchar = (c & 0x0f) << 12;++				c = (u8) *s++;+				if ((c & 0xc0) != 0xc0)+					goto fail;+				c &= 0x3f;+				uchar |= c << 6;++				c = (u8) *s++;+				if ((c & 0xc0) != 0xc0)+					goto fail;+				c &= 0x3f;+				uchar |= c;++				/* no bogus surrogates */+				if (0xd800 <= uchar && uchar <= 0xdfff)+					goto fail;++			// 4-byte sequence (surrogate pairs, currently rare):+			// 11101110wwwwzzzzyy + 110111yyyyxxxxxx+			//     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx+			// (uuuuu = wwww + 1)+			// FIXME accept the surrogate code points (only)++			} else+				goto fail;+		} else+			uchar = c;+		put_unaligned (cpu_to_le16 (uchar), cp++);+		count++;+		len--;+	}+	return count;+fail:+	return -1;+}+++/**+ * usb_gadget_get_string - fill out a string descriptor+ * @table: of c strings encoded using UTF-8+ * @id: string id, from low byte of wValue in get string descriptor+ * @buf: at least 256 bytes+ *+ * Finds the UTF-8 string matching the ID, and converts it into a+ * string descriptor in utf16-le.+ * Returns length of descriptor (always even) or negative errno+ *+ * If your driver needs stings in multiple languages, you'll probably+ * "switch (wIndex) { ... }"  in your ep0 string descriptor logic,+ * using this routine after choosing which set of UTF-8 strings to use.+ * Note that US-ASCII is a strict subset of UTF-8; any string bytes with+ * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1+ * characters (which are also widely used in C strings).+ */+int+usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)+{+	struct usb_string	*s;+	int			len;++	/* descriptor 0 has the language id */+	if (id == 0) {+		buf [0] = 4;+		buf [1] = USB_DT_STRING;+		buf [2] = (u8) table->language;+		buf [3] = (u8) (table->language >> 8);+		return 4;+	}+	for (s = table->strings; s && s->s; s++)+		if (s->id == id)+			break;++	/* unrecognized: stall. */+	if (!s || !s->s)+		return -EINVAL;++	/* string descriptors have length, tag, then UTF16-LE text */+	len = min ((size_t) 126, strlen (s->s));+	memset (buf + 2, 0, 2 * len);	/* zero all the bytes */+	len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len);+	if (len < 0)+		return -EINVAL;+	buf [0] = (len + 1) * 2;+	buf [1] = USB_DT_STRING;+	return buf [0];+}+++/*-------------------------------------------------------------------------*/+/*-------------------------------------------------------------------------*/+++/**+ * usb_descriptor_fillbuf - fill buffer with descriptors+ * @buf: Buffer to be filled+ * @buflen: Size of buf+ * @src: Array of descriptor pointers, terminated by null pointer.+ *+ * Copies descriptors into the buffer, returning the length or a+ * negative error code if they can't all be copied.  Useful when+ * assembling descriptors for an associated set of interfaces used+ * as part of configuring a composite device; or in other cases where+ * sets of descriptors need to be marshaled.+ */+int+usb_descriptor_fillbuf(void *buf, unsigned buflen,+		const struct usb_descriptor_header **src)+{+	u8	*dest = buf;++	if (!src)+		return -EINVAL;++	/* fill buffer from src[] until null descriptor ptr */+	for (; 0 != *src; src++) {+		unsigned		len = (*src)->bLength;++		if (len > buflen)+			return -EINVAL;+		memcpy(dest, *src, len);+		buflen -= len;+		dest += len;+	}+	return dest - (u8 *)buf;+}+++/**+ * usb_gadget_config_buf - builts a complete configuration descriptor+ * @config: Header for the descriptor, including characteristics such+ *	as power requirements and number of interfaces.+ * @desc: Null-terminated vector of pointers to the descriptors (interface,+ *	endpoint, etc) defining all functions in this device configuration.+ * @buf: Buffer for the resulting configuration descriptor.+ * @length: Length of buffer.  If this is not big enough to hold the+ *	entire configuration descriptor, an error code will be returned.+ *+ * This copies descriptors into the response buffer, building a descriptor+ * for that configuration.  It returns the buffer length or a negative+ * status code.  The config.wTotalLength field is set to match the length+ * of the result, but other descriptor fields (including power usage and+ * interface count) must be set by the caller.+ *+ * Gadget drivers could use this when constructing a config descriptor+ * in response to USB_REQ_GET_DESCRIPTOR.  They will need to patch the+ * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.+ */+int usb_gadget_config_buf(+	const struct usb_config_descriptor	*config,+	void					*buf,+	unsigned				length,+	const struct usb_descriptor_header	**desc+)+{+	struct usb_config_descriptor		*cp = buf;+	int					len;++	/* config descriptor first */+	if (length < USB_DT_CONFIG_SIZE || !desc)+		return -EINVAL;+	*cp = *config;++	/* then interface/endpoint/class/vendor/... */+	len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,+			length - USB_DT_CONFIG_SIZE, desc);+	if (len < 0)+		return len;+	len += USB_DT_CONFIG_SIZE;+	if (len > 0xffff)+		return -EINVAL;++	/* patch up the config descriptor */+	cp->bLength = USB_DT_CONFIG_SIZE;+	cp->bDescriptorType = USB_DT_CONFIG;+	cp->wTotalLength = cpu_to_le16(len);+	cp->bmAttributes |= USB_CONFIG_ATT_ONE;+	return len;+}++/*-------------------------------------------------------------------------*/+/*-------------------------------------------------------------------------*/+++#define RBUF_LEN (1024*1024)+static int rbuf_start;+static int rbuf_len;+static __u8 rbuf[RBUF_LEN];++/*-------------------------------------------------------------------------*/++#define DRIVER_VERSION		"St Patrick's Day 2004"++static const char shortname [] = "zero";+static const char longname [] = "YAMAHA YST-MS35D USB Speaker  ";++static const char source_sink [] = "source and sink data";+static const char loopback [] = "loop input to output";++/*-------------------------------------------------------------------------*/++/*+ * driver assumes self-powered hardware, and+ * has no way for users to trigger remote wakeup.+ *+ * this version autoconfigures as much as possible,+ * which is reasonable for most "bulk-only" drivers.+ */+static const char *EP_IN_NAME;		/* source */+static const char *EP_OUT_NAME;		/* sink */++/*-------------------------------------------------------------------------*/++/* big enough to hold our biggest descriptor */+#define USB_BUFSIZ	512++struct zero_dev {+	spinlock_t		lock;+	struct usb_gadget	*gadget;+	struct usb_request	*req;		/* for control responses */++	/* when configured, we have one of two configs:+	 * - source data (in to host) and sink it (out from host)+	 * - or loop it back (out from host back in to host)+	 */+	u8			config;+	struct usb_ep		*in_ep, *out_ep;++	/* autoresume timer */+	struct timer_list	resume;+};++#define xprintk(d,level,fmt,args...) \+	dev_printk(level , &(d)->gadget->dev , fmt , ## args)++#ifdef DEBUG+#define DBG(dev,fmt,args...) \+	xprintk(dev , KERN_DEBUG , fmt , ## args)+#else+#define DBG(dev,fmt,args...) \+	do { } while (0)+#endif /* DEBUG */++#ifdef VERBOSE+#define VDBG	DBG+#else+#define VDBG(dev,fmt,args...) \+	do { } while (0)+#endif /* VERBOSE */++#define ERROR(dev,fmt,args...) \+	xprintk(dev , KERN_ERR , fmt , ## args)+#define WARN(dev,fmt,args...) \+	xprintk(dev , KERN_WARNING , fmt , ## args)+#define INFO(dev,fmt,args...) \+	xprintk(dev , KERN_INFO , fmt , ## args)++/*-------------------------------------------------------------------------*/++static unsigned buflen = 4096;+static unsigned qlen = 32;+static unsigned pattern = 0;++module_param (buflen, uint, S_IRUGO|S_IWUSR);+module_param (qlen, uint, S_IRUGO|S_IWUSR);+module_param (pattern, uint, S_IRUGO|S_IWUSR);++/*+ * if it's nonzero, autoresume says how many seconds to wait+ * before trying to wake up the host after suspend.+ */+static unsigned autoresume = 0;+module_param (autoresume, uint, 0);++/*+ * Normally the "loopback" configuration is second (index 1) so+ * it's not the default.  Here's where to change that order, to+ * work better with hosts where config changes are problematic.+ * Or controllers (like superh) that only support one config.+ */+static int loopdefault = 0;++module_param (loopdefault, bool, S_IRUGO|S_IWUSR);++/*-------------------------------------------------------------------------*/++/* Thanks to NetChip Technologies for donating this product ID.+ *+ * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!+ * Instead:  allocate your own, using normal USB-IF procedures.+ */+#ifndef	CONFIG_USB_ZERO_HNPTEST+#define DRIVER_VENDOR_NUM	0x0525		/* NetChip */+#define DRIVER_PRODUCT_NUM	0xa4a0		/* Linux-USB "Gadget Zero" */+#else+#define DRIVER_VENDOR_NUM	0x1a0a		/* OTG test device IDs */+#define DRIVER_PRODUCT_NUM	0xbadd+#endif++/*-------------------------------------------------------------------------*/++/*+ * DESCRIPTORS ... most are static, but strings and (full)+ * configuration descriptors are built on demand.+ */++/*+#define STRING_MANUFACTURER		25+#define STRING_PRODUCT			42+#define STRING_SERIAL			101+*/+#define STRING_MANUFACTURER		1+#define STRING_PRODUCT			2+#define STRING_SERIAL			3++#define STRING_SOURCE_SINK		250+#define STRING_LOOPBACK			251++/*+ * This device advertises two configurations; these numbers work+ * on a pxa250 as well as more flexible hardware.+ */+#define	CONFIG_SOURCE_SINK	3+#define	CONFIG_LOOPBACK		2++/*+static struct usb_device_descriptor+device_desc = {+	.bLength =		sizeof device_desc,+	.bDescriptorType =	USB_DT_DEVICE,++	.bcdUSB =		__constant_cpu_to_le16 (0x0200),+	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,++	.idVendor =		__constant_cpu_to_le16 (DRIVER_VENDOR_NUM),+	.idProduct =		__constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),+	.iManufacturer =	STRING_MANUFACTURER,+	.iProduct =		STRING_PRODUCT,+	.iSerialNumber =	STRING_SERIAL,+	.bNumConfigurations =	2,+};+*/+static struct usb_device_descriptor+device_desc = {+	.bLength =		sizeof device_desc,+	.bDescriptorType =	USB_DT_DEVICE,+	.bcdUSB =		__constant_cpu_to_le16 (0x0100),+	.bDeviceClass =		USB_CLASS_PER_INTERFACE,+	.bDeviceSubClass =      0,+	.bDeviceProtocol =      0,+	.bMaxPacketSize0 =      64,+	.bcdDevice =            __constant_cpu_to_le16 (0x0100),+	.idVendor =		__constant_cpu_to_le16 (0x0499),+	.idProduct =		__constant_cpu_to_le16 (0x3002),+	.iManufacturer =	STRING_MANUFACTURER,+	.iProduct =		STRING_PRODUCT,+	.iSerialNumber =	STRING_SERIAL,+	.bNumConfigurations =	1,+};++static struct usb_config_descriptor+z_config = {+	.bLength =		sizeof z_config,+	.bDescriptorType =	USB_DT_CONFIG,++	/* compute wTotalLength on the fly */+	.bNumInterfaces =	2,+	.bConfigurationValue =	1,+	.iConfiguration =	0,+	.bmAttributes =		0x40,+	.bMaxPower =		0,	/* self-powered */+};+++static struct usb_otg_descriptor+otg_descriptor = {+	.bLength =		sizeof otg_descriptor,+	.bDescriptorType =	USB_DT_OTG,++	.bmAttributes =		USB_OTG_SRP,+};++/* one interface in each configuration */+#ifdef	CONFIG_USB_GADGET_DUALSPEED++/*+ * usb 2.0 devices need to expose both high speed and full speed+ * descriptors, unless they only run at full speed.+ *+ * that means alternate endpoint descriptors (bigger packets)+ * and a "device qualifier" ... plus more construction options+ * for the config descriptor.+ */++static struct usb_qualifier_descriptor+dev_qualifier = {+	.bLength =		sizeof dev_qualifier,+	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,++	.bcdUSB =		__constant_cpu_to_le16 (0x0200),+	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,++	.bNumConfigurations =	2,+};+++struct usb_cs_as_general_descriptor {+	__u8  bLength;+	__u8  bDescriptorType;++	__u8  bDescriptorSubType;+	__u8  bTerminalLink;+	__u8  bDelay;+	__u16  wFormatTag;+} __attribute__ ((packed));++struct usb_cs_as_format_descriptor {+	__u8  bLength;+	__u8  bDescriptorType;++	__u8  bDescriptorSubType;+	__u8  bFormatType;+	__u8  bNrChannels;+	__u8  bSubframeSize;+	__u8  bBitResolution;+	__u8  bSamfreqType;+	__u8  tLowerSamFreq[3];+	__u8  tUpperSamFreq[3];+} __attribute__ ((packed));++static const struct usb_interface_descriptor+z_audio_control_if_desc = {+	.bLength =		sizeof z_audio_control_if_desc,+	.bDescriptorType =	USB_DT_INTERFACE,+	.bInterfaceNumber = 0,+	.bAlternateSetting = 0,+	.bNumEndpoints = 0,+	.bInterfaceClass = USB_CLASS_AUDIO,+	.bInterfaceSubClass = 0x1,+	.bInterfaceProtocol = 0,+	.iInterface = 0,+};++static const struct usb_interface_descriptor+z_audio_if_desc = {+	.bLength =		sizeof z_audio_if_desc,+	.bDescriptorType =	USB_DT_INTERFACE,+	.bInterfaceNumber = 1,+	.bAlternateSetting = 0,+	.bNumEndpoints = 0,+	.bInterfaceClass = USB_CLASS_AUDIO,+	.bInterfaceSubClass = 0x2,+	.bInterfaceProtocol = 0,+	.iInterface = 0,+};++static const struct usb_interface_descriptor+z_audio_if_desc2 = {+	.bLength =		sizeof z_audio_if_desc,+	.bDescriptorType =	USB_DT_INTERFACE,+	.bInterfaceNumber = 1,+	.bAlternateSetting = 1,+	.bNumEndpoints = 1,+	.bInterfaceClass = USB_CLASS_AUDIO,+	.bInterfaceSubClass = 0x2,+	.bInterfaceProtocol = 0,+	.iInterface = 0,+};++static const struct usb_cs_as_general_descriptor+z_audio_cs_as_if_desc = {+	.bLength = 7,+	.bDescriptorType = 0x24,++	.bDescriptorSubType = 0x01,+	.bTerminalLink = 0x01,+	.bDelay = 0x0,+	.wFormatTag = __constant_cpu_to_le16 (0x0001)+};+++static const struct usb_cs_as_format_descriptor+z_audio_cs_as_format_desc = {+	.bLength = 0xe,+	.bDescriptorType = 0x24,++	.bDescriptorSubType = 2,+	.bFormatType = 1,+	.bNrChannels = 1,+	.bSubframeSize = 1,+	.bBitResolution = 8,+	.bSamfreqType = 0,+	.tLowerSamFreq = {0x7e, 0x13, 0x00},+	.tUpperSamFreq = {0xe2, 0xd6, 0x00},+};++static const struct usb_endpoint_descriptor+z_iso_ep = {+	.bLength = 0x09,+	.bDescriptorType = 0x05,+	.bEndpointAddress = 0x04,+	.bmAttributes = 0x09,+	.wMaxPacketSize = 0x0038,+	.bInterval = 0x01,+	.bRefresh = 0x00,+	.bSynchAddress = 0x00,+};++static char z_iso_ep2[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};++// 9 bytes+static char z_ac_interface_header_desc[] =+{ 0x09, 0x24, 0x01, 0x00, 0x01, 0x2b, 0x00, 0x01, 0x01 };++// 12 bytes+static char z_0[] = {0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02,+		     0x03, 0x00, 0x00, 0x00};+// 13 bytes+static char z_1[] = {0x0d, 0x24, 0x06, 0x02, 0x01, 0x02, 0x15, 0x00,+		     0x02, 0x00, 0x02, 0x00, 0x00};+// 9 bytes+static char z_2[] = {0x09, 0x24, 0x03, 0x03, 0x01, 0x03, 0x00, 0x02,+		     0x00};++static char za_0[] = {0x09, 0x04, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00,+		      0x00};++static char za_1[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};++static char za_2[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x01, 0x08, 0x00,+		      0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};++static char za_3[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,+		      0x00};++static char za_4[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};++static char za_5[] = {0x09, 0x04, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00,+		      0x00};++static char za_6[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};++static char za_7[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x02, 0x10, 0x00,+		      0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};++static char za_8[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,+		      0x00};++static char za_9[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};++static char za_10[] = {0x09, 0x04, 0x01, 0x04, 0x01, 0x01, 0x02, 0x00,+		       0x00};++static char za_11[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};++static char za_12[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x00,+		       0x73, 0x13, 0x00, 0xe2, 0xd6, 0x00};++static char za_13[] = {0x09, 0x05, 0x04, 0x09, 0xe0, 0x00, 0x01, 0x00,+		       0x00};++static char za_14[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};++static char za_15[] = {0x09, 0x04, 0x01, 0x05, 0x01, 0x01, 0x02, 0x00,+		       0x00};++static char za_16[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};++static char za_17[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x03, 0x14, 0x00,+		       0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};++static char za_18[] = {0x09, 0x05, 0x04, 0x09, 0xa8, 0x00, 0x01, 0x00,+		       0x00};++static char za_19[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};++static char za_20[] = {0x09, 0x04, 0x01, 0x06, 0x01, 0x01, 0x02, 0x00,+		       0x00};++static char za_21[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};++static char za_22[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x03, 0x14, 0x00,+		       0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};++static char za_23[] = {0x09, 0x05, 0x04, 0x09, 0x50, 0x01, 0x01, 0x00,+		       0x00};++static char za_24[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};++++static const struct usb_descriptor_header *z_function [] = {+	(struct usb_descriptor_header *) &z_audio_control_if_desc,+	(struct usb_descriptor_header *) &z_ac_interface_header_desc,+	(struct usb_descriptor_header *) &z_0,+	(struct usb_descriptor_header *) &z_1,+	(struct usb_descriptor_header *) &z_2,+	(struct usb_descriptor_header *) &z_audio_if_desc,+	(struct usb_descriptor_header *) &z_audio_if_desc2,+	(struct usb_descriptor_header *) &z_audio_cs_as_if_desc,+	(struct usb_descriptor_header *) &z_audio_cs_as_format_desc,+	(struct usb_descriptor_header *) &z_iso_ep,+	(struct usb_descriptor_header *) &z_iso_ep2,+	(struct usb_descriptor_header *) &za_0,+	(struct usb_descriptor_header *) &za_1,+	(struct usb_descriptor_header *) &za_2,+	(struct usb_descriptor_header *) &za_3,+	(struct usb_descriptor_header *) &za_4,+	(struct usb_descriptor_header *) &za_5,+	(struct usb_descriptor_header *) &za_6,+	(struct usb_descriptor_header *) &za_7,+	(struct usb_descriptor_header *) &za_8,+	(struct usb_descriptor_header *) &za_9,+	(struct usb_descriptor_header *) &za_10,+	(struct usb_descriptor_header *) &za_11,+	(struct usb_descriptor_header *) &za_12,+	(struct usb_descriptor_header *) &za_13,+	(struct usb_descriptor_header *) &za_14,+	(struct usb_descriptor_header *) &za_15,+	(struct usb_descriptor_header *) &za_16,+	(struct usb_descriptor_header *) &za_17,+	(struct usb_descriptor_header *) &za_18,+	(struct usb_descriptor_header *) &za_19,+	(struct usb_descriptor_header *) &za_20,+	(struct usb_descriptor_header *) &za_21,+	(struct usb_descriptor_header *) &za_22,+	(struct usb_descriptor_header *) &za_23,+	(struct usb_descriptor_header *) &za_24,+	NULL,+};++/* maxpacket and other transfer characteristics vary by speed. */+#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))++#else++/* if there's no high speed support, maxpacket doesn't change. */+#define ep_desc(g,hs,fs) fs++#endif	/* !CONFIG_USB_GADGET_DUALSPEED */++static char				manufacturer [40];+//static char				serial [40];+static char				serial [] = "Ser 00 em";++/* static strings, in UTF-8 */+static struct usb_string		strings [] = {+	{ STRING_MANUFACTURER, manufacturer, },+	{ STRING_PRODUCT, longname, },+	{ STRING_SERIAL, serial, },+	{ STRING_LOOPBACK, loopback, },+	{ STRING_SOURCE_SINK, source_sink, },+	{  }			/* end of list */+};++static struct usb_gadget_strings	stringtab = {+	.language	= 0x0409,	/* en-us */+	.strings	= strings,+};++/*+ * config descriptors are also handcrafted.  these must agree with code+ * that sets configurations, and with code managing interfaces and their+ * altsettings.  other complexity may come from:+ *+ *  - high speed support, including "other speed config" rules+ *  - multiple configurations+ *  - interfaces with alternate settings+ *  - embedded class or vendor-specific descriptors+ *+ * this handles high speed, and has a second config that could as easily+ * have been an alternate interface setting (on most hardware).+ *+ * NOTE:  to demonstrate (and test) more USB capabilities, this driver+ * should include an altsetting to test interrupt transfers, including+ * high bandwidth modes at high speed.  (Maybe work like Intel's test+ * device?)+ */+static int+config_buf (struct usb_gadget *gadget, u8 *buf, u8 type, unsigned index)+{+	int len;+	const struct usb_descriptor_header **function;++	function = z_function;+	len = usb_gadget_config_buf (&z_config, buf, USB_BUFSIZ, function);+	if (len < 0)+		return len;+	((struct usb_config_descriptor *) buf)->bDescriptorType = type;+	return len;+}++/*-------------------------------------------------------------------------*/++static struct usb_request *+alloc_ep_req (struct usb_ep *ep, unsigned length)+{+	struct usb_request	*req;++	req = usb_ep_alloc_request (ep, GFP_ATOMIC);+	if (req) {+		req->length = length;+		req->buf = usb_ep_alloc_buffer (ep, length,+				&req->dma, GFP_ATOMIC);+		if (!req->buf) {+			usb_ep_free_request (ep, req);+			req = NULL;+		}+	}+	return req;+}++static void free_ep_req (struct usb_ep *ep, struct usb_request *req)+{+	if (req->buf)+		usb_ep_free_buffer (ep, req->buf, req->dma, req->length);+	usb_ep_free_request (ep, req);+}++/*-------------------------------------------------------------------------*/++/* optionally require specific source/sink data patterns  */++static int+check_read_data (+	struct zero_dev		*dev,+	struct usb_ep		*ep,+	struct usb_request	*req+)+{+	unsigned	i;+	u8		*buf = req->buf;++	for (i = 0; i < req->actual; i++, buf++) {+		switch (pattern) {+		/* all-zeroes has no synchronization issues */+		case 0:+			if (*buf == 0)+				continue;+			break;+		/* mod63 stays in sync with short-terminated transfers,+		 * or otherwise when host and gadget agree on how large+		 * each usb transfer request should be.  resync is done+		 * with set_interface or set_config.+		 */+		case 1:+			if (*buf == (u8)(i % 63))+				continue;+			break;+		}+		ERROR (dev, "bad OUT byte, buf [%d] = %d\n", i, *buf);+		usb_ep_set_halt (ep);+		return -EINVAL;+	}+	return 0;+}++/*-------------------------------------------------------------------------*/++static void zero_reset_config (struct zero_dev *dev)+{+	if (dev->config == 0)+		return;++	DBG (dev, "reset config\n");++	/* just disable endpoints, forcing completion of pending i/o.+	 * all our completion handlers free their requests in this case.+	 */+	if (dev->in_ep) {+		usb_ep_disable (dev->in_ep);+		dev->in_ep = NULL;+	}+	if (dev->out_ep) {+		usb_ep_disable (dev->out_ep);+		dev->out_ep = NULL;+	}+	dev->config = 0;+	del_timer (&dev->resume);+}++#define _write(f, buf, sz) (f->f_op->write(f, buf, sz, &f->f_pos))++static void+zero_isoc_complete (struct usb_ep *ep, struct usb_request *req)+{+	struct zero_dev	*dev = ep->driver_data;+	int		status = req->status;+	int i, j;++	switch (status) {++	case 0: 			/* normal completion? */+		//printk ("\nzero ---------------> isoc normal completion %d bytes\n", req->actual);+		for (i=0, j=rbuf_start; i<req->actual; i++) {+			//printk ("%02x ", ((__u8*)req->buf)[i]);+			rbuf[j] = ((__u8*)req->buf)[i];+			j++;+			if (j >= RBUF_LEN) j=0;+		}+		rbuf_start = j;+		//printk ("\n\n");++		if (rbuf_len < RBUF_LEN) {+			rbuf_len += req->actual;+			if (rbuf_len > RBUF_LEN) {+				rbuf_len = RBUF_LEN;+			}+		}++		break;++	/* this endpoint is normally active while we're configured */+	case -ECONNABORTED: 		/* hardware forced ep reset */+	case -ECONNRESET:		/* request dequeued */+	case -ESHUTDOWN:		/* disconnect from host */+		VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status,+				req->actual, req->length);+		if (ep == dev->out_ep)+			check_read_data (dev, ep, req);+		free_ep_req (ep, req);+		return;++	case -EOVERFLOW:		/* buffer overrun on read means that+					 * we didn't provide a big enough+					 * buffer.+					 */+	default:+#if 1+		DBG (dev, "%s complete --> %d, %d/%d\n", ep->name,+				status, req->actual, req->length);+#endif+	case -EREMOTEIO:		/* short read */+		break;+	}++	status = usb_ep_queue (ep, req, GFP_ATOMIC);+	if (status) {+		ERROR (dev, "kill %s:  resubmit %d bytes --> %d\n",+				ep->name, req->length, status);+		usb_ep_set_halt (ep);+		/* FIXME recover later ... somehow */+	}+}++static struct usb_request *+zero_start_isoc_ep (struct usb_ep *ep, int gfp_flags)+{+	struct usb_request	*req;+	int			status;++	req = alloc_ep_req (ep, 512);+	if (!req)+		return NULL;++	req->complete = zero_isoc_complete;++	status = usb_ep_queue (ep, req, gfp_flags);+	if (status) {+		struct zero_dev	*dev = ep->driver_data;++		ERROR (dev, "start %s --> %d\n", ep->name, status);+		free_ep_req (ep, req);+		req = NULL;+	}++	return req;+}++/* change our operational config.  this code must agree with the code+ * that returns config descriptors, and altsetting code.+ *+ * it's also responsible for power management interactions. some+ * configurations might not work with our current power sources.+ *+ * note that some device controller hardware will constrain what this+ * code can do, perhaps by disallowing more than one configuration or+ * by limiting configuration choices (like the pxa2xx).+ */+static int+zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags)+{+	int			result = 0;+	struct usb_gadget	*gadget = dev->gadget;+	const struct usb_endpoint_descriptor	*d;+	struct usb_ep		*ep;++	if (number == dev->config)+		return 0;++	zero_reset_config (dev);++	gadget_for_each_ep (ep, gadget) {++		if (strcmp (ep->name, "ep4") == 0) {++			d = (struct usb_endpoint_descripter *)&za_23; // isoc ep desc for audio i/f alt setting 6+			result = usb_ep_enable (ep, d);++			if (result == 0) {+				ep->driver_data = dev;+				dev->in_ep = ep;++				if (zero_start_isoc_ep (ep, gfp_flags) != 0) {++					dev->in_ep = ep;+					continue;+				}++				usb_ep_disable (ep);+				result = -EIO;+			}+		}++	}++	dev->config = number;+	return result;+}++/*-------------------------------------------------------------------------*/++static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req)+{+	if (req->status || req->actual != req->length)+		DBG ((struct zero_dev *) ep->driver_data,+				"setup complete --> %d, %d/%d\n",+				req->status, req->actual, req->length);+}++/*+ * The setup() callback implements all the ep0 functionality that's+ * not handled lower down, in hardware or the hardware driver (like+ * device and endpoint feature flags, and their status).  It's all+ * housekeeping for the gadget function we're implementing.  Most of+ * the work is in config-specific setup.+ */+static int+zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)+{+	struct zero_dev		*dev = get_gadget_data (gadget);+	struct usb_request	*req = dev->req;+	int			value = -EOPNOTSUPP;++	/* usually this stores reply data in the pre-allocated ep0 buffer,+	 * but config change events will reconfigure hardware.+	 */+	req->zero = 0;+	switch (ctrl->bRequest) {++	case USB_REQ_GET_DESCRIPTOR:++		switch (ctrl->wValue >> 8) {++		case USB_DT_DEVICE:+			value = min (ctrl->wLength, (u16) sizeof device_desc);+			memcpy (req->buf, &device_desc, value);+			break;+#ifdef CONFIG_USB_GADGET_DUALSPEED+		case USB_DT_DEVICE_QUALIFIER:+			if (!gadget->is_dualspeed)+				break;+			value = min (ctrl->wLength, (u16) sizeof dev_qualifier);+			memcpy (req->buf, &dev_qualifier, value);+			break;++		case USB_DT_OTHER_SPEED_CONFIG:+			if (!gadget->is_dualspeed)+				break;+			// FALLTHROUGH+#endif /* CONFIG_USB_GADGET_DUALSPEED */+		case USB_DT_CONFIG:+			value = config_buf (gadget, req->buf,+					ctrl->wValue >> 8,+					ctrl->wValue & 0xff);+			if (value >= 0)+				value = min (ctrl->wLength, (u16) value);+			break;++		case USB_DT_STRING:+			/* wIndex == language code.+			 * this driver only handles one language, you can+			 * add string tables for other languages, using+			 * any UTF-8 characters+			 */+			value = usb_gadget_get_string (&stringtab,+					ctrl->wValue & 0xff, req->buf);+			if (value >= 0) {+				value = min (ctrl->wLength, (u16) value);+			}+			break;+		}+		break;++	/* currently two configs, two speeds */+	case USB_REQ_SET_CONFIGURATION:+		if (ctrl->bRequestType != 0)+			goto unknown;++		spin_lock (&dev->lock);+		value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC);+		spin_unlock (&dev->lock);+		break;+	case USB_REQ_GET_CONFIGURATION:+		if (ctrl->bRequestType != USB_DIR_IN)+			goto unknown;+		*(u8 *)req->buf = dev->config;+		value = min (ctrl->wLength, (u16) 1);+		break;++	/* until we add altsetting support, or other interfaces,+	 * only 0/0 are possible.  pxa2xx only supports 0/0 (poorly)+	 * and already killed pending endpoint I/O.+	 */+	case USB_REQ_SET_INTERFACE:++		if (ctrl->bRequestType != USB_RECIP_INTERFACE)+			goto unknown;+		spin_lock (&dev->lock);+		if (dev->config) {+			u8		config = dev->config;++			/* resets interface configuration, forgets about+			 * previous transaction state (queued bufs, etc)+			 * and re-inits endpoint state (toggle etc)+			 * no response queued, just zero status == success.+			 * if we had more than one interface we couldn't+			 * use this "reset the config" shortcut.+			 */+			zero_reset_config (dev);+			zero_set_config (dev, config, GFP_ATOMIC);+			value = 0;+		}+		spin_unlock (&dev->lock);+		break;+	case USB_REQ_GET_INTERFACE:+		if ((ctrl->bRequestType == 0x21) && (ctrl->wIndex == 0x02)) {+			value = ctrl->wLength;+			break;+		}+		else {+			if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))+				goto unknown;+			if (!dev->config)+				break;+			if (ctrl->wIndex != 0) {+				value = -EDOM;+				break;+			}+			*(u8 *)req->buf = 0;+			value = min (ctrl->wLength, (u16) 1);+		}+		break;++	/*+	 * These are the same vendor-specific requests supported by+	 * Intel's USB 2.0 compliance test devices.  We exceed that+	 * device spec by allowing multiple-packet requests.+	 */+	case 0x5b:	/* control WRITE test -- fill the buffer */+		if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))+			goto unknown;+		if (ctrl->wValue || ctrl->wIndex)+			break;+		/* just read that many bytes into the buffer */+		if (ctrl->wLength > USB_BUFSIZ)+			break;+		value = ctrl->wLength;+		break;+	case 0x5c:	/* control READ test -- return the buffer */+		if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))+			goto unknown;+		if (ctrl->wValue || ctrl->wIndex)+			break;+		/* expect those bytes are still in the buffer; send back */+		if (ctrl->wLength > USB_BUFSIZ+				|| ctrl->wLength != req->length)+			break;+		value = ctrl->wLength;+		break;++	case 0x01: // SET_CUR+	case 0x02:+	case 0x03:+	case 0x04:+	case 0x05:+		value = ctrl->wLength;+		break;+	case 0x81:+		switch (ctrl->wValue) {+		case 0x0201:+		case 0x0202:+			((u8*)req->buf)[0] = 0x00;+			((u8*)req->buf)[1] = 0xe3;+			break;+		case 0x0300:+		case 0x0500:+			((u8*)req->buf)[0] = 0x00;+			break;+		}+		//((u8*)req->buf)[0] = 0x81;+		//((u8*)req->buf)[1] = 0x81;+		value = ctrl->wLength;+		break;+	case 0x82:+		switch (ctrl->wValue) {+		case 0x0201:+		case 0x0202:+			((u8*)req->buf)[0] = 0x00;+			((u8*)req->buf)[1] = 0xc3;+			break;+		case 0x0300:+		case 0x0500:+			((u8*)req->buf)[0] = 0x00;+			break;+		}+		//((u8*)req->buf)[0] = 0x82;+		//((u8*)req->buf)[1] = 0x82;+		value = ctrl->wLength;+		break;+	case 0x83:+		switch (ctrl->wValue) {+		case 0x0201:+		case 0x0202:+			((u8*)req->buf)[0] = 0x00;+			((u8*)req->buf)[1] = 0x00;+			break;+		case 0x0300:+			((u8*)req->buf)[0] = 0x60;+			break;+		case 0x0500:+			((u8*)req->buf)[0] = 0x18;+			break;+		}+		//((u8*)req->buf)[0] = 0x83;+		//((u8*)req->buf)[1] = 0x83;+		value = ctrl->wLength;+		break;+	case 0x84:+		switch (ctrl->wValue) {+		case 0x0201:+		case 0x0202:+			((u8*)req->buf)[0] = 0x00;+			((u8*)req->buf)[1] = 0x01;+			break;+		case 0x0300:+		case 0x0500:+			((u8*)req->buf)[0] = 0x08;+			break;+		}+		//((u8*)req->buf)[0] = 0x84;+		//((u8*)req->buf)[1] = 0x84;+		value = ctrl->wLength;+		break;+	case 0x85:+		((u8*)req->buf)[0] = 0x85;+		((u8*)req->buf)[1] = 0x85;+		value = ctrl->wLength;+		break;+++	default:+unknown:+		printk("unknown control req%02x.%02x v%04x i%04x l%d\n",+			ctrl->bRequestType, ctrl->bRequest,+			ctrl->wValue, ctrl->wIndex, ctrl->wLength);+	}++	/* respond with data transfer before status phase? */+	if (value >= 0) {+		req->length = value;+		req->zero = value < ctrl->wLength+				&& (value % gadget->ep0->maxpacket) == 0;+		value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);+		if (value < 0) {+			DBG (dev, "ep_queue < 0 --> %d\n", value);+			req->status = 0;+			zero_setup_complete (gadget->ep0, req);+		}+	}++	/* device either stalls (value < 0) or reports success */+	return value;+}++static void+zero_disconnect (struct usb_gadget *gadget)+{+	struct zero_dev		*dev = get_gadget_data (gadget);+	unsigned long		flags;++	spin_lock_irqsave (&dev->lock, flags);+	zero_reset_config (dev);++	/* a more significant application might have some non-usb+	 * activities to quiesce here, saving resources like power+	 * or pushing the notification up a network stack.+	 */+	spin_unlock_irqrestore (&dev->lock, flags);++	/* next we may get setup() calls to enumerate new connections;+	 * or an unbind() during shutdown (including removing module).+	 */+}++static void+zero_autoresume (unsigned long _dev)+{+	struct zero_dev	*dev = (struct zero_dev *) _dev;+	int		status;++	/* normally the host would be woken up for something+	 * more significant than just a timer firing...+	 */+	if (dev->gadget->speed != USB_SPEED_UNKNOWN) {+		status = usb_gadget_wakeup (dev->gadget);+		DBG (dev, "wakeup --> %d\n", status);+	}+}++/*-------------------------------------------------------------------------*/++static void+zero_unbind (struct usb_gadget *gadget)+{+	struct zero_dev		*dev = get_gadget_data (gadget);++	DBG (dev, "unbind\n");++	/* we've already been disconnected ... no i/o is active */+	if (dev->req)+		free_ep_req (gadget->ep0, dev->req);+	del_timer_sync (&dev->resume);+	kfree (dev);+	set_gadget_data (gadget, NULL);+}++static int+zero_bind (struct usb_gadget *gadget)+{+	struct zero_dev		*dev;+	//struct usb_ep		*ep;++	printk("binding\n");+	/*+	 * DRIVER POLICY CHOICE:  you may want to do this differently.+	 * One thing to avoid is reusing a bcdDevice revision code+	 * with different host-visible configurations or behavior+	 * restrictions -- using ep1in/ep2out vs ep1out/ep3in, etc+	 */+	//device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);+++	/* ok, we made sense of the hardware ... */+	dev = kmalloc (sizeof *dev, SLAB_KERNEL);+	if (!dev)+		return -ENOMEM;+	memset (dev, 0, sizeof *dev);+	spin_lock_init (&dev->lock);+	dev->gadget = gadget;+	set_gadget_data (gadget, dev);++	/* preallocate control response and buffer */+	dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);+	if (!dev->req)+		goto enomem;+	dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,+				&dev->req->dma, GFP_KERNEL);+	if (!dev->req->buf)+		goto enomem;++	dev->req->complete = zero_setup_complete;++	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;++#ifdef CONFIG_USB_GADGET_DUALSPEED+	/* assume ep0 uses the same value for both speeds ... */+	dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;++	/* and that all endpoints are dual-speed */+	//hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;+	//hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;+#endif++	usb_gadget_set_selfpowered (gadget);++	init_timer (&dev->resume);+	dev->resume.function = zero_autoresume;+	dev->resume.data = (unsigned long) dev;++	gadget->ep0->driver_data = dev;++	INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);+	INFO (dev, "using %s, OUT %s IN %s\n", gadget->name,+		EP_OUT_NAME, EP_IN_NAME);++	snprintf (manufacturer, sizeof manufacturer,+		UTS_SYSNAME " " UTS_RELEASE " with %s",+		gadget->name);++	return 0;++enomem:+	zero_unbind (gadget);+	return -ENOMEM;+}++/*-------------------------------------------------------------------------*/++static void+zero_suspend (struct usb_gadget *gadget)+{+	struct zero_dev		*dev = get_gadget_data (gadget);++	if (gadget->speed == USB_SPEED_UNKNOWN)+		return;++	if (autoresume) {+		mod_timer (&dev->resume, jiffies + (HZ * autoresume));+		DBG (dev, "suspend, wakeup in %d seconds\n", autoresume);+	} else+		DBG (dev, "suspend\n");+}++static void+zero_resume (struct usb_gadget *gadget)+{+	struct zero_dev		*dev = get_gadget_data (gadget);++	DBG (dev, "resume\n");+	del_timer (&dev->resume);+}+++/*-------------------------------------------------------------------------*/++static struct usb_gadget_driver zero_driver = {+#ifdef CONFIG_USB_GADGET_DUALSPEED+	.speed		= USB_SPEED_HIGH,+#else+	.speed		= USB_SPEED_FULL,+#endif+	.function	= (char *) longname,+	.bind		= zero_bind,+	.unbind		= zero_unbind,++	.setup		= zero_setup,+	.disconnect	= zero_disconnect,++	.suspend	= zero_suspend,+	.resume		= zero_resume,++	.driver 	= {+		.name		= (char *) shortname,+		// .shutdown = ...+		// .suspend = ...+		// .resume = ...+	},+};++MODULE_AUTHOR ("David Brownell");+MODULE_LICENSE ("Dual BSD/GPL");++static struct proc_dir_entry *pdir, *pfile;++static int isoc_read_data (char *page, char **start,+			   off_t off, int count,+			   int *eof, void *data)+{+	int i;+	static int c = 0;+	static int done = 0;+	static int s = 0;++/*+	printk ("\ncount: %d\n", count);+	printk ("rbuf_start: %d\n", rbuf_start);+	printk ("rbuf_len: %d\n", rbuf_len);+	printk ("off: %d\n", off);+	printk ("start: %p\n\n", *start);+*/+	if (done) {+		c = 0;+		done = 0;+		*eof = 1;+		return 0;+	}++	if (c == 0) {+		if (rbuf_len == RBUF_LEN)+			s = rbuf_start;+		else s = 0;+	}++	for (i=0; i<count && c<rbuf_len; i++, c++) {+		page[i] = rbuf[(c+s) % RBUF_LEN];+	}+	*start = page;++	if (c >= rbuf_len) {+		*eof = 1;+		done = 1;+	}+++	return i;+}++static int __init init (void)+{++	int retval = 0;++	pdir = proc_mkdir("isoc_test", NULL);+	if(pdir == NULL) {+		retval = -ENOMEM;+		printk("Error creating dir\n");+		goto done;+	}+	pdir->owner = THIS_MODULE;++	pfile = create_proc_read_entry("isoc_data",+				       0444, pdir,+				       isoc_read_data,+				       NULL);+	if (pfile == NULL) {+		retval = -ENOMEM;+		printk("Error creating file\n");+		goto no_file;+	}+	pfile->owner = THIS_MODULE;++	return usb_gadget_register_driver (&zero_driver);++ no_file:+	remove_proc_entry("isoc_data", NULL);+ done:+	return retval;+}+module_init (init);++static void __exit cleanup (void)+{++	usb_gadget_unregister_driver (&zero_driver);++	remove_proc_entry("isoc_data", pdir);+	remove_proc_entry("isoc_test", NULL);+}+module_exit (cleanup);diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_cfi_common.h linux-3.11.10/drivers/usb/host/dwc_otg/dwc_cfi_common.h--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_cfi_common.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_cfi_common.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,142 @@+/* ==========================================================================+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */++#if !defined(__DWC_CFI_COMMON_H__)+#define __DWC_CFI_COMMON_H__++//#include <linux/types.h>++/**+ * @file+ *+ * This file contains the CFI specific common constants, interfaces+ * (functions and macros) and structures for Linux. No PCD specific+ * data structure or definition is to be included in this file.+ *+ */++/** This is a request for all Core Features */+#define VEN_CORE_GET_FEATURES		0xB1++/** This is a request to get the value of a specific Core Feature */+#define VEN_CORE_GET_FEATURE		0xB2++/** This command allows the host to set the value of a specific Core Feature */+#define VEN_CORE_SET_FEATURE		0xB3++/** This command allows the host to set the default values of+ * either all or any specific Core Feature+ */+#define VEN_CORE_RESET_FEATURES		0xB4++/** This command forces the PCD to write the deferred values of a Core Features */+#define VEN_CORE_ACTIVATE_FEATURES	0xB5++/** This request reads a DWORD value from a register at the specified offset */+#define VEN_CORE_READ_REGISTER		0xB6++/** This request writes a DWORD value into a register at the specified offset */+#define VEN_CORE_WRITE_REGISTER		0xB7++/** This structure is the header of the Core Features dataset returned to+ *  the Host+ */+struct cfi_all_features_header {+/** The features header structure length is */+#define CFI_ALL_FEATURES_HDR_LEN		8+	/**+	 * The total length of the features dataset returned to the Host+	 */+	uint16_t wTotalLen;++	/**+	 * CFI version number inBinary-Coded Decimal (i.e., 1.00 is 100H).+	 * This field identifies the version of the CFI Specification with which+	 * the device is compliant.+	 */+	uint16_t wVersion;++	/** The ID of the Core */+	uint16_t wCoreID;+#define CFI_CORE_ID_UDC		1+#define CFI_CORE_ID_OTG		2+#define CFI_CORE_ID_WUDEV	3++	/** Number of features returned by VEN_CORE_GET_FEATURES request */+	uint16_t wNumFeatures;+} UPACKED;++typedef struct cfi_all_features_header cfi_all_features_header_t;++/** This structure is a header of the Core Feature descriptor dataset returned to+ *  the Host after the VEN_CORE_GET_FEATURES request+ */+struct cfi_feature_desc_header {+#define CFI_FEATURE_DESC_HDR_LEN	8++	/** The feature ID */+	uint16_t wFeatureID;++	/** Length of this feature descriptor in bytes - including the+	 * length of the feature name string+	 */+	uint16_t wLength;++	/** The data length of this feature in bytes */+	uint16_t wDataLength;++	/**+	 * Attributes of this features+	 * D0: Access rights+	 * 0 - Read/Write+	 * 1 - Read only+	 */+	uint8_t bmAttributes;+#define CFI_FEATURE_ATTR_RO		1+#define CFI_FEATURE_ATTR_RW		0++	/** Length of the feature name in bytes */+	uint8_t bNameLen;++	/** The feature name buffer */+	//uint8_t *name;+} UPACKED;++typedef struct cfi_feature_desc_header cfi_feature_desc_header_t;++/**+ * This structure describes a NULL terminated string referenced by its id field.+ * It is very similar to usb_string structure but has the id field type set to 16-bit.+ */+struct cfi_string {+	uint16_t id;+	const uint8_t *s;+};+typedef struct cfi_string cfi_string_t;++#endifdiff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_adp.c linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_adp.c--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_adp.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_adp.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,854 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $+ * $Revision: #12 $+ * $Date: 2011/10/26 $+ * $Change: 1873028 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */++#include "dwc_os.h"+#include "dwc_otg_regs.h"+#include "dwc_otg_cil.h"+#include "dwc_otg_adp.h"++/** @file+ *+ * This file contains the most of the Attach Detect Protocol implementation for+ * the driver to support OTG Rev2.0.+ *+ */++void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value)+{+	adpctl_data_t adpctl;++	adpctl.d32 = value;+	adpctl.b.ar = 0x2;++	DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);++	while (adpctl.b.ar) {+		adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);+	}++}++/**+ * Function is called to read ADP registers+ */+uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if)+{+	adpctl_data_t adpctl;++	adpctl.d32 = 0;+	adpctl.b.ar = 0x1;++	DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);++	while (adpctl.b.ar) {+		adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);+	}++	return adpctl.d32;+}++/**+ * Function is called to read ADPCTL register and filter Write-clear bits+ */+uint32_t dwc_otg_adp_read_reg_filter(dwc_otg_core_if_t * core_if)+{+	adpctl_data_t adpctl;++	adpctl.d32 = dwc_otg_adp_read_reg(core_if);+	adpctl.b.adp_tmout_int = 0;+	adpctl.b.adp_prb_int = 0;+	adpctl.b.adp_tmout_int = 0;++	return adpctl.d32;+}++/**+ * Function is called to write ADP registers+ */+void dwc_otg_adp_modify_reg(dwc_otg_core_if_t * core_if, uint32_t clr,+			    uint32_t set)+{+	dwc_otg_adp_write_reg(core_if,+			      (dwc_otg_adp_read_reg(core_if) & (~clr)) | set);+}++static void adp_sense_timeout(void *ptr)+{+	dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;+	core_if->adp.sense_timer_started = 0;+	DWC_PRINTF("ADP SENSE TIMEOUT\n");+	if (core_if->adp_enable) {+		dwc_otg_adp_sense_stop(core_if);+		dwc_otg_adp_probe_start(core_if);+	}+}++/**+ * This function is called when the ADP vbus timer expires. Timeout is 1.1s.+ */+static void adp_vbuson_timeout(void *ptr)+{+	gpwrdn_data_t gpwrdn;+	dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;+	hprt0_data_t hprt0 = {.d32 = 0 };+	pcgcctl_data_t pcgcctl = {.d32 = 0 };+	DWC_PRINTF("%s: 1.1 seconds expire after turning on VBUS\n",__FUNCTION__);+	if (core_if) {+		core_if->adp.vbuson_timer_started = 0;+		/* Turn off vbus */+		hprt0.b.prtpwr = 1;+		DWC_MODIFY_REG32(core_if->host_if->hprt0, hprt0.d32, 0);+		gpwrdn.d32 = 0;++		/* Power off the core */+		if (core_if->power_down == 2) {+			/* Enable Wakeup Logic */+//                      gpwrdn.b.wkupactiv = 1;+			gpwrdn.b.pmuactv = 0;+			gpwrdn.b.pwrdnrstn = 1;+			gpwrdn.b.pwrdnclmp = 1;+			DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,+					 gpwrdn.d32);++			/* Suspend the Phy Clock */+			pcgcctl.b.stoppclk = 1;+			DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);++			/* Switch on VDD */+//                      gpwrdn.b.wkupactiv = 1;+			gpwrdn.b.pmuactv = 1;+			gpwrdn.b.pwrdnrstn = 1;+			gpwrdn.b.pwrdnclmp = 1;+			DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,+					 gpwrdn.d32);+		} else {+			/* Enable Power Down Logic */+			gpwrdn.b.pmuintsel = 1;+			gpwrdn.b.pmuactv = 1;+			DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);+		}++		/* Power off the core */+		if (core_if->power_down == 2) {+			gpwrdn.d32 = 0;+			gpwrdn.b.pwrdnswtch = 1;+			DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn,+					 gpwrdn.d32, 0);+		}++		/* Unmask SRP detected interrupt from Power Down Logic */+		gpwrdn.d32 = 0;+		gpwrdn.b.srp_det_msk = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);++		dwc_otg_adp_probe_start(core_if);+		dwc_otg_dump_global_registers(core_if);+		dwc_otg_dump_host_registers(core_if);+	}++}++/**+ * Start the ADP Initial Probe timer to detect if Port Connected interrupt is+ * not asserted within 1.1 seconds.+ *+ * @param core_if the pointer to core_if strucure.+ */+void dwc_otg_adp_vbuson_timer_start(dwc_otg_core_if_t * core_if)+{+	core_if->adp.vbuson_timer_started = 1;+	if (core_if->adp.vbuson_timer)+	{+		DWC_PRINTF("SCHEDULING VBUSON TIMER\n");+		/* 1.1 secs + 60ms necessary for cil_hcd_start*/+		DWC_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 1160);+	} else {+		DWC_WARN("VBUSON_TIMER = %p\n",core_if->adp.vbuson_timer);+	}+}++#if 0+/**+ * Masks all DWC OTG core interrupts+ *+ */+static void mask_all_interrupts(dwc_otg_core_if_t * core_if)+{+	int i;+	gahbcfg_data_t ahbcfg = {.d32 = 0 };++	/* Mask Host Interrupts */++	/* Clear and disable HCINTs */+	for (i = 0; i < core_if->core_params->host_channels; i++) {+		DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, 0);+		DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcint, 0xFFFFFFFF);++	}++	/* Clear and disable HAINT */+	DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, 0x0000);+	DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haint, 0xFFFFFFFF);++	/* Mask Device Interrupts */+	if (!core_if->multiproc_int_enable) {+		/* Clear and disable IN Endpoint interrupts */+		DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, 0);+		for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {+			DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->+					diepint, 0xFFFFFFFF);+		}++		/* Clear and disable OUT Endpoint interrupts */+		DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 0);+		for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {+			DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->+					doepint, 0xFFFFFFFF);+		}++		/* Clear and disable DAINT */+		DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daint,+				0xFFFFFFFF);+		DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, 0);+	} else {+		for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {+			DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->+					diepeachintmsk[i], 0);+			DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->+					diepint, 0xFFFFFFFF);+		}++		for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {+			DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->+					doepeachintmsk[i], 0);+			DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->+					doepint, 0xFFFFFFFF);+		}++		DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,+				0);+		DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachint,+				0xFFFFFFFF);++	}++	/* Disable interrupts */+	ahbcfg.b.glblintrmsk = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);++	/* Disable all interrupts. */+	DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);++	/* Clear any pending interrupts */+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);++	/* Clear any pending OTG Interrupts */+	DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, 0xFFFFFFFF);+}++/**+ * Unmask Port Connection Detected interrupt+ *+ */+static void unmask_conn_det_intr(dwc_otg_core_if_t * core_if)+{+	gintmsk_data_t gintmsk = {.d32 = 0,.b.portintr = 1 };++	DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);+}+#endif++/**+ * Starts the ADP Probing+ *+ * @param core_if the pointer to core_if structure.+ */+uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if)+{++	adpctl_data_t adpctl = {.d32 = 0};+	gpwrdn_data_t gpwrdn;+#if 0+	adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1,+								.b.adp_sns_int = 1, b.adp_tmout_int};+#endif+	dwc_otg_disable_global_interrupts(core_if);+	DWC_PRINTF("ADP Probe Start\n");+	core_if->adp.probe_enabled = 1;++	adpctl.b.adpres = 1;+	dwc_otg_adp_write_reg(core_if, adpctl.d32);++	while (adpctl.b.adpres) {+		adpctl.d32 = dwc_otg_adp_read_reg(core_if);+	}++	adpctl.d32 = 0;+	gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);++	/* In Host mode unmask SRP detected interrupt */+	gpwrdn.d32 = 0;+	gpwrdn.b.sts_chngint_msk = 1;+	if (!gpwrdn.b.idsts) {+		gpwrdn.b.srp_det_msk = 1;+	}+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);++	adpctl.b.adp_tmout_int_msk = 1;+	adpctl.b.adp_prb_int_msk = 1;+	adpctl.b.prb_dschg = 1;+	adpctl.b.prb_delta = 1;+	adpctl.b.prb_per = 1;+	adpctl.b.adpen = 1;+	adpctl.b.enaprb = 1;++	dwc_otg_adp_write_reg(core_if, adpctl.d32);+	DWC_PRINTF("ADP Probe Finish\n");+	return 0;+}++/**+ * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted+ * within 3 seconds.+ *+ * @param core_if the pointer to core_if strucure.+ */+void dwc_otg_adp_sense_timer_start(dwc_otg_core_if_t * core_if)+{+	core_if->adp.sense_timer_started = 1;+	DWC_TIMER_SCHEDULE(core_if->adp.sense_timer, 3000 /* 3 secs */ );+}++/**+ * Starts the ADP Sense+ *+ * @param core_if the pointer to core_if strucure.+ */+uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if)+{+	adpctl_data_t adpctl;++	DWC_PRINTF("ADP Sense Start\n");++	/* Unmask ADP sense interrupt and mask all other from the core */+	adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);+	adpctl.b.adp_sns_int_msk = 1;+	dwc_otg_adp_write_reg(core_if, adpctl.d32);+	dwc_otg_disable_global_interrupts(core_if); // vahrama++	/* Set ADP reset bit*/+	adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);+	adpctl.b.adpres = 1;+	dwc_otg_adp_write_reg(core_if, adpctl.d32);++	while (adpctl.b.adpres) {+		adpctl.d32 = dwc_otg_adp_read_reg(core_if);+	}++	adpctl.b.adpres = 0;+	adpctl.b.adpen = 1;+	adpctl.b.enasns = 1;+	dwc_otg_adp_write_reg(core_if, adpctl.d32);++	dwc_otg_adp_sense_timer_start(core_if);++	return 0;+}++/**+ * Stops the ADP Probing+ *+ * @param core_if the pointer to core_if strucure.+ */+uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if)+{++	adpctl_data_t adpctl;+	DWC_PRINTF("Stop ADP probe\n");+	core_if->adp.probe_enabled = 0;+	core_if->adp.probe_counter = 0;+	adpctl.d32 = dwc_otg_adp_read_reg(core_if);++	adpctl.b.adpen = 0;+	adpctl.b.adp_prb_int = 1;+	adpctl.b.adp_tmout_int = 1;+	adpctl.b.adp_sns_int = 1;+	dwc_otg_adp_write_reg(core_if, adpctl.d32);++	return 0;+}++/**+ * Stops the ADP Sensing+ *+ * @param core_if the pointer to core_if strucure.+ */+uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if)+{+	adpctl_data_t adpctl;++	core_if->adp.sense_enabled = 0;++	adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);+	adpctl.b.enasns = 0;+	adpctl.b.adp_sns_int = 1;+	dwc_otg_adp_write_reg(core_if, adpctl.d32);++	return 0;+}++/**+ * Called to turn on the VBUS after initial ADP probe in host mode.+ * If port power was already enabled in cil_hcd_start function then+ * only schedule a timer.+ *+ * @param core_if the pointer to core_if structure.+ */+void dwc_otg_adp_turnon_vbus(dwc_otg_core_if_t * core_if)+{+	hprt0_data_t hprt0 = {.d32 = 0 };+	hprt0.d32 = dwc_otg_read_hprt0(core_if);+	DWC_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr);++	if (hprt0.b.prtpwr == 0) {+		hprt0.b.prtpwr = 1;+		//DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+	}++	dwc_otg_adp_vbuson_timer_start(core_if);+}++/**+ * Called right after driver is loaded+ * to perform initial actions for ADP+ *+ * @param core_if the pointer to core_if structure.+ * @param is_host - flag for current mode of operation either from GINTSTS or GPWRDN+ */+void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host)+{+	gpwrdn_data_t gpwrdn;++	DWC_PRINTF("ADP Initial Start\n");+	core_if->adp.adp_started = 1;++	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);+	dwc_otg_disable_global_interrupts(core_if);+	if (is_host) {+		DWC_PRINTF("HOST MODE\n");+		/* Enable Power Down Logic Interrupt*/+		gpwrdn.d32 = 0;+		gpwrdn.b.pmuintsel = 1;+		gpwrdn.b.pmuactv = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);+		/* Initialize first ADP probe to obtain Ramp Time value */+		core_if->adp.initial_probe = 1;+		dwc_otg_adp_probe_start(core_if);+	} else {+		gotgctl_data_t gotgctl;+		gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);+		DWC_PRINTF("DEVICE MODE\n");+		if (gotgctl.b.bsesvld == 0) {+			/* Enable Power Down Logic Interrupt*/+			gpwrdn.d32 = 0;+			DWC_PRINTF("VBUS is not valid - start ADP probe\n");+			gpwrdn.b.pmuintsel = 1;+			gpwrdn.b.pmuactv = 1;+			DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);+			core_if->adp.initial_probe = 1;+			dwc_otg_adp_probe_start(core_if);+		} else {+			DWC_PRINTF("VBUS is valid - initialize core as a Device\n");+			core_if->op_state = B_PERIPHERAL;+			dwc_otg_core_init(core_if);+			dwc_otg_enable_global_interrupts(core_if);+			cil_pcd_start(core_if);+			dwc_otg_dump_global_registers(core_if);+			dwc_otg_dump_dev_registers(core_if);+		}+	}+}++void dwc_otg_adp_init(dwc_otg_core_if_t * core_if)+{+	core_if->adp.adp_started = 0;+	core_if->adp.initial_probe = 0;+	core_if->adp.probe_timer_values[0] = -1;+	core_if->adp.probe_timer_values[1] = -1;+	core_if->adp.probe_enabled = 0;+	core_if->adp.sense_enabled = 0;+	core_if->adp.sense_timer_started = 0;+	core_if->adp.vbuson_timer_started = 0;+	core_if->adp.probe_counter = 0;+	core_if->adp.gpwrdn = 0;+	core_if->adp.attached = DWC_OTG_ADP_UNKOWN;+	/* Initialize timers */+	core_if->adp.sense_timer =+	    DWC_TIMER_ALLOC("ADP SENSE TIMER", adp_sense_timeout, core_if);+	core_if->adp.vbuson_timer =+	    DWC_TIMER_ALLOC("ADP VBUS ON TIMER", adp_vbuson_timeout, core_if);+	if (!core_if->adp.sense_timer || !core_if->adp.vbuson_timer)+	{+		DWC_ERROR("Could not allocate memory for ADP timers\n");+	}+}++void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if)+{+	gpwrdn_data_t gpwrdn = { .d32 = 0 };+	gpwrdn.b.pmuintsel = 1;+	gpwrdn.b.pmuactv = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++	if (core_if->adp.probe_enabled)+		dwc_otg_adp_probe_stop(core_if);+	if (core_if->adp.sense_enabled)+		dwc_otg_adp_sense_stop(core_if);+	if (core_if->adp.sense_timer_started)+		DWC_TIMER_CANCEL(core_if->adp.sense_timer);+	if (core_if->adp.vbuson_timer_started)+		DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);+	DWC_TIMER_FREE(core_if->adp.sense_timer);+	DWC_TIMER_FREE(core_if->adp.vbuson_timer);+}++/////////////////////////////////////////////////////////////////////+////////////// ADP Interrupt Handlers ///////////////////////////////+/////////////////////////////////////////////////////////////////////+/**+ * This function sets Ramp Timer values+ */+static uint32_t set_timer_value(dwc_otg_core_if_t * core_if, uint32_t val)+{+	if (core_if->adp.probe_timer_values[0] == -1) {+		core_if->adp.probe_timer_values[0] = val;+		core_if->adp.probe_timer_values[1] = -1;+		return 1;+	} else {+		core_if->adp.probe_timer_values[1] =+		    core_if->adp.probe_timer_values[0];+		core_if->adp.probe_timer_values[0] = val;+		return 0;+	}+}++/**+ * This function compares Ramp Timer values+ */+static uint32_t compare_timer_values(dwc_otg_core_if_t * core_if)+{+	uint32_t diff;+	if (core_if->adp.probe_timer_values[0]>=core_if->adp.probe_timer_values[1])+			diff = core_if->adp.probe_timer_values[0]-core_if->adp.probe_timer_values[1];+	else+			diff = core_if->adp.probe_timer_values[1]-core_if->adp.probe_timer_values[0];+	if(diff < 2) {+		return 0;+	} else {+		return 1;+	}+}++/**+ * This function handles ADP Probe Interrupts+ */+static int32_t dwc_otg_adp_handle_prb_intr(dwc_otg_core_if_t * core_if,+						 uint32_t val)+{+	adpctl_data_t adpctl = {.d32 = 0 };+	gpwrdn_data_t gpwrdn, temp;+	adpctl.d32 = val;++	temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);+	core_if->adp.probe_counter++;+	core_if->adp.gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);+	if (adpctl.b.rtim == 0 && !temp.b.idsts){+		DWC_PRINTF("RTIM value is 0\n");+		goto exit;+	}+	if (set_timer_value(core_if, adpctl.b.rtim) &&+	    core_if->adp.initial_probe) {+		core_if->adp.initial_probe = 0;+		dwc_otg_adp_probe_stop(core_if);+		gpwrdn.d32 = 0;+		gpwrdn.b.pmuactv = 1;+		gpwrdn.b.pmuintsel = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+		DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);++		/* check which value is for device mode and which for Host mode */+		if (!temp.b.idsts) {	/* considered host mode value is 0 */+			/*+			 * Turn on VBUS after initial ADP probe.+			 */+			core_if->op_state = A_HOST;+			dwc_otg_enable_global_interrupts(core_if);+			DWC_SPINUNLOCK(core_if->lock);+			cil_hcd_start(core_if);+			dwc_otg_adp_turnon_vbus(core_if);+			DWC_SPINLOCK(core_if->lock);+		} else {+			/*+			 * Initiate SRP after initial ADP probe.+			 */+			dwc_otg_enable_global_interrupts(core_if);+			dwc_otg_initiate_srp(core_if);+		}+	} else if (core_if->adp.probe_counter > 2){+		gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);+		if (compare_timer_values(core_if)) {+			DWC_PRINTF("Difference in timer values !!! \n");+//                      core_if->adp.attached = DWC_OTG_ADP_ATTACHED;+			dwc_otg_adp_probe_stop(core_if);++			/* Power on the core */+			if (core_if->power_down == 2) {+				gpwrdn.b.pwrdnswtch = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, 0, gpwrdn.d32);+			}++			/* check which value is for device mode and which for Host mode */+			if (!temp.b.idsts) {	/* considered host mode value is 0 */+				/* Disable Interrupt from Power Down Logic */+				gpwrdn.d32 = 0;+				gpwrdn.b.pmuintsel = 1;+				gpwrdn.b.pmuactv = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, gpwrdn.d32, 0);++				/*+				 * Initialize the Core for Host mode.+				 */+				core_if->op_state = A_HOST;+				dwc_otg_core_init(core_if);+				dwc_otg_enable_global_interrupts(core_if);+				cil_hcd_start(core_if);+			} else {+				gotgctl_data_t gotgctl;+				/* Mask SRP detected interrupt from Power Down Logic */+				gpwrdn.d32 = 0;+				gpwrdn.b.srp_det_msk = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, gpwrdn.d32, 0);++				/* Disable Power Down Logic */+				gpwrdn.d32 = 0;+				gpwrdn.b.pmuintsel = 1;+				gpwrdn.b.pmuactv = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, gpwrdn.d32, 0);++				/*+				 * Initialize the Core for Device mode.+				 */+				core_if->op_state = B_PERIPHERAL;+				dwc_otg_core_init(core_if);+				dwc_otg_enable_global_interrupts(core_if);+				cil_pcd_start(core_if);++				gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);+				if (!gotgctl.b.bsesvld) {+					dwc_otg_initiate_srp(core_if);+				}+			}+		}+		if (core_if->power_down == 2) {+			if (gpwrdn.b.bsessvld) {+				/* Mask SRP detected interrupt from Power Down Logic */+				gpwrdn.d32 = 0;+				gpwrdn.b.srp_det_msk = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++				/* Disable Power Down Logic */+				gpwrdn.d32 = 0;+				gpwrdn.b.pmuactv = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++				/*+				 * Initialize the Core for Device mode.+				 */+				core_if->op_state = B_PERIPHERAL;+				dwc_otg_core_init(core_if);+				dwc_otg_enable_global_interrupts(core_if);+				cil_pcd_start(core_if);+			}+		}+	}+exit:+	/* Clear interrupt */+	adpctl.d32 = dwc_otg_adp_read_reg(core_if);+	adpctl.b.adp_prb_int = 1;+	dwc_otg_adp_write_reg(core_if, adpctl.d32);++	return 0;+}++/**+ * This function hadles ADP Sense Interrupt+ */+static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t * core_if)+{+	adpctl_data_t adpctl;+	/* Stop ADP Sense timer */+	DWC_TIMER_CANCEL(core_if->adp.sense_timer);++	/* Restart ADP Sense timer */+	dwc_otg_adp_sense_timer_start(core_if);++	/* Clear interrupt */+	adpctl.d32 = dwc_otg_adp_read_reg(core_if);+	adpctl.b.adp_sns_int = 1;+	dwc_otg_adp_write_reg(core_if, adpctl.d32);++	return 0;+}++/**+ * This function handles ADP Probe Interrupts+ */+static int32_t dwc_otg_adp_handle_prb_tmout_intr(dwc_otg_core_if_t * core_if,+						 uint32_t val)+{+	adpctl_data_t adpctl = {.d32 = 0 };+	adpctl.d32 = val;+	set_timer_value(core_if, adpctl.b.rtim);++	/* Clear interrupt */+	adpctl.d32 = dwc_otg_adp_read_reg(core_if);+	adpctl.b.adp_tmout_int = 1;+	dwc_otg_adp_write_reg(core_if, adpctl.d32);++	return 0;+}++/**+ * ADP Interrupt handler.+ *+ */+int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if)+{+	int retval = 0;+	adpctl_data_t adpctl = {.d32 = 0};++	adpctl.d32 = dwc_otg_adp_read_reg(core_if);+	DWC_PRINTF("ADPCTL = %08x\n",adpctl.d32);++	if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) {+		DWC_PRINTF("ADP Sense interrupt\n");+		retval |= dwc_otg_adp_handle_sns_intr(core_if);+	}+	if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) {+		DWC_PRINTF("ADP timeout interrupt\n");+		retval |= dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32);+	}+	if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) {+		DWC_PRINTF("ADP Probe interrupt\n");+		adpctl.b.adp_prb_int = 1;+		retval |= dwc_otg_adp_handle_prb_intr(core_if, adpctl.d32);+	}++//	dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0);+	//dwc_otg_adp_write_reg(core_if, adpctl.d32);+	DWC_PRINTF("RETURN FROM ADP ISR\n");++	return retval;+}++/**+ *+ * @param core_if Programming view of DWC_otg controller.+ */+int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if)+{++#ifndef DWC_HOST_ONLY+	hprt0_data_t hprt0;+	gpwrdn_data_t gpwrdn;+	DWC_DEBUGPL(DBG_ANY, "++ Power Down Logic Session Request Interrupt++\n");++	gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);+	/* check which value is for device mode and which for Host mode */+	if (!gpwrdn.b.idsts) {	/* considered host mode value is 0 */+		DWC_PRINTF("SRP: Host mode\n");++		if (core_if->adp_enable) {+			dwc_otg_adp_probe_stop(core_if);++			/* Power on the core */+			if (core_if->power_down == 2) {+				gpwrdn.b.pwrdnswtch = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, 0, gpwrdn.d32);+			}++			core_if->op_state = A_HOST;+			dwc_otg_core_init(core_if);+			dwc_otg_enable_global_interrupts(core_if);+			cil_hcd_start(core_if);+		}++		/* Turn on the port power bit. */+		hprt0.d32 = dwc_otg_read_hprt0(core_if);+		hprt0.b.prtpwr = 1;+		DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);++		/* Start the Connection timer. So a message can be displayed+		 * if connect does not occur within 10 seconds. */+		cil_hcd_session_start(core_if);+	} else {+		DWC_PRINTF("SRP: Device mode %s\n", __FUNCTION__);+		if (core_if->adp_enable) {+			dwc_otg_adp_probe_stop(core_if);++			/* Power on the core */+			if (core_if->power_down == 2) {+				gpwrdn.b.pwrdnswtch = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, 0, gpwrdn.d32);+			}++			gpwrdn.d32 = 0;+			gpwrdn.b.pmuactv = 0;+			DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,+					 gpwrdn.d32);++			core_if->op_state = B_PERIPHERAL;+			dwc_otg_core_init(core_if);+			dwc_otg_enable_global_interrupts(core_if);+			cil_pcd_start(core_if);+		}+	}+#endif+	return 1;+}diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_adp.h linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_adp.h--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_adp.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_adp.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,80 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.h $+ * $Revision: #7 $+ * $Date: 2011/10/24 $+ * $Change: 1871159 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */++#ifndef __DWC_OTG_ADP_H__+#define __DWC_OTG_ADP_H__++/**+ * @file+ *+ * This file contains the Attach Detect Protocol interfaces and defines+ * (functions) and structures for Linux.+ *+ */++#define DWC_OTG_ADP_UNATTACHED	0+#define DWC_OTG_ADP_ATTACHED	1+#define DWC_OTG_ADP_UNKOWN	2++typedef struct dwc_otg_adp {+	uint32_t adp_started;+	uint32_t initial_probe;+	int32_t probe_timer_values[2];+	uint32_t probe_enabled;+	uint32_t sense_enabled;+	dwc_timer_t *sense_timer;+	uint32_t sense_timer_started;+	dwc_timer_t *vbuson_timer;+	uint32_t vbuson_timer_started;+	uint32_t attached;+	uint32_t probe_counter;+	uint32_t gpwrdn;+} dwc_otg_adp_t;++/**+ * Attach Detect Protocol functions+ */++extern void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value);+extern uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if);+extern uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if);+extern uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if);+extern uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if);+extern uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if);+extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host);+extern void dwc_otg_adp_init(dwc_otg_core_if_t * core_if);+extern void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if);+extern int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if);+extern int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if);++#endif //__DWC_OTG_ADP_H__diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_attr.c--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_attr.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_attr.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,1210 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $+ * $Revision: #44 $+ * $Date: 2010/11/29 $+ * $Change: 1636033 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */++/** @file+ *+ * The diagnostic interface will provide access to the controller for+ * bringing up the hardware and testing.  The Linux driver attributes+ * feature will be used to provide the Linux Diagnostic+ * Interface. These attributes are accessed through sysfs.+ */++/** @page "Linux Module Attributes"+ *+ * The Linux module attributes feature is used to provide the Linux+ * Diagnostic Interface.  These attributes are accessed through sysfs.+ * The diagnostic interface will provide access to the controller for+ * bringing up the hardware and testing.++ The following table shows the attributes.+ <table>+ <tr>+ <td><b> Name</b></td>+ <td><b> Description</b></td>+ <td><b> Access</b></td>+ </tr>++ <tr>+ <td> mode </td>+ <td> Returns the current mode: 0 for device mode, 1 for host mode</td>+ <td> Read</td>+ </tr>++ <tr>+ <td> hnpcapable </td>+ <td> Gets or sets the "HNP-capable" bit in the Core USB Configuraton Register.+ Read returns the current value.</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> srpcapable </td>+ <td> Gets or sets the "SRP-capable" bit in the Core USB Configuraton Register.+ Read returns the current value.</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> hsic_connect </td>+ <td> Gets or sets the "HSIC-Connect" bit in the GLPMCFG Register.+ Read returns the current value.</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> inv_sel_hsic </td>+ <td> Gets or sets the "Invert Select HSIC" bit in the GLPMFG Register.+ Read returns the current value.</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> hnp </td>+ <td> Initiates the Host Negotiation Protocol.  Read returns the status.</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> srp </td>+ <td> Initiates the Session Request Protocol.  Read returns the status.</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> buspower </td>+ <td> Gets or sets the Power State of the bus (0 - Off or 1 - On)</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> bussuspend </td>+ <td> Suspends the USB bus.</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> busconnected </td>+ <td> Gets the connection status of the bus</td>+ <td> Read</td>+ </tr>++ <tr>+ <td> gotgctl </td>+ <td> Gets or sets the Core Control Status Register.</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> gusbcfg </td>+ <td> Gets or sets the Core USB Configuration Register</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> grxfsiz </td>+ <td> Gets or sets the Receive FIFO Size Register</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> gnptxfsiz </td>+ <td> Gets or sets the non-periodic Transmit Size Register</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> gpvndctl </td>+ <td> Gets or sets the PHY Vendor Control Register</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> ggpio </td>+ <td> Gets the value in the lower 16-bits of the General Purpose IO Register+ or sets the upper 16 bits.</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> guid </td>+ <td> Gets or sets the value of the User ID Register</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> gsnpsid </td>+ <td> Gets the value of the Synopsys ID Regester</td>+ <td> Read</td>+ </tr>++ <tr>+ <td> devspeed </td>+ <td> Gets or sets the device speed setting in the DCFG register</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> enumspeed </td>+ <td> Gets the device enumeration Speed.</td>+ <td> Read</td>+ </tr>++ <tr>+ <td> hptxfsiz </td>+ <td> Gets the value of the Host Periodic Transmit FIFO</td>+ <td> Read</td>+ </tr>++ <tr>+ <td> hprt0 </td>+ <td> Gets or sets the value in the Host Port Control and Status Register</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> regoffset </td>+ <td> Sets the register offset for the next Register Access</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> regvalue </td>+ <td> Gets or sets the value of the register at the offset in the regoffset attribute.</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> remote_wakeup </td>+ <td> On read, shows the status of Remote Wakeup. On write, initiates a remote+ wakeup of the host. When bit 0 is 1 and Remote Wakeup is enabled, the Remote+ Wakeup signalling bit in the Device Control Register is set for 1+ milli-second.</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> rem_wakeup_pwrdn </td>+ <td> On read, shows the status core - hibernated or not. On write, initiates+ a remote wakeup of the device from Hibernation. </td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> mode_ch_tim_en </td>+ <td> This bit is used to enable or disable the host core to wait for 200 PHY+ clock cycles at the end of Resume to change the opmode signal to the PHY to 00+ after Suspend or LPM. </td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> fr_interval </td>+ <td> On read, shows the value of HFIR Frame Interval. On write, dynamically+ reload HFIR register during runtime. The application can write a value to this+ register only after the Port Enable bit of the Host Port Control and Status+ register (HPRT.PrtEnaPort) has been set </td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> disconnect_us </td>+ <td> On read, shows the status of disconnect_device_us. On write, sets disconnect_us+ which causes soft disconnect for 100us. Applicable only for device mode of operation.</td>+ <td> Read/Write</td>+ </tr>++ <tr>+ <td> regdump </td>+ <td> Dumps the contents of core registers.</td>+ <td> Read</td>+ </tr>++ <tr>+ <td> spramdump </td>+ <td> Dumps the contents of core registers.</td>+ <td> Read</td>+ </tr>++ <tr>+ <td> hcddump </td>+ <td> Dumps the current HCD state.</td>+ <td> Read</td>+ </tr>++ <tr>+ <td> hcd_frrem </td>+ <td> Shows the average value of the Frame Remaining+ field in the Host Frame Number/Frame Remaining register when an SOF interrupt+ occurs. This can be used to determine the average interrupt latency. Also+ shows the average Frame Remaining value for start_transfer and the "a" and+ "b" sample points. The "a" and "b" sample points may be used during debugging+ bto determine how long it takes to execute a section of the HCD code.</td>+ <td> Read</td>+ </tr>++ <tr>+ <td> rd_reg_test </td>+ <td> Displays the time required to read the GNPTXFSIZ register many times+ (the output shows the number of times the register is read).+ <td> Read</td>+ </tr>++ <tr>+ <td> wr_reg_test </td>+ <td> Displays the time required to write the GNPTXFSIZ register many times+ (the output shows the number of times the register is written).+ <td> Read</td>+ </tr>++ <tr>+ <td> lpm_response </td>+ <td> Gets or sets lpm_response mode. Applicable only in device mode.+ <td> Write</td>+ </tr>++ <tr>+ <td> sleep_status </td>+ <td> Shows sleep status of device.+ <td> Read</td>+ </tr>++ </table>++ Example usage:+ To get the current mode:+ cat /sys/devices/lm0/mode++ To power down the USB:+ echo 0 > /sys/devices/lm0/buspower+ */++#include "dwc_otg_os_dep.h"+#include "dwc_os.h"+#include "dwc_otg_driver.h"+#include "dwc_otg_attr.h"+#include "dwc_otg_core_if.h"+#include "dwc_otg_pcd_if.h"+#include "dwc_otg_hcd_if.h"++/*+ * MACROs for defining sysfs attribute+ */+#ifdef LM_INTERFACE++#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \+static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \+{ \+	struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \+	dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);		\+	uint32_t val; \+	val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \+	return sprintf (buf, "%s = 0x%x\n", _string_, val); \+}+#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \+static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \+					const char *buf, size_t count) \+{ \+	struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \+	dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \+	uint32_t set = simple_strtoul(buf, NULL, 16); \+	dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\+	return count; \+}++#elif defined(PCI_INTERFACE)++#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \+static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \+{ \+	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);	\+	uint32_t val; \+	val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \+	return sprintf (buf, "%s = 0x%x\n", _string_, val); \+}+#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \+static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \+					const char *buf, size_t count) \+{ \+	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \+	uint32_t set = simple_strtoul(buf, NULL, 16); \+	dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\+	return count; \+}++#elif defined(PLATFORM_INTERFACE)++#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \+static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \+{ \+        struct platform_device *platform_dev = \+                container_of(_dev, struct platform_device, dev); \+        dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);  \+	uint32_t val; \+	DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \+                    __func__, _dev, platform_dev, otg_dev); \+	val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \+	return sprintf (buf, "%s = 0x%x\n", _string_, val); \+}+#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \+static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \+					const char *buf, size_t count) \+{ \+        struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \+        dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \+	uint32_t set = simple_strtoul(buf, NULL, 16); \+	dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\+	return count; \+}+#endif++/*+ * MACROs for defining sysfs attribute for 32-bit registers+ */+#ifdef LM_INTERFACE+#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \+static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \+{ \+	struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \+	dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \+	uint32_t val; \+	val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \+	return sprintf (buf, "%s = 0x%08x\n", _string_, val); \+}+#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \+static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \+					const char *buf, size_t count) \+{ \+	struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \+	dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \+	uint32_t val = simple_strtoul(buf, NULL, 16); \+	dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \+	return count; \+}+#elif defined(PCI_INTERFACE)+#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \+static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \+{ \+	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \+	uint32_t val; \+	val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \+	return sprintf (buf, "%s = 0x%08x\n", _string_, val); \+}+#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \+static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \+					const char *buf, size_t count) \+{ \+	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \+	uint32_t val = simple_strtoul(buf, NULL, 16); \+	dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \+	return count; \+}++#elif defined(PLATFORM_INTERFACE)+#include "dwc_otg_dbg.h"+#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \+static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \+{ \+	struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \+	dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \+	uint32_t val; \+	DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \+                    __func__, _dev, platform_dev, otg_dev); \+	val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \+	return sprintf (buf, "%s = 0x%08x\n", _string_, val); \+}+#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \+static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \+					const char *buf, size_t count) \+{ \+	struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \+	dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \+	uint32_t val = simple_strtoul(buf, NULL, 16); \+	dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \+	return count; \+}++#endif++#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_,_string_) \+DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \+DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \+DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);++#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_,_string_) \+DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \+DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);++#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_,_addr_,_string_) \+DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \+DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \+DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);++#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_,_addr_,_string_) \+DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \+DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);++/** @name Functions for Show/Store of Attributes */+/**@{*/++/**+ * Helper function returning the otg_device structure of the given device+ */+static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev)+{+        dwc_otg_device_t *otg_dev;+        DWC_OTG_GETDRVDEV(otg_dev, _dev);+        return otg_dev;+}++/**+ * Show the register offset of the Register Access.+ */+static ssize_t regoffset_show(struct device *_dev,+			      struct device_attribute *attr, char *buf)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n",+			otg_dev->os_dep.reg_offset);+}++/**+ * Set the register offset for the next Register Access 	Read/Write+ */+static ssize_t regoffset_store(struct device *_dev,+			       struct device_attribute *attr,+			       const char *buf, size_t count)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	uint32_t offset = simple_strtoul(buf, NULL, 16);+#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)+	if (offset < SZ_256K) {+#elif  defined(PCI_INTERFACE)+	if (offset < 0x00040000) {+#endif+		otg_dev->os_dep.reg_offset = offset;+	} else {+		dev_err(_dev, "invalid offset\n");+	}++	return count;+}++DEVICE_ATTR(regoffset, S_IRUGO | S_IWUSR, regoffset_show, regoffset_store);++/**+ * Show the value of the register at the offset in the reg_offset+ * attribute.+ */+static ssize_t regvalue_show(struct device *_dev,+			     struct device_attribute *attr, char *buf)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	uint32_t val;+	volatile uint32_t *addr;++	if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) {+		/* Calculate the address */+		addr = (uint32_t *) (otg_dev->os_dep.reg_offset ++				     (uint8_t *) otg_dev->os_dep.base);+		val = DWC_READ_REG32(addr);+		return snprintf(buf,+				sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n") + 1,+				"Reg@0x%06x = 0x%08x\n", otg_dev->os_dep.reg_offset,+				val);+	} else {+		dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->os_dep.reg_offset);+		return sprintf(buf, "invalid offset\n");+	}+}++/**+ * Store the value in the register at the offset in the reg_offset+ * attribute.+ *+ */+static ssize_t regvalue_store(struct device *_dev,+			      struct device_attribute *attr,+			      const char *buf, size_t count)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	volatile uint32_t *addr;+	uint32_t val = simple_strtoul(buf, NULL, 16);+	//dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val);+	if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) {+		/* Calculate the address */+		addr = (uint32_t *) (otg_dev->os_dep.reg_offset ++				     (uint8_t *) otg_dev->os_dep.base);+		DWC_WRITE_REG32(addr, val);+	} else {+		dev_err(_dev, "Invalid Register Offset (0x%08x)\n",+			otg_dev->os_dep.reg_offset);+	}+	return count;+}++DEVICE_ATTR(regvalue, S_IRUGO | S_IWUSR, regvalue_show, regvalue_store);++/*+ * Attributes+ */+DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode, "Mode");+DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable, "HNPCapable");+DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, "SRPCapable");+DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hsic_connect, "HSIC Connect");+DWC_OTG_DEVICE_ATTR_BITFIELD_RW(inv_sel_hsic, "Invert Select HSIC");++//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(buspower,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");+//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");+DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected, "Bus Connected");++DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl, 0, "GOTGCTL");+DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg,+			     &(otg_dev->core_if->core_global_regs->gusbcfg),+			     "GUSBCFG");+DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz,+			     &(otg_dev->core_if->core_global_regs->grxfsiz),+			     "GRXFSIZ");+DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz,+			     &(otg_dev->core_if->core_global_regs->gnptxfsiz),+			     "GNPTXFSIZ");+DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl,+			     &(otg_dev->core_if->core_global_regs->gpvndctl),+			     "GPVNDCTL");+DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio,+			     &(otg_dev->core_if->core_global_regs->ggpio),+			     "GGPIO");+DWC_OTG_DEVICE_ATTR_REG32_RW(guid, &(otg_dev->core_if->core_global_regs->guid),+			     "GUID");+DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid,+			     &(otg_dev->core_if->core_global_regs->gsnpsid),+			     "GSNPSID");+DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed, "Device Speed");+DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed, "Device Enumeration Speed");++DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz,+			     &(otg_dev->core_if->core_global_regs->hptxfsiz),+			     "HPTXFSIZ");+DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0, otg_dev->core_if->host_if->hprt0, "HPRT0");++/**+ * @todo Add code to initiate the HNP.+ */+/**+ * Show the HNP status bit+ */+static ssize_t hnp_show(struct device *_dev,+			struct device_attribute *attr, char *buf)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	return sprintf(buf, "HstNegScs = 0x%x\n",+		       dwc_otg_get_hnpstatus(otg_dev->core_if));+}++/**+ * Set the HNP Request bit+ */+static ssize_t hnp_store(struct device *_dev,+			 struct device_attribute *attr,+			 const char *buf, size_t count)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	uint32_t in = simple_strtoul(buf, NULL, 16);+	dwc_otg_set_hnpreq(otg_dev->core_if, in);+	return count;+}++DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store);++/**+ * @todo Add code to initiate the SRP.+ */+/**+ * Show the SRP status bit+ */+static ssize_t srp_show(struct device *_dev,+			struct device_attribute *attr, char *buf)+{+#ifndef DWC_HOST_ONLY+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	return sprintf(buf, "SesReqScs = 0x%x\n",+		       dwc_otg_get_srpstatus(otg_dev->core_if));+#else+	return sprintf(buf, "Host Only Mode!\n");+#endif+}++/**+ * Set the SRP Request bit+ */+static ssize_t srp_store(struct device *_dev,+			 struct device_attribute *attr,+			 const char *buf, size_t count)+{+#ifndef DWC_HOST_ONLY+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	dwc_otg_pcd_initiate_srp(otg_dev->pcd);+#endif+	return count;+}++DEVICE_ATTR(srp, 0644, srp_show, srp_store);++/**+ * @todo Need to do more for power on/off?+ */+/**+ * Show the Bus Power status+ */+static ssize_t buspower_show(struct device *_dev,+			     struct device_attribute *attr, char *buf)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	return sprintf(buf, "Bus Power = 0x%x\n",+		       dwc_otg_get_prtpower(otg_dev->core_if));+}++/**+ * Set the Bus Power status+ */+static ssize_t buspower_store(struct device *_dev,+			      struct device_attribute *attr,+			      const char *buf, size_t count)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	uint32_t on = simple_strtoul(buf, NULL, 16);+	dwc_otg_set_prtpower(otg_dev->core_if, on);+	return count;+}++DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store);++/**+ * @todo Need to do more for suspend?+ */+/**+ * Show the Bus Suspend status+ */+static ssize_t bussuspend_show(struct device *_dev,+			       struct device_attribute *attr, char *buf)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	return sprintf(buf, "Bus Suspend = 0x%x\n",+		       dwc_otg_get_prtsuspend(otg_dev->core_if));+}++/**+ * Set the Bus Suspend status+ */+static ssize_t bussuspend_store(struct device *_dev,+				struct device_attribute *attr,+				const char *buf, size_t count)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	uint32_t in = simple_strtoul(buf, NULL, 16);+	dwc_otg_set_prtsuspend(otg_dev->core_if, in);+	return count;+}++DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store);++/**+ * Show the Mode Change Ready Timer status+ */+static ssize_t mode_ch_tim_en_show(struct device *_dev,+				   struct device_attribute *attr, char *buf)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	return sprintf(buf, "Mode Change Ready Timer Enable = 0x%x\n",+		       dwc_otg_get_mode_ch_tim(otg_dev->core_if));+}++/**+ * Set the Mode Change Ready Timer status+ */+static ssize_t mode_ch_tim_en_store(struct device *_dev,+				    struct device_attribute *attr,+				    const char *buf, size_t count)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	uint32_t in = simple_strtoul(buf, NULL, 16);+	dwc_otg_set_mode_ch_tim(otg_dev->core_if, in);+	return count;+}++DEVICE_ATTR(mode_ch_tim_en, 0644, mode_ch_tim_en_show, mode_ch_tim_en_store);++/**+ * Show the value of HFIR Frame Interval bitfield+ */+static ssize_t fr_interval_show(struct device *_dev,+				struct device_attribute *attr, char *buf)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	return sprintf(buf, "Frame Interval = 0x%x\n",+		       dwc_otg_get_fr_interval(otg_dev->core_if));+}++/**+ * Set the HFIR Frame Interval value+ */+static ssize_t fr_interval_store(struct device *_dev,+				 struct device_attribute *attr,+				 const char *buf, size_t count)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	uint32_t in = simple_strtoul(buf, NULL, 10);+	dwc_otg_set_fr_interval(otg_dev->core_if, in);+	return count;+}++DEVICE_ATTR(fr_interval, 0644, fr_interval_show, fr_interval_store);++/**+ * Show the status of Remote Wakeup.+ */+static ssize_t remote_wakeup_show(struct device *_dev,+				  struct device_attribute *attr, char *buf)+{+#ifndef DWC_HOST_ONLY+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);++	return sprintf(buf,+		       "Remote Wakeup Sig = %d Enabled = %d LPM Remote Wakeup = %d\n",+		       dwc_otg_get_remotewakesig(otg_dev->core_if),+		       dwc_otg_pcd_get_rmwkup_enable(otg_dev->pcd),+		       dwc_otg_get_lpm_remotewakeenabled(otg_dev->core_if));+#else+	return sprintf(buf, "Host Only Mode!\n");+#endif /* DWC_HOST_ONLY */+}++/**+ * Initiate a remote wakeup of the host.  The Device control register+ * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable+ * flag is set.+ *+ */+static ssize_t remote_wakeup_store(struct device *_dev,+				   struct device_attribute *attr,+				   const char *buf, size_t count)+{+#ifndef DWC_HOST_ONLY+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	uint32_t val = simple_strtoul(buf, NULL, 16);++	if (val & 1) {+		dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1);+	} else {+		dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0);+	}+#endif /* DWC_HOST_ONLY */+	return count;+}++DEVICE_ATTR(remote_wakeup, S_IRUGO | S_IWUSR, remote_wakeup_show,+	    remote_wakeup_store);++/**+ * Show the whether core is hibernated or not.+ */+static ssize_t rem_wakeup_pwrdn_show(struct device *_dev,+				     struct device_attribute *attr, char *buf)+{+#ifndef DWC_HOST_ONLY+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);++	if (dwc_otg_get_core_state(otg_dev->core_if)) {+		DWC_PRINTF("Core is in hibernation\n");+	} else {+		DWC_PRINTF("Core is not in hibernation\n");+	}+#endif /* DWC_HOST_ONLY */+	return 0;+}++extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,+					      int rem_wakeup, int reset);++/**+ * Initiate a remote wakeup of the device to exit from hibernation.+ */+static ssize_t rem_wakeup_pwrdn_store(struct device *_dev,+				      struct device_attribute *attr,+				      const char *buf, size_t count)+{+#ifndef DWC_HOST_ONLY+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	dwc_otg_device_hibernation_restore(otg_dev->core_if, 1, 0);+#endif+	return count;+}++DEVICE_ATTR(rem_wakeup_pwrdn, S_IRUGO | S_IWUSR, rem_wakeup_pwrdn_show,+	    rem_wakeup_pwrdn_store);++static ssize_t disconnect_us(struct device *_dev,+			     struct device_attribute *attr,+			     const char *buf, size_t count)+{++#ifndef DWC_HOST_ONLY+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	uint32_t val = simple_strtoul(buf, NULL, 16);+	DWC_PRINTF("The Passed value is %04x\n", val);++	dwc_otg_pcd_disconnect_us(otg_dev->pcd, 50);++#endif /* DWC_HOST_ONLY */+	return count;+}++DEVICE_ATTR(disconnect_us, S_IWUSR, 0, disconnect_us);++/**+ * Dump global registers and either host or device registers (depending on the+ * current mode of the core).+ */+static ssize_t regdump_show(struct device *_dev,+			    struct device_attribute *attr, char *buf)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);++	dwc_otg_dump_global_registers(otg_dev->core_if);+	if (dwc_otg_is_host_mode(otg_dev->core_if)) {+		dwc_otg_dump_host_registers(otg_dev->core_if);+	} else {+		dwc_otg_dump_dev_registers(otg_dev->core_if);++	}+	return sprintf(buf, "Register Dump\n");+}++DEVICE_ATTR(regdump, S_IRUGO, regdump_show, 0);++/**+ * Dump global registers and either host or device registers (depending on the+ * current mode of the core).+ */+static ssize_t spramdump_show(struct device *_dev,+			      struct device_attribute *attr, char *buf)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);++	//dwc_otg_dump_spram(otg_dev->core_if);++	return sprintf(buf, "SPRAM Dump\n");+}++DEVICE_ATTR(spramdump, S_IRUGO, spramdump_show, 0);++/**+ * Dump the current hcd state.+ */+static ssize_t hcddump_show(struct device *_dev,+			    struct device_attribute *attr, char *buf)+{+#ifndef DWC_DEVICE_ONLY+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	dwc_otg_hcd_dump_state(otg_dev->hcd);+#endif /* DWC_DEVICE_ONLY */+	return sprintf(buf, "HCD Dump\n");+}++DEVICE_ATTR(hcddump, S_IRUGO, hcddump_show, 0);++/**+ * Dump the average frame remaining at SOF. This can be used to+ * determine average interrupt latency. Frame remaining is also shown for+ * start transfer and two additional sample points.+ */+static ssize_t hcd_frrem_show(struct device *_dev,+			      struct device_attribute *attr, char *buf)+{+#ifndef DWC_DEVICE_ONLY+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);++	dwc_otg_hcd_dump_frrem(otg_dev->hcd);+#endif /* DWC_DEVICE_ONLY */+	return sprintf(buf, "HCD Dump Frame Remaining\n");+}++DEVICE_ATTR(hcd_frrem, S_IRUGO, hcd_frrem_show, 0);++/**+ * Displays the time required to read the GNPTXFSIZ register many times (the+ * output shows the number of times the register is read).+ */+#define RW_REG_COUNT 10000000+#define MSEC_PER_JIFFIE 1000/HZ+static ssize_t rd_reg_test_show(struct device *_dev,+				struct device_attribute *attr, char *buf)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	int i;+	int time;+	int start_jiffies;++	printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",+	       HZ, MSEC_PER_JIFFIE, loops_per_jiffy);+	start_jiffies = jiffies;+	for (i = 0; i < RW_REG_COUNT; i++) {+		dwc_otg_get_gnptxfsiz(otg_dev->core_if);+	}+	time = jiffies - start_jiffies;+	return sprintf(buf,+		       "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",+		       RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);+}++DEVICE_ATTR(rd_reg_test, S_IRUGO, rd_reg_test_show, 0);++/**+ * Displays the time required to write the GNPTXFSIZ register many times (the+ * output shows the number of times the register is written).+ */+static ssize_t wr_reg_test_show(struct device *_dev,+				struct device_attribute *attr, char *buf)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	uint32_t reg_val;+	int i;+	int time;+	int start_jiffies;++	printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",+	       HZ, MSEC_PER_JIFFIE, loops_per_jiffy);+	reg_val = dwc_otg_get_gnptxfsiz(otg_dev->core_if);+	start_jiffies = jiffies;+	for (i = 0; i < RW_REG_COUNT; i++) {+		dwc_otg_set_gnptxfsiz(otg_dev->core_if, reg_val);+	}+	time = jiffies - start_jiffies;+	return sprintf(buf,+		       "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",+		       RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);+}++DEVICE_ATTR(wr_reg_test, S_IRUGO, wr_reg_test_show, 0);++#ifdef CONFIG_USB_DWC_OTG_LPM++/**+* Show the lpm_response attribute.+*/+static ssize_t lpmresp_show(struct device *_dev,+			    struct device_attribute *attr, char *buf)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);++	if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if))+		return sprintf(buf, "** LPM is DISABLED **\n");++	if (!dwc_otg_is_device_mode(otg_dev->core_if)) {+		return sprintf(buf, "** Current mode is not device mode\n");+	}+	return sprintf(buf, "lpm_response = %d\n",+		       dwc_otg_get_lpmresponse(otg_dev->core_if));+}++/**+* Store the lpm_response attribute.+*/+static ssize_t lpmresp_store(struct device *_dev,+			     struct device_attribute *attr,+			     const char *buf, size_t count)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	uint32_t val = simple_strtoul(buf, NULL, 16);++	if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) {+		return 0;+	}++	if (!dwc_otg_is_device_mode(otg_dev->core_if)) {+		return 0;+	}++	dwc_otg_set_lpmresponse(otg_dev->core_if, val);+	return count;+}++DEVICE_ATTR(lpm_response, S_IRUGO | S_IWUSR, lpmresp_show, lpmresp_store);++/**+* Show the sleep_status attribute.+*/+static ssize_t sleepstatus_show(struct device *_dev,+				struct device_attribute *attr, char *buf)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	return sprintf(buf, "Sleep Status = %d\n",+		       dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if));+}++/**+ * Store the sleep_status attribure.+ */+static ssize_t sleepstatus_store(struct device *_dev,+				 struct device_attribute *attr,+				 const char *buf, size_t count)+{+        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);+	dwc_otg_core_if_t *core_if = otg_dev->core_if;++	if (dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)) {+		if (dwc_otg_is_host_mode(core_if)) {++			DWC_PRINTF("Host initiated resume\n");+			dwc_otg_set_prtresume(otg_dev->core_if, 1);+		}+	}++	return count;+}++DEVICE_ATTR(sleep_status, S_IRUGO | S_IWUSR, sleepstatus_show,+	    sleepstatus_store);++#endif /* CONFIG_USB_DWC_OTG_LPM_ENABLE */++/**@}*/++/**+ * Create the device files+ */+void dwc_otg_attr_create(+#ifdef LM_INTERFACE+	struct lm_device *dev+#elif  defined(PCI_INTERFACE)+	struct pci_dev *dev+#elif  defined(PLATFORM_INTERFACE)+        struct platform_device *dev+#endif+    )+{+	int error;++	error = device_create_file(&dev->dev, &dev_attr_regoffset);+	error = device_create_file(&dev->dev, &dev_attr_regvalue);+	error = device_create_file(&dev->dev, &dev_attr_mode);+	error = device_create_file(&dev->dev, &dev_attr_hnpcapable);+	error = device_create_file(&dev->dev, &dev_attr_srpcapable);+	error = device_create_file(&dev->dev, &dev_attr_hsic_connect);+	error = device_create_file(&dev->dev, &dev_attr_inv_sel_hsic);+	error = device_create_file(&dev->dev, &dev_attr_hnp);+	error = device_create_file(&dev->dev, &dev_attr_srp);+	error = device_create_file(&dev->dev, &dev_attr_buspower);+	error = device_create_file(&dev->dev, &dev_attr_bussuspend);+	error = device_create_file(&dev->dev, &dev_attr_mode_ch_tim_en);+	error = device_create_file(&dev->dev, &dev_attr_fr_interval);+	error = device_create_file(&dev->dev, &dev_attr_busconnected);+	error = device_create_file(&dev->dev, &dev_attr_gotgctl);+	error = device_create_file(&dev->dev, &dev_attr_gusbcfg);+	error = device_create_file(&dev->dev, &dev_attr_grxfsiz);+	error = device_create_file(&dev->dev, &dev_attr_gnptxfsiz);+	error = device_create_file(&dev->dev, &dev_attr_gpvndctl);+	error = device_create_file(&dev->dev, &dev_attr_ggpio);+	error = device_create_file(&dev->dev, &dev_attr_guid);+	error = device_create_file(&dev->dev, &dev_attr_gsnpsid);+	error = device_create_file(&dev->dev, &dev_attr_devspeed);+	error = device_create_file(&dev->dev, &dev_attr_enumspeed);+	error = device_create_file(&dev->dev, &dev_attr_hptxfsiz);+	error = device_create_file(&dev->dev, &dev_attr_hprt0);+	error = device_create_file(&dev->dev, &dev_attr_remote_wakeup);+	error = device_create_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn);+	error = device_create_file(&dev->dev, &dev_attr_disconnect_us);+	error = device_create_file(&dev->dev, &dev_attr_regdump);+	error = device_create_file(&dev->dev, &dev_attr_spramdump);+	error = device_create_file(&dev->dev, &dev_attr_hcddump);+	error = device_create_file(&dev->dev, &dev_attr_hcd_frrem);+	error = device_create_file(&dev->dev, &dev_attr_rd_reg_test);+	error = device_create_file(&dev->dev, &dev_attr_wr_reg_test);+#ifdef CONFIG_USB_DWC_OTG_LPM+	error = device_create_file(&dev->dev, &dev_attr_lpm_response);+	error = device_create_file(&dev->dev, &dev_attr_sleep_status);+#endif+}++/**+ * Remove the device files+ */+void dwc_otg_attr_remove(+#ifdef LM_INTERFACE+	struct lm_device *dev+#elif  defined(PCI_INTERFACE)+	struct pci_dev *dev+#elif  defined(PLATFORM_INTERFACE)+	struct platform_device *dev+#endif+    )+{+	device_remove_file(&dev->dev, &dev_attr_regoffset);+	device_remove_file(&dev->dev, &dev_attr_regvalue);+	device_remove_file(&dev->dev, &dev_attr_mode);+	device_remove_file(&dev->dev, &dev_attr_hnpcapable);+	device_remove_file(&dev->dev, &dev_attr_srpcapable);+	device_remove_file(&dev->dev, &dev_attr_hsic_connect);+	device_remove_file(&dev->dev, &dev_attr_inv_sel_hsic);+	device_remove_file(&dev->dev, &dev_attr_hnp);+	device_remove_file(&dev->dev, &dev_attr_srp);+	device_remove_file(&dev->dev, &dev_attr_buspower);+	device_remove_file(&dev->dev, &dev_attr_bussuspend);+	device_remove_file(&dev->dev, &dev_attr_mode_ch_tim_en);+	device_remove_file(&dev->dev, &dev_attr_fr_interval);+	device_remove_file(&dev->dev, &dev_attr_busconnected);+	device_remove_file(&dev->dev, &dev_attr_gotgctl);+	device_remove_file(&dev->dev, &dev_attr_gusbcfg);+	device_remove_file(&dev->dev, &dev_attr_grxfsiz);+	device_remove_file(&dev->dev, &dev_attr_gnptxfsiz);+	device_remove_file(&dev->dev, &dev_attr_gpvndctl);+	device_remove_file(&dev->dev, &dev_attr_ggpio);+	device_remove_file(&dev->dev, &dev_attr_guid);+	device_remove_file(&dev->dev, &dev_attr_gsnpsid);+	device_remove_file(&dev->dev, &dev_attr_devspeed);+	device_remove_file(&dev->dev, &dev_attr_enumspeed);+	device_remove_file(&dev->dev, &dev_attr_hptxfsiz);+	device_remove_file(&dev->dev, &dev_attr_hprt0);+	device_remove_file(&dev->dev, &dev_attr_remote_wakeup);+	device_remove_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn);+	device_remove_file(&dev->dev, &dev_attr_disconnect_us);+	device_remove_file(&dev->dev, &dev_attr_regdump);+	device_remove_file(&dev->dev, &dev_attr_spramdump);+	device_remove_file(&dev->dev, &dev_attr_hcddump);+	device_remove_file(&dev->dev, &dev_attr_hcd_frrem);+	device_remove_file(&dev->dev, &dev_attr_rd_reg_test);+	device_remove_file(&dev->dev, &dev_attr_wr_reg_test);+#ifdef CONFIG_USB_DWC_OTG_LPM+	device_remove_file(&dev->dev, &dev_attr_lpm_response);+	device_remove_file(&dev->dev, &dev_attr_sleep_status);+#endif+}diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_attr.h linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_attr.h--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_attr.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_attr.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,89 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.h $+ * $Revision: #13 $+ * $Date: 2010/06/21 $+ * $Change: 1532021 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */++#if !defined(__DWC_OTG_ATTR_H__)+#define __DWC_OTG_ATTR_H__++/** @file+ * This file contains the interface to the Linux device attributes.+ */+extern struct device_attribute dev_attr_regoffset;+extern struct device_attribute dev_attr_regvalue;++extern struct device_attribute dev_attr_mode;+extern struct device_attribute dev_attr_hnpcapable;+extern struct device_attribute dev_attr_srpcapable;+extern struct device_attribute dev_attr_hnp;+extern struct device_attribute dev_attr_srp;+extern struct device_attribute dev_attr_buspower;+extern struct device_attribute dev_attr_bussuspend;+extern struct device_attribute dev_attr_mode_ch_tim_en;+extern struct device_attribute dev_attr_fr_interval;+extern struct device_attribute dev_attr_busconnected;+extern struct device_attribute dev_attr_gotgctl;+extern struct device_attribute dev_attr_gusbcfg;+extern struct device_attribute dev_attr_grxfsiz;+extern struct device_attribute dev_attr_gnptxfsiz;+extern struct device_attribute dev_attr_gpvndctl;+extern struct device_attribute dev_attr_ggpio;+extern struct device_attribute dev_attr_guid;+extern struct device_attribute dev_attr_gsnpsid;+extern struct device_attribute dev_attr_devspeed;+extern struct device_attribute dev_attr_enumspeed;+extern struct device_attribute dev_attr_hptxfsiz;+extern struct device_attribute dev_attr_hprt0;+#ifdef CONFIG_USB_DWC_OTG_LPM+extern struct device_attribute dev_attr_lpm_response;+extern struct device_attribute devi_attr_sleep_status;+#endif++void dwc_otg_attr_create(+#ifdef LM_INTERFACE+				struct lm_device *dev+#elif  defined(PCI_INTERFACE)+				struct pci_dev *dev+#elif  defined(PLATFORM_INTERFACE)+	struct platform_device *dev+#endif+    );++void dwc_otg_attr_remove(+#ifdef LM_INTERFACE+				struct lm_device *dev+#elif  defined(PCI_INTERFACE)+				struct pci_dev *dev+#elif  defined(PLATFORM_INTERFACE)+	struct platform_device *dev+#endif+    );+#endifdiff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_cfi.c--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_cfi.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_cfi.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,1876 @@+/* ==========================================================================+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */++/** @file+ *+ * This file contains the most of the CFI(Core Feature Interface)+ * implementation for the OTG.+ */++#ifdef DWC_UTE_CFI++#include "dwc_otg_pcd.h"+#include "dwc_otg_cfi.h"++/** This definition should actually migrate to the Portability Library */+#define DWC_CONSTANT_CPU_TO_LE16(x) (x)++extern dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex);++static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen);+static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,+				 struct dwc_otg_pcd *pcd,+				 struct cfi_usb_ctrlrequest *ctrl_req);+static int cfi_set_feature_value(struct dwc_otg_pcd *pcd);+static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,+			     struct cfi_usb_ctrlrequest *req);+static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,+				 struct cfi_usb_ctrlrequest *req);+static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,+				struct cfi_usb_ctrlrequest *req);+static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,+			     struct cfi_usb_ctrlrequest *req);+static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep);++static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if);+static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue);+static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue);++static uint8_t resize_fifos(dwc_otg_core_if_t * core_if);++/** This is the header of the all features descriptor */+static cfi_all_features_header_t all_props_desc_header = {+	.wVersion = DWC_CONSTANT_CPU_TO_LE16(0x100),+	.wCoreID = DWC_CONSTANT_CPU_TO_LE16(CFI_CORE_ID_OTG),+	.wNumFeatures = DWC_CONSTANT_CPU_TO_LE16(9),+};++/** This is an array of statically allocated feature descriptors */+static cfi_feature_desc_header_t prop_descs[] = {++	/* FT_ID_DMA_MODE */+	{+	 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_MODE),+	 .bmAttributes = CFI_FEATURE_ATTR_RW,+	 .wDataLength = DWC_CONSTANT_CPU_TO_LE16(1),+	 },++	/* FT_ID_DMA_BUFFER_SETUP */+	{+	 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFFER_SETUP),+	 .bmAttributes = CFI_FEATURE_ATTR_RW,+	 .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),+	 },++	/* FT_ID_DMA_BUFF_ALIGN */+	{+	 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFF_ALIGN),+	 .bmAttributes = CFI_FEATURE_ATTR_RW,+	 .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),+	 },++	/* FT_ID_DMA_CONCAT_SETUP */+	{+	 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CONCAT_SETUP),+	 .bmAttributes = CFI_FEATURE_ATTR_RW,+	 //.wDataLength  = DWC_CONSTANT_CPU_TO_LE16(6),+	 },++	/* FT_ID_DMA_CIRCULAR */+	{+	 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CIRCULAR),+	 .bmAttributes = CFI_FEATURE_ATTR_RW,+	 .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),+	 },++	/* FT_ID_THRESHOLD_SETUP */+	{+	 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_THRESHOLD_SETUP),+	 .bmAttributes = CFI_FEATURE_ATTR_RW,+	 .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),+	 },++	/* FT_ID_DFIFO_DEPTH */+	{+	 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DFIFO_DEPTH),+	 .bmAttributes = CFI_FEATURE_ATTR_RO,+	 .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),+	 },++	/* FT_ID_TX_FIFO_DEPTH */+	{+	 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_TX_FIFO_DEPTH),+	 .bmAttributes = CFI_FEATURE_ATTR_RW,+	 .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),+	 },++	/* FT_ID_RX_FIFO_DEPTH */+	{+	 .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_RX_FIFO_DEPTH),+	 .bmAttributes = CFI_FEATURE_ATTR_RW,+	 .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),+	 }+};++/** The table of feature names */+cfi_string_t prop_name_table[] = {+	{FT_ID_DMA_MODE, "dma_mode"},+	{FT_ID_DMA_BUFFER_SETUP, "buffer_setup"},+	{FT_ID_DMA_BUFF_ALIGN, "buffer_align"},+	{FT_ID_DMA_CONCAT_SETUP, "concat_setup"},+	{FT_ID_DMA_CIRCULAR, "buffer_circular"},+	{FT_ID_THRESHOLD_SETUP, "threshold_setup"},+	{FT_ID_DFIFO_DEPTH, "dfifo_depth"},+	{FT_ID_TX_FIFO_DEPTH, "txfifo_depth"},+	{FT_ID_RX_FIFO_DEPTH, "rxfifo_depth"},+	{}+};++/************************************************************************/++/**+ * Returns the name of the feature by its ID+ * or NULL if no featute ID matches.+ *+ */+const uint8_t *get_prop_name(uint16_t prop_id, int *len)+{+	cfi_string_t *pstr;+	*len = 0;++	for (pstr = prop_name_table; pstr && pstr->s; pstr++) {+		if (pstr->id == prop_id) {+			*len = DWC_STRLEN(pstr->s);+			return pstr->s;+		}+	}+	return NULL;+}++/**+ * This function handles all CFI specific control requests.+ *+ * Return a negative value to stall the DCE.+ */+int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl)+{+	int retval = 0;+	dwc_otg_pcd_ep_t *ep = NULL;+	cfiobject_t *cfi = pcd->cfi;+	struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);+	uint16_t wLen = DWC_LE16_TO_CPU(&ctrl->wLength);+	uint16_t wValue = DWC_LE16_TO_CPU(&ctrl->wValue);+	uint16_t wIndex = DWC_LE16_TO_CPU(&ctrl->wIndex);+	uint32_t regaddr = 0;+	uint32_t regval = 0;++	/* Save this Control Request in the CFI object.+	 * The data field will be assigned in the data stage completion CB function.+	 */+	cfi->ctrl_req = *ctrl;+	cfi->ctrl_req.data = NULL;++	cfi->need_gadget_att = 0;+	cfi->need_status_in_complete = 0;++	switch (ctrl->bRequest) {+	case VEN_CORE_GET_FEATURES:+		retval = cfi_core_features_buf(cfi->buf_in.buf, CFI_IN_BUF_LEN);+		if (retval >= 0) {+			//dump_msg(cfi->buf_in.buf, retval);+			ep = &pcd->ep0;++			retval = min((uint16_t) retval, wLen);+			/* Transfer this buffer to the host through the EP0-IN EP */+			ep->dwc_ep.dma_addr = cfi->buf_in.addr;+			ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;+			ep->dwc_ep.xfer_buff = cfi->buf_in.buf;+			ep->dwc_ep.xfer_len = retval;+			ep->dwc_ep.xfer_count = 0;+			ep->dwc_ep.sent_zlp = 0;+			ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;++			pcd->ep0_pending = 1;+			dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);+		}+		retval = 0;+		break;++	case VEN_CORE_GET_FEATURE:+		CFI_INFO("VEN_CORE_GET_FEATURE\n");+		retval = cfi_get_feature_value(cfi->buf_in.buf, CFI_IN_BUF_LEN,+					       pcd, ctrl);+		if (retval >= 0) {+			ep = &pcd->ep0;++			retval = min((uint16_t) retval, wLen);+			/* Transfer this buffer to the host through the EP0-IN EP */+			ep->dwc_ep.dma_addr = cfi->buf_in.addr;+			ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;+			ep->dwc_ep.xfer_buff = cfi->buf_in.buf;+			ep->dwc_ep.xfer_len = retval;+			ep->dwc_ep.xfer_count = 0;+			ep->dwc_ep.sent_zlp = 0;+			ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;++			pcd->ep0_pending = 1;+			dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);+		}+		CFI_INFO("VEN_CORE_GET_FEATURE=%d\n", retval);+		dump_msg(cfi->buf_in.buf, retval);+		break;++	case VEN_CORE_SET_FEATURE:+		CFI_INFO("VEN_CORE_SET_FEATURE\n");+		/* Set up an XFER to get the data stage of the control request,+		 * which is the new value of the feature to be modified.+		 */+		ep = &pcd->ep0;+		ep->dwc_ep.is_in = 0;+		ep->dwc_ep.dma_addr = cfi->buf_out.addr;+		ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;+		ep->dwc_ep.xfer_buff = cfi->buf_out.buf;+		ep->dwc_ep.xfer_len = wLen;+		ep->dwc_ep.xfer_count = 0;+		ep->dwc_ep.sent_zlp = 0;+		ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;++		pcd->ep0_pending = 1;+		/* Read the control write's data stage */+		dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);+		retval = 0;+		break;++	case VEN_CORE_RESET_FEATURES:+		CFI_INFO("VEN_CORE_RESET_FEATURES\n");+		cfi->need_gadget_att = 1;+		cfi->need_status_in_complete = 1;+		retval = cfi_preproc_reset(pcd, ctrl);+		CFI_INFO("VEN_CORE_RESET_FEATURES = (%d)\n", retval);+		break;++	case VEN_CORE_ACTIVATE_FEATURES:+		CFI_INFO("VEN_CORE_ACTIVATE_FEATURES\n");+		break;++	case VEN_CORE_READ_REGISTER:+		CFI_INFO("VEN_CORE_READ_REGISTER\n");+		/* wValue optionally contains the HI WORD of the register offset and+		 * wIndex contains the LOW WORD of the register offset+		 */+		if (wValue == 0) {+			/* @TODO - MAS - fix the access to the base field */+			regaddr = 0;+			//regaddr = (uint32_t) pcd->otg_dev->os_dep.base;+			//GET_CORE_IF(pcd)->co+			regaddr |= wIndex;+		} else {+			regaddr = (wValue << 16) | wIndex;+		}++		/* Read a 32-bit value of the memory at the regaddr */+		regval = DWC_READ_REG32((uint32_t *) regaddr);++		ep = &pcd->ep0;+		dwc_memcpy(cfi->buf_in.buf, ®val, sizeof(uint32_t));+		ep->dwc_ep.is_in = 1;+		ep->dwc_ep.dma_addr = cfi->buf_in.addr;+		ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;+		ep->dwc_ep.xfer_buff = cfi->buf_in.buf;+		ep->dwc_ep.xfer_len = wLen;+		ep->dwc_ep.xfer_count = 0;+		ep->dwc_ep.sent_zlp = 0;+		ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;++		pcd->ep0_pending = 1;+		dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);+		cfi->need_gadget_att = 0;+		retval = 0;+		break;++	case VEN_CORE_WRITE_REGISTER:+		CFI_INFO("VEN_CORE_WRITE_REGISTER\n");+		/* Set up an XFER to get the data stage of the control request,+		 * which is the new value of the register to be modified.+		 */+		ep = &pcd->ep0;+		ep->dwc_ep.is_in = 0;+		ep->dwc_ep.dma_addr = cfi->buf_out.addr;+		ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;+		ep->dwc_ep.xfer_buff = cfi->buf_out.buf;+		ep->dwc_ep.xfer_len = wLen;+		ep->dwc_ep.xfer_count = 0;+		ep->dwc_ep.sent_zlp = 0;+		ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;++		pcd->ep0_pending = 1;+		/* Read the control write's data stage */+		dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);+		retval = 0;+		break;++	default:+		retval = -DWC_E_NOT_SUPPORTED;+		break;+	}++	return retval;+}++/**+ * This function prepares the core features descriptors and copies its+ * raw representation into the buffer <buf>.+ *+ * The buffer structure is as follows:+ *	all_features_header (8 bytes)+ *	features_#1 (8 bytes + feature name string length)+ *	features_#2 (8 bytes + feature name string length)+ *	.....+ *	features_#n - where n=the total count of feature descriptors+ */+static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen)+{+	cfi_feature_desc_header_t *prop_hdr = prop_descs;+	cfi_feature_desc_header_t *prop;+	cfi_all_features_header_t *all_props_hdr = &all_props_desc_header;+	cfi_all_features_header_t *tmp;+	uint8_t *tmpbuf = buf;+	const uint8_t *pname = NULL;+	int i, j, namelen = 0, totlen;++	/* Prepare and copy the core features into the buffer */+	CFI_INFO("%s:\n", __func__);++	tmp = (cfi_all_features_header_t *) tmpbuf;+	*tmp = *all_props_hdr;+	tmpbuf += CFI_ALL_FEATURES_HDR_LEN;++	j = sizeof(prop_descs) / sizeof(cfi_all_features_header_t);+	for (i = 0; i < j; i++, prop_hdr++) {+		pname = get_prop_name(prop_hdr->wFeatureID, &namelen);+		prop = (cfi_feature_desc_header_t *) tmpbuf;+		*prop = *prop_hdr;++		prop->bNameLen = namelen;+		prop->wLength =+		    DWC_CONSTANT_CPU_TO_LE16(CFI_FEATURE_DESC_HDR_LEN ++					     namelen);++		tmpbuf += CFI_FEATURE_DESC_HDR_LEN;+		dwc_memcpy(tmpbuf, pname, namelen);+		tmpbuf += namelen;+	}++	totlen = tmpbuf - buf;++	if (totlen > 0) {+		tmp = (cfi_all_features_header_t *) buf;+		tmp->wTotalLen = DWC_CONSTANT_CPU_TO_LE16(totlen);+	}++	return totlen;+}++/**+ * This function releases all the dynamic memory in the CFI object.+ */+static void cfi_release(cfiobject_t * cfiobj)+{+	cfi_ep_t *cfiep;+	dwc_list_link_t *tmp;++	CFI_INFO("%s\n", __func__);++	if (cfiobj->buf_in.buf) {+		DWC_DMA_FREE(CFI_IN_BUF_LEN, cfiobj->buf_in.buf,+			     cfiobj->buf_in.addr);+		cfiobj->buf_in.buf = NULL;+	}++	if (cfiobj->buf_out.buf) {+		DWC_DMA_FREE(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf,+			     cfiobj->buf_out.addr);+		cfiobj->buf_out.buf = NULL;+	}++	/* Free the Buffer Setup values for each EP */+	//list_for_each_entry(cfiep, &cfiobj->active_eps, lh) {+	DWC_LIST_FOREACH(tmp, &cfiobj->active_eps) {+		cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);+		cfi_free_ep_bs_dyn_data(cfiep);+	}+}++/**+ * This function frees the dynamically allocated EP buffer setup data.+ */+static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep)+{+	if (cfiep->bm_sg) {+		DWC_FREE(cfiep->bm_sg);+		cfiep->bm_sg = NULL;+	}++	if (cfiep->bm_align) {+		DWC_FREE(cfiep->bm_align);+		cfiep->bm_align = NULL;+	}++	if (cfiep->bm_concat) {+		if (NULL != cfiep->bm_concat->wTxBytes) {+			DWC_FREE(cfiep->bm_concat->wTxBytes);+			cfiep->bm_concat->wTxBytes = NULL;+		}+		DWC_FREE(cfiep->bm_concat);+		cfiep->bm_concat = NULL;+	}+}++/**+ * This function initializes the default values of the features+ * for a specific endpoint and should be called only once when+ * the EP is enabled first time.+ */+static int cfi_ep_init_defaults(struct dwc_otg_pcd *pcd, cfi_ep_t * cfiep)+{+	int retval = 0;++	cfiep->bm_sg = DWC_ALLOC(sizeof(ddma_sg_buffer_setup_t));+	if (NULL == cfiep->bm_sg) {+		CFI_INFO("Failed to allocate memory for SG feature value\n");+		return -DWC_E_NO_MEMORY;+	}+	dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));++	/* For the Concatenation feature's default value we do not allocate+	 * memory for the wTxBytes field - it will be done in the set_feature_value+	 * request handler.+	 */+	cfiep->bm_concat = DWC_ALLOC(sizeof(ddma_concat_buffer_setup_t));+	if (NULL == cfiep->bm_concat) {+		CFI_INFO+		    ("Failed to allocate memory for CONCATENATION feature value\n");+		DWC_FREE(cfiep->bm_sg);+		return -DWC_E_NO_MEMORY;+	}+	dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));++	cfiep->bm_align = DWC_ALLOC(sizeof(ddma_align_buffer_setup_t));+	if (NULL == cfiep->bm_align) {+		CFI_INFO+		    ("Failed to allocate memory for Alignment feature value\n");+		DWC_FREE(cfiep->bm_sg);+		DWC_FREE(cfiep->bm_concat);+		return -DWC_E_NO_MEMORY;+	}+	dwc_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t));++	return retval;+}++/**+ * The callback function that notifies the CFI on the activation of+ * an endpoint in the PCD. The following steps are done in this function:+ *+ *	Create a dynamically allocated cfi_ep_t object (a CFI wrapper to the PCD's+ *		active endpoint)+ *	Create MAX_DMA_DESCS_PER_EP count DMA Descriptors for the EP+ *	Set the Buffer Mode to standard+ *	Initialize the default values for all EP modes (SG, Circular, Concat, Align)+ *	Add the cfi_ep_t object to the list of active endpoints in the CFI object+ */+static int cfi_ep_enable(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,+			 struct dwc_otg_pcd_ep *ep)+{+	cfi_ep_t *cfiep;+	int retval = -DWC_E_NOT_SUPPORTED;++	CFI_INFO("%s: epname=%s; epnum=0x%02x\n", __func__,+		 "EP_" /*ep->ep.name */ , ep->desc->bEndpointAddress);+	/* MAS - Check whether this endpoint already is in the list */+	cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);++	if (NULL == cfiep) {+		/* Allocate a cfi_ep_t object */+		cfiep = DWC_ALLOC(sizeof(cfi_ep_t));+		if (NULL == cfiep) {+			CFI_INFO+			    ("Unable to allocate memory for <cfiep> in function %s\n",+			     __func__);+			return -DWC_E_NO_MEMORY;+		}+		dwc_memset(cfiep, 0, sizeof(cfi_ep_t));++		/* Save the dwc_otg_pcd_ep pointer in the cfiep object */+		cfiep->ep = ep;++		/* Allocate the DMA Descriptors chain of MAX_DMA_DESCS_PER_EP count */+		ep->dwc_ep.descs =+		    DWC_DMA_ALLOC(MAX_DMA_DESCS_PER_EP *+				  sizeof(dwc_otg_dma_desc_t),+				  &ep->dwc_ep.descs_dma_addr);++		if (NULL == ep->dwc_ep.descs) {+			DWC_FREE(cfiep);+			return -DWC_E_NO_MEMORY;+		}++		DWC_LIST_INIT(&cfiep->lh);++		/* Set the buffer mode to BM_STANDARD. It will be modified+		 * when building descriptors for a specific buffer mode */+		ep->dwc_ep.buff_mode = BM_STANDARD;++		/* Create and initialize the default values for this EP's Buffer modes */+		if ((retval = cfi_ep_init_defaults(pcd, cfiep)) < 0)+			return retval;++		/* Add the cfi_ep_t object to the CFI object's list of active endpoints */+		DWC_LIST_INSERT_TAIL(&cfi->active_eps, &cfiep->lh);+		retval = 0;+	} else {		/* The sought EP already is in the list */+		CFI_INFO("%s: The sought EP already is in the list\n",+			 __func__);+	}++	return retval;+}++/**+ * This function is called when the data stage of a 3-stage Control Write request+ * is complete.+ *+ */+static int cfi_ctrl_write_complete(struct cfiobject *cfi,+				   struct dwc_otg_pcd *pcd)+{+	uint32_t addr, reg_value;+	uint16_t wIndex, wValue;+	uint8_t bRequest;+	uint8_t *buf = cfi->buf_out.buf;+	//struct usb_ctrlrequest *ctrl_req = &cfi->ctrl_req_saved;+	struct cfi_usb_ctrlrequest *ctrl_req = &cfi->ctrl_req;+	int retval = -DWC_E_NOT_SUPPORTED;++	CFI_INFO("%s\n", __func__);++	bRequest = ctrl_req->bRequest;+	wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);+	wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);++	/*+	 * Save the pointer to the data stage in the ctrl_req's <data> field.+	 * The request should be already saved in the command stage by now.+	 */+	ctrl_req->data = cfi->buf_out.buf;+	cfi->need_status_in_complete = 0;+	cfi->need_gadget_att = 0;++	switch (bRequest) {+	case VEN_CORE_WRITE_REGISTER:+		/* The buffer contains raw data of the new value for the register */+		reg_value = *((uint32_t *) buf);+		if (wValue == 0) {+			addr = 0;+			//addr = (uint32_t) pcd->otg_dev->os_dep.base;+			addr += wIndex;+		} else {+			addr = (wValue << 16) | wIndex;+		}++		//writel(reg_value, addr);++		retval = 0;+		cfi->need_status_in_complete = 1;+		break;++	case VEN_CORE_SET_FEATURE:+		/* The buffer contains raw data of the new value of the feature */+		retval = cfi_set_feature_value(pcd);+		if (retval < 0)+			return retval;++		cfi->need_status_in_complete = 1;+		break;++	default:+		break;+	}++	return retval;+}++/**+ * This function builds the DMA descriptors for the SG buffer mode.+ */+static void cfi_build_sg_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,+			       dwc_otg_pcd_request_t * req)+{+	struct dwc_otg_pcd_ep *ep = cfiep->ep;+	ddma_sg_buffer_setup_t *sgval = cfiep->bm_sg;+	struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;+	struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;+	dma_addr_t buff_addr = req->dma;+	int i;+	uint32_t txsize, off;++	txsize = sgval->wSize;+	off = sgval->bOffset;++//      CFI_INFO("%s: %s TXSIZE=0x%08x; OFFSET=0x%08x\n",+//              __func__, cfiep->ep->ep.name, txsize, off);++	for (i = 0; i < sgval->bCount; i++) {+		desc->status.b.bs = BS_HOST_BUSY;+		desc->buf = buff_addr;+		desc->status.b.l = 0;+		desc->status.b.ioc = 0;+		desc->status.b.sp = 0;+		desc->status.b.bytes = txsize;+		desc->status.b.bs = BS_HOST_READY;++		/* Set the next address of the buffer */+		buff_addr += txsize + off;+		desc_last = desc;+		desc++;+	}++	/* Set the last, ioc and sp bits on the Last DMA Descriptor */+	desc_last->status.b.l = 1;+	desc_last->status.b.ioc = 1;+	desc_last->status.b.sp = ep->dwc_ep.sent_zlp;+	/* Save the last DMA descriptor pointer */+	cfiep->dma_desc_last = desc_last;+	cfiep->desc_count = sgval->bCount;+}++/**+ * This function builds the DMA descriptors for the Concatenation buffer mode.+ */+static void cfi_build_concat_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,+				   dwc_otg_pcd_request_t * req)+{+	struct dwc_otg_pcd_ep *ep = cfiep->ep;+	ddma_concat_buffer_setup_t *concatval = cfiep->bm_concat;+	struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;+	struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;+	dma_addr_t buff_addr = req->dma;+	int i;+	uint16_t *txsize;++	txsize = concatval->wTxBytes;++	for (i = 0; i < concatval->hdr.bDescCount; i++) {+		desc->buf = buff_addr;+		desc->status.b.bs = BS_HOST_BUSY;+		desc->status.b.l = 0;+		desc->status.b.ioc = 0;+		desc->status.b.sp = 0;+		desc->status.b.bytes = *txsize;+		desc->status.b.bs = BS_HOST_READY;++		txsize++;+		/* Set the next address of the buffer */+		buff_addr += UGETW(ep->desc->wMaxPacketSize);+		desc_last = desc;+		desc++;+	}++	/* Set the last, ioc and sp bits on the Last DMA Descriptor */+	desc_last->status.b.l = 1;+	desc_last->status.b.ioc = 1;+	desc_last->status.b.sp = ep->dwc_ep.sent_zlp;+	cfiep->dma_desc_last = desc_last;+	cfiep->desc_count = concatval->hdr.bDescCount;+}++/**+ * This function builds the DMA descriptors for the Circular buffer mode+ */+static void cfi_build_circ_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,+				 dwc_otg_pcd_request_t * req)+{+	/* @todo: MAS - add implementation when this feature needs to be tested */+}++/**+ * This function builds the DMA descriptors for the Alignment buffer mode+ */+static void cfi_build_align_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,+				  dwc_otg_pcd_request_t * req)+{+	struct dwc_otg_pcd_ep *ep = cfiep->ep;+	ddma_align_buffer_setup_t *alignval = cfiep->bm_align;+	struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;+	dma_addr_t buff_addr = req->dma;++	desc->status.b.bs = BS_HOST_BUSY;+	desc->status.b.l = 1;+	desc->status.b.ioc = 1;+	desc->status.b.sp = ep->dwc_ep.sent_zlp;+	desc->status.b.bytes = req->length;+	/* Adjust the buffer alignment */+	desc->buf = (buff_addr + alignval->bAlign);+	desc->status.b.bs = BS_HOST_READY;+	cfiep->dma_desc_last = desc;+	cfiep->desc_count = 1;+}++/**+ * This function builds the DMA descriptors chain for different modes of the+ * buffer setup of an endpoint.+ */+static void cfi_build_descriptors(struct cfiobject *cfi,+				  struct dwc_otg_pcd *pcd,+				  struct dwc_otg_pcd_ep *ep,+				  dwc_otg_pcd_request_t * req)+{+	cfi_ep_t *cfiep;++	/* Get the cfiep by the dwc_otg_pcd_ep */+	cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);+	if (NULL == cfiep) {+		CFI_INFO("%s: Unable to find a matching active endpoint\n",+			 __func__);+		return;+	}++	cfiep->xfer_len = req->length;++	/* Iterate through all the DMA descriptors */+	switch (cfiep->ep->dwc_ep.buff_mode) {+	case BM_SG:+		cfi_build_sg_descs(cfi, cfiep, req);+		break;++	case BM_CONCAT:+		cfi_build_concat_descs(cfi, cfiep, req);+		break;++	case BM_CIRCULAR:+		cfi_build_circ_descs(cfi, cfiep, req);+		break;++	case BM_ALIGN:+		cfi_build_align_descs(cfi, cfiep, req);+		break;++	default:+		break;+	}+}++/**+ * Allocate DMA buffer for different Buffer modes.+ */+static void *cfi_ep_alloc_buf(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,+			      struct dwc_otg_pcd_ep *ep, dma_addr_t * dma,+			      unsigned size, gfp_t flags)+{+	return DWC_DMA_ALLOC(size, dma);+}++/**+ * This function initializes the CFI object.+ */+int init_cfi(cfiobject_t * cfiobj)+{+	CFI_INFO("%s\n", __func__);++	/* Allocate a buffer for IN XFERs */+	cfiobj->buf_in.buf =+	    DWC_DMA_ALLOC(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr);+	if (NULL == cfiobj->buf_in.buf) {+		CFI_INFO("Unable to allocate buffer for INs\n");+		return -DWC_E_NO_MEMORY;+	}++	/* Allocate a buffer for OUT XFERs */+	cfiobj->buf_out.buf =+	    DWC_DMA_ALLOC(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr);+	if (NULL == cfiobj->buf_out.buf) {+		CFI_INFO("Unable to allocate buffer for OUT\n");+		return -DWC_E_NO_MEMORY;+	}++	/* Initialize the callback function pointers */+	cfiobj->ops.release = cfi_release;+	cfiobj->ops.ep_enable = cfi_ep_enable;+	cfiobj->ops.ctrl_write_complete = cfi_ctrl_write_complete;+	cfiobj->ops.build_descriptors = cfi_build_descriptors;+	cfiobj->ops.ep_alloc_buf = cfi_ep_alloc_buf;++	/* Initialize the list of active endpoints in the CFI object */+	DWC_LIST_INIT(&cfiobj->active_eps);++	return 0;+}++/**+ * This function reads the required feature's current value into the buffer+ *+ * @retval: Returns negative as error, or the data length of the feature+ */+static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,+				 struct dwc_otg_pcd *pcd,+				 struct cfi_usb_ctrlrequest *ctrl_req)+{+	int retval = -DWC_E_NOT_SUPPORTED;+	struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);+	uint16_t dfifo, rxfifo, txfifo;++	switch (ctrl_req->wIndex) {+		/* Whether the DDMA is enabled or not */+	case FT_ID_DMA_MODE:+		*buf = (coreif->dma_enable && coreif->dma_desc_enable) ? 1 : 0;+		retval = 1;+		break;++	case FT_ID_DMA_BUFFER_SETUP:+		retval = cfi_ep_get_sg_val(buf, pcd, ctrl_req);+		break;++	case FT_ID_DMA_BUFF_ALIGN:+		retval = cfi_ep_get_align_val(buf, pcd, ctrl_req);+		break;++	case FT_ID_DMA_CONCAT_SETUP:+		retval = cfi_ep_get_concat_val(buf, pcd, ctrl_req);+		break;++	case FT_ID_DMA_CIRCULAR:+		CFI_INFO("GetFeature value (FT_ID_DMA_CIRCULAR)\n");+		break;++	case FT_ID_THRESHOLD_SETUP:+		CFI_INFO("GetFeature value (FT_ID_THRESHOLD_SETUP)\n");+		break;++	case FT_ID_DFIFO_DEPTH:+		dfifo = get_dfifo_size(coreif);+		*((uint16_t *) buf) = dfifo;+		retval = sizeof(uint16_t);+		break;++	case FT_ID_TX_FIFO_DEPTH:+		retval = get_txfifo_size(pcd, ctrl_req->wValue);+		if (retval >= 0) {+			txfifo = retval;+			*((uint16_t *) buf) = txfifo;+			retval = sizeof(uint16_t);+		}+		break;++	case FT_ID_RX_FIFO_DEPTH:+		retval = get_rxfifo_size(coreif, ctrl_req->wValue);+		if (retval >= 0) {+			rxfifo = retval;+			*((uint16_t *) buf) = rxfifo;+			retval = sizeof(uint16_t);+		}+		break;+	}++	return retval;+}++/**+ * This function resets the SG for the specified EP to its default value+ */+static int cfi_reset_sg_val(cfi_ep_t * cfiep)+{+	dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));+	return 0;+}++/**+ * This function resets the Alignment for the specified EP to its default value+ */+static int cfi_reset_align_val(cfi_ep_t * cfiep)+{+	dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));+	return 0;+}++/**+ * This function resets the Concatenation for the specified EP to its default value+ * This function will also set the value of the wTxBytes field to NULL after+ * freeing the memory previously allocated for this field.+ */+static int cfi_reset_concat_val(cfi_ep_t * cfiep)+{+	/* First we need to free the wTxBytes field */+	if (cfiep->bm_concat->wTxBytes) {+		DWC_FREE(cfiep->bm_concat->wTxBytes);+		cfiep->bm_concat->wTxBytes = NULL;+	}++	dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));+	return 0;+}++/**+ * This function resets all the buffer setups of the specified endpoint+ */+static int cfi_ep_reset_all_setup_vals(cfi_ep_t * cfiep)+{+	cfi_reset_sg_val(cfiep);+	cfi_reset_align_val(cfiep);+	cfi_reset_concat_val(cfiep);+	return 0;+}++static int cfi_handle_reset_fifo_val(struct dwc_otg_pcd *pcd, uint8_t ep_addr,+				     uint8_t rx_rst, uint8_t tx_rst)+{+	int retval = -DWC_E_INVALID;+	uint16_t tx_siz[15];+	uint16_t rx_siz = 0;+	dwc_otg_pcd_ep_t *ep = NULL;+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;++	if (rx_rst) {+		rx_siz = params->dev_rx_fifo_size;+		params->dev_rx_fifo_size = GET_CORE_IF(pcd)->init_rxfsiz;+	}++	if (tx_rst) {+		if (ep_addr == 0) {+			int i;++			for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {+				tx_siz[i] =+				    core_if->core_params->dev_tx_fifo_size[i];+				core_if->core_params->dev_tx_fifo_size[i] =+				    core_if->init_txfsiz[i];+			}+		} else {++			ep = get_ep_by_addr(pcd, ep_addr);++			if (NULL == ep) {+				CFI_INFO+				    ("%s: Unable to get the endpoint addr=0x%02x\n",+				     __func__, ep_addr);+				return -DWC_E_INVALID;+			}++			tx_siz[0] =+			    params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num -+						     1];+			params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] =+			    GET_CORE_IF(pcd)->init_txfsiz[ep->+							  dwc_ep.tx_fifo_num -+							  1];+		}+	}++	if (resize_fifos(GET_CORE_IF(pcd))) {+		retval = 0;+	} else {+		CFI_INFO+		    ("%s: Error resetting the feature Reset All(FIFO size)\n",+		     __func__);+		if (rx_rst) {+			params->dev_rx_fifo_size = rx_siz;+		}++		if (tx_rst) {+			if (ep_addr == 0) {+				int i;+				for (i = 0; i < core_if->hwcfg4.b.num_in_eps;+				     i++) {+					core_if->+					    core_params->dev_tx_fifo_size[i] =+					    tx_siz[i];+				}+			} else {+				params->dev_tx_fifo_size[ep->+							 dwc_ep.tx_fifo_num -+							 1] = tx_siz[0];+			}+		}+		retval = -DWC_E_INVALID;+	}+	return retval;+}++static int cfi_handle_reset_all(struct dwc_otg_pcd *pcd, uint8_t addr)+{+	int retval = 0;+	cfi_ep_t *cfiep;+	cfiobject_t *cfi = pcd->cfi;+	dwc_list_link_t *tmp;++	retval = cfi_handle_reset_fifo_val(pcd, addr, 1, 1);+	if (retval < 0) {+		return retval;+	}++	/* If the EP address is known then reset the features for only that EP */+	if (addr) {+		cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);+		if (NULL == cfiep) {+			CFI_INFO("%s: Error getting the EP address 0x%02x\n",+				 __func__, addr);+			return -DWC_E_INVALID;+		}+		retval = cfi_ep_reset_all_setup_vals(cfiep);+		cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;+	}+	/* Otherwise (wValue == 0), reset all features of all EP's */+	else {+		/* Traverse all the active EP's and reset the feature(s) value(s) */+		//list_for_each_entry(cfiep, &cfi->active_eps, lh) {+		DWC_LIST_FOREACH(tmp, &cfi->active_eps) {+			cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);+			retval = cfi_ep_reset_all_setup_vals(cfiep);+			cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;+			if (retval < 0) {+				CFI_INFO+				    ("%s: Error resetting the feature Reset All\n",+				     __func__);+				return retval;+			}+		}+	}+	return retval;+}++static int cfi_handle_reset_dma_buff_setup(struct dwc_otg_pcd *pcd,+					   uint8_t addr)+{+	int retval = 0;+	cfi_ep_t *cfiep;+	cfiobject_t *cfi = pcd->cfi;+	dwc_list_link_t *tmp;++	/* If the EP address is known then reset the features for only that EP */+	if (addr) {+		cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);+		if (NULL == cfiep) {+			CFI_INFO("%s: Error getting the EP address 0x%02x\n",+				 __func__, addr);+			return -DWC_E_INVALID;+		}+		retval = cfi_reset_sg_val(cfiep);+	}+	/* Otherwise (wValue == 0), reset all features of all EP's */+	else {+		/* Traverse all the active EP's and reset the feature(s) value(s) */+		//list_for_each_entry(cfiep, &cfi->active_eps, lh) {+		DWC_LIST_FOREACH(tmp, &cfi->active_eps) {+			cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);+			retval = cfi_reset_sg_val(cfiep);+			if (retval < 0) {+				CFI_INFO+				    ("%s: Error resetting the feature Buffer Setup\n",+				     __func__);+				return retval;+			}+		}+	}+	return retval;+}++static int cfi_handle_reset_concat_val(struct dwc_otg_pcd *pcd, uint8_t addr)+{+	int retval = 0;+	cfi_ep_t *cfiep;+	cfiobject_t *cfi = pcd->cfi;+	dwc_list_link_t *tmp;++	/* If the EP address is known then reset the features for only that EP */+	if (addr) {+		cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);+		if (NULL == cfiep) {+			CFI_INFO("%s: Error getting the EP address 0x%02x\n",+				 __func__, addr);+			return -DWC_E_INVALID;+		}+		retval = cfi_reset_concat_val(cfiep);+	}+	/* Otherwise (wValue == 0), reset all features of all EP's */+	else {+		/* Traverse all the active EP's and reset the feature(s) value(s) */+		//list_for_each_entry(cfiep, &cfi->active_eps, lh) {+		DWC_LIST_FOREACH(tmp, &cfi->active_eps) {+			cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);+			retval = cfi_reset_concat_val(cfiep);+			if (retval < 0) {+				CFI_INFO+				    ("%s: Error resetting the feature Concatenation Value\n",+				     __func__);+				return retval;+			}+		}+	}+	return retval;+}++static int cfi_handle_reset_align_val(struct dwc_otg_pcd *pcd, uint8_t addr)+{+	int retval = 0;+	cfi_ep_t *cfiep;+	cfiobject_t *cfi = pcd->cfi;+	dwc_list_link_t *tmp;++	/* If the EP address is known then reset the features for only that EP */+	if (addr) {+		cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);+		if (NULL == cfiep) {+			CFI_INFO("%s: Error getting the EP address 0x%02x\n",+				 __func__, addr);+			return -DWC_E_INVALID;+		}+		retval = cfi_reset_align_val(cfiep);+	}+	/* Otherwise (wValue == 0), reset all features of all EP's */+	else {+		/* Traverse all the active EP's and reset the feature(s) value(s) */+		//list_for_each_entry(cfiep, &cfi->active_eps, lh) {+		DWC_LIST_FOREACH(tmp, &cfi->active_eps) {+			cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);+			retval = cfi_reset_align_val(cfiep);+			if (retval < 0) {+				CFI_INFO+				    ("%s: Error resetting the feature Aliignment Value\n",+				     __func__);+				return retval;+			}+		}+	}+	return retval;++}++static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,+			     struct cfi_usb_ctrlrequest *req)+{+	int retval = 0;++	switch (req->wIndex) {+	case 0:+		/* Reset all features */+		retval = cfi_handle_reset_all(pcd, req->wValue & 0xff);+		break;++	case FT_ID_DMA_BUFFER_SETUP:+		/* Reset the SG buffer setup */+		retval =+		    cfi_handle_reset_dma_buff_setup(pcd, req->wValue & 0xff);+		break;++	case FT_ID_DMA_CONCAT_SETUP:+		/* Reset the Concatenation buffer setup */+		retval = cfi_handle_reset_concat_val(pcd, req->wValue & 0xff);+		break;++	case FT_ID_DMA_BUFF_ALIGN:+		/* Reset the Alignment buffer setup */+		retval = cfi_handle_reset_align_val(pcd, req->wValue & 0xff);+		break;++	case FT_ID_TX_FIFO_DEPTH:+		retval =+		    cfi_handle_reset_fifo_val(pcd, req->wValue & 0xff, 0, 1);+		pcd->cfi->need_gadget_att = 0;+		break;++	case FT_ID_RX_FIFO_DEPTH:+		retval = cfi_handle_reset_fifo_val(pcd, 0, 1, 0);+		pcd->cfi->need_gadget_att = 0;+		break;+	default:+		break;+	}+	return retval;+}++/**+ * This function sets a new value for the SG buffer setup.+ */+static int cfi_ep_set_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd)+{+	uint8_t inaddr, outaddr;+	cfi_ep_t *epin, *epout;+	ddma_sg_buffer_setup_t *psgval;+	uint32_t desccount, size;++	CFI_INFO("%s\n", __func__);++	psgval = (ddma_sg_buffer_setup_t *) buf;+	desccount = (uint32_t) psgval->bCount;+	size = (uint32_t) psgval->wSize;++	/* Check the DMA descriptor count */+	if ((desccount > MAX_DMA_DESCS_PER_EP) || (desccount == 0)) {+		CFI_INFO+		    ("%s: The count of DMA Descriptors should be between 1 and %d\n",+		     __func__, MAX_DMA_DESCS_PER_EP);+		return -DWC_E_INVALID;+	}++	/* Check the DMA descriptor count */++	if (size == 0) {++		CFI_INFO("%s: The transfer size should be at least 1 byte\n",+			 __func__);++		return -DWC_E_INVALID;++	}++	inaddr = psgval->bInEndpointAddress;+	outaddr = psgval->bOutEndpointAddress;++	epin = get_cfi_ep_by_addr(pcd->cfi, inaddr);+	epout = get_cfi_ep_by_addr(pcd->cfi, outaddr);++	if (NULL == epin || NULL == epout) {+		CFI_INFO+		    ("%s: Unable to get the endpoints inaddr=0x%02x outaddr=0x%02x\n",+		     __func__, inaddr, outaddr);+		return -DWC_E_INVALID;+	}++	epin->ep->dwc_ep.buff_mode = BM_SG;+	dwc_memcpy(epin->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));++	epout->ep->dwc_ep.buff_mode = BM_SG;+	dwc_memcpy(epout->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));++	return 0;+}++/**+ * This function sets a new value for the buffer Alignment setup.+ */+static int cfi_ep_set_alignment_val(uint8_t * buf, struct dwc_otg_pcd *pcd)+{+	cfi_ep_t *ep;+	uint8_t addr;+	ddma_align_buffer_setup_t *palignval;++	palignval = (ddma_align_buffer_setup_t *) buf;+	addr = palignval->bEndpointAddress;++	ep = get_cfi_ep_by_addr(pcd->cfi, addr);++	if (NULL == ep) {+		CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",+			 __func__, addr);+		return -DWC_E_INVALID;+	}++	ep->ep->dwc_ep.buff_mode = BM_ALIGN;+	dwc_memcpy(ep->bm_align, palignval, sizeof(ddma_align_buffer_setup_t));++	return 0;+}++/**+ * This function sets a new value for the Concatenation buffer setup.+ */+static int cfi_ep_set_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd)+{+	uint8_t addr;+	cfi_ep_t *ep;+	struct _ddma_concat_buffer_setup_hdr *pConcatValHdr;+	uint16_t *pVals;+	uint32_t desccount;+	int i;+	uint16_t mps;++	pConcatValHdr = (struct _ddma_concat_buffer_setup_hdr *)buf;+	desccount = (uint32_t) pConcatValHdr->bDescCount;+	pVals = (uint16_t *) (buf + BS_CONCAT_VAL_HDR_LEN);++	/* Check the DMA descriptor count */+	if (desccount > MAX_DMA_DESCS_PER_EP) {+		CFI_INFO("%s: Maximum DMA Descriptor count should be %d\n",+			 __func__, MAX_DMA_DESCS_PER_EP);+		return -DWC_E_INVALID;+	}++	addr = pConcatValHdr->bEndpointAddress;+	ep = get_cfi_ep_by_addr(pcd->cfi, addr);+	if (NULL == ep) {+		CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",+			 __func__, addr);+		return -DWC_E_INVALID;+	}++	mps = UGETW(ep->ep->desc->wMaxPacketSize);++#if 0+	for (i = 0; i < desccount; i++) {+		CFI_INFO("%s: wTxSize[%d]=0x%04x\n", __func__, i, pVals[i]);+	}+	CFI_INFO("%s: epname=%s; mps=%d\n", __func__, ep->ep->ep.name, mps);+#endif++	/* Check the wTxSizes to be less than or equal to the mps */+	for (i = 0; i < desccount; i++) {+		if (pVals[i] > mps) {+			CFI_INFO+			    ("%s: ERROR - the wTxSize[%d] should be <= MPS (wTxSize=%d)\n",+			     __func__, i, pVals[i]);+			return -DWC_E_INVALID;+		}+	}++	ep->ep->dwc_ep.buff_mode = BM_CONCAT;+	dwc_memcpy(ep->bm_concat, pConcatValHdr, BS_CONCAT_VAL_HDR_LEN);++	/* Free the previously allocated storage for the wTxBytes */+	if (ep->bm_concat->wTxBytes) {+		DWC_FREE(ep->bm_concat->wTxBytes);+	}++	/* Allocate a new storage for the wTxBytes field */+	ep->bm_concat->wTxBytes =+	    DWC_ALLOC(sizeof(uint16_t) * pConcatValHdr->bDescCount);+	if (NULL == ep->bm_concat->wTxBytes) {+		CFI_INFO("%s: Unable to allocate memory\n", __func__);+		return -DWC_E_NO_MEMORY;+	}++	/* Copy the new values into the wTxBytes filed */+	dwc_memcpy(ep->bm_concat->wTxBytes, buf + BS_CONCAT_VAL_HDR_LEN,+		   sizeof(uint16_t) * pConcatValHdr->bDescCount);++	return 0;+}++/**+ * This function calculates the total of all FIFO sizes+ *+ * @param core_if Programming view of DWC_otg controller+ *+ * @return The total of data FIFO sizes.+ *+ */+static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if)+{+	dwc_otg_core_params_t *params = core_if->core_params;+	uint16_t dfifo_total = 0;+	int i;++	/* The shared RxFIFO size */+	dfifo_total =+	    params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;++	/* Add up each TxFIFO size to the total */+	for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {+		dfifo_total += params->dev_tx_fifo_size[i];+	}++	return dfifo_total;+}++/**+ * This function returns Rx FIFO size+ *+ * @param core_if Programming view of DWC_otg controller+ *+ * @return The total of data FIFO sizes.+ *+ */+static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue)+{+	switch (wValue >> 8) {+	case 0:+		return (core_if->pwron_rxfsiz <+			32768) ? core_if->pwron_rxfsiz : 32768;+		break;+	case 1:+		return core_if->core_params->dev_rx_fifo_size;+		break;+	default:+		return -DWC_E_INVALID;+		break;+	}+}++/**+ * This function returns Tx FIFO size for IN EP+ *+ * @param core_if Programming view of DWC_otg controller+ *+ * @return The total of data FIFO sizes.+ *+ */+static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue)+{+	dwc_otg_pcd_ep_t *ep;++	ep = get_ep_by_addr(pcd, wValue & 0xff);++	if (NULL == ep) {+		CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",+			 __func__, wValue & 0xff);+		return -DWC_E_INVALID;+	}++	if (!ep->dwc_ep.is_in) {+		CFI_INFO+		    ("%s: No Tx FIFO assingned to the Out endpoint addr=0x%02x\n",+		     __func__, wValue & 0xff);+		return -DWC_E_INVALID;+	}++	switch (wValue >> 8) {+	case 0:+		return (GET_CORE_IF(pcd)->pwron_txfsiz+			[ep->dwc_ep.tx_fifo_num - 1] <+			768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep->+							      dwc_ep.tx_fifo_num+							      - 1] : 32768;+		break;+	case 1:+		return GET_CORE_IF(pcd)->core_params->+		    dev_tx_fifo_size[ep->dwc_ep.num - 1];+		break;+	default:+		return -DWC_E_INVALID;+		break;+	}+}++/**+ * This function checks if the submitted combination of+ * device mode FIFO sizes is possible or not.+ *+ * @param core_if Programming view of DWC_otg controller+ *+ * @return 1 if possible, 0 otherwise.+ *+ */+static uint8_t check_fifo_sizes(dwc_otg_core_if_t * core_if)+{+	uint16_t dfifo_actual = 0;+	dwc_otg_core_params_t *params = core_if->core_params;+	uint16_t start_addr = 0;+	int i;++	dfifo_actual =+	    params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;++	for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {+		dfifo_actual += params->dev_tx_fifo_size[i];+	}++	if (dfifo_actual > core_if->total_fifo_size) {+		return 0;+	}++	if (params->dev_rx_fifo_size > 32768 || params->dev_rx_fifo_size < 16)+		return 0;++	if (params->dev_nperio_tx_fifo_size > 32768+	    || params->dev_nperio_tx_fifo_size < 16)+		return 0;++	for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {++		if (params->dev_tx_fifo_size[i] > 768+		    || params->dev_tx_fifo_size[i] < 4)+			return 0;+	}++	if (params->dev_rx_fifo_size > core_if->pwron_rxfsiz)+		return 0;+	start_addr = params->dev_rx_fifo_size;++	if (params->dev_nperio_tx_fifo_size > core_if->pwron_gnptxfsiz)+		return 0;+	start_addr += params->dev_nperio_tx_fifo_size;++	for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {++		if (params->dev_tx_fifo_size[i] > core_if->pwron_txfsiz[i])+			return 0;+		start_addr += params->dev_tx_fifo_size[i];+	}++	return 1;+}++/**+ * This function resizes Device mode FIFOs+ *+ * @param core_if Programming view of DWC_otg controller+ *+ * @return 1 if successful, 0 otherwise+ *+ */+static uint8_t resize_fifos(dwc_otg_core_if_t * core_if)+{+	int i = 0;+	dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;+	dwc_otg_core_params_t *params = core_if->core_params;+	uint32_t rx_fifo_size;+	fifosize_data_t nptxfifosize;+	fifosize_data_t txfifosize[15];++	uint32_t rx_fsz_bak;+	uint32_t nptxfsz_bak;+	uint32_t txfsz_bak[15];++	uint16_t start_address;+	uint8_t retval = 1;++	if (!check_fifo_sizes(core_if)) {+		return 0;+	}++	/* Configure data FIFO sizes */+	if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {+		rx_fsz_bak = DWC_READ_REG32(&global_regs->grxfsiz);+		rx_fifo_size = params->dev_rx_fifo_size;+		DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size);++		/*+		 * Tx FIFOs These FIFOs are numbered from 1 to 15.+		 * Indexes of the FIFO size module parameters in the+		 * dev_tx_fifo_size array and the FIFO size registers in+		 * the dtxfsiz array run from 0 to 14.+		 */++		/* Non-periodic Tx FIFO */+		nptxfsz_bak = DWC_READ_REG32(&global_regs->gnptxfsiz);+		nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;+		start_address = params->dev_rx_fifo_size;+		nptxfifosize.b.startaddr = start_address;++		DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);++		start_address += nptxfifosize.b.depth;++		for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {+			txfsz_bak[i] = DWC_READ_REG32(&global_regs->dtxfsiz[i]);++			txfifosize[i].b.depth = params->dev_tx_fifo_size[i];+			txfifosize[i].b.startaddr = start_address;+			DWC_WRITE_REG32(&global_regs->dtxfsiz[i],+					txfifosize[i].d32);++			start_address += txfifosize[i].b.depth;+		}++		/** Check if register values are set correctly */+		if (rx_fifo_size != DWC_READ_REG32(&global_regs->grxfsiz)) {+			retval = 0;+		}++		if (nptxfifosize.d32 != DWC_READ_REG32(&global_regs->gnptxfsiz)) {+			retval = 0;+		}++		for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {+			if (txfifosize[i].d32 !=+			    DWC_READ_REG32(&global_regs->dtxfsiz[i])) {+				retval = 0;+			}+		}++		/** If register values are not set correctly, reset old values */+		if (retval == 0) {+			DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fsz_bak);++			/* Non-periodic Tx FIFO */+			DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfsz_bak);++			for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {+				DWC_WRITE_REG32(&global_regs->dtxfsiz[i],+						txfsz_bak[i]);+			}+		}+	} else {+		return 0;+	}++	/* Flush the FIFOs */+	dwc_otg_flush_tx_fifo(core_if, 0x10);	/* all Tx FIFOs */+	dwc_otg_flush_rx_fifo(core_if);++	return retval;+}++/**+ * This function sets a new value for the buffer Alignment setup.+ */+static int cfi_ep_set_tx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)+{+	int retval;+	uint32_t fsiz;+	uint16_t size;+	uint16_t ep_addr;+	dwc_otg_pcd_ep_t *ep;+	dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;+	tx_fifo_size_setup_t *ptxfifoval;++	ptxfifoval = (tx_fifo_size_setup_t *) buf;+	ep_addr = ptxfifoval->bEndpointAddress;+	size = ptxfifoval->wDepth;++	ep = get_ep_by_addr(pcd, ep_addr);++	CFI_INFO+	    ("%s: Set Tx FIFO size: endpoint addr=0x%02x, depth=%d, FIFO Num=%d\n",+	     __func__, ep_addr, size, ep->dwc_ep.tx_fifo_num);++	if (NULL == ep) {+		CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",+			 __func__, ep_addr);+		return -DWC_E_INVALID;+	}++	fsiz = params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1];+	params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = size;++	if (resize_fifos(GET_CORE_IF(pcd))) {+		retval = 0;+	} else {+		CFI_INFO+		    ("%s: Error setting the feature Tx FIFO Size for EP%d\n",+		     __func__, ep_addr);+		params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = fsiz;+		retval = -DWC_E_INVALID;+	}++	return retval;+}++/**+ * This function sets a new value for the buffer Alignment setup.+ */+static int cfi_set_rx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)+{+	int retval;+	uint32_t fsiz;+	uint16_t size;+	dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;+	rx_fifo_size_setup_t *prxfifoval;++	prxfifoval = (rx_fifo_size_setup_t *) buf;+	size = prxfifoval->wDepth;++	fsiz = params->dev_rx_fifo_size;+	params->dev_rx_fifo_size = size;++	if (resize_fifos(GET_CORE_IF(pcd))) {+		retval = 0;+	} else {+		CFI_INFO("%s: Error setting the feature Rx FIFO Size\n",+			 __func__);+		params->dev_rx_fifo_size = fsiz;+		retval = -DWC_E_INVALID;+	}++	return retval;+}++/**+ * This function reads the SG of an EP's buffer setup into the buffer buf+ */+static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,+			     struct cfi_usb_ctrlrequest *req)+{+	int retval = -DWC_E_INVALID;+	uint8_t addr;+	cfi_ep_t *ep;++	/* The Low Byte of the wValue contains a non-zero address of the endpoint */+	addr = req->wValue & 0xFF;+	if (addr == 0)		/* The address should be non-zero */+		return retval;++	ep = get_cfi_ep_by_addr(pcd->cfi, addr);+	if (NULL == ep) {+		CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",+			 __func__, addr);+		return retval;+	}++	dwc_memcpy(buf, ep->bm_sg, BS_SG_VAL_DESC_LEN);+	retval = BS_SG_VAL_DESC_LEN;+	return retval;+}++/**+ * This function reads the Concatenation value of an EP's buffer mode into+ * the buffer buf+ */+static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,+				 struct cfi_usb_ctrlrequest *req)+{+	int retval = -DWC_E_INVALID;+	uint8_t addr;+	cfi_ep_t *ep;+	uint8_t desc_count;++	/* The Low Byte of the wValue contains a non-zero address of the endpoint */+	addr = req->wValue & 0xFF;+	if (addr == 0)		/* The address should be non-zero */+		return retval;++	ep = get_cfi_ep_by_addr(pcd->cfi, addr);+	if (NULL == ep) {+		CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",+			 __func__, addr);+		return retval;+	}++	/* Copy the header to the buffer */+	dwc_memcpy(buf, ep->bm_concat, BS_CONCAT_VAL_HDR_LEN);+	/* Advance the buffer pointer by the header size */+	buf += BS_CONCAT_VAL_HDR_LEN;++	desc_count = ep->bm_concat->hdr.bDescCount;+	/* Copy alll the wTxBytes to the buffer */+	dwc_memcpy(buf, ep->bm_concat->wTxBytes, sizeof(uid16_t) * desc_count);++	retval = BS_CONCAT_VAL_HDR_LEN + sizeof(uid16_t) * desc_count;+	return retval;+}++/**+ * This function reads the buffer Alignment value of an EP's buffer mode into+ * the buffer buf+ *+ * @return The total number of bytes copied to the buffer or negative error code.+ */+static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,+				struct cfi_usb_ctrlrequest *req)+{+	int retval = -DWC_E_INVALID;+	uint8_t addr;+	cfi_ep_t *ep;++	/* The Low Byte of the wValue contains a non-zero address of the endpoint */+	addr = req->wValue & 0xFF;+	if (addr == 0)		/* The address should be non-zero */+		return retval;++	ep = get_cfi_ep_by_addr(pcd->cfi, addr);+	if (NULL == ep) {+		CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",+			 __func__, addr);+		return retval;+	}++	dwc_memcpy(buf, ep->bm_align, BS_ALIGN_VAL_HDR_LEN);+	retval = BS_ALIGN_VAL_HDR_LEN;++	return retval;+}++/**+ * This function sets a new value for the specified feature+ *+ * @param	pcd	A pointer to the PCD object+ *+ * @return 0 if successful, negative error code otherwise to stall the DCE.+ */+static int cfi_set_feature_value(struct dwc_otg_pcd *pcd)+{+	int retval = -DWC_E_NOT_SUPPORTED;+	uint16_t wIndex, wValue;+	uint8_t bRequest;+	struct dwc_otg_core_if *coreif;+	cfiobject_t *cfi = pcd->cfi;+	struct cfi_usb_ctrlrequest *ctrl_req;+	uint8_t *buf;+	ctrl_req = &cfi->ctrl_req;++	buf = pcd->cfi->ctrl_req.data;++	coreif = GET_CORE_IF(pcd);+	bRequest = ctrl_req->bRequest;+	wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);+	wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);++	/* See which feature is to be modified */+	switch (wIndex) {+	case FT_ID_DMA_BUFFER_SETUP:+		/* Modify the feature */+		if ((retval = cfi_ep_set_sg_val(buf, pcd)) < 0)+			return retval;++		/* And send this request to the gadget */+		cfi->need_gadget_att = 1;+		break;++	case FT_ID_DMA_BUFF_ALIGN:+		if ((retval = cfi_ep_set_alignment_val(buf, pcd)) < 0)+			return retval;+		cfi->need_gadget_att = 1;+		break;++	case FT_ID_DMA_CONCAT_SETUP:+		/* Modify the feature */+		if ((retval = cfi_ep_set_concat_val(buf, pcd)) < 0)+			return retval;+		cfi->need_gadget_att = 1;+		break;++	case FT_ID_DMA_CIRCULAR:+		CFI_INFO("FT_ID_DMA_CIRCULAR\n");+		break;++	case FT_ID_THRESHOLD_SETUP:+		CFI_INFO("FT_ID_THRESHOLD_SETUP\n");+		break;++	case FT_ID_DFIFO_DEPTH:+		CFI_INFO("FT_ID_DFIFO_DEPTH\n");+		break;++	case FT_ID_TX_FIFO_DEPTH:+		CFI_INFO("FT_ID_TX_FIFO_DEPTH\n");+		if ((retval = cfi_ep_set_tx_fifo_val(buf, pcd)) < 0)+			return retval;+		cfi->need_gadget_att = 0;+		break;++	case FT_ID_RX_FIFO_DEPTH:+		CFI_INFO("FT_ID_RX_FIFO_DEPTH\n");+		if ((retval = cfi_set_rx_fifo_val(buf, pcd)) < 0)+			return retval;+		cfi->need_gadget_att = 0;+		break;+	}++	return retval;+}++#endif //DWC_UTE_CFIdiff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_cfi.h--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_cfi.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_cfi.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,320 @@+/* ==========================================================================+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */++#if !defined(__DWC_OTG_CFI_H__)+#define __DWC_OTG_CFI_H__++#include "dwc_otg_pcd.h"+#include "dwc_cfi_common.h"++/**+ * @file+ * This file contains the CFI related OTG PCD specific common constants,+ * interfaces(functions and macros) and data structures.The CFI Protocol is an+ * optional interface for internal testing purposes that a DUT may implement to+ * support testing of configurable features.+ *+ */++struct dwc_otg_pcd;+struct dwc_otg_pcd_ep;++/** OTG CFI Features (properties) ID constants */+/** This is a request for all Core Features */+#define FT_ID_DMA_MODE					0x0001+#define FT_ID_DMA_BUFFER_SETUP			0x0002+#define FT_ID_DMA_BUFF_ALIGN			0x0003+#define FT_ID_DMA_CONCAT_SETUP			0x0004+#define FT_ID_DMA_CIRCULAR				0x0005+#define FT_ID_THRESHOLD_SETUP			0x0006+#define FT_ID_DFIFO_DEPTH				0x0007+#define FT_ID_TX_FIFO_DEPTH				0x0008+#define FT_ID_RX_FIFO_DEPTH				0x0009++/**********************************************************/+#define CFI_INFO_DEF++#ifdef CFI_INFO_DEF+#define CFI_INFO(fmt...)	DWC_PRINTF("CFI: " fmt);+#else+#define CFI_INFO(fmt...)+#endif++#define min(x,y) ({ \+	x < y ? x : y; })++#define max(x,y) ({ \+	x > y ? x : y; })++/**+ * Descriptor DMA SG Buffer setup structure (SG buffer). This structure is+ * also used for setting up a buffer for Circular DDMA.+ */+struct _ddma_sg_buffer_setup {+#define BS_SG_VAL_DESC_LEN	6+	/* The OUT EP address */+	uint8_t bOutEndpointAddress;+	/* The IN EP address */+	uint8_t bInEndpointAddress;+	/* Number of bytes to put between transfer segments (must be DWORD boundaries) */+	uint8_t bOffset;+	/* The number of transfer segments (a DMA descriptors per each segment) */+	uint8_t bCount;+	/* Size (in byte) of each transfer segment */+	uint16_t wSize;+} __attribute__ ((packed));+typedef struct _ddma_sg_buffer_setup ddma_sg_buffer_setup_t;++/** Descriptor DMA Concatenation Buffer setup structure */+struct _ddma_concat_buffer_setup_hdr {+#define BS_CONCAT_VAL_HDR_LEN	4+	/* The endpoint for which the buffer is to be set up */+	uint8_t bEndpointAddress;+	/* The count of descriptors to be used */+	uint8_t bDescCount;+	/* The total size of the transfer */+	uint16_t wSize;+} __attribute__ ((packed));+typedef struct _ddma_concat_buffer_setup_hdr ddma_concat_buffer_setup_hdr_t;++/** Descriptor DMA Concatenation Buffer setup structure */+struct _ddma_concat_buffer_setup {+	/* The SG header */+	ddma_concat_buffer_setup_hdr_t hdr;++	/* The XFER sizes pointer (allocated dynamically) */+	uint16_t *wTxBytes;+} __attribute__ ((packed));+typedef struct _ddma_concat_buffer_setup ddma_concat_buffer_setup_t;++/** Descriptor DMA Alignment Buffer setup structure */+struct _ddma_align_buffer_setup {+#define BS_ALIGN_VAL_HDR_LEN	2+	uint8_t bEndpointAddress;+	uint8_t bAlign;+} __attribute__ ((packed));+typedef struct _ddma_align_buffer_setup ddma_align_buffer_setup_t;++/** Transmit FIFO Size setup structure */+struct _tx_fifo_size_setup {+	uint8_t bEndpointAddress;+	uint16_t wDepth;+} __attribute__ ((packed));+typedef struct _tx_fifo_size_setup tx_fifo_size_setup_t;++/** Transmit FIFO Size setup structure */+struct _rx_fifo_size_setup {+	uint16_t wDepth;+} __attribute__ ((packed));+typedef struct _rx_fifo_size_setup rx_fifo_size_setup_t;++/**+ * struct cfi_usb_ctrlrequest - the CFI implementation of the struct usb_ctrlrequest+ * This structure encapsulates the standard usb_ctrlrequest and adds a pointer+ * to the data returned in the data stage of a 3-stage Control Write requests.+ */+struct cfi_usb_ctrlrequest {+	uint8_t bRequestType;+	uint8_t bRequest;+	uint16_t wValue;+	uint16_t wIndex;+	uint16_t wLength;+	uint8_t *data;+} UPACKED;++/*---------------------------------------------------------------------------*/++/**+ * The CFI wrapper of the enabled and activated dwc_otg_pcd_ep structures.+ * This structure is used to store the buffer setup data for any+ * enabled endpoint in the PCD.+ */+struct cfi_ep {+	/* Entry for the list container */+	dwc_list_link_t lh;+	/* Pointer to the active PCD endpoint structure */+	struct dwc_otg_pcd_ep *ep;+	/* The last descriptor in the chain of DMA descriptors of the endpoint */+	struct dwc_otg_dma_desc *dma_desc_last;+	/* The SG feature value */+	ddma_sg_buffer_setup_t *bm_sg;+	/* The Circular feature value */+	ddma_sg_buffer_setup_t *bm_circ;+	/* The Concatenation feature value */+	ddma_concat_buffer_setup_t *bm_concat;+	/* The Alignment feature value */+	ddma_align_buffer_setup_t *bm_align;+	/* XFER length */+	uint32_t xfer_len;+	/*+	 * Count of DMA descriptors currently used.+	 * The total should not exceed the MAX_DMA_DESCS_PER_EP value+	 * defined in the dwc_otg_cil.h+	 */+	uint32_t desc_count;+};+typedef struct cfi_ep cfi_ep_t;++typedef struct cfi_dma_buff {+#define CFI_IN_BUF_LEN	1024+#define CFI_OUT_BUF_LEN	1024+	dma_addr_t addr;+	uint8_t *buf;+} cfi_dma_buff_t;++struct cfiobject;++/**+ * This is the interface for the CFI operations.+ *+ * @param	ep_enable			Called when any endpoint is enabled and activated.+ * @param	release				Called when the CFI object is released and it needs to correctly+ *								deallocate the dynamic memory+ * @param	ctrl_write_complete	Called when the data stage of the request is complete+ */+typedef struct cfi_ops {+	int (*ep_enable) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd,+			  struct dwc_otg_pcd_ep * ep);+	void *(*ep_alloc_buf) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd,+			       struct dwc_otg_pcd_ep * ep, dma_addr_t * dma,+			       unsigned size, gfp_t flags);+	void (*release) (struct cfiobject * cfi);+	int (*ctrl_write_complete) (struct cfiobject * cfi,+				    struct dwc_otg_pcd * pcd);+	void (*build_descriptors) (struct cfiobject * cfi,+				   struct dwc_otg_pcd * pcd,+				   struct dwc_otg_pcd_ep * ep,+				   dwc_otg_pcd_request_t * req);+} cfi_ops_t;++struct cfiobject {+	cfi_ops_t ops;+	struct dwc_otg_pcd *pcd;+	struct usb_gadget *gadget;++	/* Buffers used to send/receive CFI-related request data */+	cfi_dma_buff_t buf_in;+	cfi_dma_buff_t buf_out;++	/* CFI specific Control request wrapper */+	struct cfi_usb_ctrlrequest ctrl_req;++	/* The list of active EP's in the PCD of type cfi_ep_t */+	dwc_list_link_t active_eps;++	/* This flag shall control the propagation of a specific request+	 * to the gadget's processing routines.+	 * 0 - no gadget handling+	 * 1 - the gadget needs to know about this request (w/o completing a status+	 * phase - just return a 0 to the _setup callback)+	 */+	uint8_t need_gadget_att;++	/* Flag indicating whether the status IN phase needs to be+	 * completed by the PCD+	 */+	uint8_t need_status_in_complete;+};+typedef struct cfiobject cfiobject_t;++#define DUMP_MSG++#if defined(DUMP_MSG)+static inline void dump_msg(const u8 * buf, unsigned int length)+{+	unsigned int start, num, i;+	char line[52], *p;++	if (length >= 512)+		return;++	start = 0;+	while (length > 0) {+		num = min(length, 16u);+		p = line;+		for (i = 0; i < num; ++i) {+			if (i == 8)+				*p++ = ' ';+			DWC_SPRINTF(p, " %02x", buf[i]);+			p += 3;+		}+		*p = 0;+		DWC_DEBUG("%6x: %s\n", start, line);+		buf += num;+		start += num;+		length -= num;+	}+}+#else+static inline void dump_msg(const u8 * buf, unsigned int length)+{+}+#endif++/**+ * This function returns a pointer to cfi_ep_t object with the addr address.+ */+static inline struct cfi_ep *get_cfi_ep_by_addr(struct cfiobject *cfi,+						uint8_t addr)+{+	struct cfi_ep *pcfiep;+	dwc_list_link_t *tmp;++	DWC_LIST_FOREACH(tmp, &cfi->active_eps) {+		pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);++		if (pcfiep->ep->desc->bEndpointAddress == addr) {+			return pcfiep;+		}+	}++	return NULL;+}++/**+ * This function returns a pointer to cfi_ep_t object that matches+ * the dwc_otg_pcd_ep object.+ */+static inline struct cfi_ep *get_cfi_ep_by_pcd_ep(struct cfiobject *cfi,+						  struct dwc_otg_pcd_ep *ep)+{+	struct cfi_ep *pcfiep = NULL;+	dwc_list_link_t *tmp;++	DWC_LIST_FOREACH(tmp, &cfi->active_eps) {+		pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);+		if (pcfiep->ep == ep) {+			return pcfiep;+		}+	}+	return NULL;+}++int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl);++#endif /* (__DWC_OTG_CFI_H__) */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_cil.c--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_cil.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_cil.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,7151 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $+ * $Revision: #191 $+ * $Date: 2012/08/10 $+ * $Change: 2047372 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */++/** @file+ *+ * The Core Interface Layer provides basic services for accessing and+ * managing the DWC_otg hardware. These services are used by both the+ * Host Controller Driver and the Peripheral Controller Driver.+ *+ * The CIL manages the memory map for the core so that the HCD and PCD+ * don't have to do this separately. It also handles basic tasks like+ * reading/writing the registers and data FIFOs in the controller.+ * Some of the data access functions provide encapsulation of several+ * operations required to perform a task, such as writing multiple+ * registers to start a transfer. Finally, the CIL performs basic+ * services that are not specific to either the host or device modes+ * of operation. These services include management of the OTG Host+ * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A+ * Diagnostic API is also provided to allow testing of the controller+ * hardware.+ *+ * The Core Interface Layer has the following requirements:+ * - Provides basic controller operations.+ * - Minimal use of OS services.+ * - The OS services used will be abstracted by using inline functions+ *	 or macros.+ *+ */++#include "dwc_os.h"+#include "dwc_otg_regs.h"+#include "dwc_otg_cil.h"++static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if);++/**+ * This function is called to initialize the DWC_otg CSR data+ * structures. The register addresses in the device and host+ * structures are initialized from the base address supplied by the+ * caller. The calling function must make the OS calls to get the+ * base address of the DWC_otg controller registers. The core_params+ * argument holds the parameters that specify how the core should be+ * configured.+ *+ * @param reg_base_addr Base address of DWC_otg core registers+ *+ */+dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr)+{+	dwc_otg_core_if_t *core_if = 0;+	dwc_otg_dev_if_t *dev_if = 0;+	dwc_otg_host_if_t *host_if = 0;+	uint8_t *reg_base = (uint8_t *) reg_base_addr;+	int i = 0;++	DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, reg_base_addr);++	core_if = DWC_ALLOC(sizeof(dwc_otg_core_if_t));++	if (core_if == NULL) {+		DWC_DEBUGPL(DBG_CIL,+			    "Allocation of dwc_otg_core_if_t failed\n");+		return 0;+	}+	core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base;++	/*+	 * Allocate the Device Mode structures.+	 */+	dev_if = DWC_ALLOC(sizeof(dwc_otg_dev_if_t));++	if (dev_if == NULL) {+		DWC_DEBUGPL(DBG_CIL, "Allocation of dwc_otg_dev_if_t failed\n");+		DWC_FREE(core_if);+		return 0;+	}++	dev_if->dev_global_regs =+	    (dwc_otg_device_global_regs_t *) (reg_base ++					      DWC_DEV_GLOBAL_REG_OFFSET);++	for (i = 0; i < MAX_EPS_CHANNELS; i++) {+		dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *)+		    (reg_base + DWC_DEV_IN_EP_REG_OFFSET ++		     (i * DWC_EP_REG_OFFSET));++		dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *)+		    (reg_base + DWC_DEV_OUT_EP_REG_OFFSET ++		     (i * DWC_EP_REG_OFFSET));+		DWC_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p\n",+			    i, &dev_if->in_ep_regs[i]->diepctl);+		DWC_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p\n",+			    i, &dev_if->out_ep_regs[i]->doepctl);+	}++	dev_if->speed = 0;	// unknown++	core_if->dev_if = dev_if;++	/*+	 * Allocate the Host Mode structures.+	 */+	host_if = DWC_ALLOC(sizeof(dwc_otg_host_if_t));++	if (host_if == NULL) {+		DWC_DEBUGPL(DBG_CIL,+			    "Allocation of dwc_otg_host_if_t failed\n");+		DWC_FREE(dev_if);+		DWC_FREE(core_if);+		return 0;+	}++	host_if->host_global_regs = (dwc_otg_host_global_regs_t *)+	    (reg_base + DWC_OTG_HOST_GLOBAL_REG_OFFSET);++	host_if->hprt0 =+	    (uint32_t *) (reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET);++	for (i = 0; i < MAX_EPS_CHANNELS; i++) {+		host_if->hc_regs[i] = (dwc_otg_hc_regs_t *)+		    (reg_base + DWC_OTG_HOST_CHAN_REGS_OFFSET ++		     (i * DWC_OTG_CHAN_REGS_OFFSET));+		DWC_DEBUGPL(DBG_CILV, "hc_reg[%d]->hcchar=%p\n",+			    i, &host_if->hc_regs[i]->hcchar);+	}++	host_if->num_host_channels = MAX_EPS_CHANNELS;+	core_if->host_if = host_if;++	for (i = 0; i < MAX_EPS_CHANNELS; i++) {+		core_if->data_fifo[i] =+		    (uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET ++				  (i * DWC_OTG_DATA_FIFO_SIZE));+		DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08lx\n",+			    i, (unsigned long)core_if->data_fifo[i]);+	}++	core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET);++	/* Initiate lx_state to L3 disconnected state */+	core_if->lx_state = DWC_OTG_L3;+	/*+	 * Store the contents of the hardware configuration registers here for+	 * easy access later.+	 */+	core_if->hwcfg1.d32 =+	    DWC_READ_REG32(&core_if->core_global_regs->ghwcfg1);+	core_if->hwcfg2.d32 =+	    DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);+	core_if->hwcfg3.d32 =+	    DWC_READ_REG32(&core_if->core_global_regs->ghwcfg3);+	core_if->hwcfg4.d32 =+	    DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);++	/* Force host mode to get HPTXFSIZ exact power on value */+	{+		gusbcfg_data_t gusbcfg = {.d32 = 0 };+		gusbcfg.d32 =  DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);+		gusbcfg.b.force_host_mode = 1;+		DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);+		dwc_mdelay(100);+		core_if->hptxfsiz.d32 =+		DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);+		gusbcfg.d32 =  DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);+		gusbcfg.b.force_host_mode = 0;+		DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);+		dwc_mdelay(100);+	}++	DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32);+	DWC_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32);+	DWC_DEBUGPL(DBG_CILV, "hwcfg3=%08x\n", core_if->hwcfg3.d32);+	DWC_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32);++	core_if->hcfg.d32 =+	    DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);+	core_if->dcfg.d32 =+	    DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);++	DWC_DEBUGPL(DBG_CILV, "hcfg=%08x\n", core_if->hcfg.d32);+	DWC_DEBUGPL(DBG_CILV, "dcfg=%08x\n", core_if->dcfg.d32);++	DWC_DEBUGPL(DBG_CILV, "op_mode=%0x\n", core_if->hwcfg2.b.op_mode);+	DWC_DEBUGPL(DBG_CILV, "arch=%0x\n", core_if->hwcfg2.b.architecture);+	DWC_DEBUGPL(DBG_CILV, "num_dev_ep=%d\n", core_if->hwcfg2.b.num_dev_ep);+	DWC_DEBUGPL(DBG_CILV, "num_host_chan=%d\n",+		    core_if->hwcfg2.b.num_host_chan);+	DWC_DEBUGPL(DBG_CILV, "nonperio_tx_q_depth=0x%0x\n",+		    core_if->hwcfg2.b.nonperio_tx_q_depth);+	DWC_DEBUGPL(DBG_CILV, "host_perio_tx_q_depth=0x%0x\n",+		    core_if->hwcfg2.b.host_perio_tx_q_depth);+	DWC_DEBUGPL(DBG_CILV, "dev_token_q_depth=0x%0x\n",+		    core_if->hwcfg2.b.dev_token_q_depth);++	DWC_DEBUGPL(DBG_CILV, "Total FIFO SZ=%d\n",+		    core_if->hwcfg3.b.dfifo_depth);+	DWC_DEBUGPL(DBG_CILV, "xfer_size_cntr_width=%0x\n",+		    core_if->hwcfg3.b.xfer_size_cntr_width);++	/*+	 * Set the SRP sucess bit for FS-I2c+	 */+	core_if->srp_success = 0;+	core_if->srp_timer_started = 0;++	/*+	 * Create new workqueue and init works+	 */+	core_if->wq_otg = DWC_WORKQ_ALLOC("dwc_otg");+	if (core_if->wq_otg == 0) {+		DWC_WARN("DWC_WORKQ_ALLOC failed\n");+		DWC_FREE(host_if);+		DWC_FREE(dev_if);+		DWC_FREE(core_if);+		return 0;+	}++	core_if->snpsid = DWC_READ_REG32(&core_if->core_global_regs->gsnpsid);++	DWC_PRINTF("Core Release: %x.%x%x%x\n",+		   (core_if->snpsid >> 12 & 0xF),+		   (core_if->snpsid >> 8 & 0xF),+		   (core_if->snpsid >> 4 & 0xF), (core_if->snpsid & 0xF));++	core_if->wkp_timer = DWC_TIMER_ALLOC("Wake Up Timer",+					     w_wakeup_detected, core_if);+	if (core_if->wkp_timer == 0) {+		DWC_WARN("DWC_TIMER_ALLOC failed\n");+		DWC_FREE(host_if);+		DWC_FREE(dev_if);+		DWC_WORKQ_FREE(core_if->wq_otg);+		DWC_FREE(core_if);+		return 0;+	}++	if (dwc_otg_setup_params(core_if)) {+		DWC_WARN("Error while setting core params\n");+	}++	core_if->hibernation_suspend = 0;++	/** ADP initialization */+	dwc_otg_adp_init(core_if);++	return core_if;+}++/**+ * This function frees the structures allocated by dwc_otg_cil_init().+ *+ * @param core_if The core interface pointer returned from+ * 		  dwc_otg_cil_init().+ *+ */+void dwc_otg_cil_remove(dwc_otg_core_if_t * core_if)+{+	dctl_data_t dctl = {.d32 = 0 };+	DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if);++	/* Disable all interrupts */+	DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 1, 0);+	DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);++	dctl.b.sftdiscon = 1;+	if (core_if->snpsid >= OTG_CORE_REV_3_00a) {+		DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0,+				 dctl.d32);+	}++	if (core_if->wq_otg) {+		DWC_WORKQ_WAIT_WORK_DONE(core_if->wq_otg, 500);+		DWC_WORKQ_FREE(core_if->wq_otg);+	}+	if (core_if->dev_if) {+		DWC_FREE(core_if->dev_if);+	}+	if (core_if->host_if) {+		DWC_FREE(core_if->host_if);+	}++	/** Remove ADP Stuff  */+	dwc_otg_adp_remove(core_if);+	if (core_if->core_params) {+		DWC_FREE(core_if->core_params);+	}+	if (core_if->wkp_timer) {+		DWC_TIMER_FREE(core_if->wkp_timer);+	}+	if (core_if->srp_timer) {+		DWC_TIMER_FREE(core_if->srp_timer);+	}+	DWC_FREE(core_if);+}++/**+ * This function enables the controller's Global Interrupt in the AHB Config+ * register.+ *+ * @param core_if Programming view of DWC_otg controller.+ */+void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * core_if)+{+	gahbcfg_data_t ahbcfg = {.d32 = 0 };+	ahbcfg.b.glblintrmsk = 1;	/* Enable interrupts */+	DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32);+}++/**+ * This function disables the controller's Global Interrupt in the AHB Config+ * register.+ *+ * @param core_if Programming view of DWC_otg controller.+ */+void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * core_if)+{+	gahbcfg_data_t ahbcfg = {.d32 = 0 };+	ahbcfg.b.glblintrmsk = 1;	/* Disable interrupts */+	DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);+}++/**+ * This function initializes the commmon interrupts, used in both+ * device and host modes.+ *+ * @param core_if Programming view of the DWC_otg controller+ *+ */+static void dwc_otg_enable_common_interrupts(dwc_otg_core_if_t * core_if)+{+	dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;+	gintmsk_data_t intr_mask = {.d32 = 0 };++	/* Clear any pending OTG Interrupts */+	DWC_WRITE_REG32(&global_regs->gotgint, 0xFFFFFFFF);++	/* Clear any pending interrupts */+	DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);++	/*+	 * Enable the interrupts in the GINTMSK.+	 */+	intr_mask.b.modemismatch = 1;+	intr_mask.b.otgintr = 1;++	if (!core_if->dma_enable) {+		intr_mask.b.rxstsqlvl = 1;+	}++	intr_mask.b.conidstschng = 1;+	intr_mask.b.wkupintr = 1;+	intr_mask.b.disconnect = 0;+	intr_mask.b.usbsuspend = 1;+	intr_mask.b.sessreqintr = 1;+#ifdef CONFIG_USB_DWC_OTG_LPM+	if (core_if->core_params->lpm_enable) {+		intr_mask.b.lpmtranrcvd = 1;+	}+#endif+	DWC_WRITE_REG32(&global_regs->gintmsk, intr_mask.d32);+}++/*+ * The restore operation is modified to support Synopsys Emulated Powerdown and+ * Hibernation. This function is for exiting from Device mode hibernation by+ * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup.+ * @param core_if Programming view of DWC_otg controller.+ * @param rem_wakeup - indicates whether resume is initiated by Device or Host.+ * @param reset - indicates whether resume is initiated by Reset.+ */+int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,+				       int rem_wakeup, int reset)+{+	gpwrdn_data_t gpwrdn = {.d32 = 0 };+	pcgcctl_data_t pcgcctl = {.d32 = 0 };+	dctl_data_t dctl = {.d32 = 0 };++	int timeout = 2000;++	if (!core_if->hibernation_suspend) {+		DWC_PRINTF("Already exited from Hibernation\n");+		return 1;+	}++	DWC_DEBUGPL(DBG_PCD, "%s called\n", __FUNCTION__);+	/* Switch-on voltage to the core */+	gpwrdn.b.pwrdnswtch = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+	dwc_udelay(10);++	/* Reset core */+	gpwrdn.d32 = 0;+	gpwrdn.b.pwrdnrstn = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+	dwc_udelay(10);++	/* Assert Restore signal */+	gpwrdn.d32 = 0;+	gpwrdn.b.restore = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);+	dwc_udelay(10);++	/* Disable power clamps */+	gpwrdn.d32 = 0;+	gpwrdn.b.pwrdnclmp = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++	if (rem_wakeup) {+		dwc_udelay(70);+	}++	/* Deassert Reset core */+	gpwrdn.d32 = 0;+	gpwrdn.b.pwrdnrstn = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);+	dwc_udelay(10);++	/* Disable PMU interrupt */+	gpwrdn.d32 = 0;+	gpwrdn.b.pmuintsel = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++	/* Mask interrupts from gpwrdn */+	gpwrdn.d32 = 0;+	gpwrdn.b.connect_det_msk = 1;+	gpwrdn.b.srp_det_msk = 1;+	gpwrdn.b.disconn_det_msk = 1;+	gpwrdn.b.rst_det_msk = 1;+	gpwrdn.b.lnstchng_msk = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++	/* Indicates that we are going out from hibernation */+	core_if->hibernation_suspend = 0;++	/*+	 * Set Restore Essential Regs bit in PCGCCTL register, restore_mode = 1+	 * indicates restore from remote_wakeup+	 */+	restore_essential_regs(core_if, rem_wakeup, 0);++	/*+	 * Wait a little for seeing new value of variable hibernation_suspend if+	 * Restore done interrupt received before polling+	 */+	dwc_udelay(10);++	if (core_if->hibernation_suspend == 0) {+		/*+		 * Wait For Restore_done Interrupt. This mechanism of polling the+		 * interrupt is introduced to avoid any possible race conditions+		 */+		do {+			gintsts_data_t gintsts;+			gintsts.d32 =+			    DWC_READ_REG32(&core_if->core_global_regs->gintsts);+			if (gintsts.b.restoredone) {+				gintsts.d32 = 0;+				gintsts.b.restoredone = 1;+				DWC_WRITE_REG32(&core_if->core_global_regs->+						gintsts, gintsts.d32);+				DWC_PRINTF("Restore Done Interrupt seen\n");+				break;+			}+			dwc_udelay(10);+		} while (--timeout);+		if (!timeout) {+			DWC_PRINTF("Restore Done interrupt wasn't generated here\n");+		}+	}+	/* Clear all pending interupts */+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);++	/* De-assert Restore */+	gpwrdn.d32 = 0;+	gpwrdn.b.restore = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+	dwc_udelay(10);++	if (!rem_wakeup) {+		pcgcctl.d32 = 0;+		pcgcctl.b.rstpdwnmodule = 1;+		DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);+	}++	/* Restore GUSBCFG and DCFG */+	DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,+			core_if->gr_backup->gusbcfg_local);+	DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,+			core_if->dr_backup->dcfg);++	/* De-assert Wakeup Logic */+	gpwrdn.d32 = 0;+	gpwrdn.b.pmuactv = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+	dwc_udelay(10);++	if (!rem_wakeup) {+		/* Set Device programming done bit */+		dctl.b.pwronprgdone = 1;+		DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);+	} else {+		/* Start Remote Wakeup Signaling */+		dctl.d32 = core_if->dr_backup->dctl;+		dctl.b.rmtwkupsig = 1;+		DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);+	}++	dwc_mdelay(2);+	/* Clear all pending interupts */+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);++	/* Restore global registers */+	dwc_otg_restore_global_regs(core_if);+	/* Restore device global registers */+	dwc_otg_restore_dev_regs(core_if, rem_wakeup);++	if (rem_wakeup) {+		dwc_mdelay(7);+		dctl.d32 = 0;+		dctl.b.rmtwkupsig = 1;+		DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);+	}++	core_if->hibernation_suspend = 0;+	/* The core will be in ON STATE */+	core_if->lx_state = DWC_OTG_L0;+	DWC_PRINTF("Hibernation recovery completes here\n");++	return 1;+}++/*+ * The restore operation is modified to support Synopsys Emulated Powerdown and+ * Hibernation. This function is for exiting from Host mode hibernation by+ * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup.+ * @param core_if Programming view of DWC_otg controller.+ * @param rem_wakeup - indicates whether resume is initiated by Device or Host.+ * @param reset - indicates whether resume is initiated by Reset.+ */+int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if,+				     int rem_wakeup, int reset)+{+	gpwrdn_data_t gpwrdn = {.d32 = 0 };+	hprt0_data_t hprt0 = {.d32 = 0 };++	int timeout = 2000;++	DWC_DEBUGPL(DBG_HCD, "%s called\n", __FUNCTION__);+	/* Switch-on voltage to the core */+	gpwrdn.b.pwrdnswtch = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+	dwc_udelay(10);++	/* Reset core */+	gpwrdn.d32 = 0;+	gpwrdn.b.pwrdnrstn = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+	dwc_udelay(10);++	/* Assert Restore signal */+	gpwrdn.d32 = 0;+	gpwrdn.b.restore = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);+	dwc_udelay(10);++	/* Disable power clamps */+	gpwrdn.d32 = 0;+	gpwrdn.b.pwrdnclmp = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++	if (!rem_wakeup) {+		dwc_udelay(50);+	}++	/* Deassert Reset core */+	gpwrdn.d32 = 0;+	gpwrdn.b.pwrdnrstn = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);+	dwc_udelay(10);++	/* Disable PMU interrupt */+	gpwrdn.d32 = 0;+	gpwrdn.b.pmuintsel = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++	gpwrdn.d32 = 0;+	gpwrdn.b.connect_det_msk = 1;+	gpwrdn.b.srp_det_msk = 1;+	gpwrdn.b.disconn_det_msk = 1;+	gpwrdn.b.rst_det_msk = 1;+	gpwrdn.b.lnstchng_msk = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++	/* Indicates that we are going out from hibernation */+	core_if->hibernation_suspend = 0;++	/* Set Restore Essential Regs bit in PCGCCTL register */+	restore_essential_regs(core_if, rem_wakeup, 1);++	/* Wait a little for seeing new value of variable hibernation_suspend if+	 * Restore done interrupt received before polling */+	dwc_udelay(10);++	if (core_if->hibernation_suspend == 0) {+		/* Wait For Restore_done Interrupt. This mechanism of polling the+		 * interrupt is introduced to avoid any possible race conditions+		 */+		do {+			gintsts_data_t gintsts;+			gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);+			if (gintsts.b.restoredone) {+				gintsts.d32 = 0;+				gintsts.b.restoredone = 1;+			DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);+				DWC_DEBUGPL(DBG_HCD,"Restore Done Interrupt seen\n");+				break;+			}+			dwc_udelay(10);+		} while (--timeout);+		if (!timeout) {+			DWC_WARN("Restore Done interrupt wasn't generated\n");+		}+	}++	/* Set the flag's value to 0 again after receiving restore done interrupt */+	core_if->hibernation_suspend = 0;++	/* This step is not described in functional spec but if not wait for this+	 * delay, mismatch interrupts occurred because just after restore core is+	 * in Device mode(gintsts.curmode == 0) */+	dwc_mdelay(100);++	/* Clear all pending interrupts */+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);++	/* De-assert Restore */+	gpwrdn.d32 = 0;+	gpwrdn.b.restore = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+	dwc_udelay(10);++	/* Restore GUSBCFG and HCFG */+	DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,+			core_if->gr_backup->gusbcfg_local);+	DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg,+			core_if->hr_backup->hcfg_local);++	/* De-assert Wakeup Logic */+	gpwrdn.d32 = 0;+	gpwrdn.b.pmuactv = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+	dwc_udelay(10);++	/* Start the Resume operation by programming HPRT0 */+	hprt0.d32 = core_if->hr_backup->hprt0_local;+	hprt0.b.prtpwr = 1;+	hprt0.b.prtena = 0;+	hprt0.b.prtsusp = 0;+	DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);++	DWC_PRINTF("Resume Starts Now\n");+	if (!reset) {		// Indicates it is Resume Operation+		hprt0.d32 = core_if->hr_backup->hprt0_local;+		hprt0.b.prtres = 1;+		hprt0.b.prtpwr = 1;+		hprt0.b.prtena = 0;+		hprt0.b.prtsusp = 0;+		DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);++		if (!rem_wakeup)+			hprt0.b.prtres = 0;+		/* Wait for Resume time and then program HPRT again */+		dwc_mdelay(100);+		DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);++	} else {		// Indicates it is Reset Operation+		hprt0.d32 = core_if->hr_backup->hprt0_local;+		hprt0.b.prtrst = 1;+		hprt0.b.prtpwr = 1;+		hprt0.b.prtena = 0;+		hprt0.b.prtsusp = 0;+		DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+		/* Wait for Reset time and then program HPRT again */+		dwc_mdelay(60);+		hprt0.b.prtrst = 0;+		DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+	}+	/* Clear all interrupt status */+	hprt0.d32 = dwc_otg_read_hprt0(core_if);+	hprt0.b.prtconndet = 1;+	hprt0.b.prtenchng = 1;+	DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);++	/* Clear all pending interupts */+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);++	/* Restore global registers */+	dwc_otg_restore_global_regs(core_if);+	/* Restore host global registers */+	dwc_otg_restore_host_regs(core_if, reset);++	/* The core will be in ON STATE */+	core_if->lx_state = DWC_OTG_L0;+	DWC_PRINTF("Hibernation recovery is complete here\n");+	return 0;+}++/** Saves some register values into system memory. */+int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if)+{+	struct dwc_otg_global_regs_backup *gr;+	int i;++	gr = core_if->gr_backup;+	if (!gr) {+		gr = DWC_ALLOC(sizeof(*gr));+		if (!gr) {+			return -DWC_E_NO_MEMORY;+		}+		core_if->gr_backup = gr;+	}++	gr->gotgctl_local = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);+	gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);+	gr->gahbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);+	gr->gusbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);+	gr->grxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);+	gr->gnptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz);+	gr->hptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);+#ifdef CONFIG_USB_DWC_OTG_LPM+	gr->glpmcfg_local = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);+#endif+	gr->gi2cctl_local = DWC_READ_REG32(&core_if->core_global_regs->gi2cctl);+	gr->pcgcctl_local = DWC_READ_REG32(core_if->pcgcctl);+	gr->gdfifocfg_local =+	    DWC_READ_REG32(&core_if->core_global_regs->gdfifocfg);+	for (i = 0; i < MAX_EPS_CHANNELS; i++) {+		gr->dtxfsiz_local[i] =+		    DWC_READ_REG32(&(core_if->core_global_regs->dtxfsiz[i]));+	}++	DWC_DEBUGPL(DBG_ANY, "===========Backing Global registers==========\n");+	DWC_DEBUGPL(DBG_ANY, "Backed up gotgctl   = %08x\n", gr->gotgctl_local);+	DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk   = %08x\n", gr->gintmsk_local);+	DWC_DEBUGPL(DBG_ANY, "Backed up gahbcfg   = %08x\n", gr->gahbcfg_local);+	DWC_DEBUGPL(DBG_ANY, "Backed up gusbcfg   = %08x\n", gr->gusbcfg_local);+	DWC_DEBUGPL(DBG_ANY, "Backed up grxfsiz   = %08x\n", gr->grxfsiz_local);+	DWC_DEBUGPL(DBG_ANY, "Backed up gnptxfsiz = %08x\n",+		    gr->gnptxfsiz_local);+	DWC_DEBUGPL(DBG_ANY, "Backed up hptxfsiz  = %08x\n",+		    gr->hptxfsiz_local);+#ifdef CONFIG_USB_DWC_OTG_LPM+	DWC_DEBUGPL(DBG_ANY, "Backed up glpmcfg   = %08x\n", gr->glpmcfg_local);+#endif+	DWC_DEBUGPL(DBG_ANY, "Backed up gi2cctl   = %08x\n", gr->gi2cctl_local);+	DWC_DEBUGPL(DBG_ANY, "Backed up pcgcctl   = %08x\n", gr->pcgcctl_local);+	DWC_DEBUGPL(DBG_ANY,"Backed up gdfifocfg   = %08x\n",gr->gdfifocfg_local);++	return 0;+}++/** Saves GINTMSK register before setting the msk bits. */+int dwc_otg_save_gintmsk_reg(dwc_otg_core_if_t * core_if)+{+	struct dwc_otg_global_regs_backup *gr;++	gr = core_if->gr_backup;+	if (!gr) {+		gr = DWC_ALLOC(sizeof(*gr));+		if (!gr) {+			return -DWC_E_NO_MEMORY;+		}+		core_if->gr_backup = gr;+	}++	gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);++	DWC_DEBUGPL(DBG_ANY,"=============Backing GINTMSK registers============\n");+	DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk   = %08x\n", gr->gintmsk_local);++	return 0;+}++int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if)+{+	struct dwc_otg_dev_regs_backup *dr;+	int i;++	dr = core_if->dr_backup;+	if (!dr) {+		dr = DWC_ALLOC(sizeof(*dr));+		if (!dr) {+			return -DWC_E_NO_MEMORY;+		}+		core_if->dr_backup = dr;+	}++	dr->dcfg = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);+	dr->dctl = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);+	dr->daintmsk =+	    DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);+	dr->diepmsk =+	    DWC_READ_REG32(&core_if->dev_if->dev_global_regs->diepmsk);+	dr->doepmsk =+	    DWC_READ_REG32(&core_if->dev_if->dev_global_regs->doepmsk);++	for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {+		dr->diepctl[i] =+		    DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl);+		dr->dieptsiz[i] =+		    DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz);+		dr->diepdma[i] =+		    DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma);+	}++	DWC_DEBUGPL(DBG_ANY,+		    "=============Backing Host registers==============\n");+	DWC_DEBUGPL(DBG_ANY, "Backed up dcfg            = %08x\n", dr->dcfg);+	DWC_DEBUGPL(DBG_ANY, "Backed up dctl        = %08x\n", dr->dctl);+	DWC_DEBUGPL(DBG_ANY, "Backed up daintmsk            = %08x\n",+		    dr->daintmsk);+	DWC_DEBUGPL(DBG_ANY, "Backed up diepmsk        = %08x\n", dr->diepmsk);+	DWC_DEBUGPL(DBG_ANY, "Backed up doepmsk        = %08x\n", dr->doepmsk);+	for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {+		DWC_DEBUGPL(DBG_ANY, "Backed up diepctl[%d]        = %08x\n", i,+			    dr->diepctl[i]);+		DWC_DEBUGPL(DBG_ANY, "Backed up dieptsiz[%d]        = %08x\n",+			    i, dr->dieptsiz[i]);+		DWC_DEBUGPL(DBG_ANY, "Backed up diepdma[%d]        = %08x\n", i,+			    dr->diepdma[i]);+	}++	return 0;+}++int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if)+{+	struct dwc_otg_host_regs_backup *hr;+	int i;++	hr = core_if->hr_backup;+	if (!hr) {+		hr = DWC_ALLOC(sizeof(*hr));+		if (!hr) {+			return -DWC_E_NO_MEMORY;+		}+		core_if->hr_backup = hr;+	}++	hr->hcfg_local =+	    DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);+	hr->haintmsk_local =+	    DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk);+	for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {+		hr->hcintmsk_local[i] =+		    DWC_READ_REG32(&core_if->host_if->hc_regs[i]->hcintmsk);+	}+	hr->hprt0_local = DWC_READ_REG32(core_if->host_if->hprt0);+	hr->hfir_local =+	    DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);++	DWC_DEBUGPL(DBG_ANY,+		    "=============Backing Host registers===============\n");+	DWC_DEBUGPL(DBG_ANY, "Backed up hcfg		= %08x\n",+		    hr->hcfg_local);+	DWC_DEBUGPL(DBG_ANY, "Backed up haintmsk = %08x\n", hr->haintmsk_local);+	for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {+		DWC_DEBUGPL(DBG_ANY, "Backed up hcintmsk[%02d]=%08x\n", i,+			    hr->hcintmsk_local[i]);+	}+	DWC_DEBUGPL(DBG_ANY, "Backed up hprt0           = %08x\n",+		    hr->hprt0_local);+	DWC_DEBUGPL(DBG_ANY, "Backed up hfir           = %08x\n",+		    hr->hfir_local);++	return 0;+}++int dwc_otg_restore_global_regs(dwc_otg_core_if_t *core_if)+{+	struct dwc_otg_global_regs_backup *gr;+	int i;++	gr = core_if->gr_backup;+	if (!gr) {+		return -DWC_E_INVALID;+	}++	DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, gr->gotgctl_local);+	DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gr->gintmsk_local);+	DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gr->gusbcfg_local);+	DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gr->gahbcfg_local);+	DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, gr->grxfsiz_local);+	DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz,+			gr->gnptxfsiz_local);+	DWC_WRITE_REG32(&core_if->core_global_regs->hptxfsiz,+			gr->hptxfsiz_local);+	DWC_WRITE_REG32(&core_if->core_global_regs->gdfifocfg,+			gr->gdfifocfg_local);+	for (i = 0; i < MAX_EPS_CHANNELS; i++) {+		DWC_WRITE_REG32(&core_if->core_global_regs->dtxfsiz[i],+				gr->dtxfsiz_local[i]);+	}++	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);+	DWC_WRITE_REG32(core_if->host_if->hprt0, 0x0000100A);+	DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg,+			(gr->gahbcfg_local));+	return 0;+}++int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, int rem_wakeup)+{+	struct dwc_otg_dev_regs_backup *dr;+	int i;++	dr = core_if->dr_backup;++	if (!dr) {+		return -DWC_E_INVALID;+	}++	if (!rem_wakeup) {+		DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,+				dr->dctl);+	}++	DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, dr->daintmsk);+	DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, dr->diepmsk);+	DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, dr->doepmsk);++	for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {+		DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz, dr->dieptsiz[i]);+		DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma, dr->diepdma[i]);+		DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl, dr->diepctl[i]);+	}++	return 0;+}++int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset)+{+	struct dwc_otg_host_regs_backup *hr;+	int i;+	hr = core_if->hr_backup;++	if (!hr) {+		return -DWC_E_INVALID;+	}++	DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hr->hcfg_local);+	//if (!reset)+	//{+	//      DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hr->hfir_local);+	//}++	DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk,+			hr->haintmsk_local);+	for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {+		DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk,+				hr->hcintmsk_local[i]);+	}++	return 0;+}++int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if)+{+	struct dwc_otg_global_regs_backup *gr;++	gr = core_if->gr_backup;++	/* Restore values for LPM and I2C */+#ifdef CONFIG_USB_DWC_OTG_LPM+	DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, gr->glpmcfg_local);+#endif+	DWC_WRITE_REG32(&core_if->core_global_regs->gi2cctl, gr->gi2cctl_local);++	return 0;+}++int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode, int is_host)+{+	struct dwc_otg_global_regs_backup *gr;+	pcgcctl_data_t pcgcctl = {.d32 = 0 };+	gahbcfg_data_t gahbcfg = {.d32 = 0 };+	gusbcfg_data_t gusbcfg = {.d32 = 0 };+	gintmsk_data_t gintmsk = {.d32 = 0 };++	/* Restore LPM and I2C registers */+	restore_lpm_i2c_regs(core_if);++	/* Set PCGCCTL to 0 */+	DWC_WRITE_REG32(core_if->pcgcctl, 0x00000000);++	gr = core_if->gr_backup;+	/* Load restore values for [31:14] bits */+	DWC_WRITE_REG32(core_if->pcgcctl,+			((gr->pcgcctl_local & 0xffffc000) | 0x00020000));++	/* Umnask global Interrupt in GAHBCFG and restore it */+	gahbcfg.d32 = gr->gahbcfg_local;+	gahbcfg.b.glblintrmsk = 1;+	DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32);++	/* Clear all pending interupts */+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);++	/* Unmask restore done interrupt */+	gintmsk.b.restoredone = 1;+	DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);++	/* Restore GUSBCFG and HCFG/DCFG */+	gusbcfg.d32 = core_if->gr_backup->gusbcfg_local;+	DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);++	if (is_host) {+		hcfg_data_t hcfg = {.d32 = 0 };+		hcfg.d32 = core_if->hr_backup->hcfg_local;+		DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg,+				hcfg.d32);++		/* Load restore values for [31:14] bits */+		pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;+		pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;++		if (rmode)+			pcgcctl.b.restoremode = 1;+		DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);+		dwc_udelay(10);++		/* Load restore values for [31:14] bits and set EssRegRestored bit */+		pcgcctl.d32 = gr->pcgcctl_local | 0xffffc000;+		pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;+		pcgcctl.b.ess_reg_restored = 1;+		if (rmode)+			pcgcctl.b.restoremode = 1;+		DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);+	} else {+		dcfg_data_t dcfg = {.d32 = 0 };+		dcfg.d32 = core_if->dr_backup->dcfg;+		DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);++		/* Load restore values for [31:14] bits */+		pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;+		pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;+		if (!rmode) {+			pcgcctl.d32 |= 0x208;+		}+		DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);+		dwc_udelay(10);++		/* Load restore values for [31:14] bits */+		pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;+		pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;+		pcgcctl.b.ess_reg_restored = 1;+		if (!rmode)+			pcgcctl.d32 |= 0x208;+		DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);+	}++	return 0;+}++/**+ * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY+ * type.+ */+static void init_fslspclksel(dwc_otg_core_if_t * core_if)+{+	uint32_t val;+	hcfg_data_t hcfg;++	if (((core_if->hwcfg2.b.hs_phy_type == 2) &&+	     (core_if->hwcfg2.b.fs_phy_type == 1) &&+	     (core_if->core_params->ulpi_fs_ls)) ||+	    (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {+		/* Full speed PHY */+		val = DWC_HCFG_48_MHZ;+	} else {+		/* High speed PHY running at full speed or high speed */+		val = DWC_HCFG_30_60_MHZ;+	}++	DWC_DEBUGPL(DBG_CIL, "Initializing HCFG.FSLSPClkSel to 0x%1x\n", val);+	hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);+	hcfg.b.fslspclksel = val;+	DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32);+}++/**+ * Initializes the DevSpd field of the DCFG register depending on the PHY type+ * and the enumeration speed of the device.+ */+static void init_devspd(dwc_otg_core_if_t * core_if)+{+	uint32_t val;+	dcfg_data_t dcfg;++	if (((core_if->hwcfg2.b.hs_phy_type == 2) &&+	     (core_if->hwcfg2.b.fs_phy_type == 1) &&+	     (core_if->core_params->ulpi_fs_ls)) ||+	    (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {+		/* Full speed PHY */+		val = 0x3;+	} else if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {+		/* High speed PHY running at full speed */+		val = 0x1;+	} else {+		/* High speed PHY running at high speed */+		val = 0x0;+	}++	DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val);++	dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);+	dcfg.b.devspd = val;+	DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);+}++/**+ * This function calculates the number of IN EPS+ * using GHWCFG1 and GHWCFG2 registers values+ *+ * @param core_if Programming view of the DWC_otg controller+ */+static uint32_t calc_num_in_eps(dwc_otg_core_if_t * core_if)+{+	uint32_t num_in_eps = 0;+	uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep;+	uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 3;+	uint32_t num_tx_fifos = core_if->hwcfg4.b.num_in_eps;+	int i;++	for (i = 0; i < num_eps; ++i) {+		if (!(hwcfg1 & 0x1))+			num_in_eps++;++		hwcfg1 >>= 2;+	}++	if (core_if->hwcfg4.b.ded_fifo_en) {+		num_in_eps =+		    (num_in_eps > num_tx_fifos) ? num_tx_fifos : num_in_eps;+	}++	return num_in_eps;+}++/**+ * This function calculates the number of OUT EPS+ * using GHWCFG1 and GHWCFG2 registers values+ *+ * @param core_if Programming view of the DWC_otg controller+ */+static uint32_t calc_num_out_eps(dwc_otg_core_if_t * core_if)+{+	uint32_t num_out_eps = 0;+	uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep;+	uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 2;+	int i;++	for (i = 0; i < num_eps; ++i) {+		if (!(hwcfg1 & 0x1))+			num_out_eps++;++		hwcfg1 >>= 2;+	}+	return num_out_eps;+}++/**+ * This function initializes the DWC_otg controller registers and+ * prepares the core for device mode or host mode operation.+ *+ * @param core_if Programming view of the DWC_otg controller+ *+ */+void dwc_otg_core_init(dwc_otg_core_if_t * core_if)+{+	int i = 0;+	dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;+	dwc_otg_dev_if_t *dev_if = core_if->dev_if;+	gahbcfg_data_t ahbcfg = {.d32 = 0 };+	gusbcfg_data_t usbcfg = {.d32 = 0 };+	gi2cctl_data_t i2cctl = {.d32 = 0 };++	DWC_DEBUGPL(DBG_CILV, "dwc_otg_core_init(%p) regs at %p\n",+                    core_if, global_regs);++	/* Common Initialization */+	usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);++	/* Program the ULPI External VBUS bit if needed */+	usbcfg.b.ulpi_ext_vbus_drv =+	    (core_if->core_params->phy_ulpi_ext_vbus ==+	     DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;++	/* Set external TS Dline pulsing */+	usbcfg.b.term_sel_dl_pulse =+	    (core_if->core_params->ts_dline == 1) ? 1 : 0;+	DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);++	/* Reset the Controller */+	dwc_otg_core_reset(core_if);++	core_if->adp_enable = core_if->core_params->adp_supp_enable;+	core_if->power_down = core_if->core_params->power_down;+	core_if->otg_sts = 0;++	/* Initialize parameters from Hardware configuration registers. */+	dev_if->num_in_eps = calc_num_in_eps(core_if);+	dev_if->num_out_eps = calc_num_out_eps(core_if);++	DWC_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n",+		    core_if->hwcfg4.b.num_dev_perio_in_ep);++	for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {+		dev_if->perio_tx_fifo_size[i] =+		    DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16;+		DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n",+			    i, dev_if->perio_tx_fifo_size[i]);+	}++	for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {+		dev_if->tx_fifo_size[i] =+		    DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16;+		DWC_DEBUGPL(DBG_CIL, "Tx FIFO SZ #%d=0x%0x\n",+			    i, dev_if->tx_fifo_size[i]);+	}++	core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth;+	core_if->rx_fifo_size = DWC_READ_REG32(&global_regs->grxfsiz);+	core_if->nperio_tx_fifo_size =+	    DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16;++	DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", core_if->total_fifo_size);+	DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", core_if->rx_fifo_size);+	DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO SZ=%d\n",+		    core_if->nperio_tx_fifo_size);++	/* This programming sequence needs to happen in FS mode before any other+	 * programming occurs */+	if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) &&+	    (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {+		/* If FS mode with FS PHY */++		/* core_init() is now called on every switch so only call the+		 * following for the first time through. */+		if (!core_if->phy_init_done) {+			core_if->phy_init_done = 1;+			DWC_DEBUGPL(DBG_CIL, "FS_PHY detected\n");+			usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);+			usbcfg.b.physel = 1;+			DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);++			/* Reset after a PHY select */+			dwc_otg_core_reset(core_if);+		}++		/* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS.      Also+		 * do this on HNP Dev/Host mode switches (done in dev_init and+		 * host_init). */+		if (dwc_otg_is_host_mode(core_if)) {+			init_fslspclksel(core_if);+		} else {+			init_devspd(core_if);+		}++		if (core_if->core_params->i2c_enable) {+			DWC_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n");+			/* Program GUSBCFG.OtgUtmifsSel to I2C */+			usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);+			usbcfg.b.otgutmifssel = 1;+			DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);++			/* Program GI2CCTL.I2CEn */+			i2cctl.d32 = DWC_READ_REG32(&global_regs->gi2cctl);+			i2cctl.b.i2cdevaddr = 1;+			i2cctl.b.i2cen = 0;+			DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32);+			i2cctl.b.i2cen = 1;+			DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32);+		}++	} /* endif speed == DWC_SPEED_PARAM_FULL */+	else {+		/* High speed PHY. */+		if (!core_if->phy_init_done) {+			core_if->phy_init_done = 1;+			/* HS PHY parameters.  These parameters are preserved+			 * during soft reset so only program the first time.  Do+			 * a soft reset immediately after setting phyif.  */++			if (core_if->core_params->phy_type == 2) {+				/* ULPI interface */+				usbcfg.b.ulpi_utmi_sel = 1;+				usbcfg.b.phyif = 0;+				usbcfg.b.ddrsel =+				    core_if->core_params->phy_ulpi_ddr;+			} else if (core_if->core_params->phy_type == 1) {+				/* UTMI+ interface */+				usbcfg.b.ulpi_utmi_sel = 0;+				if (core_if->core_params->phy_utmi_width == 16) {+					usbcfg.b.phyif = 1;++				} else {+					usbcfg.b.phyif = 0;+				}+			} else {+				DWC_ERROR("FS PHY TYPE\n");+			}+			DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);+			/* Reset after setting the PHY parameters */+			dwc_otg_core_reset(core_if);+		}+	}++	if ((core_if->hwcfg2.b.hs_phy_type == 2) &&+	    (core_if->hwcfg2.b.fs_phy_type == 1) &&+	    (core_if->core_params->ulpi_fs_ls)) {+		DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n");+		usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);+		usbcfg.b.ulpi_fsls = 1;+		usbcfg.b.ulpi_clk_sus_m = 1;+		DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);+	} else {+		usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);+		usbcfg.b.ulpi_fsls = 0;+		usbcfg.b.ulpi_clk_sus_m = 0;+		DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);+	}++	/* Program the GAHBCFG Register. */+	switch (core_if->hwcfg2.b.architecture) {++	case DWC_SLAVE_ONLY_ARCH:+		DWC_DEBUGPL(DBG_CIL, "Slave Only Mode\n");+		ahbcfg.b.nptxfemplvl_txfemplvl =+		    DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;+		ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;+		core_if->dma_enable = 0;+		core_if->dma_desc_enable = 0;+		break;++	case DWC_EXT_DMA_ARCH:+		DWC_DEBUGPL(DBG_CIL, "External DMA Mode\n");+		{+			uint8_t brst_sz = core_if->core_params->dma_burst_size;+			ahbcfg.b.hburstlen = 0;+			while (brst_sz > 1) {+				ahbcfg.b.hburstlen++;+				brst_sz >>= 1;+			}+		}+		core_if->dma_enable = (core_if->core_params->dma_enable != 0);+		core_if->dma_desc_enable =+		    (core_if->core_params->dma_desc_enable != 0);+		break;++	case DWC_INT_DMA_ARCH:+		DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n");+		/* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for+		  Host mode ISOC in issue fix - vahrama */+		/* Broadcom had altered to (1<<3)|(0<<0) - WRESP=1, max 4 beats */+		ahbcfg.b.hburstlen = (1<<3)|(0<<0);//DWC_GAHBCFG_INT_DMA_BURST_INCR4;+		core_if->dma_enable = (core_if->core_params->dma_enable != 0);+		core_if->dma_desc_enable =+		    (core_if->core_params->dma_desc_enable != 0);+		break;++	}+	if (core_if->dma_enable) {+		if (core_if->dma_desc_enable) {+			DWC_PRINTF("Using Descriptor DMA mode\n");+		} else {+			DWC_PRINTF("Using Buffer DMA mode\n");++		}+	} else {+		DWC_PRINTF("Using Slave mode\n");+		core_if->dma_desc_enable = 0;+	}++	if (core_if->core_params->ahb_single) {+		ahbcfg.b.ahbsingle = 1;+	}++	ahbcfg.b.dmaenable = core_if->dma_enable;+	DWC_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32);++	core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en;++	core_if->pti_enh_enable = core_if->core_params->pti_enable != 0;+	core_if->multiproc_int_enable = core_if->core_params->mpi_enable;+	DWC_PRINTF("Periodic Transfer Interrupt Enhancement - %s\n",+		   ((core_if->pti_enh_enable) ? "enabled" : "disabled"));+	DWC_PRINTF("Multiprocessor Interrupt Enhancement - %s\n",+		   ((core_if->multiproc_int_enable) ? "enabled" : "disabled"));++	/*+	 * Program the GUSBCFG register.+	 */+	usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);++	switch (core_if->hwcfg2.b.op_mode) {+	case DWC_MODE_HNP_SRP_CAPABLE:+		usbcfg.b.hnpcap = (core_if->core_params->otg_cap ==+				   DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);+		usbcfg.b.srpcap = (core_if->core_params->otg_cap !=+				   DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);+		break;++	case DWC_MODE_SRP_ONLY_CAPABLE:+		usbcfg.b.hnpcap = 0;+		usbcfg.b.srpcap = (core_if->core_params->otg_cap !=+				   DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);+		break;++	case DWC_MODE_NO_HNP_SRP_CAPABLE:+		usbcfg.b.hnpcap = 0;+		usbcfg.b.srpcap = 0;+		break;++	case DWC_MODE_SRP_CAPABLE_DEVICE:+		usbcfg.b.hnpcap = 0;+		usbcfg.b.srpcap = (core_if->core_params->otg_cap !=+				   DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);+		break;++	case DWC_MODE_NO_SRP_CAPABLE_DEVICE:+		usbcfg.b.hnpcap = 0;+		usbcfg.b.srpcap = 0;+		break;++	case DWC_MODE_SRP_CAPABLE_HOST:+		usbcfg.b.hnpcap = 0;+		usbcfg.b.srpcap = (core_if->core_params->otg_cap !=+				   DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);+		break;++	case DWC_MODE_NO_SRP_CAPABLE_HOST:+		usbcfg.b.hnpcap = 0;+		usbcfg.b.srpcap = 0;+		break;+	}++	DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);++#ifdef CONFIG_USB_DWC_OTG_LPM+	if (core_if->core_params->lpm_enable) {+		glpmcfg_data_t lpmcfg = {.d32 = 0 };++		/* To enable LPM support set lpm_cap_en bit */+		lpmcfg.b.lpm_cap_en = 1;++		/* Make AppL1Res ACK */+		lpmcfg.b.appl_resp = 1;++		/* Retry 3 times */+		lpmcfg.b.retry_count = 3;++		DWC_MODIFY_REG32(&core_if->core_global_regs->glpmcfg,+				 0, lpmcfg.d32);++	}+#endif+	if (core_if->core_params->ic_usb_cap) {+		gusbcfg_data_t gusbcfg = {.d32 = 0 };+		gusbcfg.b.ic_usb_cap = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gusbcfg,+				 0, gusbcfg.d32);+	}+	{+		gotgctl_data_t gotgctl = {.d32 = 0 };+		gotgctl.b.otgver = core_if->core_params->otg_ver;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, 0,+				 gotgctl.d32);+		/* Set OTG version supported */+		core_if->otg_ver = core_if->core_params->otg_ver;+		DWC_PRINTF("OTG VER PARAM: %d, OTG VER FLAG: %d\n",+			   core_if->core_params->otg_ver, core_if->otg_ver);+	}+++	/* Enable common interrupts */+	dwc_otg_enable_common_interrupts(core_if);++	/* Do device or host intialization based on mode during PCD+	 * and HCD initialization  */+	if (dwc_otg_is_host_mode(core_if)) {+		DWC_DEBUGPL(DBG_ANY, "Host Mode\n");+		core_if->op_state = A_HOST;+	} else {+		DWC_DEBUGPL(DBG_ANY, "Device Mode\n");+		core_if->op_state = B_PERIPHERAL;+#ifdef DWC_DEVICE_ONLY+		dwc_otg_core_dev_init(core_if);+#endif+	}+}++/**+ * This function enables the Device mode interrupts.+ *+ * @param core_if Programming view of DWC_otg controller+ */+void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if)+{+	gintmsk_data_t intr_mask = {.d32 = 0 };+	dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;++	DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__);++	/* Disable all interrupts. */+	DWC_WRITE_REG32(&global_regs->gintmsk, 0);++	/* Clear any pending interrupts */+	DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);++	/* Enable the common interrupts */+	dwc_otg_enable_common_interrupts(core_if);++	/* Enable interrupts */+	intr_mask.b.usbreset = 1;+	intr_mask.b.enumdone = 1;+	/* Disable Disconnect interrupt in Device mode */+	intr_mask.b.disconnect = 0;++	if (!core_if->multiproc_int_enable) {+		intr_mask.b.inepintr = 1;+		intr_mask.b.outepintr = 1;+	}++	intr_mask.b.erlysuspend = 1;++	if (core_if->en_multiple_tx_fifo == 0) {+		intr_mask.b.epmismatch = 1;+	}++	//intr_mask.b.incomplisoout = 1;+	intr_mask.b.incomplisoin = 1;++/* Enable the ignore frame number for ISOC xfers - MAS */+/* Disable to support high bandwith ISOC transfers - manukz */+#if 0+#ifdef DWC_UTE_PER_IO+	if (core_if->dma_enable) {+		if (core_if->dma_desc_enable) {+			dctl_data_t dctl1 = {.d32 = 0 };+			dctl1.b.ifrmnum = 1;+			DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->+					 dctl, 0, dctl1.d32);+			DWC_DEBUG("----Enabled Ignore frame number (0x%08x)",+				  DWC_READ_REG32(&core_if->dev_if->+						 dev_global_regs->dctl));+		}+	}+#endif+#endif+#ifdef DWC_EN_ISOC+	if (core_if->dma_enable) {+		if (core_if->dma_desc_enable == 0) {+			if (core_if->pti_enh_enable) {+				dctl_data_t dctl = {.d32 = 0 };+				dctl.b.ifrmnum = 1;+				DWC_MODIFY_REG32(&core_if->+						 dev_if->dev_global_regs->dctl,+						 0, dctl.d32);+			} else {+				intr_mask.b.incomplisoin = 1;+				intr_mask.b.incomplisoout = 1;+			}+		}+	} else {+		intr_mask.b.incomplisoin = 1;+		intr_mask.b.incomplisoout = 1;+	}+#endif /* DWC_EN_ISOC */++	/** @todo NGS: Should this be a module parameter? */+#ifdef USE_PERIODIC_EP+	intr_mask.b.isooutdrop = 1;+	intr_mask.b.eopframe = 1;+	intr_mask.b.incomplisoin = 1;+	intr_mask.b.incomplisoout = 1;+#endif++	DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);++	DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__,+		    DWC_READ_REG32(&global_regs->gintmsk));+}++/**+ * This function initializes the DWC_otg controller registers for+ * device mode.+ *+ * @param core_if Programming view of DWC_otg controller+ *+ */+void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if)+{+	int i;+	dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;+	dwc_otg_dev_if_t *dev_if = core_if->dev_if;+	dwc_otg_core_params_t *params = core_if->core_params;+	dcfg_data_t dcfg = {.d32 = 0 };+	depctl_data_t diepctl = {.d32 = 0 };+	grstctl_t resetctl = {.d32 = 0 };+	uint32_t rx_fifo_size;+	fifosize_data_t nptxfifosize;+	fifosize_data_t txfifosize;+	dthrctl_data_t dthrctl;+	fifosize_data_t ptxfifosize;+	uint16_t rxfsiz, nptxfsiz;+	gdfifocfg_data_t gdfifocfg = {.d32 = 0 };+	hwcfg3_data_t hwcfg3 = {.d32 = 0 };++	/* Restart the Phy Clock */+	DWC_WRITE_REG32(core_if->pcgcctl, 0);++	/* Device configuration register */+	init_devspd(core_if);+	dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);+	dcfg.b.descdma = (core_if->dma_desc_enable) ? 1 : 0;+	dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;+	/* Enable Device OUT NAK in case of DDMA mode*/+	if (core_if->core_params->dev_out_nak) {+		dcfg.b.endevoutnak = 1;+	}++	if (core_if->core_params->cont_on_bna) {+		dctl_data_t dctl = {.d32 = 0 };+		dctl.b.encontonbna = 1;+		DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32);+	}+++	DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);++	/* Configure data FIFO sizes */+	if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {+		DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n",+			    core_if->total_fifo_size);+		DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n",+			    params->dev_rx_fifo_size);+		DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n",+			    params->dev_nperio_tx_fifo_size);++		/* Rx FIFO */+		DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",+			    DWC_READ_REG32(&global_regs->grxfsiz));++#ifdef DWC_UTE_CFI+		core_if->pwron_rxfsiz = DWC_READ_REG32(&global_regs->grxfsiz);+		core_if->init_rxfsiz = params->dev_rx_fifo_size;+#endif+		rx_fifo_size = params->dev_rx_fifo_size;+		DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size);++		DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",+			    DWC_READ_REG32(&global_regs->grxfsiz));++		/** Set Periodic Tx FIFO Mask all bits 0 */+		core_if->p_tx_msk = 0;++		/** Set Tx FIFO Mask all bits 0 */+		core_if->tx_msk = 0;++		if (core_if->en_multiple_tx_fifo == 0) {+			/* Non-periodic Tx FIFO */+			DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",+				    DWC_READ_REG32(&global_regs->gnptxfsiz));++			nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;+			nptxfifosize.b.startaddr = params->dev_rx_fifo_size;++			DWC_WRITE_REG32(&global_regs->gnptxfsiz,+					nptxfifosize.d32);++			DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",+				    DWC_READ_REG32(&global_regs->gnptxfsiz));++			/**@todo NGS: Fix Periodic FIFO Sizing! */+			/*+			 * Periodic Tx FIFOs These FIFOs are numbered from 1 to 15.+			 * Indexes of the FIFO size module parameters in the+			 * dev_perio_tx_fifo_size array and the FIFO size registers in+			 * the dptxfsiz array run from 0 to 14.+			 */+			/** @todo Finish debug of this */+			ptxfifosize.b.startaddr =+			    nptxfifosize.b.startaddr + nptxfifosize.b.depth;+			for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {+				ptxfifosize.b.depth =+				    params->dev_perio_tx_fifo_size[i];+				DWC_DEBUGPL(DBG_CIL,+					    "initial dtxfsiz[%d]=%08x\n", i,+					    DWC_READ_REG32(&global_regs->dtxfsiz+							   [i]));+				DWC_WRITE_REG32(&global_regs->dtxfsiz[i],+						ptxfifosize.d32);+				DWC_DEBUGPL(DBG_CIL, "new dtxfsiz[%d]=%08x\n",+					    i,+					    DWC_READ_REG32(&global_regs->dtxfsiz+							   [i]));+				ptxfifosize.b.startaddr += ptxfifosize.b.depth;+			}+		} else {+			/*+			 * Tx FIFOs These FIFOs are numbered from 1 to 15.+			 * Indexes of the FIFO size module parameters in the+			 * dev_tx_fifo_size array and the FIFO size registers in+			 * the dtxfsiz array run from 0 to 14.+			 */++			/* Non-periodic Tx FIFO */+			DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",+				    DWC_READ_REG32(&global_regs->gnptxfsiz));++#ifdef DWC_UTE_CFI+			core_if->pwron_gnptxfsiz =+			    (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);+			core_if->init_gnptxfsiz =+			    params->dev_nperio_tx_fifo_size;+#endif+			nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;+			nptxfifosize.b.startaddr = params->dev_rx_fifo_size;++			DWC_WRITE_REG32(&global_regs->gnptxfsiz,+					nptxfifosize.d32);++			DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",+				    DWC_READ_REG32(&global_regs->gnptxfsiz));++			txfifosize.b.startaddr =+			    nptxfifosize.b.startaddr + nptxfifosize.b.depth;++			for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {++				txfifosize.b.depth =+				    params->dev_tx_fifo_size[i];++				DWC_DEBUGPL(DBG_CIL,+					    "initial dtxfsiz[%d]=%08x\n",+					    i,+					    DWC_READ_REG32(&global_regs->dtxfsiz+							   [i]));++#ifdef DWC_UTE_CFI+				core_if->pwron_txfsiz[i] =+				    (DWC_READ_REG32+				     (&global_regs->dtxfsiz[i]) >> 16);+				core_if->init_txfsiz[i] =+				    params->dev_tx_fifo_size[i];+#endif+				DWC_WRITE_REG32(&global_regs->dtxfsiz[i],+						txfifosize.d32);++				DWC_DEBUGPL(DBG_CIL,+					    "new dtxfsiz[%d]=%08x\n",+					    i,+					    DWC_READ_REG32(&global_regs->dtxfsiz+							   [i]));++				txfifosize.b.startaddr += txfifosize.b.depth;+			}+			if (core_if->snpsid <= OTG_CORE_REV_2_94a) {+				/* Calculating DFIFOCFG for Device mode to include RxFIFO and NPTXFIFO */+				gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg);+				hwcfg3.d32 = DWC_READ_REG32(&global_regs->ghwcfg3);+				gdfifocfg.b.gdfifocfg = (DWC_READ_REG32(&global_regs->ghwcfg3) >> 16);+				DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);+				rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff);+				nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);+				gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz;+				DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);+			}+		}++		/* Flush the FIFOs */+		dwc_otg_flush_tx_fifo(core_if, 0x10);	/* all Tx FIFOs */+		dwc_otg_flush_rx_fifo(core_if);++		/* Flush the Learning Queue. */+		resetctl.b.intknqflsh = 1;+		DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);++		if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) {+			core_if->start_predict = 0;+			for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) {+				core_if->nextep_seq[i] = 0xff;	// 0xff - EP not active+			}+			core_if->nextep_seq[0] = 0;+			core_if->first_in_nextep_seq = 0;+			diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);+			diepctl.b.nextep = 0;+			DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);++			/* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */+			dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);+			dcfg.b.epmscnt = 2;+			DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);++			DWC_DEBUGPL(DBG_CILV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n",+				__func__, core_if->first_in_nextep_seq);+			for (i=0; i <= core_if->dev_if->num_in_eps; i++) {+				DWC_DEBUGPL(DBG_CILV, "%2d ", core_if->nextep_seq[i]);+			}+			DWC_DEBUGPL(DBG_CILV,"\n");+		}++		/* Clear all pending Device Interrupts */+		/** @todo - if the condition needed to be checked+		 *  or in any case all pending interrutps should be cleared?+	     */+		if (core_if->multiproc_int_enable) {+			for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {+				DWC_WRITE_REG32(&dev_if->+						dev_global_regs->diepeachintmsk[i], 0);+			}+		}++		for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {+			DWC_WRITE_REG32(&dev_if->+					dev_global_regs->doepeachintmsk[i], 0);+		}++		DWC_WRITE_REG32(&dev_if->dev_global_regs->deachint, 0xFFFFFFFF);+		DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, 0);+	} else {+		DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0);+		DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0);+		DWC_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF);+		DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0);+	}++	for (i = 0; i <= dev_if->num_in_eps; i++) {+		depctl_data_t depctl;+		depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);+		if (depctl.b.epena) {+			depctl.d32 = 0;+			depctl.b.epdis = 1;+			depctl.b.snak = 1;+		} else {+			depctl.d32 = 0;+		}++		DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);++		DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0);+		DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0);+		DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF);+	}++	for (i = 0; i <= dev_if->num_out_eps; i++) {+		depctl_data_t depctl;+		depctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);+		if (depctl.b.epena) {+			dctl_data_t dctl = {.d32 = 0 };+			gintmsk_data_t gintsts = {.d32 = 0 };+			doepint_data_t doepint = {.d32 = 0 };+			dctl.b.sgoutnak = 1;+			DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);+			do {+				dwc_udelay(10);+				gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);+			} while (!gintsts.b.goutnakeff);+			gintsts.d32 = 0;+			gintsts.b.goutnakeff = 1;+			DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);++			depctl.d32 = 0;+			depctl.b.epdis = 1;+			depctl.b.snak = 1;+			DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepctl, depctl.d32);+			do {+				dwc_udelay(10);+				doepint.d32 = DWC_READ_REG32(&core_if->dev_if->+					out_ep_regs[i]->doepint);+			} while (!doepint.b.epdisabled);++			doepint.b.epdisabled = 1;+			DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepint, doepint.d32);++			dctl.d32 = 0;+			dctl.b.cgoutnak = 1;+			DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);+		} else {+			depctl.d32 = 0;+		}++		DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32);++		DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0);+		DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0);+		DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF);+	}++	if (core_if->en_multiple_tx_fifo && core_if->dma_enable) {+		dev_if->non_iso_tx_thr_en = params->thr_ctl & 0x1;+		dev_if->iso_tx_thr_en = (params->thr_ctl >> 1) & 0x1;+		dev_if->rx_thr_en = (params->thr_ctl >> 2) & 0x1;++		dev_if->rx_thr_length = params->rx_thr_length;+		dev_if->tx_thr_length = params->tx_thr_length;++		dev_if->setup_desc_index = 0;++		dthrctl.d32 = 0;+		dthrctl.b.non_iso_thr_en = dev_if->non_iso_tx_thr_en;+		dthrctl.b.iso_thr_en = dev_if->iso_tx_thr_en;+		dthrctl.b.tx_thr_len = dev_if->tx_thr_length;+		dthrctl.b.rx_thr_en = dev_if->rx_thr_en;+		dthrctl.b.rx_thr_len = dev_if->rx_thr_length;+		dthrctl.b.ahb_thr_ratio = params->ahb_thr_ratio;++		DWC_WRITE_REG32(&dev_if->dev_global_regs->dtknqr3_dthrctl,+				dthrctl.d32);++		DWC_DEBUGPL(DBG_CIL,+			    "Non ISO Tx Thr - %d\nISO Tx Thr - %d\nRx Thr - %d\nTx Thr Len - %d\nRx Thr Len - %d\n",+			    dthrctl.b.non_iso_thr_en, dthrctl.b.iso_thr_en,+			    dthrctl.b.rx_thr_en, dthrctl.b.tx_thr_len,+			    dthrctl.b.rx_thr_len);++	}++	dwc_otg_enable_device_interrupts(core_if);++	{+		diepmsk_data_t msk = {.d32 = 0 };+		msk.b.txfifoundrn = 1;+		if (core_if->multiproc_int_enable) {+			DWC_MODIFY_REG32(&dev_if->dev_global_regs->+					 diepeachintmsk[0], msk.d32, msk.d32);+		} else {+			DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk,+					 msk.d32, msk.d32);+		}+	}++	if (core_if->multiproc_int_enable) {+		/* Set NAK on Babble */+		dctl_data_t dctl = {.d32 = 0 };+		dctl.b.nakonbble = 1;+		DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32);+	}++	if (core_if->snpsid >= OTG_CORE_REV_2_94a) {+		dctl_data_t dctl = {.d32 = 0 };+		dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);+		dctl.b.sftdiscon = 0;+		DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);+	}+}++/**+ * This function enables the Host mode interrupts.+ *+ * @param core_if Programming view of DWC_otg controller+ */+void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * core_if)+{+	dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;+	gintmsk_data_t intr_mask = {.d32 = 0 };++	DWC_DEBUGPL(DBG_CIL, "%s(%p)\n", __func__, core_if);++	/* Disable all interrupts. */+	DWC_WRITE_REG32(&global_regs->gintmsk, 0);++	/* Clear any pending interrupts. */+	DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);++	/* Enable the common interrupts */+	dwc_otg_enable_common_interrupts(core_if);++	/*+	 * Enable host mode interrupts without disturbing common+	 * interrupts.+	 */++	intr_mask.b.disconnect = 1;+	intr_mask.b.portintr = 1;+	intr_mask.b.hcintr = 1;++	DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);+}++/**+ * This function disables the Host Mode interrupts.+ *+ * @param core_if Programming view of DWC_otg controller+ */+void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * core_if)+{+	dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;+	gintmsk_data_t intr_mask = {.d32 = 0 };++	DWC_DEBUGPL(DBG_CILV, "%s()\n", __func__);++	/*+	 * Disable host mode interrupts without disturbing common+	 * interrupts.+	 */+	intr_mask.b.sofintr = 1;+	intr_mask.b.portintr = 1;+	intr_mask.b.hcintr = 1;+	intr_mask.b.ptxfempty = 1;+	intr_mask.b.nptxfempty = 1;++	DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, 0);+}++/**+ * This function initializes the DWC_otg controller registers for+ * host mode.+ *+ * This function flushes the Tx and Rx FIFOs and it flushes any entries in the+ * request queues. Host channels are reset to ensure that they are ready for+ * performing transfers.+ *+ * @param core_if Programming view of DWC_otg controller+ *+ */+void dwc_otg_core_host_init(dwc_otg_core_if_t * core_if)+{+	dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;+	dwc_otg_host_if_t *host_if = core_if->host_if;+	dwc_otg_core_params_t *params = core_if->core_params;+	hprt0_data_t hprt0 = {.d32 = 0 };+	fifosize_data_t nptxfifosize;+	fifosize_data_t ptxfifosize;+	uint16_t rxfsiz, nptxfsiz, hptxfsiz;+	gdfifocfg_data_t gdfifocfg = {.d32 = 0 };+	int i;+	hcchar_data_t hcchar;+	hcfg_data_t hcfg;+	hfir_data_t hfir;+	dwc_otg_hc_regs_t *hc_regs;+	int num_channels;+	gotgctl_data_t gotgctl = {.d32 = 0 };++	DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if);++	/* Restart the Phy Clock */+	DWC_WRITE_REG32(core_if->pcgcctl, 0);++	/* Initialize Host Configuration Register */+	init_fslspclksel(core_if);+	if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {+		hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg);+		hcfg.b.fslssupp = 1;+		DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32);++	}++	/* This bit allows dynamic reloading of the HFIR register+	 * during runtime. This bit needs to be programmed during+	 * initial configuration and its value must not be changed+	 * during runtime.*/+	if (core_if->core_params->reload_ctl == 1) {+		hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir);+		hfir.b.hfirrldctrl = 1;+		DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32);+	}++	if (core_if->core_params->dma_desc_enable) {+		uint8_t op_mode = core_if->hwcfg2.b.op_mode;+		if (!+		    (core_if->hwcfg4.b.desc_dma+		     && (core_if->snpsid >= OTG_CORE_REV_2_90a)+		     && ((op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)+			 || (op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)+			 || (op_mode ==+			     DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG)+			 || (op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)+			 || (op_mode ==+			     DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST)))) {++			DWC_ERROR("Host can't operate in Descriptor DMA mode.\n"+				  "Either core version is below 2.90a or "+				  "GHWCFG2, GHWCFG4 registers' values do not allow Descriptor DMA in host mode.\n"+				  "To run the driver in Buffer DMA host mode set dma_desc_enable "+				  "module parameter to 0.\n");+			return;+		}+		hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg);+		hcfg.b.descdma = 1;+		DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32);+	}++	/* Configure data FIFO sizes */+	if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {+		DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n",+			    core_if->total_fifo_size);+		DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n",+			    params->host_rx_fifo_size);+		DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n",+			    params->host_nperio_tx_fifo_size);+		DWC_DEBUGPL(DBG_CIL, "P Tx FIFO Size=%d\n",+			    params->host_perio_tx_fifo_size);++		/* Rx FIFO */+		DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",+			    DWC_READ_REG32(&global_regs->grxfsiz));+		DWC_WRITE_REG32(&global_regs->grxfsiz,+				params->host_rx_fifo_size);+		DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",+			    DWC_READ_REG32(&global_regs->grxfsiz));++		/* Non-periodic Tx FIFO */+		DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",+			    DWC_READ_REG32(&global_regs->gnptxfsiz));+		nptxfifosize.b.depth = params->host_nperio_tx_fifo_size;+		nptxfifosize.b.startaddr = params->host_rx_fifo_size;+		DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);+		DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",+			    DWC_READ_REG32(&global_regs->gnptxfsiz));++		/* Periodic Tx FIFO */+		DWC_DEBUGPL(DBG_CIL, "initial hptxfsiz=%08x\n",+			    DWC_READ_REG32(&global_regs->hptxfsiz));+		ptxfifosize.b.depth = params->host_perio_tx_fifo_size;+		ptxfifosize.b.startaddr =+		    nptxfifosize.b.startaddr + nptxfifosize.b.depth;+		DWC_WRITE_REG32(&global_regs->hptxfsiz, ptxfifosize.d32);+		DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n",+			    DWC_READ_REG32(&global_regs->hptxfsiz));++		if (core_if->en_multiple_tx_fifo+		    && core_if->snpsid <= OTG_CORE_REV_2_94a) {+			/* Global DFIFOCFG calculation for Host mode - include RxFIFO, NPTXFIFO and HPTXFIFO */+			gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg);+			rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff);+			nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);+			hptxfsiz = (DWC_READ_REG32(&global_regs->hptxfsiz) >> 16);+			gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz + hptxfsiz;+			DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);+		}+	}++	/* TODO - check this */+	/* Clear Host Set HNP Enable in the OTG Control Register */+	gotgctl.b.hstsethnpen = 1;+	DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);+	/* Make sure the FIFOs are flushed. */+	dwc_otg_flush_tx_fifo(core_if, 0x10 /* all TX FIFOs */ );+	dwc_otg_flush_rx_fifo(core_if);++	/* Clear Host Set HNP Enable in the OTG Control Register */+	gotgctl.b.hstsethnpen = 1;+	DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);++	if (!core_if->core_params->dma_desc_enable) {+		/* Flush out any leftover queued requests. */+		num_channels = core_if->core_params->host_channels;++		for (i = 0; i < num_channels; i++) {+			hc_regs = core_if->host_if->hc_regs[i];+			hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+			hcchar.b.chen = 0;+			hcchar.b.chdis = 1;+			hcchar.b.epdir = 0;+			DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);+		}++		/* Halt all channels to put them into a known state. */+		for (i = 0; i < num_channels; i++) {+			int count = 0;+			hc_regs = core_if->host_if->hc_regs[i];+			hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+			hcchar.b.chen = 1;+			hcchar.b.chdis = 1;+			hcchar.b.epdir = 0;+			DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);+			DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d regs %p\n", __func__, i, hc_regs);+			do {+				hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+				if (++count > 1000) {+					DWC_ERROR+					    ("%s: Unable to clear halt on channel %d (timeout HCCHAR 0x%X @%p)\n",+					     __func__, i, hcchar.d32, &hc_regs->hcchar);+					break;+				}+				dwc_udelay(1);+			} while (hcchar.b.chen);+		}+	}++	/* Turn on the vbus power. */+	DWC_PRINTF("Init: Port Power? op_state=%d\n", core_if->op_state);+	if (core_if->op_state == A_HOST) {+		hprt0.d32 = dwc_otg_read_hprt0(core_if);+		DWC_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr);+		if (hprt0.b.prtpwr == 0) {+			hprt0.b.prtpwr = 1;+			DWC_WRITE_REG32(host_if->hprt0, hprt0.d32);+		}+	}++	dwc_otg_enable_host_interrupts(core_if);+}++/**+ * Prepares a host channel for transferring packets to/from a specific+ * endpoint. The HCCHARn register is set up with the characteristics specified+ * in _hc. Host channel interrupts that may need to be serviced while this+ * transfer is in progress are enabled.+ *+ * @param core_if Programming view of DWC_otg controller+ * @param hc Information needed to initialize the host channel+ */+void dwc_otg_hc_init(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)+{+	uint32_t intr_enable;+	hcintmsk_data_t hc_intr_mask;+	gintmsk_data_t gintmsk = {.d32 = 0 };+	hcchar_data_t hcchar;+	hcsplt_data_t hcsplt;++	uint8_t hc_num = hc->hc_num;+	dwc_otg_host_if_t *host_if = core_if->host_if;+	dwc_otg_hc_regs_t *hc_regs = host_if->hc_regs[hc_num];++	/* Clear old interrupt conditions for this host channel. */+	hc_intr_mask.d32 = 0xFFFFFFFF;+	hc_intr_mask.b.reserved14_31 = 0;+	DWC_WRITE_REG32(&hc_regs->hcint, hc_intr_mask.d32);++	/* Enable channel interrupts required for this transfer. */+	hc_intr_mask.d32 = 0;+	hc_intr_mask.b.chhltd = 1;+	if (core_if->dma_enable) {+		/* For Descriptor DMA mode core halts the channel on AHB error. Interrupt is not required */+		if (!core_if->dma_desc_enable)+			hc_intr_mask.b.ahberr = 1;+		else {+			if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)+				hc_intr_mask.b.xfercompl = 1;+		}++		if (hc->error_state && !hc->do_split &&+		    hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {+			hc_intr_mask.b.ack = 1;+			if (hc->ep_is_in) {+				hc_intr_mask.b.datatglerr = 1;+				if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) {+					hc_intr_mask.b.nak = 1;+				}+			}+		}+	} else {+		switch (hc->ep_type) {+		case DWC_OTG_EP_TYPE_CONTROL:+		case DWC_OTG_EP_TYPE_BULK:+			hc_intr_mask.b.xfercompl = 1;+			hc_intr_mask.b.stall = 1;+			hc_intr_mask.b.xacterr = 1;+			hc_intr_mask.b.datatglerr = 1;+			if (hc->ep_is_in) {+				hc_intr_mask.b.bblerr = 1;+			} else {+				hc_intr_mask.b.nak = 1;+				hc_intr_mask.b.nyet = 1;+				if (hc->do_ping) {+					hc_intr_mask.b.ack = 1;+				}+			}++			if (hc->do_split) {+				hc_intr_mask.b.nak = 1;+				if (hc->complete_split) {+					hc_intr_mask.b.nyet = 1;+				} else {+					hc_intr_mask.b.ack = 1;+				}+			}++			if (hc->error_state) {+				hc_intr_mask.b.ack = 1;+			}+			break;+		case DWC_OTG_EP_TYPE_INTR:+			hc_intr_mask.b.xfercompl = 1;+			hc_intr_mask.b.nak = 1;+			hc_intr_mask.b.stall = 1;+			hc_intr_mask.b.xacterr = 1;+			hc_intr_mask.b.datatglerr = 1;+			hc_intr_mask.b.frmovrun = 1;++			if (hc->ep_is_in) {+				hc_intr_mask.b.bblerr = 1;+			}+			if (hc->error_state) {+				hc_intr_mask.b.ack = 1;+			}+			if (hc->do_split) {+				if (hc->complete_split) {+					hc_intr_mask.b.nyet = 1;+				} else {+					hc_intr_mask.b.ack = 1;+				}+			}+			break;+		case DWC_OTG_EP_TYPE_ISOC:+			hc_intr_mask.b.xfercompl = 1;+			hc_intr_mask.b.frmovrun = 1;+			hc_intr_mask.b.ack = 1;++			if (hc->ep_is_in) {+				hc_intr_mask.b.xacterr = 1;+				hc_intr_mask.b.bblerr = 1;+			}+			break;+		}+	}+	DWC_WRITE_REG32(&hc_regs->hcintmsk, hc_intr_mask.d32);++	/* Enable the top level host channel interrupt. */+	intr_enable = (1 << hc_num);+	DWC_MODIFY_REG32(&host_if->host_global_regs->haintmsk, 0, intr_enable);++	/* Make sure host channel interrupts are enabled. */+	gintmsk.b.hcintr = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32);++	/*+	 * Program the HCCHARn register with the endpoint characteristics for+	 * the current transfer.+	 */+	hcchar.d32 = 0;+	hcchar.b.devaddr = hc->dev_addr;+	hcchar.b.epnum = hc->ep_num;+	hcchar.b.epdir = hc->ep_is_in;+	hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);+	hcchar.b.eptype = hc->ep_type;+	hcchar.b.mps = hc->max_packet;++	DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32);++	DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d, Dev Addr %d, EP #%d\n",+                    __func__, hc->hc_num, hcchar.b.devaddr, hcchar.b.epnum);+	DWC_DEBUGPL(DBG_HCDV, "	 Is In %d, Is Low Speed %d, EP Type %d, "+                                "Max Pkt %d, Multi Cnt %d\n",+                    hcchar.b.epdir, hcchar.b.lspddev, hcchar.b.eptype,+                    hcchar.b.mps, hcchar.b.multicnt);++	/*+	 * Program the HCSPLIT register for SPLITs+	 */+	hcsplt.d32 = 0;+	if (hc->do_split) {+		DWC_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n",+			    hc->hc_num,+			    hc->complete_split ? "CSPLIT" : "SSPLIT");+		hcsplt.b.compsplt = hc->complete_split;+		hcsplt.b.xactpos = hc->xact_pos;+		hcsplt.b.hubaddr = hc->hub_addr;+		hcsplt.b.prtaddr = hc->port_addr;+		DWC_DEBUGPL(DBG_HCDV, "\t  comp split %d\n", hc->complete_split);+		DWC_DEBUGPL(DBG_HCDV, "\t  xact pos %d\n", hc->xact_pos);+		DWC_DEBUGPL(DBG_HCDV, "\t  hub addr %d\n", hc->hub_addr);+		DWC_DEBUGPL(DBG_HCDV, "\t  port addr %d\n", hc->port_addr);+		DWC_DEBUGPL(DBG_HCDV, "\t  is_in %d\n", hc->ep_is_in);+		DWC_DEBUGPL(DBG_HCDV, "\t  Max Pkt: %d\n", hcchar.b.mps);+		DWC_DEBUGPL(DBG_HCDV, "\t  xferlen: %d\n", hc->xfer_len);+	}+	DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32);++}++/**+ * Attempts to halt a host channel. This function should only be called in+ * Slave mode or to abort a transfer in either Slave mode or DMA mode. Under+ * normal circumstances in DMA mode, the controller halts the channel when the+ * transfer is complete or a condition occurs that requires application+ * intervention.+ *+ * In slave mode, checks for a free request queue entry, then sets the Channel+ * Enable and Channel Disable bits of the Host Channel Characteristics+ * register of the specified channel to intiate the halt. If there is no free+ * request queue entry, sets only the Channel Disable bit of the HCCHARn+ * register to flush requests for this channel. In the latter case, sets a+ * flag to indicate that the host channel needs to be halted when a request+ * queue slot is open.+ *+ * In DMA mode, always sets the Channel Enable and Channel Disable bits of the+ * HCCHARn register. The controller ensures there is space in the request+ * queue before submitting the halt request.+ *+ * Some time may elapse before the core flushes any posted requests for this+ * host channel and halts. The Channel Halted interrupt handler completes the+ * deactivation of the host channel.+ *+ * @param core_if Controller register interface.+ * @param hc Host channel to halt.+ * @param halt_status Reason for halting the channel.+ */+void dwc_otg_hc_halt(dwc_otg_core_if_t * core_if,+		     dwc_hc_t * hc, dwc_otg_halt_status_e halt_status)+{+	gnptxsts_data_t nptxsts;+	hptxsts_data_t hptxsts;+	hcchar_data_t hcchar;+	dwc_otg_hc_regs_t *hc_regs;+	dwc_otg_core_global_regs_t *global_regs;+	dwc_otg_host_global_regs_t *host_global_regs;++	hc_regs = core_if->host_if->hc_regs[hc->hc_num];+	global_regs = core_if->core_global_regs;+	host_global_regs = core_if->host_if->host_global_regs;++	DWC_ASSERT(!(halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS),+		   "halt_status = %d\n", halt_status);++	if (halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||+	    halt_status == DWC_OTG_HC_XFER_AHB_ERR) {+		/*+		 * Disable all channel interrupts except Ch Halted. The QTD+		 * and QH state associated with this transfer has been cleared+		 * (in the case of URB_DEQUEUE), so the channel needs to be+		 * shut down carefully to prevent crashes.+		 */+		hcintmsk_data_t hcintmsk;+		hcintmsk.d32 = 0;+		hcintmsk.b.chhltd = 1;+		DWC_WRITE_REG32(&hc_regs->hcintmsk, hcintmsk.d32);++		/*+		 * Make sure no other interrupts besides halt are currently+		 * pending. Handling another interrupt could cause a crash due+		 * to the QTD and QH state.+		 */+		DWC_WRITE_REG32(&hc_regs->hcint, ~hcintmsk.d32);++		/*+		 * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR+		 * even if the channel was already halted for some other+		 * reason.+		 */+		hc->halt_status = halt_status;++		hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+		if (hcchar.b.chen == 0) {+			/*+			 * The channel is either already halted or it hasn't+			 * started yet. In DMA mode, the transfer may halt if+			 * it finishes normally or a condition occurs that+			 * requires driver intervention. Don't want to halt+			 * the channel again. In either Slave or DMA mode,+			 * it's possible that the transfer has been assigned+			 * to a channel, but not started yet when an URB is+			 * dequeued. Don't want to halt a channel that hasn't+			 * started yet.+			 */+			return;+		}+	}+	if (hc->halt_pending) {+		/*+		 * A halt has already been issued for this channel. This might+		 * happen when a transfer is aborted by a higher level in+		 * the stack.+		 */+#ifdef DEBUG+		DWC_PRINTF+		    ("*** %s: Channel %d, _hc->halt_pending already set ***\n",+		     __func__, hc->hc_num);++#endif+		return;+	}++	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);++	/* No need to set the bit in DDMA for disabling the channel */+	//TODO check it everywhere channel is disabled+	if (!core_if->core_params->dma_desc_enable)+		hcchar.b.chen = 1;+	hcchar.b.chdis = 1;++	if (!core_if->dma_enable) {+		/* Check for space in the request queue to issue the halt. */+		if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||+		    hc->ep_type == DWC_OTG_EP_TYPE_BULK) {+			nptxsts.d32 = DWC_READ_REG32(&global_regs->gnptxsts);+			if (nptxsts.b.nptxqspcavail == 0) {+				hcchar.b.chen = 0;+			}+		} else {+			hptxsts.d32 =+			    DWC_READ_REG32(&host_global_regs->hptxsts);+			if ((hptxsts.b.ptxqspcavail == 0)+			    || (core_if->queuing_high_bandwidth)) {+				hcchar.b.chen = 0;+			}+		}+	}+	DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);++	hc->halt_status = halt_status;++	if (hcchar.b.chen) {+		hc->halt_pending = 1;+		hc->halt_on_queue = 0;+	} else {+		hc->halt_on_queue = 1;+	}++	DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);+	DWC_DEBUGPL(DBG_HCDV, "	 hcchar: 0x%08x\n", hcchar.d32);+	DWC_DEBUGPL(DBG_HCDV, "	 halt_pending: %d\n", hc->halt_pending);+	DWC_DEBUGPL(DBG_HCDV, "	 halt_on_queue: %d\n", hc->halt_on_queue);+	DWC_DEBUGPL(DBG_HCDV, "	 halt_status: %d\n", hc->halt_status);++	return;+}++/**+ * Clears the transfer state for a host channel. This function is normally+ * called after a transfer is done and the host channel is being released.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param hc Identifies the host channel to clean up.+ */+void dwc_otg_hc_cleanup(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)+{+	dwc_otg_hc_regs_t *hc_regs;++	hc->xfer_started = 0;++	/*+	 * Clear channel interrupt enables and any unhandled channel interrupt+	 * conditions.+	 */+	hc_regs = core_if->host_if->hc_regs[hc->hc_num];+	DWC_WRITE_REG32(&hc_regs->hcintmsk, 0);+	DWC_WRITE_REG32(&hc_regs->hcint, 0xFFFFFFFF);+#ifdef DEBUG+	DWC_TIMER_CANCEL(core_if->hc_xfer_timer[hc->hc_num]);+#endif+}++/**+ * Sets the channel property that indicates in which frame a periodic transfer+ * should occur. This is always set to the _next_ frame. This function has no+ * effect on non-periodic transfers.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param hc Identifies the host channel to set up and its properties.+ * @param hcchar Current value of the HCCHAR register for the specified host+ * channel.+ */+static inline void hc_set_even_odd_frame(dwc_otg_core_if_t * core_if,+					 dwc_hc_t * hc, hcchar_data_t * hcchar)+{+	if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||+	    hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {+		hfnum_data_t hfnum;+		hfnum.d32 =+		    DWC_READ_REG32(&core_if->host_if->host_global_regs->hfnum);++		/* 1 if _next_ frame is odd, 0 if it's even */+		hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1;+#ifdef DEBUG+		if (hc->ep_type == DWC_OTG_EP_TYPE_INTR && hc->do_split+		    && !hc->complete_split) {+			switch (hfnum.b.frnum & 0x7) {+			case 7:+				core_if->hfnum_7_samples++;+				core_if->hfnum_7_frrem_accum += hfnum.b.frrem;+				break;+			case 0:+				core_if->hfnum_0_samples++;+				core_if->hfnum_0_frrem_accum += hfnum.b.frrem;+				break;+			default:+				core_if->hfnum_other_samples++;+				core_if->hfnum_other_frrem_accum +=+				    hfnum.b.frrem;+				break;+			}+		}+#endif+	}+}++#ifdef DEBUG+void hc_xfer_timeout(void *ptr)+{+	hc_xfer_info_t *xfer_info = NULL;+	int hc_num = 0;++	if (ptr)+		xfer_info = (hc_xfer_info_t *) ptr;++	if (!xfer_info->hc) {+		DWC_ERROR("xfer_info->hc = %p\n", xfer_info->hc);+		return;+	}++	hc_num = xfer_info->hc->hc_num;+	DWC_WARN("%s: timeout on channel %d\n", __func__, hc_num);+	DWC_WARN("	start_hcchar_val 0x%08x\n",+		 xfer_info->core_if->start_hcchar_val[hc_num]);+}+#endif++void ep_xfer_timeout(void *ptr)+{+	ep_xfer_info_t *xfer_info = NULL;+	int ep_num = 0;+	dctl_data_t dctl = {.d32 = 0 };+	gintsts_data_t gintsts = {.d32 = 0 };+	gintmsk_data_t gintmsk = {.d32 = 0 };++	if (ptr)+		xfer_info = (ep_xfer_info_t *) ptr;++	if (!xfer_info->ep) {+		DWC_ERROR("xfer_info->ep = %p\n", xfer_info->ep);+		return;+	}++	ep_num = xfer_info->ep->num;+	DWC_WARN("%s: timeout on endpoit %d\n", __func__, ep_num);+	/* Put the sate to 2 as it was time outed */+	xfer_info->state = 2;++	dctl.d32 =+	    DWC_READ_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl);+	gintsts.d32 =+	    DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintsts);+	gintmsk.d32 =+	    DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintmsk);++	if (!gintmsk.b.goutnakeff) {+		/* Unmask it */+		gintmsk.b.goutnakeff = 1;+		DWC_WRITE_REG32(&xfer_info->core_if->core_global_regs->gintmsk,+				gintmsk.d32);++	}++	if (!gintsts.b.goutnakeff) {+		dctl.b.sgoutnak = 1;+	}+	DWC_WRITE_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl,+			dctl.d32);++}++void set_pid_isoc(dwc_hc_t * hc)+{+	/* Set up the initial PID for the transfer. */+	if (hc->speed == DWC_OTG_EP_SPEED_HIGH) {+		if (hc->ep_is_in) {+			if (hc->multi_count == 1) {+				hc->data_pid_start = DWC_OTG_HC_PID_DATA0;+			} else if (hc->multi_count == 2) {+				hc->data_pid_start = DWC_OTG_HC_PID_DATA1;+			} else {+				hc->data_pid_start = DWC_OTG_HC_PID_DATA2;+			}+		} else {+			if (hc->multi_count == 1) {+				hc->data_pid_start = DWC_OTG_HC_PID_DATA0;+			} else {+				hc->data_pid_start = DWC_OTG_HC_PID_MDATA;+			}+		}+	} else {+		hc->data_pid_start = DWC_OTG_HC_PID_DATA0;+	}+}++/**+ * This function does the setup for a data transfer for a host channel and+ * starts the transfer. May be called in either Slave mode or DMA mode. In+ * Slave mode, the caller must ensure that there is sufficient space in the+ * request queue and Tx Data FIFO.+ *+ * For an OUT transfer in Slave mode, it loads a data packet into the+ * appropriate FIFO. If necessary, additional data packets will be loaded in+ * the Host ISR.+ *+ * For an IN transfer in Slave mode, a data packet is requested. The data+ * packets are unloaded from the Rx FIFO in the Host ISR. If necessary,+ * additional data packets are requested in the Host ISR.+ *+ * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ+ * register along with a packet count of 1 and the channel is enabled. This+ * causes a single PING transaction to occur. Other fields in HCTSIZ are+ * simply set to 0 since no data transfer occurs in this case.+ *+ * For a PING transfer in DMA mode, the HCTSIZ register is initialized with+ * all the information required to perform the subsequent data transfer. In+ * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the+ * controller performs the entire PING protocol, then starts the data+ * transfer.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param hc Information needed to initialize the host channel. The xfer_len+ * value may be reduced to accommodate the max widths of the XferSize and+ * PktCnt fields in the HCTSIZn register. The multi_count value may be changed+ * to reflect the final xfer_len value.+ */+void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)+{+	hcchar_data_t hcchar;+	hctsiz_data_t hctsiz;+	uint16_t num_packets;+	uint32_t max_hc_xfer_size = core_if->core_params->max_transfer_size;+	uint16_t max_hc_pkt_count = core_if->core_params->max_packet_count;+	dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];++	hctsiz.d32 = 0;++	if (hc->do_ping) {+		if (!core_if->dma_enable) {+			dwc_otg_hc_do_ping(core_if, hc);+			hc->xfer_started = 1;+			return;+		} else {+			hctsiz.b.dopng = 1;+		}+	}++	if (hc->do_split) {+		num_packets = 1;++		if (hc->complete_split && !hc->ep_is_in) {+			/* For CSPLIT OUT Transfer, set the size to 0 so the+			 * core doesn't expect any data written to the FIFO */+			hc->xfer_len = 0;+		} else if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) {+			hc->xfer_len = hc->max_packet;+		} else if (!hc->ep_is_in && (hc->xfer_len > 188)) {+			hc->xfer_len = 188;+		}++		hctsiz.b.xfersize = hc->xfer_len;+	} else {+		/*+		 * Ensure that the transfer length and packet count will fit+		 * in the widths allocated for them in the HCTSIZn register.+		 */+		if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||+		    hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {+			/*+			 * Make sure the transfer size is no larger than one+			 * (micro)frame's worth of data. (A check was done+			 * when the periodic transfer was accepted to ensure+			 * that a (micro)frame's worth of data can be+			 * programmed into a channel.)+			 */+			uint32_t max_periodic_len =+			    hc->multi_count * hc->max_packet;+			if (hc->xfer_len > max_periodic_len) {+				hc->xfer_len = max_periodic_len;+			} else {+			}+		} else if (hc->xfer_len > max_hc_xfer_size) {+			/* Make sure that xfer_len is a multiple of max packet size. */+			hc->xfer_len = max_hc_xfer_size - hc->max_packet + 1;+		}++		if (hc->xfer_len > 0) {+			num_packets =+			    (hc->xfer_len + hc->max_packet -+			     1) / hc->max_packet;+			if (num_packets > max_hc_pkt_count) {+				num_packets = max_hc_pkt_count;+				hc->xfer_len = num_packets * hc->max_packet;+			}+		} else {+			/* Need 1 packet for transfer length of 0. */+			num_packets = 1;+		}++		if (hc->ep_is_in) {+			/* Always program an integral # of max packets for IN transfers. */+			hc->xfer_len = num_packets * hc->max_packet;+		}++		if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||+		    hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {+			/*+			 * Make sure that the multi_count field matches the+			 * actual transfer length.+			 */+			hc->multi_count = num_packets;+		}++		if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)+			set_pid_isoc(hc);++		hctsiz.b.xfersize = hc->xfer_len;+	}++	hc->start_pkt_count = num_packets;+	hctsiz.b.pktcnt = num_packets;+	hctsiz.b.pid = hc->data_pid_start;+	DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);++	DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);+	DWC_DEBUGPL(DBG_HCDV, "	 Xfer Size: %d\n", hctsiz.b.xfersize);+	DWC_DEBUGPL(DBG_HCDV, "	 Num Pkts: %d\n", hctsiz.b.pktcnt);+	DWC_DEBUGPL(DBG_HCDV, "	 Start PID: %d\n", hctsiz.b.pid);++	if (core_if->dma_enable) {+		dwc_dma_t dma_addr;+		if (hc->align_buff) {+			dma_addr = hc->align_buff;+		} else {+			dma_addr = ((unsigned long)hc->xfer_buff & 0xffffffff);+		}+		DWC_WRITE_REG32(&hc_regs->hcdma, dma_addr);+	}++	/* Start the split */+	if (hc->do_split) {+		hcsplt_data_t hcsplt;+		hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);+		hcsplt.b.spltena = 1;+		DWC_WRITE_REG32(&hc_regs->hcsplt, hcsplt.d32);+	}++	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+	hcchar.b.multicnt = hc->multi_count;+	hc_set_even_odd_frame(core_if, hc, &hcchar);+#ifdef DEBUG+	core_if->start_hcchar_val[hc->hc_num] = hcchar.d32;+	if (hcchar.b.chdis) {+		DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",+			 __func__, hc->hc_num, hcchar.d32);+	}+#endif++	/* Set host channel enable after all other setup is complete. */+	hcchar.b.chen = 1;+	hcchar.b.chdis = 0;+	DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);++	hc->xfer_started = 1;+	hc->requests++;++	if (!core_if->dma_enable && !hc->ep_is_in && hc->xfer_len > 0) {+		/* Load OUT packet into the appropriate Tx FIFO. */+		dwc_otg_hc_write_packet(core_if, hc);+	}+#ifdef DEBUG+	if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) {+                DWC_DEBUGPL(DBG_HCDV, "transfer %d from core_if %p\n",+                            hc->hc_num, core_if);//GRAYG+		core_if->hc_xfer_info[hc->hc_num].core_if = core_if;+		core_if->hc_xfer_info[hc->hc_num].hc = hc;++		/* Start a timer for this transfer. */+		DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000);+	}+#endif+}++/**+ * This function does the setup for a data transfer for a host channel+ * and starts the transfer in Descriptor DMA mode.+ *+ * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set.+ * Sets PID and NTD values. For periodic transfers+ * initializes SCHED_INFO field with micro-frame bitmap.+ *+ * Initializes HCDMA register with descriptor list address and CTD value+ * then starts the transfer via enabling the channel.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param hc Information needed to initialize the host channel.+ */+void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)+{+	dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];+	hcchar_data_t hcchar;+	hctsiz_data_t hctsiz;+	hcdma_data_t hcdma;++	hctsiz.d32 = 0;++	if (hc->do_ping)+		hctsiz.b_ddma.dopng = 1;++	if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)+		set_pid_isoc(hc);++	/* Packet Count and Xfer Size are not used in Descriptor DMA mode */+	hctsiz.b_ddma.pid = hc->data_pid_start;+	hctsiz.b_ddma.ntd = hc->ntd - 1;	/* 0 - 1 descriptor, 1 - 2 descriptors, etc. */+	hctsiz.b_ddma.schinfo = hc->schinfo;	/* Non-zero only for high-speed interrupt endpoints */++	DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);+	DWC_DEBUGPL(DBG_HCDV, "	 Start PID: %d\n", hctsiz.b.pid);+	DWC_DEBUGPL(DBG_HCDV, "	 NTD: %d\n", hctsiz.b_ddma.ntd);++	DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);++	hcdma.d32 = 0;+	hcdma.b.dma_addr = ((uint32_t) hc->desc_list_addr) >> 11;++	/* Always start from first descriptor. */+	hcdma.b.ctd = 0;+	DWC_WRITE_REG32(&hc_regs->hcdma, hcdma.d32);++	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+	hcchar.b.multicnt = hc->multi_count;++#ifdef DEBUG+	core_if->start_hcchar_val[hc->hc_num] = hcchar.d32;+	if (hcchar.b.chdis) {+		DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",+			 __func__, hc->hc_num, hcchar.d32);+	}+#endif++	/* Set host channel enable after all other setup is complete. */+	hcchar.b.chen = 1;+	hcchar.b.chdis = 0;++	DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);++	hc->xfer_started = 1;+	hc->requests++;++#ifdef DEBUG+	if ((hc->ep_type != DWC_OTG_EP_TYPE_INTR)+	    && (hc->ep_type != DWC_OTG_EP_TYPE_ISOC)) {+                DWC_DEBUGPL(DBG_HCDV, "DMA transfer %d from core_if %p\n",+                            hc->hc_num, core_if);//GRAYG+		core_if->hc_xfer_info[hc->hc_num].core_if = core_if;+		core_if->hc_xfer_info[hc->hc_num].hc = hc;+		/* Start a timer for this transfer. */+		DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000);+	}+#endif++}++/**+ * This function continues a data transfer that was started by previous call+ * to <code>dwc_otg_hc_start_transfer</code>. The caller must ensure there is+ * sufficient space in the request queue and Tx Data FIFO. This function+ * should only be called in Slave mode. In DMA mode, the controller acts+ * autonomously to complete transfers programmed to a host channel.+ *+ * For an OUT transfer, a new data packet is loaded into the appropriate FIFO+ * if there is any data remaining to be queued. For an IN transfer, another+ * data packet is always requested. For the SETUP phase of a control transfer,+ * this function does nothing.+ *+ * @return 1 if a new request is queued, 0 if no more requests are required+ * for this transfer.+ */+int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)+{+	DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);++	if (hc->do_split) {+		/* SPLITs always queue just once per channel */+		return 0;+	} else if (hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {+		/* SETUPs are queued only once since they can't be NAKed. */+		return 0;+	} else if (hc->ep_is_in) {+		/*+		 * Always queue another request for other IN transfers. If+		 * back-to-back INs are issued and NAKs are received for both,+		 * the driver may still be processing the first NAK when the+		 * second NAK is received. When the interrupt handler clears+		 * the NAK interrupt for the first NAK, the second NAK will+		 * not be seen. So we can't depend on the NAK interrupt+		 * handler to requeue a NAKed request. Instead, IN requests+		 * are issued each time this function is called. When the+		 * transfer completes, the extra requests for the channel will+		 * be flushed.+		 */+		hcchar_data_t hcchar;+		dwc_otg_hc_regs_t *hc_regs =+		    core_if->host_if->hc_regs[hc->hc_num];++		hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+		hc_set_even_odd_frame(core_if, hc, &hcchar);+		hcchar.b.chen = 1;+		hcchar.b.chdis = 0;+		DWC_DEBUGPL(DBG_HCDV, "	 IN xfer: hcchar = 0x%08x\n",+			    hcchar.d32);+		DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);+		hc->requests++;+		return 1;+	} else {+		/* OUT transfers. */+		if (hc->xfer_count < hc->xfer_len) {+			if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||+			    hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {+				hcchar_data_t hcchar;+				dwc_otg_hc_regs_t *hc_regs;+				hc_regs = core_if->host_if->hc_regs[hc->hc_num];+				hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+				hc_set_even_odd_frame(core_if, hc, &hcchar);+			}++			/* Load OUT packet into the appropriate Tx FIFO. */+			dwc_otg_hc_write_packet(core_if, hc);+			hc->requests++;+			return 1;+		} else {+			return 0;+		}+	}+}++/**+ * Starts a PING transfer. This function should only be called in Slave mode.+ * The Do Ping bit is set in the HCTSIZ register, then the channel is enabled.+ */+void dwc_otg_hc_do_ping(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)+{+	hcchar_data_t hcchar;+	hctsiz_data_t hctsiz;+	dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];++	DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);++	hctsiz.d32 = 0;+	hctsiz.b.dopng = 1;+	hctsiz.b.pktcnt = 1;+	DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);++	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+	hcchar.b.chen = 1;+	hcchar.b.chdis = 0;+	DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);+}++/*+ * This function writes a packet into the Tx FIFO associated with the Host+ * Channel. For a channel associated with a non-periodic EP, the non-periodic+ * Tx FIFO is written. For a channel associated with a periodic EP, the+ * periodic Tx FIFO is written. This function should only be called in Slave+ * mode.+ *+ * Upon return the xfer_buff and xfer_count fields in _hc are incremented by+ * then number of bytes written to the Tx FIFO.+ */+void dwc_otg_hc_write_packet(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)+{+	uint32_t i;+	uint32_t remaining_count;+	uint32_t byte_count;+	uint32_t dword_count;++	uint32_t *data_buff = (uint32_t *) (hc->xfer_buff);+	uint32_t *data_fifo = core_if->data_fifo[hc->hc_num];++	remaining_count = hc->xfer_len - hc->xfer_count;+	if (remaining_count > hc->max_packet) {+		byte_count = hc->max_packet;+	} else {+		byte_count = remaining_count;+	}++	dword_count = (byte_count + 3) / 4;++	if ((((unsigned long)data_buff) & 0x3) == 0) {+		/* xfer_buff is DWORD aligned. */+		for (i = 0; i < dword_count; i++, data_buff++) {+			DWC_WRITE_REG32(data_fifo, *data_buff);+		}+	} else {+		/* xfer_buff is not DWORD aligned. */+		for (i = 0; i < dword_count; i++, data_buff++) {+			uint32_t data;+			data =+			    (data_buff[0] | data_buff[1] << 8 | data_buff[2] <<+			     16 | data_buff[3] << 24);+			DWC_WRITE_REG32(data_fifo, data);+		}+	}++	hc->xfer_count += byte_count;+	hc->xfer_buff += byte_count;+}++/**+ * Gets the current USB frame number. This is the frame number from the last+ * SOF packet.+ */+uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * core_if)+{+	dsts_data_t dsts;+	dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);++	/* read current frame/microframe number from DSTS register */+	return dsts.b.soffn;+}++/**+ * Calculates and gets the frame Interval value of HFIR register according PHY+ * type and speed.The application can modify a value of HFIR register only after+ * the Port Enable bit of the Host Port Control and Status register+ * (HPRT.PrtEnaPort) has been set.+*/++uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if)+{+	gusbcfg_data_t usbcfg;+	hwcfg2_data_t hwcfg2;+	hprt0_data_t hprt0;+	int clock = 60;		// default value+	usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);+	hwcfg2.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);+	hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);+	if (!usbcfg.b.physel && usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif)+		clock = 60;+	if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 3)+		clock = 48;+	if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&+	    !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif)+		clock = 30;+	if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&+	    !usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif)+		clock = 60;+	if (usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&+	    !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif)+		clock = 48;+	if (usbcfg.b.physel && !usbcfg.b.phyif && hwcfg2.b.fs_phy_type == 2)+		clock = 48;+	if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 1)+		clock = 48;+	if (hprt0.b.prtspd == 0)+		/* High speed case */+		return 125 * clock;+	else+		/* FS/LS case */+		return 1000 * clock;+}++/**+ * This function reads a setup packet from the Rx FIFO into the destination+ * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl)+ * Interrupt routine when a SETUP packet has been received in Slave mode.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param dest Destination buffer for packet data.+ */+void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest)+{+	device_grxsts_data_t status;+	/* Get the 8 bytes of a setup transaction data */++	/* Pop 2 DWORDS off the receive data FIFO into memory */+	dest[0] = DWC_READ_REG32(core_if->data_fifo[0]);+	dest[1] = DWC_READ_REG32(core_if->data_fifo[0]);+	if (core_if->snpsid >= OTG_CORE_REV_3_00a) {+		status.d32 =+		    DWC_READ_REG32(&core_if->core_global_regs->grxstsp);+		DWC_DEBUGPL(DBG_ANY,+			    "EP:%d BCnt:%d " "pktsts:%x Frame:%d(0x%0x)\n",+			    status.b.epnum, status.b.bcnt, status.b.pktsts,+			    status.b.fn, status.b.fn);+	}+}++/**+ * This function enables EP0 OUT to receive SETUP packets and configures EP0+ * IN for transmitting packets. It is normally called when the+ * "Enumeration Done" interrupt occurs.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP0 data.+ */+void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)+{+	dwc_otg_dev_if_t *dev_if = core_if->dev_if;+	dsts_data_t dsts;+	depctl_data_t diepctl;+	depctl_data_t doepctl;+	dctl_data_t dctl = {.d32 = 0 };++	ep->stp_rollover = 0;+	/* Read the Device Status and Endpoint 0 Control registers */+	dsts.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dsts);+	diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);+	doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl);++	/* Set the MPS of the IN EP based on the enumeration speed */+	switch (dsts.b.enumspd) {+	case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:+	case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:+	case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:+		diepctl.b.mps = DWC_DEP0CTL_MPS_64;+		break;+	case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:+		diepctl.b.mps = DWC_DEP0CTL_MPS_8;+		break;+	}++	DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);++	/* Enable OUT EP for receive */+	if (core_if->snpsid <= OTG_CORE_REV_2_94a) {+	doepctl.b.epena = 1;+	DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);+	}+#ifdef VERBOSE+	DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",+		    DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));+	DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",+		    DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl));+#endif+	dctl.b.cgnpinnak = 1;++	DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);+	DWC_DEBUGPL(DBG_PCDV, "dctl=%0x\n",+		    DWC_READ_REG32(&dev_if->dev_global_regs->dctl));++}++/**+ * This function activates an EP.  The Device EP control register for+ * the EP is configured as defined in the ep structure. Note: This+ * function is not used for EP0.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP to activate.+ */+void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)+{+	dwc_otg_dev_if_t *dev_if = core_if->dev_if;+	depctl_data_t depctl;+	volatile uint32_t *addr;+	daint_data_t daintmsk = {.d32 = 0 };+	dcfg_data_t dcfg;+	uint8_t i;++	DWC_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, ep->num,+		    (ep->is_in ? "IN" : "OUT"));++#ifdef DWC_UTE_PER_IO+	ep->xiso_frame_num = 0xFFFFFFFF;+	ep->xiso_active_xfers = 0;+	ep->xiso_queued_xfers = 0;+#endif+	/* Read DEPCTLn register */+	if (ep->is_in == 1) {+		addr = &dev_if->in_ep_regs[ep->num]->diepctl;+		daintmsk.ep.in = 1 << ep->num;+	} else {+		addr = &dev_if->out_ep_regs[ep->num]->doepctl;+		daintmsk.ep.out = 1 << ep->num;+	}++	/* If the EP is already active don't change the EP Control+	 * register. */+	depctl.d32 = DWC_READ_REG32(addr);+	if (!depctl.b.usbactep) {+		depctl.b.mps = ep->maxpacket;+		depctl.b.eptype = ep->type;+		depctl.b.txfnum = ep->tx_fifo_num;++		if (ep->type == DWC_OTG_EP_TYPE_ISOC) {+			depctl.b.setd0pid = 1;	// ???+		} else {+			depctl.b.setd0pid = 1;+		}+		depctl.b.usbactep = 1;++		/* Update nextep_seq array and EPMSCNT in DCFG*/+		if (!(depctl.b.eptype & 1) && (ep->is_in == 1)) {	// NP IN EP+			for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {+				if (core_if->nextep_seq[i] == core_if->first_in_nextep_seq)+				break;+			}+			core_if->nextep_seq[i] = ep->num;+			core_if->nextep_seq[ep->num] = core_if->first_in_nextep_seq;+			depctl.b.nextep = core_if->nextep_seq[ep->num];+			dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);+			dcfg.b.epmscnt++;+			DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);++			DWC_DEBUGPL(DBG_PCDV,+				    "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",+				__func__, core_if->first_in_nextep_seq);+			for (i=0; i <= core_if->dev_if->num_in_eps; i++) {+				DWC_DEBUGPL(DBG_PCDV, "%2d\n",+					    core_if->nextep_seq[i]);+			}++		}+++		DWC_WRITE_REG32(addr, depctl.d32);+		DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", DWC_READ_REG32(addr));+	}++	/* Enable the Interrupt for this EP */+	if (core_if->multiproc_int_enable) {+		if (ep->is_in == 1) {+			diepmsk_data_t diepmsk = {.d32 = 0 };+			diepmsk.b.xfercompl = 1;+			diepmsk.b.timeout = 1;+			diepmsk.b.epdisabled = 1;+			diepmsk.b.ahberr = 1;+			diepmsk.b.intknepmis = 1;+			if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)+				diepmsk.b.intknepmis = 0;+			diepmsk.b.txfifoundrn = 1;	//?????+			if (ep->type == DWC_OTG_EP_TYPE_ISOC) {+				diepmsk.b.nak = 1;+			}++++/*+			if (core_if->dma_desc_enable) {+				diepmsk.b.bna = 1;+			}+*/+/*+			if (core_if->dma_enable) {+				doepmsk.b.nak = 1;+			}+*/+			DWC_WRITE_REG32(&dev_if->dev_global_regs->+					diepeachintmsk[ep->num], diepmsk.d32);++		} else {+			doepmsk_data_t doepmsk = {.d32 = 0 };+			doepmsk.b.xfercompl = 1;+			doepmsk.b.ahberr = 1;+			doepmsk.b.epdisabled = 1;+			if (ep->type == DWC_OTG_EP_TYPE_ISOC)+				doepmsk.b.outtknepdis = 1;++/*++			if (core_if->dma_desc_enable) {+				doepmsk.b.bna = 1;+			}+*/+/*+			doepmsk.b.babble = 1;+			doepmsk.b.nyet = 1;+			doepmsk.b.nak = 1;+*/+			DWC_WRITE_REG32(&dev_if->dev_global_regs->+					doepeachintmsk[ep->num], doepmsk.d32);+		}+		DWC_MODIFY_REG32(&dev_if->dev_global_regs->deachintmsk,+				 0, daintmsk.d32);+	} else {+		if (ep->type == DWC_OTG_EP_TYPE_ISOC) {+			if (ep->is_in) {+				diepmsk_data_t diepmsk = {.d32 = 0 };+				diepmsk.b.nak = 1;+				DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32);+			} else {+				doepmsk_data_t doepmsk = {.d32 = 0 };+				doepmsk.b.outtknepdis = 1;+				DWC_MODIFY_REG32(&dev_if->dev_global_regs->doepmsk, 0, doepmsk.d32);+			}+		}+		DWC_MODIFY_REG32(&dev_if->dev_global_regs->daintmsk,+				 0, daintmsk.d32);+	}++	DWC_DEBUGPL(DBG_PCDV, "DAINTMSK=%0x\n",+		    DWC_READ_REG32(&dev_if->dev_global_regs->daintmsk));++	ep->stall_clear_flag = 0;++	return;+}++/**+ * This function deactivates an EP. This is done by clearing the USB Active+ * EP bit in the Device EP control register. Note: This function is not used+ * for EP0. EP0 cannot be deactivated.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP to deactivate.+ */+void dwc_otg_ep_deactivate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)+{+	depctl_data_t depctl = {.d32 = 0 };+	volatile uint32_t *addr;+	daint_data_t daintmsk = {.d32 = 0 };+	dcfg_data_t dcfg;+	uint8_t i = 0;++#ifdef DWC_UTE_PER_IO+	ep->xiso_frame_num = 0xFFFFFFFF;+	ep->xiso_active_xfers = 0;+	ep->xiso_queued_xfers = 0;+#endif++	/* Read DEPCTLn register */+	if (ep->is_in == 1) {+		addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;+		daintmsk.ep.in = 1 << ep->num;+	} else {+		addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;+		daintmsk.ep.out = 1 << ep->num;+	}++	depctl.d32 = DWC_READ_REG32(addr);++	depctl.b.usbactep = 0;++	/* Update nextep_seq array and EPMSCNT in DCFG*/+	if (!(depctl.b.eptype & 1) && ep->is_in == 1) {	// NP EP IN+		for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {+			if (core_if->nextep_seq[i] == ep->num)+			break;+		}+		core_if->nextep_seq[i] = core_if->nextep_seq[ep->num];+		if (core_if->first_in_nextep_seq == ep->num)+			core_if->first_in_nextep_seq = i;+		core_if->nextep_seq[ep->num] = 0xff;+		depctl.b.nextep = 0;+		dcfg.d32 =+		    DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);+		dcfg.b.epmscnt--;+		DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,+				dcfg.d32);++		DWC_DEBUGPL(DBG_PCDV,+			    "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",+				__func__, core_if->first_in_nextep_seq);+			for (i=0; i <= core_if->dev_if->num_in_eps; i++) {+				DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]);+			}+	}++	if (ep->is_in == 1)+		depctl.b.txfnum = 0;++	if (core_if->dma_desc_enable)+		depctl.b.epdis = 1;++	DWC_WRITE_REG32(addr, depctl.d32);+	depctl.d32 = DWC_READ_REG32(addr);+	if (core_if->dma_enable && ep->type == DWC_OTG_EP_TYPE_ISOC+	    && depctl.b.epena) {+		depctl_data_t depctl = {.d32 = 0};+		if (ep->is_in) {+			diepint_data_t diepint = {.d32 = 0};++			depctl.b.snak = 1;+			DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->+					diepctl, depctl.d32);+			do {+				dwc_udelay(10);+				diepint.d32 =+				    DWC_READ_REG32(&core_if->+						   dev_if->in_ep_regs[ep->num]->+						   diepint);+			} while (!diepint.b.inepnakeff);+			diepint.b.inepnakeff = 1;+			DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->+					diepint, diepint.d32);+			depctl.d32 = 0;+			depctl.b.epdis = 1;+			DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->+					diepctl, depctl.d32);+			do {+				dwc_udelay(10);+				diepint.d32 =+				    DWC_READ_REG32(&core_if->+						   dev_if->in_ep_regs[ep->num]->+						   diepint);+			} while (!diepint.b.epdisabled);+			diepint.b.epdisabled = 1;+			DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->+					diepint, diepint.d32);+		} else {+			dctl_data_t dctl = {.d32 = 0};+			gintmsk_data_t gintsts = {.d32 = 0};+			doepint_data_t doepint = {.d32 = 0};+			dctl.b.sgoutnak = 1;+			DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->+					 dctl, 0, dctl.d32);+			do {+				dwc_udelay(10);+				gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);+			} while (!gintsts.b.goutnakeff);+			gintsts.d32 = 0;+			gintsts.b.goutnakeff = 1;+			DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);++			depctl.d32 = 0;+			depctl.b.epdis = 1;+			depctl.b.snak = 1;+			DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepctl, depctl.d32);+			do+			{+				dwc_udelay(10);+				doepint.d32 = DWC_READ_REG32(&core_if->dev_if->+											out_ep_regs[ep->num]->doepint);+			} while (!doepint.b.epdisabled);++			doepint.b.epdisabled = 1;+			DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepint, doepint.d32);++			dctl.d32 = 0;+			dctl.b.cgoutnak = 1;+			DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);+		}+	}++	/* Disable the Interrupt for this EP */+	if (core_if->multiproc_int_enable) {+		DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,+				 daintmsk.d32, 0);++		if (ep->is_in == 1) {+			DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->+					diepeachintmsk[ep->num], 0);+		} else {+			DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->+					doepeachintmsk[ep->num], 0);+		}+	} else {+		DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->daintmsk,+				 daintmsk.d32, 0);+	}++}++/**+ * This function initializes dma descriptor chain.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP to start the transfer on.+ */+static void init_dma_desc_chain(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)+{+	dwc_otg_dev_dma_desc_t *dma_desc;+	uint32_t offset;+	uint32_t xfer_est;+	int i;+	unsigned maxxfer_local, total_len;++	if (!ep->is_in && ep->type == DWC_OTG_EP_TYPE_INTR &&+					(ep->maxpacket%4)) {+		maxxfer_local = ep->maxpacket;+		total_len = ep->xfer_len;+	} else {+		maxxfer_local = ep->maxxfer;+		total_len = ep->total_len;+	}++	ep->desc_cnt = (total_len / maxxfer_local) ++            ((total_len % maxxfer_local) ? 1 : 0);++	if (!ep->desc_cnt)+		ep->desc_cnt = 1;++	if (ep->desc_cnt > MAX_DMA_DESC_CNT)+		ep->desc_cnt = MAX_DMA_DESC_CNT;++	dma_desc = ep->desc_addr;+	if (maxxfer_local == ep->maxpacket) {+		if ((total_len % maxxfer_local) &&+				(total_len/maxxfer_local < MAX_DMA_DESC_CNT)) {+			xfer_est = (ep->desc_cnt - 1) * maxxfer_local ++					(total_len % maxxfer_local);+		} else+			xfer_est = ep->desc_cnt * maxxfer_local;+	} else+		xfer_est = total_len;+	offset = 0;+	for (i = 0; i < ep->desc_cnt; ++i) {+		/** DMA Descriptor Setup */+		if (xfer_est > maxxfer_local) {+			dma_desc->status.b.bs = BS_HOST_BUSY;+			dma_desc->status.b.l = 0;+			dma_desc->status.b.ioc = 0;+			dma_desc->status.b.sp = 0;+			dma_desc->status.b.bytes = maxxfer_local;+			dma_desc->buf = ep->dma_addr + offset;+			dma_desc->status.b.sts = 0;+			dma_desc->status.b.bs = BS_HOST_READY;++			xfer_est -= maxxfer_local;+			offset += maxxfer_local;+		} else {+			dma_desc->status.b.bs = BS_HOST_BUSY;+			dma_desc->status.b.l = 1;+			dma_desc->status.b.ioc = 1;+			if (ep->is_in) {+				dma_desc->status.b.sp =+				    (xfer_est %+				     ep->maxpacket) ? 1 : ((ep->+							    sent_zlp) ? 1 : 0);+				dma_desc->status.b.bytes = xfer_est;+			} else {+				if (maxxfer_local == ep->maxpacket)+					dma_desc->status.b.bytes = xfer_est;+				else+					dma_desc->status.b.bytes =+						xfer_est + ((4 - (xfer_est & 0x3)) & 0x3);+			}++			dma_desc->buf = ep->dma_addr + offset;+			dma_desc->status.b.sts = 0;+			dma_desc->status.b.bs = BS_HOST_READY;+		}+		dma_desc++;+	}+}+/**+ * This function is called when to write ISOC data into appropriate dedicated+ * periodic FIFO.+ */+static int32_t write_isoc_tx_fifo(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)+{+	dwc_otg_dev_if_t *dev_if = core_if->dev_if;+	dwc_otg_dev_in_ep_regs_t *ep_regs;+	dtxfsts_data_t txstatus = {.d32 = 0 };+	uint32_t len = 0;+	int epnum = dwc_ep->num;+	int dwords;++	DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);++	ep_regs = core_if->dev_if->in_ep_regs[epnum];++	len = dwc_ep->xfer_len - dwc_ep->xfer_count;++	if (len > dwc_ep->maxpacket) {+		len = dwc_ep->maxpacket;+	}++	dwords = (len + 3) / 4;++	/* While there is space in the queue and space in the FIFO and+	 * More data to tranfer, Write packets to the Tx FIFO */+	txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);+	DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);++	while (txstatus.b.txfspcavail > dwords &&+	       dwc_ep->xfer_count < dwc_ep->xfer_len && dwc_ep->xfer_len != 0) {+		/* Write the FIFO */+		dwc_otg_ep_write_packet(core_if, dwc_ep, 0);++		len = dwc_ep->xfer_len - dwc_ep->xfer_count;+		if (len > dwc_ep->maxpacket) {+			len = dwc_ep->maxpacket;+		}++		dwords = (len + 3) / 4;+		txstatus.d32 =+		    DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);+		DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,+			    txstatus.d32);+	}++	DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,+		    DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts));++	return 1;+}+/**+ * This function does the setup for a data transfer for an EP and+ * starts the transfer. For an IN transfer, the packets will be+ * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,+ * the packets are unloaded from the Rx FIFO in the ISR.  the ISR.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP to start the transfer on.+ */++void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)+{+	depctl_data_t depctl;+	deptsiz_data_t deptsiz;+	gintmsk_data_t intr_mask = {.d32 = 0 };++	DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__);+	DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "+		    "xfer_buff=%p start_xfer_buff=%p, total_len = %d\n",+		    ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len,+		    ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff,+		    ep->total_len);+	/* IN endpoint */+	if (ep->is_in == 1) {+		dwc_otg_dev_in_ep_regs_t *in_regs =+		    core_if->dev_if->in_ep_regs[ep->num];++		gnptxsts_data_t gtxstatus;++		gtxstatus.d32 =+		    DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);++		if (core_if->en_multiple_tx_fifo == 0+		    && gtxstatus.b.nptxqspcavail == 0 && !core_if->dma_enable) {+#ifdef DEBUG+			DWC_PRINTF("TX Queue Full (0x%0x)\n", gtxstatus.d32);+#endif+			return;+		}++		depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));+		deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));++		if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT)+			ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?+				ep->maxxfer : (ep->total_len - ep->xfer_len);+		else+			ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ?+				 MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);+++		/* Zero Length Packet? */+		if ((ep->xfer_len - ep->xfer_count) == 0) {+			deptsiz.b.xfersize = 0;+			deptsiz.b.pktcnt = 1;+		} else {+			/* Program the transfer size and packet count+			 *      as follows: xfersize = N * maxpacket ++			 *      short_packet pktcnt = N + (short_packet+			 *      exist ? 1 : 0)+			 */+			deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;+			deptsiz.b.pktcnt =+			    (ep->xfer_len - ep->xfer_count - 1 ++			     ep->maxpacket) / ep->maxpacket;+			if (deptsiz.b.pktcnt > MAX_PKT_CNT) {+				deptsiz.b.pktcnt = MAX_PKT_CNT;+				deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;+			}+			if (ep->type == DWC_OTG_EP_TYPE_ISOC)+				deptsiz.b.mc = deptsiz.b.pktcnt;+		}++		/* Write the DMA register */+		if (core_if->dma_enable) {+			if (core_if->dma_desc_enable == 0) {+				if (ep->type != DWC_OTG_EP_TYPE_ISOC)+					deptsiz.b.mc = 1;+				DWC_WRITE_REG32(&in_regs->dieptsiz,+						deptsiz.d32);+				DWC_WRITE_REG32(&(in_regs->diepdma),+						(uint32_t) ep->dma_addr);+			} else {+#ifdef DWC_UTE_CFI+				/* The descriptor chain should be already initialized by now */+				if (ep->buff_mode != BM_STANDARD) {+					DWC_WRITE_REG32(&in_regs->diepdma,+							ep->descs_dma_addr);+				} else {+#endif+					init_dma_desc_chain(core_if, ep);+				/** DIEPDMAn Register write */+					DWC_WRITE_REG32(&in_regs->diepdma,+							ep->dma_desc_addr);+#ifdef DWC_UTE_CFI+				}+#endif+			}+		} else {+			DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);+			if (ep->type != DWC_OTG_EP_TYPE_ISOC) {+				/**+				 * Enable the Non-Periodic Tx FIFO empty interrupt,+				 * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode,+				 * the data will be written into the fifo by the ISR.+				 */+				if (core_if->en_multiple_tx_fifo == 0) {+					intr_mask.b.nptxfempty = 1;+					DWC_MODIFY_REG32+					    (&core_if->core_global_regs->gintmsk,+					     intr_mask.d32, intr_mask.d32);+				} else {+					/* Enable the Tx FIFO Empty Interrupt for this EP */+					if (ep->xfer_len > 0) {+						uint32_t fifoemptymsk = 0;+						fifoemptymsk = 1 << ep->num;+						DWC_MODIFY_REG32+						    (&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,+						     0, fifoemptymsk);++					}+				}+			}  else {+					 write_isoc_tx_fifo(core_if, ep);+			}+		}+		if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)+			depctl.b.nextep = core_if->nextep_seq[ep->num];++		if (ep->type == DWC_OTG_EP_TYPE_ISOC) {+			dsts_data_t dsts = {.d32 = 0};+			if (ep->bInterval == 1) {+				dsts.d32 =+				    DWC_READ_REG32(&core_if->dev_if->+						   dev_global_regs->dsts);+				ep->frame_num = dsts.b.soffn + ep->bInterval;+				if (ep->frame_num > 0x3FFF) {+					ep->frm_overrun = 1;+					ep->frame_num &= 0x3FFF;+				} else+					ep->frm_overrun = 0;+				if (ep->frame_num & 0x1) {+					depctl.b.setd1pid = 1;+				} else {+					depctl.b.setd0pid = 1;+				}+			}+		}+		/* EP enable, IN data in FIFO */+		depctl.b.cnak = 1;+		depctl.b.epena = 1;+		DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);++	} else {+		/* OUT endpoint */+		dwc_otg_dev_out_ep_regs_t *out_regs =+		    core_if->dev_if->out_ep_regs[ep->num];++		depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));+		deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));++		if (!core_if->dma_desc_enable) {+			if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT)+				ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?+				ep->maxxfer : (ep->total_len - ep->xfer_len);+                else+					ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len+					- ep->xfer_len)) ? MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);+		}++		/* Program the transfer size and packet count as follows:+		 *+		 *      pktcnt = N+		 *      xfersize = N * maxpacket+		 */+		if ((ep->xfer_len - ep->xfer_count) == 0) {+			/* Zero Length Packet */+			deptsiz.b.xfersize = ep->maxpacket;+			deptsiz.b.pktcnt = 1;+		} else {+			deptsiz.b.pktcnt =+			    (ep->xfer_len - ep->xfer_count ++			     (ep->maxpacket - 1)) / ep->maxpacket;+			if (deptsiz.b.pktcnt > MAX_PKT_CNT) {+				deptsiz.b.pktcnt = MAX_PKT_CNT;+			}+			if (!core_if->dma_desc_enable) {+				ep->xfer_len =+					deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count;+			}+			deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;+		}++		DWC_DEBUGPL(DBG_PCDV, "ep%d xfersize=%d pktcnt=%d\n",+			    ep->num, deptsiz.b.xfersize, deptsiz.b.pktcnt);++		if (core_if->dma_enable) {+			if (!core_if->dma_desc_enable) {+				DWC_WRITE_REG32(&out_regs->doeptsiz,+						deptsiz.d32);++				DWC_WRITE_REG32(&(out_regs->doepdma),+						(uint32_t) ep->dma_addr);+			} else {+#ifdef DWC_UTE_CFI+				/* The descriptor chain should be already initialized by now */+				if (ep->buff_mode != BM_STANDARD) {+					DWC_WRITE_REG32(&out_regs->doepdma,+							ep->descs_dma_addr);+				} else {+#endif+					/** This is used for interrupt out transfers*/+					if (!ep->xfer_len)+						ep->xfer_len = ep->total_len;+					init_dma_desc_chain(core_if, ep);++					if (core_if->core_params->dev_out_nak) {+						if (ep->type == DWC_OTG_EP_TYPE_BULK) {+							deptsiz.b.pktcnt = (ep->total_len ++								(ep->maxpacket - 1)) / ep->maxpacket;+							deptsiz.b.xfersize = ep->total_len;+							/* Remember initial value of doeptsiz */+							core_if->start_doeptsiz_val[ep->num] = deptsiz.d32;+							DWC_WRITE_REG32(&out_regs->doeptsiz,+								deptsiz.d32);+						}+					}+				/** DOEPDMAn Register write */+					DWC_WRITE_REG32(&out_regs->doepdma,+							ep->dma_desc_addr);+#ifdef DWC_UTE_CFI+				}+#endif+			}+		} else {+			DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);+		}++		if (ep->type == DWC_OTG_EP_TYPE_ISOC) {+			dsts_data_t dsts = {.d32 = 0};+			if (ep->bInterval == 1) {+				dsts.d32 =+				    DWC_READ_REG32(&core_if->dev_if->+						   dev_global_regs->dsts);+				ep->frame_num = dsts.b.soffn + ep->bInterval;+				if (ep->frame_num > 0x3FFF) {+					ep->frm_overrun = 1;+					ep->frame_num &= 0x3FFF;+				} else+					ep->frm_overrun = 0;++				if (ep->frame_num & 0x1) {+					depctl.b.setd1pid = 1;+				} else {+					depctl.b.setd0pid = 1;+				}+			}+		}++		/* EP enable */+		depctl.b.cnak = 1;+		depctl.b.epena = 1;++		DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);++		DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n",+			    DWC_READ_REG32(&out_regs->doepctl),+			    DWC_READ_REG32(&out_regs->doeptsiz));+		DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n",+			    DWC_READ_REG32(&core_if->dev_if->dev_global_regs->+					   daintmsk),+			    DWC_READ_REG32(&core_if->core_global_regs->+					   gintmsk));++		/* Timer is scheduling only for out bulk transfers for+		 * "Device DDMA OUT NAK Enhancement" feature to inform user+		 * about received data payload in case of timeout+		 */+		if (core_if->core_params->dev_out_nak) {+			if (ep->type == DWC_OTG_EP_TYPE_BULK) {+				core_if->ep_xfer_info[ep->num].core_if = core_if;+				core_if->ep_xfer_info[ep->num].ep = ep;+				core_if->ep_xfer_info[ep->num].state = 1;++				/* Start a timer for this transfer. */+				DWC_TIMER_SCHEDULE(core_if->ep_xfer_timer[ep->num], 10000);+			}+		}+	}+}++/**+ * This function setup a zero length transfer in Buffer DMA and+ * Slave modes for usb requests with zero field set+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP to start the transfer on.+ *+ */+void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)+{++	depctl_data_t depctl;+	deptsiz_data_t deptsiz;+	gintmsk_data_t intr_mask = {.d32 = 0 };++	DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__);+	DWC_PRINTF("zero length transfer is called\n");++	/* IN endpoint */+	if (ep->is_in == 1) {+		dwc_otg_dev_in_ep_regs_t *in_regs =+		    core_if->dev_if->in_ep_regs[ep->num];++		depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));+		deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));++		deptsiz.b.xfersize = 0;+		deptsiz.b.pktcnt = 1;++		/* Write the DMA register */+		if (core_if->dma_enable) {+			if (core_if->dma_desc_enable == 0) {+				deptsiz.b.mc = 1;+				DWC_WRITE_REG32(&in_regs->dieptsiz,+						deptsiz.d32);+				DWC_WRITE_REG32(&(in_regs->diepdma),+						(uint32_t) ep->dma_addr);+			}+		} else {+			DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);+			/**+			 * Enable the Non-Periodic Tx FIFO empty interrupt,+			 * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode,+			 * the data will be written into the fifo by the ISR.+			 */+			if (core_if->en_multiple_tx_fifo == 0) {+				intr_mask.b.nptxfempty = 1;+				DWC_MODIFY_REG32(&core_if->+						 core_global_regs->gintmsk,+						 intr_mask.d32, intr_mask.d32);+			} else {+				/* Enable the Tx FIFO Empty Interrupt for this EP */+				if (ep->xfer_len > 0) {+					uint32_t fifoemptymsk = 0;+					fifoemptymsk = 1 << ep->num;+					DWC_MODIFY_REG32(&core_if->+							 dev_if->dev_global_regs->dtknqr4_fifoemptymsk,+							 0, fifoemptymsk);+				}+			}+		}++		if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)+			depctl.b.nextep = core_if->nextep_seq[ep->num];+		/* EP enable, IN data in FIFO */+		depctl.b.cnak = 1;+		depctl.b.epena = 1;+		DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);++	} else {+		/* OUT endpoint */+		dwc_otg_dev_out_ep_regs_t *out_regs =+		    core_if->dev_if->out_ep_regs[ep->num];++		depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));+		deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));++		/* Zero Length Packet */+		deptsiz.b.xfersize = ep->maxpacket;+		deptsiz.b.pktcnt = 1;++		if (core_if->dma_enable) {+			if (!core_if->dma_desc_enable) {+				DWC_WRITE_REG32(&out_regs->doeptsiz,+						deptsiz.d32);++				DWC_WRITE_REG32(&(out_regs->doepdma),+						(uint32_t) ep->dma_addr);+			}+		} else {+			DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);+		}++		/* EP enable */+		depctl.b.cnak = 1;+		depctl.b.epena = 1;++		DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);++	}+}++/**+ * This function does the setup for a data transfer for EP0 and starts+ * the transfer.  For an IN transfer, the packets will be loaded into+ * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are+ * unloaded from the Rx FIFO in the ISR.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP0 data.+ */+void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)+{+	depctl_data_t depctl;+	deptsiz0_data_t deptsiz;+	gintmsk_data_t intr_mask = {.d32 = 0 };+	dwc_otg_dev_dma_desc_t *dma_desc;++	DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "+		    "xfer_buff=%p start_xfer_buff=%p \n",+		    ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len,+		    ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff);++	ep->total_len = ep->xfer_len;++	/* IN endpoint */+	if (ep->is_in == 1) {+		dwc_otg_dev_in_ep_regs_t *in_regs =+		    core_if->dev_if->in_ep_regs[0];++		gnptxsts_data_t gtxstatus;++		if (core_if->snpsid >= OTG_CORE_REV_3_00a) {+			depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);+			if (depctl.b.epena)+				return;+		}++		gtxstatus.d32 =+		    DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);++		/* If dedicated FIFO every time flush fifo before enable ep*/+		if (core_if->en_multiple_tx_fifo && core_if->snpsid >= OTG_CORE_REV_3_00a)+			dwc_otg_flush_tx_fifo(core_if, ep->tx_fifo_num);++		if (core_if->en_multiple_tx_fifo == 0+		    && gtxstatus.b.nptxqspcavail == 0+		    && !core_if->dma_enable) {+#ifdef DEBUG+			deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);+			DWC_DEBUGPL(DBG_PCD, "DIEPCTL0=%0x\n",+				    DWC_READ_REG32(&in_regs->diepctl));+			DWC_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n",+				    deptsiz.d32,+				    deptsiz.b.xfersize, deptsiz.b.pktcnt);+			DWC_PRINTF("TX Queue or FIFO Full (0x%0x)\n",+				   gtxstatus.d32);+#endif+			return;+		}++		depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);+		deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);++		/* Zero Length Packet? */+		if (ep->xfer_len == 0) {+			deptsiz.b.xfersize = 0;+			deptsiz.b.pktcnt = 1;+		} else {+			/* Program the transfer size and packet count+			 *      as follows: xfersize = N * maxpacket ++			 *      short_packet pktcnt = N + (short_packet+			 *      exist ? 1 : 0)+			 */+			if (ep->xfer_len > ep->maxpacket) {+				ep->xfer_len = ep->maxpacket;+				deptsiz.b.xfersize = ep->maxpacket;+			} else {+				deptsiz.b.xfersize = ep->xfer_len;+			}+			deptsiz.b.pktcnt = 1;++		}+		DWC_DEBUGPL(DBG_PCDV,+			    "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",+			    ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,+			    deptsiz.d32);++		/* Write the DMA register */+		if (core_if->dma_enable) {+			if (core_if->dma_desc_enable == 0) {+				DWC_WRITE_REG32(&in_regs->dieptsiz,+						deptsiz.d32);++				DWC_WRITE_REG32(&(in_regs->diepdma),+						(uint32_t) ep->dma_addr);+			} else {+				dma_desc = core_if->dev_if->in_desc_addr;++				/** DMA Descriptor Setup */+				dma_desc->status.b.bs = BS_HOST_BUSY;+				dma_desc->status.b.l = 1;+				dma_desc->status.b.ioc = 1;+				dma_desc->status.b.sp =+				    (ep->xfer_len == ep->maxpacket) ? 0 : 1;+				dma_desc->status.b.bytes = ep->xfer_len;+				dma_desc->buf = ep->dma_addr;+				dma_desc->status.b.sts = 0;+				dma_desc->status.b.bs = BS_HOST_READY;++				/** DIEPDMA0 Register write */+				DWC_WRITE_REG32(&in_regs->diepdma,+						core_if->+						dev_if->dma_in_desc_addr);+			}+		} else {+			DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);+		}++		if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)+			depctl.b.nextep = core_if->nextep_seq[ep->num];+		/* EP enable, IN data in FIFO */+		depctl.b.cnak = 1;+		depctl.b.epena = 1;+		DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);++		/**+		 * Enable the Non-Periodic Tx FIFO empty interrupt, the+		 * data will be written into the fifo by the ISR.+		 */+		if (!core_if->dma_enable) {+			if (core_if->en_multiple_tx_fifo == 0) {+				intr_mask.b.nptxfempty = 1;+				DWC_MODIFY_REG32(&core_if->+						 core_global_regs->gintmsk,+						 intr_mask.d32, intr_mask.d32);+			} else {+				/* Enable the Tx FIFO Empty Interrupt for this EP */+				if (ep->xfer_len > 0) {+					uint32_t fifoemptymsk = 0;+					fifoemptymsk |= 1 << ep->num;+					DWC_MODIFY_REG32(&core_if->+							 dev_if->dev_global_regs->dtknqr4_fifoemptymsk,+							 0, fifoemptymsk);+				}+			}+		}+	} else {+		/* OUT endpoint */+		dwc_otg_dev_out_ep_regs_t *out_regs =+		    core_if->dev_if->out_ep_regs[0];++		depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);+		deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);++		/* Program the transfer size and packet count as follows:+		 *      xfersize = N * (maxpacket + 4 - (maxpacket % 4))+		 *      pktcnt = N                                                                                      */+		/* Zero Length Packet */+		deptsiz.b.xfersize = ep->maxpacket;+		deptsiz.b.pktcnt = 1;+		if (core_if->snpsid >= OTG_CORE_REV_3_00a)+			deptsiz.b.supcnt = 3;++		DWC_DEBUGPL(DBG_PCDV, "len=%d  xfersize=%d pktcnt=%d\n",+			    ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt);++		if (core_if->dma_enable) {+			if (!core_if->dma_desc_enable) {+				DWC_WRITE_REG32(&out_regs->doeptsiz,+						deptsiz.d32);++				DWC_WRITE_REG32(&(out_regs->doepdma),+						(uint32_t) ep->dma_addr);+			} else {+				dma_desc = core_if->dev_if->out_desc_addr;++				/** DMA Descriptor Setup */+				dma_desc->status.b.bs = BS_HOST_BUSY;+				if (core_if->snpsid >= OTG_CORE_REV_3_00a) {+					dma_desc->status.b.mtrf = 0;+					dma_desc->status.b.sr = 0;+				}+				dma_desc->status.b.l = 1;+				dma_desc->status.b.ioc = 1;+				dma_desc->status.b.bytes = ep->maxpacket;+				dma_desc->buf = ep->dma_addr;+				dma_desc->status.b.sts = 0;+				dma_desc->status.b.bs = BS_HOST_READY;++				/** DOEPDMA0 Register write */+				DWC_WRITE_REG32(&out_regs->doepdma,+						core_if->dev_if->+						dma_out_desc_addr);+			}+		} else {+			DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);+		}++		/* EP enable */+		depctl.b.cnak = 1;+		depctl.b.epena = 1;+		DWC_WRITE_REG32(&(out_regs->doepctl), depctl.d32);+	}+}++/**+ * This function continues control IN transfers started by+ * dwc_otg_ep0_start_transfer, when the transfer does not fit in a+ * single packet.  NOTE: The DIEPCTL0/DOEPCTL0 registers only have one+ * bit for the packet count.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP0 data.+ */+void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)+{+	depctl_data_t depctl;+	deptsiz0_data_t deptsiz;+	gintmsk_data_t intr_mask = {.d32 = 0 };+	dwc_otg_dev_dma_desc_t *dma_desc;++	if (ep->is_in == 1) {+		dwc_otg_dev_in_ep_regs_t *in_regs =+		    core_if->dev_if->in_ep_regs[0];+		gnptxsts_data_t tx_status = {.d32 = 0 };++		tx_status.d32 =+		    DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);+		/** @todo Should there be check for room in the Tx+		 * Status Queue.  If not remove the code above this comment. */++		depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);+		deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);++		/* Program the transfer size and packet count+		 *      as follows: xfersize = N * maxpacket ++		 *      short_packet pktcnt = N + (short_packet+		 *      exist ? 1 : 0)+		 */++		if (core_if->dma_desc_enable == 0) {+			deptsiz.b.xfersize =+			    (ep->total_len - ep->xfer_count) >+			    ep->maxpacket ? ep->maxpacket : (ep->total_len -+							     ep->xfer_count);+			deptsiz.b.pktcnt = 1;+			if (core_if->dma_enable == 0) {+				ep->xfer_len += deptsiz.b.xfersize;+			} else {+				ep->xfer_len = deptsiz.b.xfersize;+			}+			DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);+		} else {+			ep->xfer_len =+			    (ep->total_len - ep->xfer_count) >+			    ep->maxpacket ? ep->maxpacket : (ep->total_len -+							     ep->xfer_count);++			dma_desc = core_if->dev_if->in_desc_addr;++			/** DMA Descriptor Setup */+			dma_desc->status.b.bs = BS_HOST_BUSY;+			dma_desc->status.b.l = 1;+			dma_desc->status.b.ioc = 1;+			dma_desc->status.b.sp =+			    (ep->xfer_len == ep->maxpacket) ? 0 : 1;+			dma_desc->status.b.bytes = ep->xfer_len;+			dma_desc->buf = ep->dma_addr;+			dma_desc->status.b.sts = 0;+			dma_desc->status.b.bs = BS_HOST_READY;++			/** DIEPDMA0 Register write */+			DWC_WRITE_REG32(&in_regs->diepdma,+					core_if->dev_if->dma_in_desc_addr);+		}++		DWC_DEBUGPL(DBG_PCDV,+			    "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",+			    ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,+			    deptsiz.d32);++		/* Write the DMA register */+		if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) {+			if (core_if->dma_desc_enable == 0)+				DWC_WRITE_REG32(&(in_regs->diepdma),+						(uint32_t) ep->dma_addr);+		}+		if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)+			depctl.b.nextep = core_if->nextep_seq[ep->num];+		/* EP enable, IN data in FIFO */+		depctl.b.cnak = 1;+		depctl.b.epena = 1;+		DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);++		/**+		 * Enable the Non-Periodic Tx FIFO empty interrupt, the+		 * data will be written into the fifo by the ISR.+		 */+		if (!core_if->dma_enable) {+			if (core_if->en_multiple_tx_fifo == 0) {+				/* First clear it from GINTSTS */+				intr_mask.b.nptxfempty = 1;+				DWC_MODIFY_REG32(&core_if->+						 core_global_regs->gintmsk,+						 intr_mask.d32, intr_mask.d32);++			} else {+				/* Enable the Tx FIFO Empty Interrupt for this EP */+				if (ep->xfer_len > 0) {+					uint32_t fifoemptymsk = 0;+					fifoemptymsk |= 1 << ep->num;+					DWC_MODIFY_REG32(&core_if->+							 dev_if->dev_global_regs->dtknqr4_fifoemptymsk,+							 0, fifoemptymsk);+				}+			}+		}+	} else {+		dwc_otg_dev_out_ep_regs_t *out_regs =+		    core_if->dev_if->out_ep_regs[0];++		depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);+		deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);++		/* Program the transfer size and packet count+		 *      as follows: xfersize = N * maxpacket ++		 *      short_packet pktcnt = N + (short_packet+		 *      exist ? 1 : 0)+		 */+		deptsiz.b.xfersize = ep->maxpacket;+		deptsiz.b.pktcnt = 1;++		if (core_if->dma_desc_enable == 0) {+			DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);+		} else {+			dma_desc = core_if->dev_if->out_desc_addr;++			/** DMA Descriptor Setup */+			dma_desc->status.b.bs = BS_HOST_BUSY;+			dma_desc->status.b.l = 1;+			dma_desc->status.b.ioc = 1;+			dma_desc->status.b.bytes = ep->maxpacket;+			dma_desc->buf = ep->dma_addr;+			dma_desc->status.b.sts = 0;+			dma_desc->status.b.bs = BS_HOST_READY;++			/** DOEPDMA0 Register write */+			DWC_WRITE_REG32(&out_regs->doepdma,+					core_if->dev_if->dma_out_desc_addr);+		}++		DWC_DEBUGPL(DBG_PCDV,+			    "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",+			    ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,+			    deptsiz.d32);++		/* Write the DMA register */+		if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) {+			if (core_if->dma_desc_enable == 0)+				DWC_WRITE_REG32(&(out_regs->doepdma),+						(uint32_t) ep->dma_addr);++		}++		/* EP enable, IN data in FIFO */+		depctl.b.cnak = 1;+		depctl.b.epena = 1;+		DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);++	}+}++#ifdef DEBUG+void dump_msg(const u8 * buf, unsigned int length)+{+	unsigned int start, num, i;+	char line[52], *p;++	if (length >= 512)+		return;+	start = 0;+	while (length > 0) {+		num = length < 16u ? length : 16u;+		p = line;+		for (i = 0; i < num; ++i) {+			if (i == 8)+				*p++ = ' ';+			DWC_SPRINTF(p, " %02x", buf[i]);+			p += 3;+		}+		*p = 0;+		DWC_PRINTF("%6x: %s\n", start, line);+		buf += num;+		start += num;+		length -= num;+	}+}+#else+static inline void dump_msg(const u8 * buf, unsigned int length)+{+}+#endif++/**+ * This function writes a packet into the Tx FIFO associated with the+ * EP. For non-periodic EPs the non-periodic Tx FIFO is written.  For+ * periodic EPs the periodic Tx FIFO associated with the EP is written+ * with all packets for the next micro-frame.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP to write packet for.+ * @param dma Indicates if DMA is being used.+ */+void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep,+			     int dma)+{+	/**+	 * The buffer is padded to DWORD on a per packet basis in+	 * slave/dma mode if the MPS is not DWORD aligned. The last+	 * packet, if short, is also padded to a multiple of DWORD.+	 *+	 * ep->xfer_buff always starts DWORD aligned in memory and is a+	 * multiple of DWORD in length+	 *+	 * ep->xfer_len can be any number of bytes+	 *+	 * ep->xfer_count is a multiple of ep->maxpacket until the last+	 *	packet+	 *+	 * FIFO access is DWORD */++	uint32_t i;+	uint32_t byte_count;+	uint32_t dword_count;+	uint32_t *fifo;+	uint32_t *data_buff = (uint32_t *) ep->xfer_buff;++	DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p)\n", __func__, core_if,+		    ep);+	if (ep->xfer_count >= ep->xfer_len) {+		DWC_WARN("%s() No data for EP%d!!!\n", __func__, ep->num);+		return;+	}++	/* Find the byte length of the packet either short packet or MPS */+	if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket) {+		byte_count = ep->xfer_len - ep->xfer_count;+	} else {+		byte_count = ep->maxpacket;+	}++	/* Find the DWORD length, padded by extra bytes as neccessary if MPS+	 * is not a multiple of DWORD */+	dword_count = (byte_count + 3) / 4;++#ifdef VERBOSE+	dump_msg(ep->xfer_buff, byte_count);+#endif++	/**@todo NGS Where are the Periodic Tx FIFO addresses+	 * intialized?	What should this be? */++	fifo = core_if->data_fifo[ep->num];++	DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "fifo=%p buff=%p *p=%08x bc=%d\n",+		    fifo, data_buff, *data_buff, byte_count);++	if (!dma) {+		for (i = 0; i < dword_count; i++, data_buff++) {+			DWC_WRITE_REG32(fifo, *data_buff);+		}+	}++	ep->xfer_count += byte_count;+	ep->xfer_buff += byte_count;+	ep->dma_addr += byte_count;+}++/**+ * Set the EP STALL.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP to set the stall on.+ */+void dwc_otg_ep_set_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)+{+	depctl_data_t depctl;+	volatile uint32_t *depctl_addr;++	DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num,+		    (ep->is_in ? "IN" : "OUT"));++	if (ep->is_in == 1) {+		depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);+		depctl.d32 = DWC_READ_REG32(depctl_addr);++		/* set the disable and stall bits */+		if (depctl.b.epena) {+			depctl.b.epdis = 1;+		}+		depctl.b.stall = 1;+		DWC_WRITE_REG32(depctl_addr, depctl.d32);+	} else {+		depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);+		depctl.d32 = DWC_READ_REG32(depctl_addr);++		/* set the stall bit */+		depctl.b.stall = 1;+		DWC_WRITE_REG32(depctl_addr, depctl.d32);+	}++	DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr));++	return;+}++/**+ * Clear the EP STALL.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP to clear stall from.+ */+void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)+{+	depctl_data_t depctl;+	volatile uint32_t *depctl_addr;++	DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num,+		    (ep->is_in ? "IN" : "OUT"));++	if (ep->is_in == 1) {+		depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);+	} else {+		depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);+	}++	depctl.d32 = DWC_READ_REG32(depctl_addr);++	/* clear the stall bits */+	depctl.b.stall = 0;++	/*+	 * USB Spec 9.4.5: For endpoints using data toggle, regardless+	 * of whether an endpoint has the Halt feature set, a+	 * ClearFeature(ENDPOINT_HALT) request always results in the+	 * data toggle being reinitialized to DATA0.+	 */+	if (ep->type == DWC_OTG_EP_TYPE_INTR ||+	    ep->type == DWC_OTG_EP_TYPE_BULK) {+		depctl.b.setd0pid = 1;	/* DATA0 */+	}++	DWC_WRITE_REG32(depctl_addr, depctl.d32);+	DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr));+	return;+}++/**+ * This function reads a packet from the Rx FIFO into the destination+ * buffer. To read SETUP data use dwc_otg_read_setup_packet.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param dest	  Destination buffer for the packet.+ * @param bytes  Number of bytes to copy to the destination.+ */+void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,+			 uint8_t * dest, uint16_t bytes)+{+	int i;+	int word_count = (bytes + 3) / 4;++	volatile uint32_t *fifo = core_if->data_fifo[0];+	uint32_t *data_buff = (uint32_t *) dest;++	/**+	 * @todo Account for the case where _dest is not dword aligned. This+	 * requires reading data from the FIFO into a uint32_t temp buffer,+	 * then moving it into the data buffer.+	 */++	DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p,%d)\n", __func__,+		    core_if, dest, bytes);++	for (i = 0; i < word_count; i++, data_buff++) {+		*data_buff = DWC_READ_REG32(fifo);+	}++	return;+}++/**+ * This functions reads the device registers and prints them+ *+ * @param core_if Programming view of DWC_otg controller.+ */+void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * core_if)+{+	int i;+	volatile uint32_t *addr;++	DWC_PRINTF("Device Global Registers\n");+	addr = &core_if->dev_if->dev_global_regs->dcfg;+	DWC_PRINTF("DCFG		 @0x%08lX : 0x%08X\n",+		   (unsigned long)addr, DWC_READ_REG32(addr));+	addr = &core_if->dev_if->dev_global_regs->dctl;+	DWC_PRINTF("DCTL		 @0x%08lX : 0x%08X\n",+		   (unsigned long)addr, DWC_READ_REG32(addr));+	addr = &core_if->dev_if->dev_global_regs->dsts;+	DWC_PRINTF("DSTS		 @0x%08lX : 0x%08X\n",+		   (unsigned long)addr, DWC_READ_REG32(addr));+	addr = &core_if->dev_if->dev_global_regs->diepmsk;+	DWC_PRINTF("DIEPMSK	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->dev_if->dev_global_regs->doepmsk;+	DWC_PRINTF("DOEPMSK	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->dev_if->dev_global_regs->daint;+	DWC_PRINTF("DAINT	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->dev_if->dev_global_regs->daintmsk;+	DWC_PRINTF("DAINTMSK	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->dev_if->dev_global_regs->dtknqr1;+	DWC_PRINTF("DTKNQR1	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	if (core_if->hwcfg2.b.dev_token_q_depth > 6) {+		addr = &core_if->dev_if->dev_global_regs->dtknqr2;+		DWC_PRINTF("DTKNQR2	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+	}++	addr = &core_if->dev_if->dev_global_regs->dvbusdis;+	DWC_PRINTF("DVBUSID	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));++	addr = &core_if->dev_if->dev_global_regs->dvbuspulse;+	DWC_PRINTF("DVBUSPULSE	@0x%08lX : 0x%08X\n",+		   (unsigned long)addr, DWC_READ_REG32(addr));++	addr = &core_if->dev_if->dev_global_regs->dtknqr3_dthrctl;+	DWC_PRINTF("DTKNQR3_DTHRCTL	 @0x%08lX : 0x%08X\n",+		   (unsigned long)addr, DWC_READ_REG32(addr));++	if (core_if->hwcfg2.b.dev_token_q_depth > 22) {+		addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk;+		DWC_PRINTF("DTKNQR4	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+	}++	addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk;+	DWC_PRINTF("FIFOEMPMSK	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));++	if (core_if->hwcfg2.b.multi_proc_int) {++		addr = &core_if->dev_if->dev_global_regs->deachint;+		DWC_PRINTF("DEACHINT	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+		addr = &core_if->dev_if->dev_global_regs->deachintmsk;+		DWC_PRINTF("DEACHINTMSK	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));++		for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {+			addr =+			    &core_if->dev_if->+			    dev_global_regs->diepeachintmsk[i];+			DWC_PRINTF("DIEPEACHINTMSK[%d]	 @0x%08lX : 0x%08X\n",+				   i, (unsigned long)addr,+				   DWC_READ_REG32(addr));+		}++		for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {+			addr =+			    &core_if->dev_if->+			    dev_global_regs->doepeachintmsk[i];+			DWC_PRINTF("DOEPEACHINTMSK[%d]	 @0x%08lX : 0x%08X\n",+				   i, (unsigned long)addr,+				   DWC_READ_REG32(addr));+		}+	}++	for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {+		DWC_PRINTF("Device IN EP %d Registers\n", i);+		addr = &core_if->dev_if->in_ep_regs[i]->diepctl;+		DWC_PRINTF("DIEPCTL	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+		addr = &core_if->dev_if->in_ep_regs[i]->diepint;+		DWC_PRINTF("DIEPINT	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+		addr = &core_if->dev_if->in_ep_regs[i]->dieptsiz;+		DWC_PRINTF("DIETSIZ	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+		addr = &core_if->dev_if->in_ep_regs[i]->diepdma;+		DWC_PRINTF("DIEPDMA	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+		addr = &core_if->dev_if->in_ep_regs[i]->dtxfsts;+		DWC_PRINTF("DTXFSTS	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+		addr = &core_if->dev_if->in_ep_regs[i]->diepdmab;+		DWC_PRINTF("DIEPDMAB	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, 0 /*DWC_READ_REG32(addr) */ );+	}++	for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {+		DWC_PRINTF("Device OUT EP %d Registers\n", i);+		addr = &core_if->dev_if->out_ep_regs[i]->doepctl;+		DWC_PRINTF("DOEPCTL	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+		addr = &core_if->dev_if->out_ep_regs[i]->doepint;+		DWC_PRINTF("DOEPINT	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+		addr = &core_if->dev_if->out_ep_regs[i]->doeptsiz;+		DWC_PRINTF("DOETSIZ	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+		addr = &core_if->dev_if->out_ep_regs[i]->doepdma;+		DWC_PRINTF("DOEPDMA	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+		if (core_if->dma_enable) {	/* Don't access this register in SLAVE mode */+			addr = &core_if->dev_if->out_ep_regs[i]->doepdmab;+			DWC_PRINTF("DOEPDMAB	 @0x%08lX : 0x%08X\n",+				   (unsigned long)addr, DWC_READ_REG32(addr));+		}++	}+}++/**+ * This functions reads the SPRAM and prints its content+ *+ * @param core_if Programming view of DWC_otg controller.+ */+void dwc_otg_dump_spram(dwc_otg_core_if_t * core_if)+{+	volatile uint8_t *addr, *start_addr, *end_addr;++	DWC_PRINTF("SPRAM Data:\n");+	start_addr = (void *)core_if->core_global_regs;+	DWC_PRINTF("Base Address: 0x%8lX\n", (unsigned long)start_addr);+	start_addr += 0x00028000;+	end_addr = (void *)core_if->core_global_regs;+	end_addr += 0x000280e0;++	for (addr = start_addr; addr < end_addr; addr += 16) {+		DWC_PRINTF+		    ("0x%8lX:\t%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n",+		     (unsigned long)addr, addr[0], addr[1], addr[2], addr[3],+		     addr[4], addr[5], addr[6], addr[7], addr[8], addr[9],+		     addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]+		    );+	}++	return;+}++/**+ * This function reads the host registers and prints them+ *+ * @param core_if Programming view of DWC_otg controller.+ */+void dwc_otg_dump_host_registers(dwc_otg_core_if_t * core_if)+{+	int i;+	volatile uint32_t *addr;++	DWC_PRINTF("Host Global Registers\n");+	addr = &core_if->host_if->host_global_regs->hcfg;+	DWC_PRINTF("HCFG		 @0x%08lX : 0x%08X\n",+		   (unsigned long)addr, DWC_READ_REG32(addr));+	addr = &core_if->host_if->host_global_regs->hfir;+	DWC_PRINTF("HFIR		 @0x%08lX : 0x%08X\n",+		   (unsigned long)addr, DWC_READ_REG32(addr));+	addr = &core_if->host_if->host_global_regs->hfnum;+	DWC_PRINTF("HFNUM	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->host_if->host_global_regs->hptxsts;+	DWC_PRINTF("HPTXSTS	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->host_if->host_global_regs->haint;+	DWC_PRINTF("HAINT	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->host_if->host_global_regs->haintmsk;+	DWC_PRINTF("HAINTMSK	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	if (core_if->dma_desc_enable) {+		addr = &core_if->host_if->host_global_regs->hflbaddr;+		DWC_PRINTF("HFLBADDR	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+	}++	addr = core_if->host_if->hprt0;+	DWC_PRINTF("HPRT0	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));++	for (i = 0; i < core_if->core_params->host_channels; i++) {+		DWC_PRINTF("Host Channel %d Specific Registers\n", i);+		addr = &core_if->host_if->hc_regs[i]->hcchar;+		DWC_PRINTF("HCCHAR	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+		addr = &core_if->host_if->hc_regs[i]->hcsplt;+		DWC_PRINTF("HCSPLT	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+		addr = &core_if->host_if->hc_regs[i]->hcint;+		DWC_PRINTF("HCINT	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+		addr = &core_if->host_if->hc_regs[i]->hcintmsk;+		DWC_PRINTF("HCINTMSK	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+		addr = &core_if->host_if->hc_regs[i]->hctsiz;+		DWC_PRINTF("HCTSIZ	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+		addr = &core_if->host_if->hc_regs[i]->hcdma;+		DWC_PRINTF("HCDMA	 @0x%08lX : 0x%08X\n",+			   (unsigned long)addr, DWC_READ_REG32(addr));+		if (core_if->dma_desc_enable) {+			addr = &core_if->host_if->hc_regs[i]->hcdmab;+			DWC_PRINTF("HCDMAB	 @0x%08lX : 0x%08X\n",+				   (unsigned long)addr, DWC_READ_REG32(addr));+		}++	}+	return;+}++/**+ * This function reads the core global registers and prints them+ *+ * @param core_if Programming view of DWC_otg controller.+ */+void dwc_otg_dump_global_registers(dwc_otg_core_if_t * core_if)+{+	int i, ep_num;+	volatile uint32_t *addr;+	char *txfsiz;++	DWC_PRINTF("Core Global Registers\n");+	addr = &core_if->core_global_regs->gotgctl;+	DWC_PRINTF("GOTGCTL	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->gotgint;+	DWC_PRINTF("GOTGINT	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->gahbcfg;+	DWC_PRINTF("GAHBCFG	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->gusbcfg;+	DWC_PRINTF("GUSBCFG	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->grstctl;+	DWC_PRINTF("GRSTCTL	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->gintsts;+	DWC_PRINTF("GINTSTS	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->gintmsk;+	DWC_PRINTF("GINTMSK	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->grxstsr;+	DWC_PRINTF("GRXSTSR	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->grxfsiz;+	DWC_PRINTF("GRXFSIZ	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->gnptxfsiz;+	DWC_PRINTF("GNPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->gnptxsts;+	DWC_PRINTF("GNPTXSTS	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->gi2cctl;+	DWC_PRINTF("GI2CCTL	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->gpvndctl;+	DWC_PRINTF("GPVNDCTL	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->ggpio;+	DWC_PRINTF("GGPIO	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->guid;+	DWC_PRINTF("GUID		 @0x%08lX : 0x%08X\n",+		   (unsigned long)addr, DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->gsnpsid;+	DWC_PRINTF("GSNPSID	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->ghwcfg1;+	DWC_PRINTF("GHWCFG1	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->ghwcfg2;+	DWC_PRINTF("GHWCFG2	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->ghwcfg3;+	DWC_PRINTF("GHWCFG3	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->ghwcfg4;+	DWC_PRINTF("GHWCFG4	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->glpmcfg;+	DWC_PRINTF("GLPMCFG	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->gpwrdn;+	DWC_PRINTF("GPWRDN	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->gdfifocfg;+	DWC_PRINTF("GDFIFOCFG	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+	addr = &core_if->core_global_regs->adpctl;+	DWC_PRINTF("ADPCTL	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   dwc_otg_adp_read_reg(core_if));+	addr = &core_if->core_global_regs->hptxfsiz;+	DWC_PRINTF("HPTXFSIZ	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));++	if (core_if->en_multiple_tx_fifo == 0) {+		ep_num = core_if->hwcfg4.b.num_dev_perio_in_ep;+		txfsiz = "DPTXFSIZ";+	} else {+		ep_num = core_if->hwcfg4.b.num_in_eps;+		txfsiz = "DIENPTXF";+	}+	for (i = 0; i < ep_num; i++) {+		addr = &core_if->core_global_regs->dtxfsiz[i];+		DWC_PRINTF("%s[%d] @0x%08lX : 0x%08X\n", txfsiz, i + 1,+			   (unsigned long)addr, DWC_READ_REG32(addr));+	}+	addr = core_if->pcgcctl;+	DWC_PRINTF("PCGCCTL	 @0x%08lX : 0x%08X\n", (unsigned long)addr,+		   DWC_READ_REG32(addr));+}++/**+ * Flush a Tx FIFO.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param num Tx FIFO to flush.+ */+void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * core_if, const int num)+{+	dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;+	volatile grstctl_t greset = {.d32 = 0 };+	int count = 0;++	DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "Flush Tx FIFO %d\n", num);++	greset.b.txfflsh = 1;+	greset.b.txfnum = num;+	DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);++	do {+		greset.d32 = DWC_READ_REG32(&global_regs->grstctl);+		if (++count > 10000) {+			DWC_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n",+				 __func__, greset.d32,+				 DWC_READ_REG32(&global_regs->gnptxsts));+			break;+		}+		dwc_udelay(1);+	} while (greset.b.txfflsh == 1);++	/* Wait for 3 PHY Clocks */+	dwc_udelay(1);+}++/**+ * Flush Rx FIFO.+ *+ * @param core_if Programming view of DWC_otg controller.+ */+void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * core_if)+{+	dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;+	volatile grstctl_t greset = {.d32 = 0 };+	int count = 0;++	DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "%s\n", __func__);+	/*+	 *+	 */+	greset.b.rxfflsh = 1;+	DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);++	do {+		greset.d32 = DWC_READ_REG32(&global_regs->grstctl);+		if (++count > 10000) {+			DWC_WARN("%s() HANG! GRSTCTL=%0x\n", __func__,+				 greset.d32);+			break;+		}+		dwc_udelay(1);+	} while (greset.b.rxfflsh == 1);++	/* Wait for 3 PHY Clocks */+	dwc_udelay(1);+}++/**+ * Do core a soft reset of the core.  Be careful with this because it+ * resets all the internal state machines of the core.+ */+void dwc_otg_core_reset(dwc_otg_core_if_t * core_if)+{+	dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;+	volatile grstctl_t greset = {.d32 = 0 };+	int count = 0;++	DWC_DEBUGPL(DBG_CILV, "%s\n", __func__);+	/* Wait for AHB master IDLE state. */+	do {+		dwc_udelay(10);+		greset.d32 = DWC_READ_REG32(&global_regs->grstctl);+		if (++count > 100000) {+			DWC_WARN("%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__,+				 greset.d32);+			return;+		}+	}+	while (greset.b.ahbidle == 0);++	/* Core Soft Reset */+	count = 0;+	greset.b.csftrst = 1;+	DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);+	do {+		greset.d32 = DWC_READ_REG32(&global_regs->grstctl);+		if (++count > 10000) {+			DWC_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n",+				 __func__, greset.d32);+			break;+		}+		dwc_udelay(1);+	}+	while (greset.b.csftrst == 1);++	/* Wait for 3 PHY Clocks */+	dwc_mdelay(100);+}++uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if)+{+	return (dwc_otg_mode(_core_if) != DWC_HOST_MODE);+}++uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if)+{+	return (dwc_otg_mode(_core_if) == DWC_HOST_MODE);+}++/**+ * Register HCD callbacks. The callbacks are used to start and stop+ * the HCD for interrupt processing.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param cb the HCD callback structure.+ * @param p pointer to be passed to callback function (usb_hcd*).+ */+void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * core_if,+					dwc_otg_cil_callbacks_t * cb, void *p)+{+	core_if->hcd_cb = cb;+	cb->p = p;+}++/**+ * Register PCD callbacks. The callbacks are used to start and stop+ * the PCD for interrupt processing.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param cb the PCD callback structure.+ * @param p pointer to be passed to callback function (pcd*).+ */+void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * core_if,+					dwc_otg_cil_callbacks_t * cb, void *p)+{+	core_if->pcd_cb = cb;+	cb->p = p;+}++#ifdef DWC_EN_ISOC++/**+ * This function writes isoc data per 1 (micro)frame into tx fifo+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP to start the transfer on.+ *+ */+void write_isoc_frame_data(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)+{+	dwc_otg_dev_in_ep_regs_t *ep_regs;+	dtxfsts_data_t txstatus = {.d32 = 0 };+	uint32_t len = 0;+	uint32_t dwords;++	ep->xfer_len = ep->data_per_frame;+	ep->xfer_count = 0;++	ep_regs = core_if->dev_if->in_ep_regs[ep->num];++	len = ep->xfer_len - ep->xfer_count;++	if (len > ep->maxpacket) {+		len = ep->maxpacket;+	}++	dwords = (len + 3) / 4;++	/* While there is space in the queue and space in the FIFO and+	 * More data to tranfer, Write packets to the Tx FIFO */+	txstatus.d32 =+	    DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dtxfsts);+	DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", ep->num, txstatus.d32);++	while (txstatus.b.txfspcavail > dwords &&+	       ep->xfer_count < ep->xfer_len && ep->xfer_len != 0) {+		/* Write the FIFO */+		dwc_otg_ep_write_packet(core_if, ep, 0);++		len = ep->xfer_len - ep->xfer_count;+		if (len > ep->maxpacket) {+			len = ep->maxpacket;+		}++		dwords = (len + 3) / 4;+		txstatus.d32 =+		    DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->+				   dtxfsts);+		DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", ep->num,+			    txstatus.d32);+	}+}++/**+ * This function initializes a descriptor chain for Isochronous transfer+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP to start the transfer on.+ *+ */+void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if,+				       dwc_ep_t * ep)+{+	deptsiz_data_t deptsiz = {.d32 = 0 };+	depctl_data_t depctl = {.d32 = 0 };+	dsts_data_t dsts = {.d32 = 0 };+	volatile uint32_t *addr;++	if (ep->is_in) {+		addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;+	} else {+		addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;+	}++	ep->xfer_len = ep->data_per_frame;+	ep->xfer_count = 0;+	ep->xfer_buff = ep->cur_pkt_addr;+	ep->dma_addr = ep->cur_pkt_dma_addr;++	if (ep->is_in) {+		/* Program the transfer size and packet count+		 *      as follows: xfersize = N * maxpacket ++		 *      short_packet pktcnt = N + (short_packet+		 *      exist ? 1 : 0)+		 */+		deptsiz.b.xfersize = ep->xfer_len;+		deptsiz.b.pktcnt =+		    (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;+		deptsiz.b.mc = deptsiz.b.pktcnt;+		DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz,+				deptsiz.d32);++		/* Write the DMA register */+		if (core_if->dma_enable) {+			DWC_WRITE_REG32(&+					(core_if->dev_if->in_ep_regs[ep->num]->+					 diepdma), (uint32_t) ep->dma_addr);+		}+	} else {+		deptsiz.b.pktcnt =+		    (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket;+		deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;++		DWC_WRITE_REG32(&core_if->dev_if->+				out_ep_regs[ep->num]->doeptsiz, deptsiz.d32);++		if (core_if->dma_enable) {+			DWC_WRITE_REG32(&+					(core_if->dev_if->+					 out_ep_regs[ep->num]->doepdma),+					(uint32_t) ep->dma_addr);+		}+	}++	/** Enable endpoint, clear nak  */++	depctl.d32 = 0;+	if (ep->bInterval == 1) {+		dsts.d32 =+		    DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);+		ep->next_frame = dsts.b.soffn + ep->bInterval;++		if (ep->next_frame & 0x1) {+			depctl.b.setd1pid = 1;+		} else {+			depctl.b.setd0pid = 1;+		}+	} else {+		ep->next_frame += ep->bInterval;++		if (ep->next_frame & 0x1) {+			depctl.b.setd1pid = 1;+		} else {+			depctl.b.setd0pid = 1;+		}+	}+	depctl.b.epena = 1;+	depctl.b.cnak = 1;++	DWC_MODIFY_REG32(addr, 0, depctl.d32);+	depctl.d32 = DWC_READ_REG32(addr);++	if (ep->is_in && core_if->dma_enable == 0) {+		write_isoc_frame_data(core_if, ep);+	}++}+#endif /* DWC_EN_ISOC */++static void dwc_otg_set_uninitialized(int32_t * p, int size)+{+	int i;+	for (i = 0; i < size; i++) {+		p[i] = -1;+	}+}++static int dwc_otg_param_initialized(int32_t val)+{+	return val != -1;+}++static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if)+{+	int i;+	core_if->core_params = DWC_ALLOC(sizeof(*core_if->core_params));+	if (!core_if->core_params) {+		return -DWC_E_NO_MEMORY;+	}+	dwc_otg_set_uninitialized((int32_t *) core_if->core_params,+				  sizeof(*core_if->core_params) /+				  sizeof(int32_t));+	DWC_PRINTF("Setting default values for core params\n");+	dwc_otg_set_param_otg_cap(core_if, dwc_param_otg_cap_default);+	dwc_otg_set_param_dma_enable(core_if, dwc_param_dma_enable_default);+	dwc_otg_set_param_dma_desc_enable(core_if,+					  dwc_param_dma_desc_enable_default);+	dwc_otg_set_param_opt(core_if, dwc_param_opt_default);+	dwc_otg_set_param_dma_burst_size(core_if,+					 dwc_param_dma_burst_size_default);+	dwc_otg_set_param_host_support_fs_ls_low_power(core_if,+						       dwc_param_host_support_fs_ls_low_power_default);+	dwc_otg_set_param_enable_dynamic_fifo(core_if,+					      dwc_param_enable_dynamic_fifo_default);+	dwc_otg_set_param_data_fifo_size(core_if,+					 dwc_param_data_fifo_size_default);+	dwc_otg_set_param_dev_rx_fifo_size(core_if,+					   dwc_param_dev_rx_fifo_size_default);+	dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,+						  dwc_param_dev_nperio_tx_fifo_size_default);+	dwc_otg_set_param_host_rx_fifo_size(core_if,+					    dwc_param_host_rx_fifo_size_default);+	dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,+						   dwc_param_host_nperio_tx_fifo_size_default);+	dwc_otg_set_param_host_perio_tx_fifo_size(core_if,+						  dwc_param_host_perio_tx_fifo_size_default);+	dwc_otg_set_param_max_transfer_size(core_if,+					    dwc_param_max_transfer_size_default);+	dwc_otg_set_param_max_packet_count(core_if,+					   dwc_param_max_packet_count_default);+	dwc_otg_set_param_host_channels(core_if,+					dwc_param_host_channels_default);+	dwc_otg_set_param_dev_endpoints(core_if,+					dwc_param_dev_endpoints_default);+	dwc_otg_set_param_phy_type(core_if, dwc_param_phy_type_default);+	dwc_otg_set_param_speed(core_if, dwc_param_speed_default);+	dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,+						    dwc_param_host_ls_low_power_phy_clk_default);+	dwc_otg_set_param_phy_ulpi_ddr(core_if, dwc_param_phy_ulpi_ddr_default);+	dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,+					    dwc_param_phy_ulpi_ext_vbus_default);+	dwc_otg_set_param_phy_utmi_width(core_if,+					 dwc_param_phy_utmi_width_default);+	dwc_otg_set_param_ts_dline(core_if, dwc_param_ts_dline_default);+	dwc_otg_set_param_i2c_enable(core_if, dwc_param_i2c_enable_default);+	dwc_otg_set_param_ulpi_fs_ls(core_if, dwc_param_ulpi_fs_ls_default);+	dwc_otg_set_param_en_multiple_tx_fifo(core_if,+					      dwc_param_en_multiple_tx_fifo_default);+	for (i = 0; i < 15; i++) {+		dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,+							 dwc_param_dev_perio_tx_fifo_size_default,+							 i);+	}++	for (i = 0; i < 15; i++) {+		dwc_otg_set_param_dev_tx_fifo_size(core_if,+						   dwc_param_dev_tx_fifo_size_default,+						   i);+	}+	dwc_otg_set_param_thr_ctl(core_if, dwc_param_thr_ctl_default);+	dwc_otg_set_param_mpi_enable(core_if, dwc_param_mpi_enable_default);+	dwc_otg_set_param_pti_enable(core_if, dwc_param_pti_enable_default);+	dwc_otg_set_param_lpm_enable(core_if, dwc_param_lpm_enable_default);+	dwc_otg_set_param_ic_usb_cap(core_if, dwc_param_ic_usb_cap_default);+	dwc_otg_set_param_tx_thr_length(core_if,+					dwc_param_tx_thr_length_default);+	dwc_otg_set_param_rx_thr_length(core_if,+					dwc_param_rx_thr_length_default);+	dwc_otg_set_param_ahb_thr_ratio(core_if,+					dwc_param_ahb_thr_ratio_default);+	dwc_otg_set_param_power_down(core_if, dwc_param_power_down_default);+	dwc_otg_set_param_reload_ctl(core_if, dwc_param_reload_ctl_default);+	dwc_otg_set_param_dev_out_nak(core_if, dwc_param_dev_out_nak_default);+	dwc_otg_set_param_cont_on_bna(core_if, dwc_param_cont_on_bna_default);+	dwc_otg_set_param_ahb_single(core_if, dwc_param_ahb_single_default);+	dwc_otg_set_param_otg_ver(core_if, dwc_param_otg_ver_default);+	dwc_otg_set_param_adp_enable(core_if, dwc_param_adp_enable_default);+	DWC_PRINTF("Finished setting default values for core params\n");++	return 0;+}++uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if)+{+	return core_if->dma_enable;+}++/* Checks if the parameter is outside of its valid range of values */+#define DWC_OTG_PARAM_TEST(_param_, _low_, _high_) \+		(((_param_) < (_low_)) || \+		((_param_) > (_high_)))++/* Parameter access functions */+int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val)+{+	int valid;+	int retval = 0;+	if (DWC_OTG_PARAM_TEST(val, 0, 2)) {+		DWC_WARN("Wrong value for otg_cap parameter\n");+		DWC_WARN("otg_cap parameter must be 0,1 or 2\n");+		retval = -DWC_E_INVALID;+		goto out;+	}++	valid = 1;+	switch (val) {+	case DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE:+		if (core_if->hwcfg2.b.op_mode !=+		    DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)+			valid = 0;+		break;+	case DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE:+		if ((core_if->hwcfg2.b.op_mode !=+		     DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)+		    && (core_if->hwcfg2.b.op_mode !=+			DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)+		    && (core_if->hwcfg2.b.op_mode !=+			DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)+		    && (core_if->hwcfg2.b.op_mode !=+			DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) {+			valid = 0;+		}+		break;+	case DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE:+		/* always valid */+		break;+	}+	if (!valid) {+		if (dwc_otg_param_initialized(core_if->core_params->otg_cap)) {+			DWC_ERROR+			    ("%d invalid for otg_cap paremter. Check HW configuration.\n",+			     val);+		}+		val =+		    (((core_if->hwcfg2.b.op_mode ==+		       DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)+		      || (core_if->hwcfg2.b.op_mode ==+			  DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)+		      || (core_if->hwcfg2.b.op_mode ==+			  DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)+		      || (core_if->hwcfg2.b.op_mode ==+			  DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) ?+		     DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE :+		     DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->otg_cap = val;+out:+	return retval;+}++int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->otg_cap;+}++int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val)+{+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("Wrong value for opt parameter\n");+		return -DWC_E_INVALID;+	}+	core_if->core_params->opt = val;+	return 0;+}++int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->opt;+}++int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("Wrong value for dma enable\n");+		return -DWC_E_INVALID;+	}++	if ((val == 1) && (core_if->hwcfg2.b.architecture == 0)) {+		if (dwc_otg_param_initialized(core_if->core_params->dma_enable)) {+			DWC_ERROR+			    ("%d invalid for dma_enable paremter. Check HW configuration.\n",+			     val);+		}+		val = 0;+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->dma_enable = val;+	if (val == 0) {+		dwc_otg_set_param_dma_desc_enable(core_if, 0);+	}+	return retval;+}++int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->dma_enable;+}++int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("Wrong value for dma_enable\n");+		DWC_WARN("dma_desc_enable must be 0 or 1\n");+		return -DWC_E_INVALID;+	}++	if ((val == 1)+	    && ((dwc_otg_get_param_dma_enable(core_if) == 0)+		|| (core_if->hwcfg4.b.desc_dma == 0))) {+		if (dwc_otg_param_initialized+		    (core_if->core_params->dma_desc_enable)) {+			DWC_ERROR+			    ("%d invalid for dma_desc_enable paremter. Check HW configuration.\n",+			     val);+		}+		val = 0;+		retval = -DWC_E_INVALID;+	}+	core_if->core_params->dma_desc_enable = val;+	return retval;+}++int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->dma_desc_enable;+}++int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t * core_if,+						   int32_t val)+{+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("Wrong value for host_support_fs_low_power\n");+		DWC_WARN("host_support_fs_low_power must be 0 or 1\n");+		return -DWC_E_INVALID;+	}+	core_if->core_params->host_support_fs_ls_low_power = val;+	return 0;+}++int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *+						       core_if)+{+	return core_if->core_params->host_support_fs_ls_low_power;+}++int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if,+					  int32_t val)+{+	int retval = 0;+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("Wrong value for enable_dynamic_fifo\n");+		DWC_WARN("enable_dynamic_fifo must be 0 or 1\n");+		return -DWC_E_INVALID;+	}++	if ((val == 1) && (core_if->hwcfg2.b.dynamic_fifo == 0)) {+		if (dwc_otg_param_initialized+		    (core_if->core_params->enable_dynamic_fifo)) {+			DWC_ERROR+			    ("%d invalid for enable_dynamic_fifo paremter. Check HW configuration.\n",+			     val);+		}+		val = 0;+		retval = -DWC_E_INVALID;+	}+	core_if->core_params->enable_dynamic_fifo = val;+	return retval;+}++int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->enable_dynamic_fifo;+}++int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;+	if (DWC_OTG_PARAM_TEST(val, 32, 32768)) {+		DWC_WARN("Wrong value for data_fifo_size\n");+		DWC_WARN("data_fifo_size must be 32-32768\n");+		return -DWC_E_INVALID;+	}++	if (val > core_if->hwcfg3.b.dfifo_depth) {+		if (dwc_otg_param_initialized+		    (core_if->core_params->data_fifo_size)) {+			DWC_ERROR+			    ("%d invalid for data_fifo_size parameter. Check HW configuration.\n",+			     val);+		}+		val = core_if->hwcfg3.b.dfifo_depth;+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->data_fifo_size = val;+	return retval;+}++int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->data_fifo_size;+}++int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;+	if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {+		DWC_WARN("Wrong value for dev_rx_fifo_size\n");+		DWC_WARN("dev_rx_fifo_size must be 16-32768\n");+		return -DWC_E_INVALID;+	}++	if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) {+		if (dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) {+		DWC_WARN("%d invalid for dev_rx_fifo_size parameter\n", val);+		}+		val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->dev_rx_fifo_size = val;+	return retval;+}++int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->dev_rx_fifo_size;+}++int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if,+					      int32_t val)+{+	int retval = 0;++	if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {+		DWC_WARN("Wrong value for dev_nperio_tx_fifo\n");+		DWC_WARN("dev_nperio_tx_fifo must be 16-32768\n");+		return -DWC_E_INVALID;+	}++	if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {+		if (dwc_otg_param_initialized+		    (core_if->core_params->dev_nperio_tx_fifo_size)) {+			DWC_ERROR+			    ("%d invalid for dev_nperio_tx_fifo_size. Check HW configuration.\n",+			     val);+		}+		val =+		    (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >>+		     16);+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->dev_nperio_tx_fifo_size = val;+	return retval;+}++int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->dev_nperio_tx_fifo_size;+}++int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if,+					int32_t val)+{+	int retval = 0;++	if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {+		DWC_WARN("Wrong value for host_rx_fifo_size\n");+		DWC_WARN("host_rx_fifo_size must be 16-32768\n");+		return -DWC_E_INVALID;+	}++	if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) {+		if (dwc_otg_param_initialized+		    (core_if->core_params->host_rx_fifo_size)) {+			DWC_ERROR+			    ("%d invalid for host_rx_fifo_size. Check HW configuration.\n",+			     val);+		}+		val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->host_rx_fifo_size = val;+	return retval;++}++int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->host_rx_fifo_size;+}++int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if,+					       int32_t val)+{+	int retval = 0;++	if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {+		DWC_WARN("Wrong value for host_nperio_tx_fifo_size\n");+		DWC_WARN("host_nperio_tx_fifo_size must be 16-32768\n");+		return -DWC_E_INVALID;+	}++	if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {+		if (dwc_otg_param_initialized+		    (core_if->core_params->host_nperio_tx_fifo_size)) {+			DWC_ERROR+			    ("%d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n",+			     val);+		}+		val =+		    (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >>+		     16);+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->host_nperio_tx_fifo_size = val;+	return retval;+}++int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->host_nperio_tx_fifo_size;+}++int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,+					      int32_t val)+{+	int retval = 0;+	if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {+		DWC_WARN("Wrong value for host_perio_tx_fifo_size\n");+		DWC_WARN("host_perio_tx_fifo_size must be 16-32768\n");+		return -DWC_E_INVALID;+	}++	if (val > ((core_if->hptxfsiz.d32) >> 16)) {+		if (dwc_otg_param_initialized+		    (core_if->core_params->host_perio_tx_fifo_size)) {+			DWC_ERROR+			    ("%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n",+			     val);+		}+		val = (core_if->hptxfsiz.d32) >> 16;+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->host_perio_tx_fifo_size = val;+	return retval;+}++int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->host_perio_tx_fifo_size;+}++int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if,+					int32_t val)+{+	int retval = 0;++	if (DWC_OTG_PARAM_TEST(val, 2047, 524288)) {+		DWC_WARN("Wrong value for max_transfer_size\n");+		DWC_WARN("max_transfer_size must be 2047-524288\n");+		return -DWC_E_INVALID;+	}++	if (val >= (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11))) {+		if (dwc_otg_param_initialized+		    (core_if->core_params->max_transfer_size)) {+			DWC_ERROR+			    ("%d invalid for max_transfer_size. Check HW configuration.\n",+			     val);+		}+		val =+		    ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 11)) -+		     1);+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->max_transfer_size = val;+	return retval;+}++int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->max_transfer_size;+}++int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;++	if (DWC_OTG_PARAM_TEST(val, 15, 511)) {+		DWC_WARN("Wrong value for max_packet_count\n");+		DWC_WARN("max_packet_count must be 15-511\n");+		return -DWC_E_INVALID;+	}++	if (val > (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4))) {+		if (dwc_otg_param_initialized+		    (core_if->core_params->max_packet_count)) {+			DWC_ERROR+			    ("%d invalid for max_packet_count. Check HW configuration.\n",+			     val);+		}+		val =+		    ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1);+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->max_packet_count = val;+	return retval;+}++int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->max_packet_count;+}++int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;++	if (DWC_OTG_PARAM_TEST(val, 1, 16)) {+		DWC_WARN("Wrong value for host_channels\n");+		DWC_WARN("host_channels must be 1-16\n");+		return -DWC_E_INVALID;+	}++	if (val > (core_if->hwcfg2.b.num_host_chan + 1)) {+		if (dwc_otg_param_initialized+		    (core_if->core_params->host_channels)) {+			DWC_ERROR+			    ("%d invalid for host_channels. Check HW configurations.\n",+			     val);+		}+		val = (core_if->hwcfg2.b.num_host_chan + 1);+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->host_channels = val;+	return retval;+}++int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->host_channels;+}++int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;++	if (DWC_OTG_PARAM_TEST(val, 1, 15)) {+		DWC_WARN("Wrong value for dev_endpoints\n");+		DWC_WARN("dev_endpoints must be 1-15\n");+		return -DWC_E_INVALID;+	}++	if (val > (core_if->hwcfg2.b.num_dev_ep)) {+		if (dwc_otg_param_initialized+		    (core_if->core_params->dev_endpoints)) {+			DWC_ERROR+			    ("%d invalid for dev_endpoints. Check HW configurations.\n",+			     val);+		}+		val = core_if->hwcfg2.b.num_dev_ep;+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->dev_endpoints = val;+	return retval;+}++int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->dev_endpoints;+}++int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;+	int valid = 0;++	if (DWC_OTG_PARAM_TEST(val, 0, 2)) {+		DWC_WARN("Wrong value for phy_type\n");+		DWC_WARN("phy_type must be 0,1 or 2\n");+		return -DWC_E_INVALID;+	}+#ifndef NO_FS_PHY_HW_CHECKS+	if ((val == DWC_PHY_TYPE_PARAM_UTMI) &&+	    ((core_if->hwcfg2.b.hs_phy_type == 1) ||+	     (core_if->hwcfg2.b.hs_phy_type == 3))) {+		valid = 1;+	} else if ((val == DWC_PHY_TYPE_PARAM_ULPI) &&+		   ((core_if->hwcfg2.b.hs_phy_type == 2) ||+		    (core_if->hwcfg2.b.hs_phy_type == 3))) {+		valid = 1;+	} else if ((val == DWC_PHY_TYPE_PARAM_FS) &&+		   (core_if->hwcfg2.b.fs_phy_type == 1)) {+		valid = 1;+	}+	if (!valid) {+		if (dwc_otg_param_initialized(core_if->core_params->phy_type)) {+			DWC_ERROR+			    ("%d invalid for phy_type. Check HW configurations.\n",+			     val);+		}+		if (core_if->hwcfg2.b.hs_phy_type) {+			if ((core_if->hwcfg2.b.hs_phy_type == 3) ||+			    (core_if->hwcfg2.b.hs_phy_type == 1)) {+				val = DWC_PHY_TYPE_PARAM_UTMI;+			} else {+				val = DWC_PHY_TYPE_PARAM_ULPI;+			}+		}+		retval = -DWC_E_INVALID;+	}+#endif+	core_if->core_params->phy_type = val;+	return retval;+}++int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->phy_type;+}++int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("Wrong value for speed parameter\n");+		DWC_WARN("max_speed parameter must be 0 or 1\n");+		return -DWC_E_INVALID;+	}+	if ((val == 0)+	    && dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS) {+		if (dwc_otg_param_initialized(core_if->core_params->speed)) {+			DWC_ERROR+			    ("%d invalid for speed paremter. Check HW configuration.\n",+			     val);+		}+		val =+		    (dwc_otg_get_param_phy_type(core_if) ==+		     DWC_PHY_TYPE_PARAM_FS ? 1 : 0);+		retval = -DWC_E_INVALID;+	}+	core_if->core_params->speed = val;+	return retval;+}++int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->speed;+}++int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if,+						int32_t val)+{+	int retval = 0;++	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN+		    ("Wrong value for host_ls_low_power_phy_clk parameter\n");+		DWC_WARN("host_ls_low_power_phy_clk must be 0 or 1\n");+		return -DWC_E_INVALID;+	}++	if ((val == DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ)+	    && (dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS)) {+		if (dwc_otg_param_initialized+		    (core_if->core_params->host_ls_low_power_phy_clk)) {+			DWC_ERROR+			    ("%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n",+			     val);+		}+		val =+		    (dwc_otg_get_param_phy_type(core_if) ==+		     DWC_PHY_TYPE_PARAM_FS) ?+		    DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ :+		    DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ;+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->host_ls_low_power_phy_clk = val;+	return retval;+}++int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->host_ls_low_power_phy_clk;+}++int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if, int32_t val)+{+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("Wrong value for phy_ulpi_ddr\n");+		DWC_WARN("phy_upli_ddr must be 0 or 1\n");+		return -DWC_E_INVALID;+	}++	core_if->core_params->phy_ulpi_ddr = val;+	return 0;+}++int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->phy_ulpi_ddr;+}++int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if,+					int32_t val)+{+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("Wrong valaue for phy_ulpi_ext_vbus\n");+		DWC_WARN("phy_ulpi_ext_vbus must be 0 or 1\n");+		return -DWC_E_INVALID;+	}++	core_if->core_params->phy_ulpi_ext_vbus = val;+	return 0;+}++int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->phy_ulpi_ext_vbus;+}++int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if, int32_t val)+{+	if (DWC_OTG_PARAM_TEST(val, 8, 8) && DWC_OTG_PARAM_TEST(val, 16, 16)) {+		DWC_WARN("Wrong valaue for phy_utmi_width\n");+		DWC_WARN("phy_utmi_width must be 8 or 16\n");+		return -DWC_E_INVALID;+	}++	core_if->core_params->phy_utmi_width = val;+	return 0;+}++int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->phy_utmi_width;+}++int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if, int32_t val)+{+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("Wrong valaue for ulpi_fs_ls\n");+		DWC_WARN("ulpi_fs_ls must be 0 or 1\n");+		return -DWC_E_INVALID;+	}++	core_if->core_params->ulpi_fs_ls = val;+	return 0;+}++int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->ulpi_fs_ls;+}++int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val)+{+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("Wrong valaue for ts_dline\n");+		DWC_WARN("ts_dline must be 0 or 1\n");+		return -DWC_E_INVALID;+	}++	core_if->core_params->ts_dline = val;+	return 0;+}++int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->ts_dline;+}++int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("Wrong valaue for i2c_enable\n");+		DWC_WARN("i2c_enable must be 0 or 1\n");+		return -DWC_E_INVALID;+	}+#ifndef NO_FS_PHY_HW_CHECK+	if (val == 1 && core_if->hwcfg3.b.i2c == 0) {+		if (dwc_otg_param_initialized(core_if->core_params->i2c_enable)) {+			DWC_ERROR+			    ("%d invalid for i2c_enable. Check HW configuration.\n",+			     val);+		}+		val = 0;+		retval = -DWC_E_INVALID;+	}+#endif++	core_if->core_params->i2c_enable = val;+	return retval;+}++int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->i2c_enable;+}++int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,+					     int32_t val, int fifo_num)+{+	int retval = 0;++	if (DWC_OTG_PARAM_TEST(val, 4, 768)) {+		DWC_WARN("Wrong value for dev_perio_tx_fifo_size\n");+		DWC_WARN("dev_perio_tx_fifo_size must be 4-768\n");+		return -DWC_E_INVALID;+	}++	if (val >+	    (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) {+		if (dwc_otg_param_initialized+		    (core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) {+			DWC_ERROR+			    ("`%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n",+			     val, fifo_num);+		}+		val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]));+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->dev_perio_tx_fifo_size[fifo_num] = val;+	return retval;+}++int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,+						 int fifo_num)+{+	return core_if->core_params->dev_perio_tx_fifo_size[fifo_num];+}++int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if,+					  int32_t val)+{+	int retval = 0;+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("Wrong valaue for en_multiple_tx_fifo,\n");+		DWC_WARN("en_multiple_tx_fifo must be 0 or 1\n");+		return -DWC_E_INVALID;+	}++	if (val == 1 && core_if->hwcfg4.b.ded_fifo_en == 0) {+		if (dwc_otg_param_initialized+		    (core_if->core_params->en_multiple_tx_fifo)) {+			DWC_ERROR+			    ("%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n",+			     val);+		}+		val = 0;+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->en_multiple_tx_fifo = val;+	return retval;+}++int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->en_multiple_tx_fifo;+}++int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val,+				       int fifo_num)+{+	int retval = 0;++	if (DWC_OTG_PARAM_TEST(val, 4, 768)) {+		DWC_WARN("Wrong value for dev_tx_fifo_size\n");+		DWC_WARN("dev_tx_fifo_size must be 4-768\n");+		return -DWC_E_INVALID;+	}++	if (val >+	    (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) {+		if (dwc_otg_param_initialized+		    (core_if->core_params->dev_tx_fifo_size[fifo_num])) {+			DWC_ERROR+			    ("`%d' invalid for parameter `dev_tx_fifo_size_%d'. Check HW configuration.\n",+			     val, fifo_num);+		}+		val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]));+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->dev_tx_fifo_size[fifo_num] = val;+	return retval;+}++int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,+					   int fifo_num)+{+	return core_if->core_params->dev_tx_fifo_size[fifo_num];+}++int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;++	if (DWC_OTG_PARAM_TEST(val, 0, 7)) {+		DWC_WARN("Wrong value for thr_ctl\n");+		DWC_WARN("thr_ctl must be 0-7\n");+		return -DWC_E_INVALID;+	}++	if ((val != 0) &&+	    (!dwc_otg_get_param_dma_enable(core_if) ||+	     !core_if->hwcfg4.b.ded_fifo_en)) {+		if (dwc_otg_param_initialized(core_if->core_params->thr_ctl)) {+			DWC_ERROR+			    ("%d invalid for parameter thr_ctl. Check HW configuration.\n",+			     val);+		}+		val = 0;+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->thr_ctl = val;+	return retval;+}++int32_t dwc_otg_get_param_thr_ctl(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->thr_ctl;+}++int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;++	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("Wrong value for lpm_enable\n");+		DWC_WARN("lpm_enable must be 0 or 1\n");+		return -DWC_E_INVALID;+	}++	if (val && !core_if->hwcfg3.b.otg_lpm_en) {+		if (dwc_otg_param_initialized(core_if->core_params->lpm_enable)) {+			DWC_ERROR+			    ("%d invalid for parameter lpm_enable. Check HW configuration.\n",+			     val);+		}+		val = 0;+		retval = -DWC_E_INVALID;+	}++	core_if->core_params->lpm_enable = val;+	return retval;+}++int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->lpm_enable;+}++int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if, int32_t val)+{+	if (DWC_OTG_PARAM_TEST(val, 8, 128)) {+		DWC_WARN("Wrong valaue for tx_thr_length\n");+		DWC_WARN("tx_thr_length must be 8 - 128\n");+		return -DWC_E_INVALID;+	}++	core_if->core_params->tx_thr_length = val;+	return 0;+}++int32_t dwc_otg_get_param_tx_thr_length(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->tx_thr_length;+}++int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if, int32_t val)+{+	if (DWC_OTG_PARAM_TEST(val, 8, 128)) {+		DWC_WARN("Wrong valaue for rx_thr_length\n");+		DWC_WARN("rx_thr_length must be 8 - 128\n");+		return -DWC_E_INVALID;+	}++	core_if->core_params->rx_thr_length = val;+	return 0;+}++int32_t dwc_otg_get_param_rx_thr_length(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->rx_thr_length;+}++int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if, int32_t val)+{+	if (DWC_OTG_PARAM_TEST(val, 1, 1) &&+	    DWC_OTG_PARAM_TEST(val, 4, 4) &&+	    DWC_OTG_PARAM_TEST(val, 8, 8) &&+	    DWC_OTG_PARAM_TEST(val, 16, 16) &&+	    DWC_OTG_PARAM_TEST(val, 32, 32) &&+	    DWC_OTG_PARAM_TEST(val, 64, 64) &&+	    DWC_OTG_PARAM_TEST(val, 128, 128) &&+	    DWC_OTG_PARAM_TEST(val, 256, 256)) {+		DWC_WARN("`%d' invalid for parameter `dma_burst_size'\n", val);+		return -DWC_E_INVALID;+	}+	core_if->core_params->dma_burst_size = val;+	return 0;+}++int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->dma_burst_size;+}++int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("`%d' invalid for parameter `pti_enable'\n", val);+		return -DWC_E_INVALID;+	}+	if (val && (core_if->snpsid < OTG_CORE_REV_2_72a)) {+		if (dwc_otg_param_initialized(core_if->core_params->pti_enable)) {+			DWC_ERROR+			    ("%d invalid for parameter pti_enable. Check HW configuration.\n",+			     val);+		}+		retval = -DWC_E_INVALID;+		val = 0;+	}+	core_if->core_params->pti_enable = val;+	return retval;+}++int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->pti_enable;+}++int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("`%d' invalid for parameter `mpi_enable'\n", val);+		return -DWC_E_INVALID;+	}+	if (val && (core_if->hwcfg2.b.multi_proc_int == 0)) {+		if (dwc_otg_param_initialized(core_if->core_params->mpi_enable)) {+			DWC_ERROR+			    ("%d invalid for parameter mpi_enable. Check HW configuration.\n",+			     val);+		}+		retval = -DWC_E_INVALID;+		val = 0;+	}+	core_if->core_params->mpi_enable = val;+	return retval;+}++int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->mpi_enable;+}++int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("`%d' invalid for parameter `adp_enable'\n", val);+		return -DWC_E_INVALID;+	}+	if (val && (core_if->hwcfg3.b.adp_supp == 0)) {+		if (dwc_otg_param_initialized+		    (core_if->core_params->adp_supp_enable)) {+			DWC_ERROR+			    ("%d invalid for parameter adp_enable. Check HW configuration.\n",+			     val);+		}+		retval = -DWC_E_INVALID;+		val = 0;+	}+	core_if->core_params->adp_supp_enable = val;+	/*Set OTG version 2.0 in case of enabling ADP*/+	if (val)+		dwc_otg_set_param_otg_ver(core_if, 1);++	return retval;+}++int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->adp_supp_enable;+}++int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("`%d' invalid for parameter `ic_usb_cap'\n", val);+		DWC_WARN("ic_usb_cap must be 0 or 1\n");+		return -DWC_E_INVALID;+	}++	if (val && (core_if->hwcfg2.b.otg_enable_ic_usb == 0)) {+		if (dwc_otg_param_initialized(core_if->core_params->ic_usb_cap)) {+			DWC_ERROR+			    ("%d invalid for parameter ic_usb_cap. Check HW configuration.\n",+			     val);+		}+		retval = -DWC_E_INVALID;+		val = 0;+	}+	core_if->core_params->ic_usb_cap = val;+	return retval;+}++int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->ic_usb_cap;+}++int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;+	int valid = 1;++	if (DWC_OTG_PARAM_TEST(val, 0, 3)) {+		DWC_WARN("`%d' invalid for parameter `ahb_thr_ratio'\n", val);+		DWC_WARN("ahb_thr_ratio must be 0 - 3\n");+		return -DWC_E_INVALID;+	}++	if (val+	    && (core_if->snpsid < OTG_CORE_REV_2_81a+		|| !dwc_otg_get_param_thr_ctl(core_if))) {+		valid = 0;+	} else if (val+		   && ((dwc_otg_get_param_tx_thr_length(core_if) / (1 << val)) <+		       4)) {+		valid = 0;+	}+	if (valid == 0) {+		if (dwc_otg_param_initialized+		    (core_if->core_params->ahb_thr_ratio)) {+			DWC_ERROR+			    ("%d invalid for parameter ahb_thr_ratio. Check HW configuration.\n",+			     val);+		}+		retval = -DWC_E_INVALID;+		val = 0;+	}++	core_if->core_params->ahb_thr_ratio = val;+	return retval;+}++int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->ahb_thr_ratio;+}++int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;+	int valid = 1;+	hwcfg4_data_t hwcfg4 = {.d32 = 0 };+	hwcfg4.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);++	if (DWC_OTG_PARAM_TEST(val, 0, 3)) {+		DWC_WARN("`%d' invalid for parameter `power_down'\n", val);+		DWC_WARN("power_down must be 0 - 2\n");+		return -DWC_E_INVALID;+	}++	if ((val == 2) && (core_if->snpsid < OTG_CORE_REV_2_91a)) {+		valid = 0;+	}+	if ((val == 3)+	    && ((core_if->snpsid < OTG_CORE_REV_3_00a)+		|| (hwcfg4.b.xhiber == 0))) {+		valid = 0;+	}+	if (valid == 0) {+		if (dwc_otg_param_initialized(core_if->core_params->power_down)) {+			DWC_ERROR+			    ("%d invalid for parameter power_down. Check HW configuration.\n",+			     val);+		}+		retval = -DWC_E_INVALID;+		val = 0;+	}+	core_if->core_params->power_down = val;+	return retval;+}++int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->power_down;+}++int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;+	int valid = 1;++	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("`%d' invalid for parameter `reload_ctl'\n", val);+		DWC_WARN("reload_ctl must be 0 or 1\n");+		return -DWC_E_INVALID;+	}++	if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_92a)) {+		valid = 0;+	}+	if (valid == 0) {+		if (dwc_otg_param_initialized(core_if->core_params->reload_ctl)) {+			DWC_ERROR("%d invalid for parameter reload_ctl."+				  "Check HW configuration.\n", val);+		}+		retval = -DWC_E_INVALID;+		val = 0;+	}+	core_if->core_params->reload_ctl = val;+	return retval;+}++int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->reload_ctl;+}++int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;+	int valid = 1;++	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("`%d' invalid for parameter `dev_out_nak'\n", val);+		DWC_WARN("dev_out_nak must be 0 or 1\n");+		return -DWC_E_INVALID;+	}++	if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_93a) ||+		!(core_if->core_params->dma_desc_enable))) {+		valid = 0;+	}+	if (valid == 0) {+		if (dwc_otg_param_initialized(core_if->core_params->dev_out_nak)) {+			DWC_ERROR("%d invalid for parameter dev_out_nak."+				"Check HW configuration.\n", val);+		}+		retval = -DWC_E_INVALID;+		val = 0;+	}+	core_if->core_params->dev_out_nak = val;+	return retval;+}++int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->dev_out_nak;+}++int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;+	int valid = 1;++	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("`%d' invalid for parameter `cont_on_bna'\n", val);+		DWC_WARN("cont_on_bna must be 0 or 1\n");+		return -DWC_E_INVALID;+	}++	if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_94a) ||+		!(core_if->core_params->dma_desc_enable))) {+			valid = 0;+	}+	if (valid == 0) {+		if (dwc_otg_param_initialized(core_if->core_params->cont_on_bna)) {+			DWC_ERROR("%d invalid for parameter cont_on_bna."+				"Check HW configuration.\n", val);+		}+		retval = -DWC_E_INVALID;+		val = 0;+	}+	core_if->core_params->cont_on_bna = val;+	return retval;+}++int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->cont_on_bna;+}++int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;+	int valid = 1;++	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("`%d' invalid for parameter `ahb_single'\n", val);+		DWC_WARN("ahb_single must be 0 or 1\n");+		return -DWC_E_INVALID;+	}++	if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_94a)) {+			valid = 0;+	}+	if (valid == 0) {+		if (dwc_otg_param_initialized(core_if->core_params->ahb_single)) {+			DWC_ERROR("%d invalid for parameter ahb_single."+				"Check HW configuration.\n", val);+		}+		retval = -DWC_E_INVALID;+		val = 0;+	}+	core_if->core_params->ahb_single = val;+	return retval;+}++int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->ahb_single;+}++int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val)+{+	int retval = 0;++	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {+		DWC_WARN("`%d' invalid for parameter `otg_ver'\n", val);+		DWC_WARN+		    ("otg_ver must be 0(for OTG 1.3 support) or 1(for OTG 2.0 support)\n");+		return -DWC_E_INVALID;+	}++	core_if->core_params->otg_ver = val;+	return retval;+}++int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if)+{+	return core_if->core_params->otg_ver;+}++uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if)+{+	gotgctl_data_t otgctl;+	otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);+	return otgctl.b.hstnegscs;+}++uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if)+{+	gotgctl_data_t otgctl;+	otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);+	return otgctl.b.sesreqscs;+}++void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val)+{+	if(core_if->otg_ver == 0) {+		gotgctl_data_t otgctl;+		otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);+		otgctl.b.hnpreq = val;+		DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, otgctl.d32);+	} else {+		core_if->otg_sts = val;+	}+}++uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if)+{+	return core_if->snpsid;+}++uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if)+{+	gintsts_data_t gintsts;+	gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);+	return gintsts.b.curmode;+}++uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if)+{+	gusbcfg_data_t usbcfg;+	usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);+	return usbcfg.b.hnpcap;+}++void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val)+{+	gusbcfg_data_t usbcfg;+	usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);+	usbcfg.b.hnpcap = val;+	DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);+}++uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if)+{+	gusbcfg_data_t usbcfg;+	usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);+	return usbcfg.b.srpcap;+}++void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val)+{+	gusbcfg_data_t usbcfg;+	usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);+	usbcfg.b.srpcap = val;+	DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);+}++uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if)+{+	dcfg_data_t dcfg;+	/* originally: dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); */++        dcfg.d32 = -1; //GRAYG+        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)\n", __func__, core_if);+        if (NULL == core_if)+                DWC_ERROR("reg request with NULL core_if\n");+        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)\n", __func__,+                    core_if, core_if->dev_if);+        if (NULL == core_if->dev_if)+                DWC_ERROR("reg request with NULL dev_if\n");+        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)->"+                    "dev_global_regs(%p)\n", __func__,+                    core_if, core_if->dev_if,+                    core_if->dev_if->dev_global_regs);+        if (NULL == core_if->dev_if->dev_global_regs)+                DWC_ERROR("reg request with NULL dev_global_regs\n");+        else {+                DWC_DEBUGPL(DBG_CILV, "%s - &core_if(%p)->dev_if(%p)->"+                            "dev_global_regs(%p)->dcfg = %p\n", __func__,+                            core_if, core_if->dev_if,+                            core_if->dev_if->dev_global_regs,+                            &core_if->dev_if->dev_global_regs->dcfg);+		dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);+        }+	return dcfg.b.devspd;+}++void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val)+{+	dcfg_data_t dcfg;+	dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);+	dcfg.b.devspd = val;+	DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);+}++uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if)+{+	hprt0_data_t hprt0;+	hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);+	return hprt0.b.prtconnsts;+}++uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if)+{+	dsts_data_t dsts;+	dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);+	return dsts.b.enumspd;+}++uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if)+{+	hprt0_data_t hprt0;+	hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);+	return hprt0.b.prtpwr;++}++uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if)+{+	return core_if->hibernation_suspend;+}++void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val)+{+	hprt0_data_t hprt0;+	hprt0.d32 = dwc_otg_read_hprt0(core_if);+	hprt0.b.prtpwr = val;+	DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+}++uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if)+{+	hprt0_data_t hprt0;+	hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);+	return hprt0.b.prtsusp;++}++void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val)+{+	hprt0_data_t hprt0;+	hprt0.d32 = dwc_otg_read_hprt0(core_if);+	hprt0.b.prtsusp = val;+	DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+}++uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if)+{+	hfir_data_t hfir;+	hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);+	return hfir.b.frint;++}++void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val)+{+	hfir_data_t hfir;+	uint32_t fram_int;+	fram_int = calc_frame_interval(core_if);+	hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);+	if (!core_if->core_params->reload_ctl) {+		DWC_WARN("\nCannot reload HFIR register.HFIR.HFIRRldCtrl bit is"+			 "not set to 1.\nShould load driver with reload_ctl=1"+			 " module parameter\n");+		return;+	}+	switch (fram_int) {+	case 3750:+		if ((val < 3350) || (val > 4150)) {+			DWC_WARN("HFIR interval for HS core and 30 MHz"+				 "clock freq should be from 3350 to 4150\n");+			return;+		}+		break;+	case 30000:+		if ((val < 26820) || (val > 33180)) {+			DWC_WARN("HFIR interval for FS/LS core and 30 MHz"+				 "clock freq should be from 26820 to 33180\n");+			return;+		}+		break;+	case 6000:+		if ((val < 5360) || (val > 6640)) {+			DWC_WARN("HFIR interval for HS core and 48 MHz"+				 "clock freq should be from 5360 to 6640\n");+			return;+		}+		break;+	case 48000:+		if ((val < 42912) || (val > 53088)) {+			DWC_WARN("HFIR interval for FS/LS core and 48 MHz"+				 "clock freq should be from 42912 to 53088\n");+			return;+		}+		break;+	case 7500:+		if ((val < 6700) || (val > 8300)) {+			DWC_WARN("HFIR interval for HS core and 60 MHz"+				 "clock freq should be from 6700 to 8300\n");+			return;+		}+		break;+	case 60000:+		if ((val < 53640) || (val > 65536)) {+			DWC_WARN("HFIR interval for FS/LS core and 60 MHz"+				 "clock freq should be from 53640 to 65536\n");+			return;+		}+		break;+	default:+		DWC_WARN("Unknown frame interval\n");+		return;+		break;++	}+	hfir.b.frint = val;+	DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hfir.d32);+}++uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if)+{+	hcfg_data_t hcfg;+	hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);+	return hcfg.b.modechtimen;++}++void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val)+{+	hcfg_data_t hcfg;+	hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);+	hcfg.b.modechtimen = val;+	DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32);+}++void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val)+{+	hprt0_data_t hprt0;+	hprt0.d32 = dwc_otg_read_hprt0(core_if);+	hprt0.b.prtres = val;+	DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+}++uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if)+{+	dctl_data_t dctl;+	dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);+	return dctl.b.rmtwkupsig;+}++uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if)+{+	glpmcfg_data_t lpmcfg;+	lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);++	DWC_ASSERT(!+		   ((core_if->lx_state == DWC_OTG_L1) ^ lpmcfg.b.prt_sleep_sts),+		   "lx_state = %d, lmpcfg.prt_sleep_sts = %d\n",+		   core_if->lx_state, lpmcfg.b.prt_sleep_sts);++	return lpmcfg.b.prt_sleep_sts;+}++uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if)+{+	glpmcfg_data_t lpmcfg;+	lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);+	return lpmcfg.b.rem_wkup_en;+}++uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if)+{+	glpmcfg_data_t lpmcfg;+	lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);+	return lpmcfg.b.appl_resp;+}++void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val)+{+	glpmcfg_data_t lpmcfg;+	lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);+	lpmcfg.b.appl_resp = val;+	DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);+}++uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if)+{+	glpmcfg_data_t lpmcfg;+	lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);+	return lpmcfg.b.hsic_connect;+}++void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val)+{+	glpmcfg_data_t lpmcfg;+	lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);+	lpmcfg.b.hsic_connect = val;+	DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);+}++uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if)+{+	glpmcfg_data_t lpmcfg;+	lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);+	return lpmcfg.b.inv_sel_hsic;++}++void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val)+{+	glpmcfg_data_t lpmcfg;+	lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);+	lpmcfg.b.inv_sel_hsic = val;+	DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);+}++uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if)+{+	return DWC_READ_REG32(&core_if->core_global_regs->gotgctl);+}++void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val)+{+	DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, val);+}++uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if)+{+	return DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);+}++void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val)+{+	DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, val);+}++uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if)+{+	return DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);+}++void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val)+{+	DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, val);+}++uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if)+{+	return DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz);+}++void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val)+{+	DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, val);+}++uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if)+{+	return DWC_READ_REG32(&core_if->core_global_regs->gpvndctl);+}++void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val)+{+	DWC_WRITE_REG32(&core_if->core_global_regs->gpvndctl, val);+}++uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if)+{+	return DWC_READ_REG32(&core_if->core_global_regs->ggpio);+}++void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val)+{+	DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, val);+}++uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if)+{+	return DWC_READ_REG32(core_if->host_if->hprt0);++}++void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val)+{+	DWC_WRITE_REG32(core_if->host_if->hprt0, val);+}++uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if)+{+	return DWC_READ_REG32(&core_if->core_global_regs->guid);+}++void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val)+{+	DWC_WRITE_REG32(&core_if->core_global_regs->guid, val);+}++uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if)+{+	return DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);+}++uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if)+{+	return ((core_if->otg_ver == 1) ? (uint16_t)0x0200 : (uint16_t)0x0103);+}++/**+ * Start the SRP timer to detect when the SRP does not complete within+ * 6 seconds.+ *+ * @param core_if the pointer to core_if strucure.+ */+void dwc_otg_pcd_start_srp_timer(dwc_otg_core_if_t * core_if)+{+	core_if->srp_timer_started = 1;+	DWC_TIMER_SCHEDULE(core_if->srp_timer, 6000 /* 6 secs */ );+}++void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if)+{+	uint32_t *addr = (uint32_t *) & (core_if->core_global_regs->gotgctl);+	gotgctl_data_t mem;+	gotgctl_data_t val;++	val.d32 = DWC_READ_REG32(addr);+	if (val.b.sesreq) {+		DWC_ERROR("Session Request Already active!\n");+		return;+	}++	DWC_INFO("Session Request Initated\n");	//NOTICE+	mem.d32 = DWC_READ_REG32(addr);+	mem.b.sesreq = 1;+	DWC_WRITE_REG32(addr, mem.d32);++	/* Start the SRP timer */+	dwc_otg_pcd_start_srp_timer(core_if);+	return;+}diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_cil.h--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_cil.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_cil.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,1464 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $+ * $Revision: #123 $+ * $Date: 2012/08/10 $+ * $Change: 2047372 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */++#if !defined(__DWC_CIL_H__)+#define __DWC_CIL_H__++#include "dwc_list.h"+#include "dwc_otg_dbg.h"+#include "dwc_otg_regs.h"++#include "dwc_otg_core_if.h"+#include "dwc_otg_adp.h"++/**+ * @file+ * This file contains the interface to the Core Interface Layer.+ */++#ifdef DWC_UTE_CFI++#define MAX_DMA_DESCS_PER_EP	256++/**+ * Enumeration for the data buffer mode+ */+typedef enum _data_buffer_mode {+	BM_STANDARD = 0,	/* data buffer is in normal mode */+	BM_SG = 1,		/* data buffer uses the scatter/gather mode */+	BM_CONCAT = 2,		/* data buffer uses the concatenation mode */+	BM_CIRCULAR = 3,	/* data buffer uses the circular DMA mode */+	BM_ALIGN = 4		/* data buffer is in buffer alignment mode */+} data_buffer_mode_e;+#endif //DWC_UTE_CFI++/** Macros defined for DWC OTG HW Release version */++#define OTG_CORE_REV_2_60a	0x4F54260A+#define OTG_CORE_REV_2_71a	0x4F54271A+#define OTG_CORE_REV_2_72a	0x4F54272A+#define OTG_CORE_REV_2_80a	0x4F54280A+#define OTG_CORE_REV_2_81a	0x4F54281A+#define OTG_CORE_REV_2_90a	0x4F54290A+#define OTG_CORE_REV_2_91a	0x4F54291A+#define OTG_CORE_REV_2_92a	0x4F54292A+#define OTG_CORE_REV_2_93a	0x4F54293A+#define OTG_CORE_REV_2_94a	0x4F54294A+#define OTG_CORE_REV_3_00a	0x4F54300A++/**+ * Information for each ISOC packet.+ */+typedef struct iso_pkt_info {+	uint32_t offset;+	uint32_t length;+	int32_t status;+} iso_pkt_info_t;++/**+ * The <code>dwc_ep</code> structure represents the state of a single+ * endpoint when acting in device mode. It contains the data items+ * needed for an endpoint to be activated and transfer packets.+ */+typedef struct dwc_ep {+	/** EP number used for register address lookup */+	uint8_t num;+	/** EP direction 0 = OUT */+	unsigned is_in:1;+	/** EP active. */+	unsigned active:1;++	/**+	 * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic+	 * Tx FIFO. If dedicated Tx FIFOs are enabled Tx FIFO # FOR IN EPs*/+	unsigned tx_fifo_num:4;+	/** EP type: 0 - Control, 1 - ISOC,	 2 - BULK,	3 - INTR */+	unsigned type:2;+#define DWC_OTG_EP_TYPE_CONTROL	   0+#define DWC_OTG_EP_TYPE_ISOC	   1+#define DWC_OTG_EP_TYPE_BULK	   2+#define DWC_OTG_EP_TYPE_INTR	   3++	/** DATA start PID for INTR and BULK EP */+	unsigned data_pid_start:1;+	/** Frame (even/odd) for ISOC EP */+	unsigned even_odd_frame:1;+	/** Max Packet bytes */+	unsigned maxpacket:11;++	/** Max Transfer size */+	uint32_t maxxfer;++	/** @name Transfer state */+	/** @{ */++	/**+	 * Pointer to the beginning of the transfer buffer -- do not modify+	 * during transfer.+	 */++	dwc_dma_t dma_addr;++	dwc_dma_t dma_desc_addr;+	dwc_otg_dev_dma_desc_t *desc_addr;++	uint8_t *start_xfer_buff;+	/** pointer to the transfer buffer */+	uint8_t *xfer_buff;+	/** Number of bytes to transfer */+	unsigned xfer_len:19;+	/** Number of bytes transferred. */+	unsigned xfer_count:19;+	/** Sent ZLP */+	unsigned sent_zlp:1;+	/** Total len for control transfer */+	unsigned total_len:19;++	/** stall clear flag */+	unsigned stall_clear_flag:1;++	/** SETUP pkt cnt rollover flag for EP0 out*/+	unsigned stp_rollover;++#ifdef DWC_UTE_CFI+	/* The buffer mode */+	data_buffer_mode_e buff_mode;++	/* The chain of DMA descriptors.+	 * MAX_DMA_DESCS_PER_EP will be allocated for each active EP.+	 */+	dwc_otg_dma_desc_t *descs;++	/* The DMA address of the descriptors chain start */+	dma_addr_t descs_dma_addr;+	/** This variable stores the length of the last enqueued request */+	uint32_t cfi_req_len;+#endif				//DWC_UTE_CFI++/** Max DMA Descriptor count for any EP */+#define MAX_DMA_DESC_CNT 256+	/** Allocated DMA Desc count */+	uint32_t desc_cnt;++	/** bInterval */+	uint32_t bInterval;+	/** Next frame num to setup next ISOC transfer */+	uint32_t frame_num;+	/** Indicates SOF number overrun in DSTS */+	uint8_t frm_overrun;++#ifdef DWC_UTE_PER_IO+	/** Next frame num for which will be setup DMA Desc */+	uint32_t xiso_frame_num;+	/** bInterval */+	uint32_t xiso_bInterval;+	/** Count of currently active transfers - shall be either 0 or 1 */+	int xiso_active_xfers;+	int xiso_queued_xfers;+#endif+#ifdef DWC_EN_ISOC+	/**+	 * Variables specific for ISOC EPs+	 *+	 */+	/** DMA addresses of ISOC buffers */+	dwc_dma_t dma_addr0;+	dwc_dma_t dma_addr1;++	dwc_dma_t iso_dma_desc_addr;+	dwc_otg_dev_dma_desc_t *iso_desc_addr;++	/** pointer to the transfer buffers */+	uint8_t *xfer_buff0;+	uint8_t *xfer_buff1;++	/** number of ISOC Buffer is processing */+	uint32_t proc_buf_num;+	/** Interval of ISOC Buffer processing */+	uint32_t buf_proc_intrvl;+	/** Data size for regular frame */+	uint32_t data_per_frame;++	/* todo - pattern data support is to be implemented in the future */+	/** Data size for pattern frame */+	uint32_t data_pattern_frame;+	/** Frame number of pattern data */+	uint32_t sync_frame;++	/** bInterval */+	uint32_t bInterval;+	/** ISO Packet number per frame */+	uint32_t pkt_per_frm;+	/** Next frame num for which will be setup DMA Desc */+	uint32_t next_frame;+	/** Number of packets per buffer processing */+	uint32_t pkt_cnt;+	/** Info for all isoc packets */+	iso_pkt_info_t *pkt_info;+	/** current pkt number */+	uint32_t cur_pkt;+	/** current pkt number */+	uint8_t *cur_pkt_addr;+	/** current pkt number */+	uint32_t cur_pkt_dma_addr;+#endif				/* DWC_EN_ISOC */++/** @} */+} dwc_ep_t;++/*+ * Reasons for halting a host channel.+ */+typedef enum dwc_otg_halt_status {+	DWC_OTG_HC_XFER_NO_HALT_STATUS,+	DWC_OTG_HC_XFER_COMPLETE,+	DWC_OTG_HC_XFER_URB_COMPLETE,+	DWC_OTG_HC_XFER_ACK,+	DWC_OTG_HC_XFER_NAK,+	DWC_OTG_HC_XFER_NYET,+	DWC_OTG_HC_XFER_STALL,+	DWC_OTG_HC_XFER_XACT_ERR,+	DWC_OTG_HC_XFER_FRAME_OVERRUN,+	DWC_OTG_HC_XFER_BABBLE_ERR,+	DWC_OTG_HC_XFER_DATA_TOGGLE_ERR,+	DWC_OTG_HC_XFER_AHB_ERR,+	DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE,+	DWC_OTG_HC_XFER_URB_DEQUEUE+} dwc_otg_halt_status_e;++/**+ * Host channel descriptor. This structure represents the state of a single+ * host channel when acting in host mode. It contains the data items needed to+ * transfer packets to an endpoint via a host channel.+ */+typedef struct dwc_hc {+	/** Host channel number used for register address lookup */+	uint8_t hc_num;++	/** Device to access */+	unsigned dev_addr:7;++	/** EP to access */+	unsigned ep_num:4;++	/** EP direction. 0: OUT, 1: IN */+	unsigned ep_is_in:1;++	/**+	 * EP speed.+	 * One of the following values:+	 *	- DWC_OTG_EP_SPEED_LOW+	 *	- DWC_OTG_EP_SPEED_FULL+	 *	- DWC_OTG_EP_SPEED_HIGH+	 */+	unsigned speed:2;+#define DWC_OTG_EP_SPEED_LOW	0+#define DWC_OTG_EP_SPEED_FULL	1+#define DWC_OTG_EP_SPEED_HIGH	2++	/**+	 * Endpoint type.+	 * One of the following values:+	 *	- DWC_OTG_EP_TYPE_CONTROL: 0+	 *	- DWC_OTG_EP_TYPE_ISOC: 1+	 *	- DWC_OTG_EP_TYPE_BULK: 2+	 *	- DWC_OTG_EP_TYPE_INTR: 3+	 */+	unsigned ep_type:2;++	/** Max packet size in bytes */+	unsigned max_packet:11;++	/**+	 * PID for initial transaction.+	 * 0: DATA0,<br>+	 * 1: DATA2,<br>+	 * 2: DATA1,<br>+	 * 3: MDATA (non-Control EP),+	 *	  SETUP (Control EP)+	 */+	unsigned data_pid_start:2;+#define DWC_OTG_HC_PID_DATA0 0+#define DWC_OTG_HC_PID_DATA2 1+#define DWC_OTG_HC_PID_DATA1 2+#define DWC_OTG_HC_PID_MDATA 3+#define DWC_OTG_HC_PID_SETUP 3++	/** Number of periodic transactions per (micro)frame */+	unsigned multi_count:2;++	/** @name Transfer State */+	/** @{ */++	/** Pointer to the current transfer buffer position. */+	uint8_t *xfer_buff;+	/**+	 * In Buffer DMA mode this buffer will be used+	 * if xfer_buff is not DWORD aligned.+	 */+	dwc_dma_t align_buff;+	/** Total number of bytes to transfer. */+	uint32_t xfer_len;+	/** Number of bytes transferred so far. */+	uint32_t xfer_count;+	/** Packet count at start of transfer.*/+	uint16_t start_pkt_count;++	/**+	 * Flag to indicate whether the transfer has been started. Set to 1 if+	 * it has been started, 0 otherwise.+	 */+	uint8_t xfer_started;++	/**+	 * Set to 1 to indicate that a PING request should be issued on this+	 * channel. If 0, process normally.+	 */+	uint8_t do_ping;++	/**+	 * Set to 1 to indicate that the error count for this transaction is+	 * non-zero. Set to 0 if the error count is 0.+	 */+	uint8_t error_state;++	/**+	 * Set to 1 to indicate that this channel should be halted the next+	 * time a request is queued for the channel. This is necessary in+	 * slave mode if no request queue space is available when an attempt+	 * is made to halt the channel.+	 */+	uint8_t halt_on_queue;++	/**+	 * Set to 1 if the host channel has been halted, but the core is not+	 * finished flushing queued requests. Otherwise 0.+	 */+	uint8_t halt_pending;++	/**+	 * Reason for halting the host channel.+	 */+	dwc_otg_halt_status_e halt_status;++	/*+	 * Split settings for the host channel+	 */+	uint8_t do_split;		   /**< Enable split for the channel */+	uint8_t complete_split;	   /**< Enable complete split */+	uint8_t hub_addr;		   /**< Address of high speed hub */++	uint8_t port_addr;		   /**< Port of the low/full speed device */+	/** Split transaction position+	 * One of the following values:+	 *	  - DWC_HCSPLIT_XACTPOS_MID+	 *	  - DWC_HCSPLIT_XACTPOS_BEGIN+	 *	  - DWC_HCSPLIT_XACTPOS_END+	 *	  - DWC_HCSPLIT_XACTPOS_ALL */+	uint8_t xact_pos;++	/** Set when the host channel does a short read. */+	uint8_t short_read;++	/**+	 * Number of requests issued for this channel since it was assigned to+	 * the current transfer (not counting PINGs).+	 */+	uint8_t requests;++	/**+	 * Queue Head for the transfer being processed by this channel.+	 */+	struct dwc_otg_qh *qh;++	/** @} */++	/** Entry in list of host channels. */+	 DWC_CIRCLEQ_ENTRY(dwc_hc) hc_list_entry;++	/** @name Descriptor DMA support */+	/** @{ */++	/** Number of Transfer Descriptors */+	uint16_t ntd;++	/** Descriptor List DMA address */+	dwc_dma_t desc_list_addr;++	/** Scheduling micro-frame bitmap. */+	uint8_t schinfo;++	/** @} */+} dwc_hc_t;++/**+ * The following parameters may be specified when starting the module. These+ * parameters define how the DWC_otg controller should be configured.+ */+typedef struct dwc_otg_core_params {+	int32_t opt;++	/**+	 * Specifies the OTG capabilities. The driver will automatically+	 * detect the value for this parameter if none is specified.+	 * 0 - HNP and SRP capable (default)+	 * 1 - SRP Only capable+	 * 2 - No HNP/SRP capable+	 */+	int32_t otg_cap;++	/**+	 * Specifies whether to use slave or DMA mode for accessing the data+	 * FIFOs. The driver will automatically detect the value for this+	 * parameter if none is specified.+	 * 0 - Slave+	 * 1 - DMA (default, if available)+	 */+	int32_t dma_enable;++	/**+	 * When DMA mode is enabled specifies whether to use address DMA or DMA+	 * Descriptor mode for accessing the data FIFOs in device mode. The driver+	 * will automatically detect the value for this if none is specified.+	 * 0 - address DMA+	 * 1 - DMA Descriptor(default, if available)+	 */+	int32_t dma_desc_enable;+	/** The DMA Burst size (applicable only for External DMA+	 * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)+	 */+	int32_t dma_burst_size;	/* Translate this to GAHBCFG values */++	/**+	 * Specifies the maximum speed of operation in host and device mode.+	 * The actual speed depends on the speed of the attached device and+	 * the value of phy_type. The actual speed depends on the speed of the+	 * attached device.+	 * 0 - High Speed (default)+	 * 1 - Full Speed+	 */+	int32_t speed;+	/** Specifies whether low power mode is supported when attached+	 *	to a Full Speed or Low Speed device in host mode.+	 * 0 - Don't support low power mode (default)+	 * 1 - Support low power mode+	 */+	int32_t host_support_fs_ls_low_power;++	/** Specifies the PHY clock rate in low power mode when connected to a+	 * Low Speed device in host mode. This parameter is applicable only if+	 * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS+	 * then defaults to 6 MHZ otherwise 48 MHZ.+	 *+	 * 0 - 48 MHz+	 * 1 - 6 MHz+	 */+	int32_t host_ls_low_power_phy_clk;++	/**+	 * 0 - Use cC FIFO size parameters+	 * 1 - Allow dynamic FIFO sizing (default)+	 */+	int32_t enable_dynamic_fifo;++	/** Total number of 4-byte words in the data FIFO memory. This+	 * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic+	 * Tx FIFOs.+	 * 32 to 32768 (default 8192)+	 * Note: The total FIFO memory depth in the FPGA configuration is 8192.+	 */+	int32_t data_fifo_size;++	/** Number of 4-byte words in the Rx FIFO in device mode when dynamic+	 * FIFO sizing is enabled.+	 * 16 to 32768 (default 1064)+	 */+	int32_t dev_rx_fifo_size;++	/** Number of 4-byte words in the non-periodic Tx FIFO in device mode+	 * when dynamic FIFO sizing is enabled.+	 * 16 to 32768 (default 1024)+	 */+	int32_t dev_nperio_tx_fifo_size;++	/** Number of 4-byte words in each of the periodic Tx FIFOs in device+	 * mode when dynamic FIFO sizing is enabled.+	 * 4 to 768 (default 256)+	 */+	uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];++	/** Number of 4-byte words in the Rx FIFO in host mode when dynamic+	 * FIFO sizing is enabled.+	 * 16 to 32768 (default 1024)+	 */+	int32_t host_rx_fifo_size;++	/** Number of 4-byte words in the non-periodic Tx FIFO in host mode+	 * when Dynamic FIFO sizing is enabled in the core.+	 * 16 to 32768 (default 1024)+	 */+	int32_t host_nperio_tx_fifo_size;++	/** Number of 4-byte words in the host periodic Tx FIFO when dynamic+	 * FIFO sizing is enabled.+	 * 16 to 32768 (default 1024)+	 */+	int32_t host_perio_tx_fifo_size;++	/** The maximum transfer size supported in bytes.+	 * 2047 to 65,535  (default 65,535)+	 */+	int32_t max_transfer_size;++	/** The maximum number of packets in a transfer.+	 * 15 to 511  (default 511)+	 */+	int32_t max_packet_count;++	/** The number of host channel registers to use.+	 * 1 to 16 (default 12)+	 * Note: The FPGA configuration supports a maximum of 12 host channels.+	 */+	int32_t host_channels;++	/** The number of endpoints in addition to EP0 available for device+	 * mode operations.+	 * 1 to 15 (default 6 IN and OUT)+	 * Note: The FPGA configuration supports a maximum of 6 IN and OUT+	 * endpoints in addition to EP0.+	 */+	int32_t dev_endpoints;++		/**+		 * Specifies the type of PHY interface to use. By default, the driver+		 * will automatically detect the phy_type.+		 *+		 * 0 - Full Speed PHY+		 * 1 - UTMI+ (default)+		 * 2 - ULPI+		 */+	int32_t phy_type;++	/**+	 * Specifies the UTMI+ Data Width. This parameter is+	 * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI+	 * PHY_TYPE, this parameter indicates the data width between+	 * the MAC and the ULPI Wrapper.) Also, this parameter is+	 * applicable only if the OTG_HSPHY_WIDTH cC parameter was set+	 * to "8 and 16 bits", meaning that the core has been+	 * configured to work at either data path width.+	 *+	 * 8 or 16 bits (default 16)+	 */+	int32_t phy_utmi_width;++	/**+	 * Specifies whether the ULPI operates at double or single+	 * data rate. This parameter is only applicable if PHY_TYPE is+	 * ULPI.+	 *+	 * 0 - single data rate ULPI interface with 8 bit wide data+	 * bus (default)+	 * 1 - double data rate ULPI interface with 4 bit wide data+	 * bus+	 */+	int32_t phy_ulpi_ddr;++	/**+	 * Specifies whether to use the internal or external supply to+	 * drive the vbus with a ULPI phy.+	 */+	int32_t phy_ulpi_ext_vbus;++	/**+	 * Specifies whether to use the I2Cinterface for full speed PHY. This+	 * parameter is only applicable if PHY_TYPE is FS.+	 * 0 - No (default)+	 * 1 - Yes+	 */+	int32_t i2c_enable;++	int32_t ulpi_fs_ls;++	int32_t ts_dline;++	/**+	 * Specifies whether dedicated transmit FIFOs are+	 * enabled for non periodic IN endpoints in device mode+	 * 0 - No+	 * 1 - Yes+	 */+	int32_t en_multiple_tx_fifo;++	/** Number of 4-byte words in each of the Tx FIFOs in device+	 * mode when dynamic FIFO sizing is enabled.+	 * 4 to 768 (default 256)+	 */+	uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];++	/** Thresholding enable flag-+	 * bit 0 - enable non-ISO Tx thresholding+	 * bit 1 - enable ISO Tx thresholding+	 * bit 2 - enable Rx thresholding+	 */+	uint32_t thr_ctl;++	/** Thresholding length for Tx+	 *	FIFOs in 32 bit DWORDs+	 */+	uint32_t tx_thr_length;++	/** Thresholding length for Rx+	 *	FIFOs in 32 bit DWORDs+	 */+	uint32_t rx_thr_length;++	/**+	 * Specifies whether LPM (Link Power Management) support is enabled+	 */+	int32_t lpm_enable;++	/** Per Transfer Interrupt+	 *	mode enable flag+	 * 1 - Enabled+	 * 0 - Disabled+	 */+	int32_t pti_enable;++	/** Multi Processor Interrupt+	 *	mode enable flag+	 * 1 - Enabled+	 * 0 - Disabled+	 */+	int32_t mpi_enable;++	/** IS_USB Capability+	 * 1 - Enabled+	 * 0 - Disabled+	 */+	int32_t ic_usb_cap;++	/** AHB Threshold Ratio+	 * 2'b00 AHB Threshold = 	MAC Threshold+	 * 2'b01 AHB Threshold = 1/2 	MAC Threshold+	 * 2'b10 AHB Threshold = 1/4	MAC Threshold+	 * 2'b11 AHB Threshold = 1/8	MAC Threshold+	 */+	int32_t ahb_thr_ratio;++	/** ADP Support+	 * 1 - Enabled+	 * 0 - Disabled+	 */+	int32_t adp_supp_enable;++	/** HFIR Reload Control+	 * 0 - The HFIR cannot be reloaded dynamically.+	 * 1 - Allow dynamic reloading of the HFIR register during runtime.+	 */+	int32_t reload_ctl;++	/** DCFG: Enable device Out NAK+	 * 0 - The core does not set NAK after Bulk Out transfer complete.+	 * 1 - The core sets NAK after Bulk OUT transfer complete.+	 */+	int32_t dev_out_nak;++	/** DCFG: Enable Continue on BNA+	 * After receiving BNA interrupt the core disables the endpoint,when the+	 * endpoint is re-enabled by the application the core starts processing+	 * 0 - from the DOEPDMA descriptor+	 * 1 - from the descriptor which received the BNA.+	 */+	int32_t cont_on_bna;++	/** GAHBCFG: AHB Single Support+	 * This bit when programmed supports SINGLE transfers for remainder+	 * data in a transfer for DMA mode of operation.+	 * 0 - in this case the remainder data will be sent using INCR burst size.+	 * 1 - in this case the remainder data will be sent using SINGLE burst size.+	 */+	int32_t ahb_single;++	/** Core Power down mode+	 * 0 - No Power Down is enabled+	 * 1 - Reserved+	 * 2 - Complete Power Down (Hibernation)+	 */+	int32_t power_down;++	/** OTG revision supported+	 * 0 - OTG 1.3 revision+	 * 1 - OTG 2.0 revision+	 */+	int32_t otg_ver;++} dwc_otg_core_params_t;++#ifdef DEBUG+struct dwc_otg_core_if;+typedef struct hc_xfer_info {+	struct dwc_otg_core_if *core_if;+	dwc_hc_t *hc;+} hc_xfer_info_t;+#endif++typedef struct ep_xfer_info {+	struct dwc_otg_core_if *core_if;+	dwc_ep_t *ep;+	uint8_t state;+} ep_xfer_info_t;+/*+ * Device States+ */+typedef enum dwc_otg_lx_state {+	/** On state */+	DWC_OTG_L0,+	/** LPM sleep state*/+	DWC_OTG_L1,+	/** USB suspend state*/+	DWC_OTG_L2,+	/** Off state*/+	DWC_OTG_L3+} dwc_otg_lx_state_e;++struct dwc_otg_global_regs_backup {+	uint32_t gotgctl_local;+	uint32_t gintmsk_local;+	uint32_t gahbcfg_local;+	uint32_t gusbcfg_local;+	uint32_t grxfsiz_local;+	uint32_t gnptxfsiz_local;+#ifdef CONFIG_USB_DWC_OTG_LPM+	uint32_t glpmcfg_local;+#endif+	uint32_t gi2cctl_local;+	uint32_t hptxfsiz_local;+	uint32_t pcgcctl_local;+	uint32_t gdfifocfg_local;+	uint32_t dtxfsiz_local[MAX_EPS_CHANNELS];+	uint32_t gpwrdn_local;+	uint32_t xhib_pcgcctl;+	uint32_t xhib_gpwrdn;+};++struct dwc_otg_host_regs_backup {+	uint32_t hcfg_local;+	uint32_t haintmsk_local;+	uint32_t hcintmsk_local[MAX_EPS_CHANNELS];+	uint32_t hprt0_local;+	uint32_t hfir_local;+};++struct dwc_otg_dev_regs_backup {+	uint32_t dcfg;+	uint32_t dctl;+	uint32_t daintmsk;+	uint32_t diepmsk;+	uint32_t doepmsk;+	uint32_t diepctl[MAX_EPS_CHANNELS];+	uint32_t dieptsiz[MAX_EPS_CHANNELS];+	uint32_t diepdma[MAX_EPS_CHANNELS];+};+/**+ * The <code>dwc_otg_core_if</code> structure contains information needed to manage+ * the DWC_otg controller acting in either host or device mode. It+ * represents the programming view of the controller as a whole.+ */+struct dwc_otg_core_if {+	/** Parameters that define how the core should be configured.*/+	dwc_otg_core_params_t *core_params;++	/** Core Global registers starting at offset 000h. */+	dwc_otg_core_global_regs_t *core_global_regs;++	/** Device-specific information */+	dwc_otg_dev_if_t *dev_if;+	/** Host-specific information */+	dwc_otg_host_if_t *host_if;++	/** Value from SNPSID register */+	uint32_t snpsid;++	/*+	 * Set to 1 if the core PHY interface bits in USBCFG have been+	 * initialized.+	 */+	uint8_t phy_init_done;++	/*+	 * SRP Success flag, set by srp success interrupt in FS I2C mode+	 */+	uint8_t srp_success;+	uint8_t srp_timer_started;+	/** Timer for SRP. If it expires before SRP is successful+	 * clear the SRP. */+	dwc_timer_t *srp_timer;++#ifdef DWC_DEV_SRPCAP+	/* This timer is needed to power on the hibernated host core if SRP is not+	 * initiated on connected SRP capable device for limited period of time+	 */+	uint8_t pwron_timer_started;+	dwc_timer_t *pwron_timer;+#endif+	/* Common configuration information */+	/** Power and Clock Gating Control Register */+	volatile uint32_t *pcgcctl;+#define DWC_OTG_PCGCCTL_OFFSET 0xE00++	/** Push/pop addresses for endpoints or host channels.*/+	uint32_t *data_fifo[MAX_EPS_CHANNELS];+#define DWC_OTG_DATA_FIFO_OFFSET 0x1000+#define DWC_OTG_DATA_FIFO_SIZE 0x1000++	/** Total RAM for FIFOs (Bytes) */+	uint16_t total_fifo_size;+	/** Size of Rx FIFO (Bytes) */+	uint16_t rx_fifo_size;+	/** Size of Non-periodic Tx FIFO (Bytes) */+	uint16_t nperio_tx_fifo_size;++	/** 1 if DMA is enabled, 0 otherwise. */+	uint8_t dma_enable;++	/** 1 if DMA descriptor is enabled, 0 otherwise. */+	uint8_t dma_desc_enable;++	/** 1 if PTI Enhancement mode is enabled, 0 otherwise. */+	uint8_t pti_enh_enable;++	/** 1 if MPI Enhancement mode is enabled, 0 otherwise. */+	uint8_t multiproc_int_enable;++	/** 1 if dedicated Tx FIFOs are enabled, 0 otherwise. */+	uint8_t en_multiple_tx_fifo;++	/** Set to 1 if multiple packets of a high-bandwidth transfer is in+	 * process of being queued */+	uint8_t queuing_high_bandwidth;++	/** Hardware Configuration -- stored here for convenience.*/+	hwcfg1_data_t hwcfg1;+	hwcfg2_data_t hwcfg2;+	hwcfg3_data_t hwcfg3;+	hwcfg4_data_t hwcfg4;+	fifosize_data_t hptxfsiz;++	/** Host and Device Configuration -- stored here for convenience.*/+	hcfg_data_t hcfg;+	dcfg_data_t dcfg;++	/** The operational State, during transations+	 * (a_host>>a_peripherial and b_device=>b_host) this may not+	 * match the core but allows the software to determine+	 * transitions.+	 */+	uint8_t op_state;++	/**+	 * Set to 1 if the HCD needs to be restarted on a session request+	 * interrupt. This is required if no connector ID status change has+	 * occurred since the HCD was last disconnected.+	 */+	uint8_t restart_hcd_on_session_req;++	/** HCD callbacks */+	/** A-Device is a_host */+#define A_HOST		(1)+	/** A-Device is a_suspend */+#define A_SUSPEND	(2)+	/** A-Device is a_peripherial */+#define A_PERIPHERAL	(3)+	/** B-Device is operating as a Peripheral. */+#define B_PERIPHERAL	(4)+	/** B-Device is operating as a Host. */+#define B_HOST		(5)++	/** HCD callbacks */+	struct dwc_otg_cil_callbacks *hcd_cb;+	/** PCD callbacks */+	struct dwc_otg_cil_callbacks *pcd_cb;++	/** Device mode Periodic Tx FIFO Mask */+	uint32_t p_tx_msk;+	/** Device mode Periodic Tx FIFO Mask */+	uint32_t tx_msk;++	/** Workqueue object used for handling several interrupts */+	dwc_workq_t *wq_otg;++	/** Timer object used for handling "Wakeup Detected" Interrupt */+	dwc_timer_t *wkp_timer;+	/** This arrays used for debug purposes for DEV OUT NAK enhancement */+	uint32_t start_doeptsiz_val[MAX_EPS_CHANNELS];+	ep_xfer_info_t ep_xfer_info[MAX_EPS_CHANNELS];+	dwc_timer_t *ep_xfer_timer[MAX_EPS_CHANNELS];+#ifdef DEBUG+	uint32_t start_hcchar_val[MAX_EPS_CHANNELS];++	hc_xfer_info_t hc_xfer_info[MAX_EPS_CHANNELS];+	dwc_timer_t *hc_xfer_timer[MAX_EPS_CHANNELS];++	uint32_t hfnum_7_samples;+	uint64_t hfnum_7_frrem_accum;+	uint32_t hfnum_0_samples;+	uint64_t hfnum_0_frrem_accum;+	uint32_t hfnum_other_samples;+	uint64_t hfnum_other_frrem_accum;+#endif++#ifdef DWC_UTE_CFI+	uint16_t pwron_rxfsiz;+	uint16_t pwron_gnptxfsiz;+	uint16_t pwron_txfsiz[15];++	uint16_t init_rxfsiz;+	uint16_t init_gnptxfsiz;+	uint16_t init_txfsiz[15];+#endif++	/** Lx state of device */+	dwc_otg_lx_state_e lx_state;++	/** Saved Core Global registers */+	struct dwc_otg_global_regs_backup *gr_backup;+	/** Saved Host registers */+	struct dwc_otg_host_regs_backup *hr_backup;+	/** Saved Device registers */+	struct dwc_otg_dev_regs_backup *dr_backup;++	/** Power Down Enable */+	uint32_t power_down;++	/** ADP support Enable */+	uint32_t adp_enable;++	/** ADP structure object */+	dwc_otg_adp_t adp;++	/** hibernation/suspend flag */+	int hibernation_suspend;++	/** Device mode extended hibernation flag */+	int xhib;++	/** OTG revision supported */+	uint32_t otg_ver;++	/** OTG status flag used for HNP polling */+	uint8_t otg_sts;++	/** Pointer to either hcd->lock or pcd->lock */+	dwc_spinlock_t *lock;++	/** Start predict NextEP based on Learning Queue if equal 1,+	 * also used as counter of disabled NP IN EP's */+	uint8_t start_predict;++	/** NextEp sequence, including EP0: nextep_seq[] = EP if non-periodic and+	 * active, 0xff otherwise */+	uint8_t nextep_seq[MAX_EPS_CHANNELS];++	/** Index of fisrt EP in nextep_seq array which should be re-enabled **/+	uint8_t first_in_nextep_seq;++	/** Frame number while entering to ISR - needed for ISOCs **/+	uint32_t frame_num;++};++#ifdef DEBUG+/*+ * This function is called when transfer is timed out.+ */+extern void hc_xfer_timeout(void *ptr);+#endif++/*+ * This function is called when transfer is timed out on endpoint.+ */+extern void ep_xfer_timeout(void *ptr);++/*+ * The following functions are functions for works+ * using during handling some interrupts+ */+extern void w_conn_id_status_change(void *p);++extern void w_wakeup_detected(void *p);++/** Saves global register values into system memory. */+extern int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if);+/** Saves device register values into system memory. */+extern int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if);+/** Saves host register values into system memory. */+extern int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if);+/** Restore global register values. */+extern int dwc_otg_restore_global_regs(dwc_otg_core_if_t * core_if);+/** Restore host register values. */+extern int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset);+/** Restore device register values. */+extern int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if,+				    int rem_wakeup);+extern int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if);+extern int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode,+				  int is_host);++extern int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if,+					    int restore_mode, int reset);+extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,+					      int rem_wakeup, int reset);++/*+ * The following functions support initialization of the CIL driver component+ * and the DWC_otg controller.+ */+extern void dwc_otg_core_host_init(dwc_otg_core_if_t * _core_if);+extern void dwc_otg_core_dev_init(dwc_otg_core_if_t * _core_if);++/** @name Device CIL Functions+ * The following functions support managing the DWC_otg controller in device+ * mode.+ */+/**@{*/+extern void dwc_otg_wakeup(dwc_otg_core_if_t * _core_if);+extern void dwc_otg_read_setup_packet(dwc_otg_core_if_t * _core_if,+				      uint32_t * _dest);+extern uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * _core_if);+extern void dwc_otg_ep0_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);+extern void dwc_otg_ep_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);+extern void dwc_otg_ep_deactivate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);+extern void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * _core_if,+				      dwc_ep_t * _ep);+extern void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * _core_if,+					 dwc_ep_t * _ep);+extern void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * _core_if,+				       dwc_ep_t * _ep);+extern void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * _core_if,+					  dwc_ep_t * _ep);+extern void dwc_otg_ep_write_packet(dwc_otg_core_if_t * _core_if,+				    dwc_ep_t * _ep, int _dma);+extern void dwc_otg_ep_set_stall(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);+extern void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * _core_if,+				   dwc_ep_t * _ep);+extern void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * _core_if);++#ifdef DWC_EN_ISOC+extern void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if,+					      dwc_ep_t * ep);+extern void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,+					      dwc_ep_t * ep);+#endif /* DWC_EN_ISOC */+/**@}*/++/** @name Host CIL Functions+ * The following functions support managing the DWC_otg controller in host+ * mode.+ */+/**@{*/+extern void dwc_otg_hc_init(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);+extern void dwc_otg_hc_halt(dwc_otg_core_if_t * _core_if,+			    dwc_hc_t * _hc, dwc_otg_halt_status_e _halt_status);+extern void dwc_otg_hc_cleanup(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);+extern void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * _core_if,+				      dwc_hc_t * _hc);+extern int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * _core_if,+					dwc_hc_t * _hc);+extern void dwc_otg_hc_do_ping(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);+extern void dwc_otg_hc_write_packet(dwc_otg_core_if_t * _core_if,+				    dwc_hc_t * _hc);+extern void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * _core_if);+extern void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * _core_if);++extern void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if,+					   dwc_hc_t * hc);++extern uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if);++/* Macro used to clear one channel interrupt */+#define clear_hc_int(_hc_regs_, _intr_) \+do { \+	hcint_data_t hcint_clear = {.d32 = 0}; \+	hcint_clear.b._intr_ = 1; \+	DWC_WRITE_REG32(&(_hc_regs_)->hcint, hcint_clear.d32); \+} while (0)++/*+ * Macro used to disable one channel interrupt. Channel interrupts are+ * disabled when the channel is halted or released by the interrupt handler.+ * There is no need to handle further interrupts of that type until the+ * channel is re-assigned. In fact, subsequent handling may cause crashes+ * because the channel structures are cleaned up when the channel is released.+ */+#define disable_hc_int(_hc_regs_, _intr_) \+do { \+	hcintmsk_data_t hcintmsk = {.d32 = 0}; \+	hcintmsk.b._intr_ = 1; \+	DWC_MODIFY_REG32(&(_hc_regs_)->hcintmsk, hcintmsk.d32, 0); \+} while (0)++/**+ * This function Reads HPRT0 in preparation to modify. It keeps the+ * WC bits 0 so that if they are read as 1, they won't clear when you+ * write it back+ */+static inline uint32_t dwc_otg_read_hprt0(dwc_otg_core_if_t * _core_if)+{+	hprt0_data_t hprt0;+	hprt0.d32 = DWC_READ_REG32(_core_if->host_if->hprt0);+	hprt0.b.prtena = 0;+	hprt0.b.prtconndet = 0;+	hprt0.b.prtenchng = 0;+	hprt0.b.prtovrcurrchng = 0;+	return hprt0.d32;+}++/**@}*/++/** @name Common CIL Functions+ * The following functions support managing the DWC_otg controller in either+ * device or host mode.+ */+/**@{*/++extern void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,+				uint8_t * dest, uint16_t bytes);++extern void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * _core_if, const int _num);+extern void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * _core_if);+extern void dwc_otg_core_reset(dwc_otg_core_if_t * _core_if);++/**+ * This function returns the Core Interrupt register.+ */+static inline uint32_t dwc_otg_read_core_intr(dwc_otg_core_if_t * core_if)+{+	return (DWC_READ_REG32(&core_if->core_global_regs->gintsts) &+		DWC_READ_REG32(&core_if->core_global_regs->gintmsk));+}++/**+ * This function returns the OTG Interrupt register.+ */+static inline uint32_t dwc_otg_read_otg_intr(dwc_otg_core_if_t * core_if)+{+	return (DWC_READ_REG32(&core_if->core_global_regs->gotgint));+}++/**+ * This function reads the Device All Endpoints Interrupt register and+ * returns the IN endpoint interrupt bits.+ */+static inline uint32_t dwc_otg_read_dev_all_in_ep_intr(dwc_otg_core_if_t *+						       core_if)+{++	uint32_t v;++	if (core_if->multiproc_int_enable) {+		v = DWC_READ_REG32(&core_if->dev_if->+				   dev_global_regs->deachint) &+		    DWC_READ_REG32(&core_if->+				   dev_if->dev_global_regs->deachintmsk);+	} else {+		v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &+		    DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);+	}+	return (v & 0xffff);+}++/**+ * This function reads the Device All Endpoints Interrupt register and+ * returns the OUT endpoint interrupt bits.+ */+static inline uint32_t dwc_otg_read_dev_all_out_ep_intr(dwc_otg_core_if_t *+							core_if)+{+	uint32_t v;++	if (core_if->multiproc_int_enable) {+		v = DWC_READ_REG32(&core_if->dev_if->+				   dev_global_regs->deachint) &+		    DWC_READ_REG32(&core_if->+				   dev_if->dev_global_regs->deachintmsk);+	} else {+		v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &+		    DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);+	}++	return ((v & 0xffff0000) >> 16);+}++/**+ * This function returns the Device IN EP Interrupt register+ */+static inline uint32_t dwc_otg_read_dev_in_ep_intr(dwc_otg_core_if_t * core_if,+						   dwc_ep_t * ep)+{+	dwc_otg_dev_if_t *dev_if = core_if->dev_if;+	uint32_t v, msk, emp;++	if (core_if->multiproc_int_enable) {+		msk =+		    DWC_READ_REG32(&dev_if->+				   dev_global_regs->diepeachintmsk[ep->num]);+		emp =+		    DWC_READ_REG32(&dev_if->+				   dev_global_regs->dtknqr4_fifoemptymsk);+		msk |= ((emp >> ep->num) & 0x1) << 7;+		v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;+	} else {+		msk = DWC_READ_REG32(&dev_if->dev_global_regs->diepmsk);+		emp =+		    DWC_READ_REG32(&dev_if->+				   dev_global_regs->dtknqr4_fifoemptymsk);+		msk |= ((emp >> ep->num) & 0x1) << 7;+		v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;+	}++	return v;+}++/**+ * This function returns the Device OUT EP Interrupt register+ */+static inline uint32_t dwc_otg_read_dev_out_ep_intr(dwc_otg_core_if_t *+						    _core_if, dwc_ep_t * _ep)+{+	dwc_otg_dev_if_t *dev_if = _core_if->dev_if;+	uint32_t v;+	doepmsk_data_t msk = {.d32 = 0 };++	if (_core_if->multiproc_int_enable) {+		msk.d32 =+		    DWC_READ_REG32(&dev_if->+				   dev_global_regs->doepeachintmsk[_ep->num]);+		if (_core_if->pti_enh_enable) {+			msk.b.pktdrpsts = 1;+		}+		v = DWC_READ_REG32(&dev_if->+				   out_ep_regs[_ep->num]->doepint) & msk.d32;+	} else {+		msk.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->doepmsk);+		if (_core_if->pti_enh_enable) {+			msk.b.pktdrpsts = 1;+		}+		v = DWC_READ_REG32(&dev_if->+				   out_ep_regs[_ep->num]->doepint) & msk.d32;+	}+	return v;+}++/**+ * This function returns the Host All Channel Interrupt register+ */+static inline uint32_t dwc_otg_read_host_all_channels_intr(dwc_otg_core_if_t *+							   _core_if)+{+	return (DWC_READ_REG32(&_core_if->host_if->host_global_regs->haint));+}++static inline uint32_t dwc_otg_read_host_channel_intr(dwc_otg_core_if_t *+						      _core_if, dwc_hc_t * _hc)+{+	return (DWC_READ_REG32+		(&_core_if->host_if->hc_regs[_hc->hc_num]->hcint));+}++/**+ * This function returns the mode of the operation, host or device.+ *+ * @return 0 - Device Mode, 1 - Host Mode+ */+static inline uint32_t dwc_otg_mode(dwc_otg_core_if_t * _core_if)+{+	return (DWC_READ_REG32(&_core_if->core_global_regs->gintsts) & 0x1);+}++/**@}*/++/**+ * DWC_otg CIL callback structure. This structure allows the HCD and+ * PCD to register functions used for starting and stopping the PCD+ * and HCD for role change on for a DRD.+ */+typedef struct dwc_otg_cil_callbacks {+	/** Start function for role change */+	int (*start) (void *_p);+	/** Stop Function for role change */+	int (*stop) (void *_p);+	/** Disconnect Function for role change */+	int (*disconnect) (void *_p);+	/** Resume/Remote wakeup Function */+	int (*resume_wakeup) (void *_p);+	/** Suspend function */+	int (*suspend) (void *_p);+	/** Session Start (SRP) */+	int (*session_start) (void *_p);+#ifdef CONFIG_USB_DWC_OTG_LPM+	/** Sleep (switch to L0 state) */+	int (*sleep) (void *_p);+#endif+	/** Pointer passed to start() and stop() */+	void *p;+} dwc_otg_cil_callbacks_t;++extern void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * _core_if,+					       dwc_otg_cil_callbacks_t * _cb,+					       void *_p);+extern void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * _core_if,+					       dwc_otg_cil_callbacks_t * _cb,+					       void *_p);++void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if);++//////////////////////////////////////////////////////////////////////+/** Start the HCD.  Helper function for using the HCD callbacks.+ *+ * @param core_if Programming view of DWC_otg controller.+ */+static inline void cil_hcd_start(dwc_otg_core_if_t * core_if)+{+	if (core_if->hcd_cb && core_if->hcd_cb->start) {+		core_if->hcd_cb->start(core_if->hcd_cb->p);+	}+}++/** Stop the HCD.  Helper function for using the HCD callbacks.+ *+ * @param core_if Programming view of DWC_otg controller.+ */+static inline void cil_hcd_stop(dwc_otg_core_if_t * core_if)+{+	if (core_if->hcd_cb && core_if->hcd_cb->stop) {+		core_if->hcd_cb->stop(core_if->hcd_cb->p);+	}+}++/** Disconnect the HCD.  Helper function for using the HCD callbacks.+ *+ * @param core_if Programming view of DWC_otg controller.+ */+static inline void cil_hcd_disconnect(dwc_otg_core_if_t * core_if)+{+	if (core_if->hcd_cb && core_if->hcd_cb->disconnect) {+		core_if->hcd_cb->disconnect(core_if->hcd_cb->p);+	}+}++/** Inform the HCD the a New Session has begun.  Helper function for+ * using the HCD callbacks.+ *+ * @param core_if Programming view of DWC_otg controller.+ */+static inline void cil_hcd_session_start(dwc_otg_core_if_t * core_if)+{+	if (core_if->hcd_cb && core_if->hcd_cb->session_start) {+		core_if->hcd_cb->session_start(core_if->hcd_cb->p);+	}+}++#ifdef CONFIG_USB_DWC_OTG_LPM+/**+ * Inform the HCD about LPM sleep.+ * Helper function for using the HCD callbacks.+ *+ * @param core_if Programming view of DWC_otg controller.+ */+static inline void cil_hcd_sleep(dwc_otg_core_if_t * core_if)+{+	if (core_if->hcd_cb && core_if->hcd_cb->sleep) {+		core_if->hcd_cb->sleep(core_if->hcd_cb->p);+	}+}+#endif++/** Resume the HCD.  Helper function for using the HCD callbacks.+ *+ * @param core_if Programming view of DWC_otg controller.+ */+static inline void cil_hcd_resume(dwc_otg_core_if_t * core_if)+{+	if (core_if->hcd_cb && core_if->hcd_cb->resume_wakeup) {+		core_if->hcd_cb->resume_wakeup(core_if->hcd_cb->p);+	}+}++/** Start the PCD.  Helper function for using the PCD callbacks.+ *+ * @param core_if Programming view of DWC_otg controller.+ */+static inline void cil_pcd_start(dwc_otg_core_if_t * core_if)+{+	if (core_if->pcd_cb && core_if->pcd_cb->start) {+		core_if->pcd_cb->start(core_if->pcd_cb->p);+	}+}++/** Stop the PCD.  Helper function for using the PCD callbacks.+ *+ * @param core_if Programming view of DWC_otg controller.+ */+static inline void cil_pcd_stop(dwc_otg_core_if_t * core_if)+{+	if (core_if->pcd_cb && core_if->pcd_cb->stop) {+		core_if->pcd_cb->stop(core_if->pcd_cb->p);+	}+}++/** Suspend the PCD.  Helper function for using the PCD callbacks.+ *+ * @param core_if Programming view of DWC_otg controller.+ */+static inline void cil_pcd_suspend(dwc_otg_core_if_t * core_if)+{+	if (core_if->pcd_cb && core_if->pcd_cb->suspend) {+		core_if->pcd_cb->suspend(core_if->pcd_cb->p);+	}+}++/** Resume the PCD.  Helper function for using the PCD callbacks.+ *+ * @param core_if Programming view of DWC_otg controller.+ */+static inline void cil_pcd_resume(dwc_otg_core_if_t * core_if)+{+	if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {+		core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);+	}+}++//////////////////////////////////////////////////////////////////////++#endifdiff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,1588 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $+ * $Revision: #32 $+ * $Date: 2012/08/10 $+ * $Change: 2047372 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */++/** @file+ *+ * The Core Interface Layer provides basic services for accessing and+ * managing the DWC_otg hardware. These services are used by both the+ * Host Controller Driver and the Peripheral Controller Driver.+ *+ * This file contains the Common Interrupt handlers.+ */+#include "dwc_os.h"+#include "dwc_otg_regs.h"+#include "dwc_otg_cil.h"+#include "dwc_otg_driver.h"+#include "dwc_otg_pcd.h"+#include "dwc_otg_hcd.h"+#include "dwc_otg_mphi_fix.h"++#ifdef DEBUG+inline const char *op_state_str(dwc_otg_core_if_t * core_if)+{+	return (core_if->op_state == A_HOST ? "a_host" :+		(core_if->op_state == A_SUSPEND ? "a_suspend" :+		 (core_if->op_state == A_PERIPHERAL ? "a_peripheral" :+		  (core_if->op_state == B_PERIPHERAL ? "b_peripheral" :+		   (core_if->op_state == B_HOST ? "b_host" : "unknown")))));+}+#endif++/** This function will log a debug message+ *+ * @param core_if Programming view of DWC_otg controller.+ */+int32_t dwc_otg_handle_mode_mismatch_intr(dwc_otg_core_if_t * core_if)+{+	gintsts_data_t gintsts;+	DWC_WARN("Mode Mismatch Interrupt: currently in %s mode\n",+		 dwc_otg_mode(core_if) ? "Host" : "Device");++	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.modemismatch = 1;+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);+	return 1;+}++/**+ * This function handles the OTG Interrupts. It reads the OTG+ * Interrupt Register (GOTGINT) to determine what interrupt has+ * occurred.+ *+ * @param core_if Programming view of DWC_otg controller.+ */+int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if)+{+	dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;+	gotgint_data_t gotgint;+	gotgctl_data_t gotgctl;+	gintmsk_data_t gintmsk;+	gpwrdn_data_t gpwrdn;++	gotgint.d32 = DWC_READ_REG32(&global_regs->gotgint);+	gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);+	DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32,+		    op_state_str(core_if));++	if (gotgint.b.sesenddet) {+		DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "+			    "Session End Detected++ (%s)\n",+			    op_state_str(core_if));+		gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);++		if (core_if->op_state == B_HOST) {+			cil_pcd_start(core_if);+			core_if->op_state = B_PERIPHERAL;+		} else {+			/* If not B_HOST and Device HNP still set. HNP+			 * Did not succeed!*/+			if (gotgctl.b.devhnpen) {+				DWC_DEBUGPL(DBG_ANY, "Session End Detected\n");+				__DWC_ERROR("Device Not Connected/Responding!\n");+			}++			/* If Session End Detected the B-Cable has+			 * been disconnected. */+			/* Reset PCD and Gadget driver to a+			 * clean state. */+			core_if->lx_state = DWC_OTG_L0;+			DWC_SPINUNLOCK(core_if->lock);+			cil_pcd_stop(core_if);+			DWC_SPINLOCK(core_if->lock);++			if (core_if->adp_enable) {+				if (core_if->power_down == 2) {+					gpwrdn.d32 = 0;+					gpwrdn.b.pwrdnswtch = 1;+					DWC_MODIFY_REG32(&core_if->+							 core_global_regs->+							 gpwrdn, gpwrdn.d32, 0);+				}++				gpwrdn.d32 = 0;+				gpwrdn.b.pmuintsel = 1;+				gpwrdn.b.pmuactv = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, 0, gpwrdn.d32);++				dwc_otg_adp_sense_start(core_if);+			}+		}++		gotgctl.d32 = 0;+		gotgctl.b.devhnpen = 1;+		DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);+	}+	if (gotgint.b.sesreqsucstschng) {+		DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "+			    "Session Reqeust Success Status Change++\n");+		gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);+		if (gotgctl.b.sesreqscs) {++			if ((core_if->core_params->phy_type ==+			     DWC_PHY_TYPE_PARAM_FS) && (core_if->core_params->i2c_enable)) {+				core_if->srp_success = 1;+			} else {+				DWC_SPINUNLOCK(core_if->lock);+				cil_pcd_resume(core_if);+				DWC_SPINLOCK(core_if->lock);+				/* Clear Session Request */+				gotgctl.d32 = 0;+				gotgctl.b.sesreq = 1;+				DWC_MODIFY_REG32(&global_regs->gotgctl,+						 gotgctl.d32, 0);+			}+		}+	}+	if (gotgint.b.hstnegsucstschng) {+		/* Print statements during the HNP interrupt handling+		 * can cause it to fail.*/+		gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);+		/* WA for 3.00a- HW is not setting cur_mode, even sometimes+		 * this does not help*/+		if (core_if->snpsid >= OTG_CORE_REV_3_00a)+			dwc_udelay(100);+		if (gotgctl.b.hstnegscs) {+			if (dwc_otg_is_host_mode(core_if)) {+				core_if->op_state = B_HOST;+				/*+				 * Need to disable SOF interrupt immediately.+				 * When switching from device to host, the PCD+				 * interrupt handler won't handle the+				 * interrupt if host mode is already set. The+				 * HCD interrupt handler won't get called if+				 * the HCD state is HALT. This means that the+				 * interrupt does not get handled and Linux+				 * complains loudly.+				 */+				gintmsk.d32 = 0;+				gintmsk.b.sofintr = 1;+				DWC_MODIFY_REG32(&global_regs->gintmsk,+						 gintmsk.d32, 0);+				/* Call callback function with spin lock released */+				DWC_SPINUNLOCK(core_if->lock);+				cil_pcd_stop(core_if);+				/*+				 * Initialize the Core for Host mode.+				 */+				cil_hcd_start(core_if);+				DWC_SPINLOCK(core_if->lock);+				core_if->op_state = B_HOST;+			}+		} else {+			gotgctl.d32 = 0;+			gotgctl.b.hnpreq = 1;+			gotgctl.b.devhnpen = 1;+			DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);+			DWC_DEBUGPL(DBG_ANY, "HNP Failed\n");+			__DWC_ERROR("Device Not Connected/Responding\n");+		}+	}+	if (gotgint.b.hstnegdet) {+		/* The disconnect interrupt is set at the same time as+		 * Host Negotiation Detected.  During the mode+		 * switch all interrupts are cleared so the disconnect+		 * interrupt handler will not get executed.+		 */+		DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "+			    "Host Negotiation Detected++ (%s)\n",+			    (dwc_otg_is_host_mode(core_if) ? "Host" :+			     "Device"));+		if (dwc_otg_is_device_mode(core_if)) {+			DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n",+				    core_if->op_state);+			DWC_SPINUNLOCK(core_if->lock);+			cil_hcd_disconnect(core_if);+			cil_pcd_start(core_if);+			DWC_SPINLOCK(core_if->lock);+			core_if->op_state = A_PERIPHERAL;+		} else {+			/*+			 * Need to disable SOF interrupt immediately. When+			 * switching from device to host, the PCD interrupt+			 * handler won't handle the interrupt if host mode is+			 * already set. The HCD interrupt handler won't get+			 * called if the HCD state is HALT. This means that+			 * the interrupt does not get handled and Linux+			 * complains loudly.+			 */+			gintmsk.d32 = 0;+			gintmsk.b.sofintr = 1;+			DWC_MODIFY_REG32(&global_regs->gintmsk, gintmsk.d32, 0);+			DWC_SPINUNLOCK(core_if->lock);+			cil_pcd_stop(core_if);+			cil_hcd_start(core_if);+			DWC_SPINLOCK(core_if->lock);+			core_if->op_state = A_HOST;+		}+	}+	if (gotgint.b.adevtoutchng) {+		DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "+			    "A-Device Timeout Change++\n");+	}+	if (gotgint.b.debdone) {+		DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Debounce Done++\n");+	}++	/* Clear GOTGINT */+	DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, gotgint.d32);++	return 1;+}++void w_conn_id_status_change(void *p)+{+	dwc_otg_core_if_t *core_if = p;+	uint32_t count = 0;+	gotgctl_data_t gotgctl = {.d32 = 0 };++	gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);+	DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32);+	DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts);++	/* B-Device connector (Device Mode) */+	if (gotgctl.b.conidsts) {+		/* Wait for switch to device mode. */+		while (!dwc_otg_is_device_mode(core_if)) {+			DWC_PRINTF("Waiting for Peripheral Mode, Mode=%s\n",+				   (dwc_otg_is_host_mode(core_if) ? "Host" :+				    "Peripheral"));+			dwc_mdelay(100);+			if (++count > 10000)+				break;+		}+		DWC_ASSERT(++count < 10000,+			   "Connection id status change timed out");+		core_if->op_state = B_PERIPHERAL;+		dwc_otg_core_init(core_if);+		dwc_otg_enable_global_interrupts(core_if);+		cil_pcd_start(core_if);+	} else {+		/* A-Device connector (Host Mode) */+		while (!dwc_otg_is_host_mode(core_if)) {+			DWC_PRINTF("Waiting for Host Mode, Mode=%s\n",+				   (dwc_otg_is_host_mode(core_if) ? "Host" :+				    "Peripheral"));+			dwc_mdelay(100);+			if (++count > 10000)+				break;+		}+		DWC_ASSERT(++count < 10000,+			   "Connection id status change timed out");+		core_if->op_state = A_HOST;+		/*+		 * Initialize the Core for Host mode.+		 */+		dwc_otg_core_init(core_if);+		dwc_otg_enable_global_interrupts(core_if);+		cil_hcd_start(core_if);+	}+}++/**+ * This function handles the Connector ID Status Change Interrupt.  It+ * reads the OTG Interrupt Register (GOTCTL) to determine whether this+ * is a Device to Host Mode transition or a Host Mode to Device+ * Transition.+ *+ * This only occurs when the cable is connected/removed from the PHY+ * connector.+ *+ * @param core_if Programming view of DWC_otg controller.+ */+int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t * core_if)+{++	/*+	 * Need to disable SOF interrupt immediately. If switching from device+	 * to host, the PCD interrupt handler won't handle the interrupt if+	 * host mode is already set. The HCD interrupt handler won't get+	 * called if the HCD state is HALT. This means that the interrupt does+	 * not get handled and Linux complains loudly.+	 */+	gintmsk_data_t gintmsk = {.d32 = 0 };+	gintsts_data_t gintsts = {.d32 = 0 };++	gintmsk.b.sofintr = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);++	DWC_DEBUGPL(DBG_CIL,+		    " ++Connector ID Status Change Interrupt++  (%s)\n",+		    (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"));++	DWC_SPINUNLOCK(core_if->lock);++	/*+	 * Need to schedule a work, as there are possible DELAY function calls+	 * Release lock before scheduling workq as it holds spinlock during scheduling+	 */++	DWC_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change,+			   core_if, "connection id status change");+	DWC_SPINLOCK(core_if->lock);++	/* Set flag and clear interrupt */+	gintsts.b.conidstschng = 1;+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);++	return 1;+}++/**+ * This interrupt indicates that a device is initiating the Session+ * Request Protocol to request the host to turn on bus power so a new+ * session can begin. The handler responds by turning on bus power. If+ * the DWC_otg controller is in low power mode, the handler brings the+ * controller out of low power mode before turning on bus power.+ *+ * @param core_if Programming view of DWC_otg controller.+ */+int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t * core_if)+{+	gintsts_data_t gintsts;++#ifndef DWC_HOST_ONLY+	DWC_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n");++	if (dwc_otg_is_device_mode(core_if)) {+		DWC_PRINTF("SRP: Device mode\n");+	} else {+		hprt0_data_t hprt0;+		DWC_PRINTF("SRP: Host mode\n");++		/* Turn on the port power bit. */+		hprt0.d32 = dwc_otg_read_hprt0(core_if);+		hprt0.b.prtpwr = 1;+		DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);++		/* Start the Connection timer. So a message can be displayed+		 * if connect does not occur within 10 seconds. */+		cil_hcd_session_start(core_if);+	}+#endif++	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.sessreqintr = 1;+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);++	return 1;+}++void w_wakeup_detected(void *p)+{+	dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) p;+	/*+	 * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms+	 * so that OPT tests pass with all PHYs).+	 */+	hprt0_data_t hprt0 = {.d32 = 0 };+#if 0+	pcgcctl_data_t pcgcctl = {.d32 = 0 };+	/* Restart the Phy Clock */+	pcgcctl.b.stoppclk = 1;+	DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);+	dwc_udelay(10);+#endif //0+	hprt0.d32 = dwc_otg_read_hprt0(core_if);+	DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32);+//      dwc_mdelay(70);+	hprt0.b.prtres = 0;	/* Resume */+	DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+	DWC_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n",+		    DWC_READ_REG32(core_if->host_if->hprt0));++	cil_hcd_resume(core_if);++	/** Change to L0 state*/+	core_if->lx_state = DWC_OTG_L0;+}++/**+ * This interrupt indicates that the DWC_otg controller has detected a+ * resume or remote wakeup sequence. If the DWC_otg controller is in+ * low power mode, the handler must brings the controller out of low+ * power mode. The controller automatically begins resume+ * signaling. The handler schedules a time to stop resume signaling.+ */+int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if)+{+	gintsts_data_t gintsts;++	DWC_DEBUGPL(DBG_ANY,+		    "++Resume and Remote Wakeup Detected Interrupt++\n");++	DWC_PRINTF("%s lxstate = %d\n", __func__, core_if->lx_state);++	if (dwc_otg_is_device_mode(core_if)) {+		dctl_data_t dctl = {.d32 = 0 };+		DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n",+			    DWC_READ_REG32(&core_if->dev_if->dev_global_regs->+					   dsts));+		if (core_if->lx_state == DWC_OTG_L2) {+#ifdef PARTIAL_POWER_DOWN+			if (core_if->hwcfg4.b.power_optimiz) {+				pcgcctl_data_t power = {.d32 = 0 };++				power.d32 = DWC_READ_REG32(core_if->pcgcctl);+				DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n",+					    power.d32);++				power.b.stoppclk = 0;+				DWC_WRITE_REG32(core_if->pcgcctl, power.d32);++				power.b.pwrclmp = 0;+				DWC_WRITE_REG32(core_if->pcgcctl, power.d32);++				power.b.rstpdwnmodule = 0;+				DWC_WRITE_REG32(core_if->pcgcctl, power.d32);+			}+#endif+			/* Clear the Remote Wakeup Signaling */+			dctl.b.rmtwkupsig = 1;+			DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->+					 dctl, dctl.d32, 0);++			DWC_SPINUNLOCK(core_if->lock);+			if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {+				core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);+			}+			DWC_SPINLOCK(core_if->lock);+		} else {+			glpmcfg_data_t lpmcfg;+			lpmcfg.d32 =+			    DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);+			lpmcfg.b.hird_thres &= (~(1 << 4));+			DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,+					lpmcfg.d32);+		}+		/** Change to L0 state*/+		core_if->lx_state = DWC_OTG_L0;+	} else {+		if (core_if->lx_state != DWC_OTG_L1) {+			pcgcctl_data_t pcgcctl = {.d32 = 0 };++			/* Restart the Phy Clock */+			pcgcctl.b.stoppclk = 1;+			DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);+			DWC_TIMER_SCHEDULE(core_if->wkp_timer, 71);+		} else {+			/** Change to L0 state*/+			core_if->lx_state = DWC_OTG_L0;+		}+	}++	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.wkupintr = 1;+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);++	return 1;+}++/**+ * This interrupt indicates that the Wakeup Logic has detected a+ * Device disconnect.+ */+static int32_t dwc_otg_handle_pwrdn_disconnect_intr(dwc_otg_core_if_t *core_if)+{+	gpwrdn_data_t gpwrdn = { .d32 = 0 };+	gpwrdn_data_t gpwrdn_temp = { .d32 = 0 };+	gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);++	DWC_PRINTF("%s called\n", __FUNCTION__);++	if (!core_if->hibernation_suspend) {+		DWC_PRINTF("Already exited from Hibernation\n");+		return 1;+	}++	/* Switch on the voltage to the core */+	gpwrdn.b.pwrdnswtch = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+	dwc_udelay(10);++	/* Reset the core */+	gpwrdn.d32 = 0;+	gpwrdn.b.pwrdnrstn = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+	dwc_udelay(10);++	/* Disable power clamps*/+	gpwrdn.d32 = 0;+	gpwrdn.b.pwrdnclmp = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++	/* Remove reset the core signal */+	gpwrdn.d32 = 0;+	gpwrdn.b.pwrdnrstn = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);+	dwc_udelay(10);++	/* Disable PMU interrupt */+	gpwrdn.d32 = 0;+	gpwrdn.b.pmuintsel = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++	core_if->hibernation_suspend = 0;++	/* Disable PMU */+	gpwrdn.d32 = 0;+	gpwrdn.b.pmuactv = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+	dwc_udelay(10);++	if (gpwrdn_temp.b.idsts) {+		core_if->op_state = B_PERIPHERAL;+		dwc_otg_core_init(core_if);+		dwc_otg_enable_global_interrupts(core_if);+		cil_pcd_start(core_if);+	} else {+		core_if->op_state = A_HOST;+		dwc_otg_core_init(core_if);+		dwc_otg_enable_global_interrupts(core_if);+		cil_hcd_start(core_if);+	}++	return 1;+}++/**+ * This interrupt indicates that the Wakeup Logic has detected a+ * remote wakeup sequence.+ */+static int32_t dwc_otg_handle_pwrdn_wakeup_detected_intr(dwc_otg_core_if_t * core_if)+{+	gpwrdn_data_t gpwrdn = {.d32 = 0 };+	DWC_DEBUGPL(DBG_ANY,+		    "++Powerdown Remote Wakeup Detected Interrupt++\n");++	if (!core_if->hibernation_suspend) {+		DWC_PRINTF("Already exited from Hibernation\n");+		return 1;+	}++	gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);+	if (gpwrdn.b.idsts) {	// Device Mode+		if ((core_if->power_down == 2)+		    && (core_if->hibernation_suspend == 1)) {+			dwc_otg_device_hibernation_restore(core_if, 0, 0);+		}+	} else {+		if ((core_if->power_down == 2)+		    && (core_if->hibernation_suspend == 1)) {+			dwc_otg_host_hibernation_restore(core_if, 1, 0);+		}+	}+	return 1;+}++static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_device_t *otg_dev)+{+	gpwrdn_data_t gpwrdn = {.d32 = 0 };+	gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };+	dwc_otg_core_if_t *core_if = otg_dev->core_if;++	DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);+	gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);+	if (core_if->power_down == 2) {+		if (!core_if->hibernation_suspend) {+			DWC_PRINTF("Already exited from Hibernation\n");+			return 1;+		}+		DWC_DEBUGPL(DBG_ANY, "Exit from hibernation on ID sts change\n");+		/* Switch on the voltage to the core */+		gpwrdn.b.pwrdnswtch = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+		dwc_udelay(10);++		/* Reset the core */+		gpwrdn.d32 = 0;+		gpwrdn.b.pwrdnrstn = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+		dwc_udelay(10);++		/* Disable power clamps */+		gpwrdn.d32 = 0;+		gpwrdn.b.pwrdnclmp = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++		/* Remove reset the core signal */+		gpwrdn.d32 = 0;+		gpwrdn.b.pwrdnrstn = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);+		dwc_udelay(10);++		/* Disable PMU interrupt */+		gpwrdn.d32 = 0;+		gpwrdn.b.pmuintsel = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++		/*Indicates that we are exiting from hibernation */+		core_if->hibernation_suspend = 0;++		/* Disable PMU */+		gpwrdn.d32 = 0;+		gpwrdn.b.pmuactv = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+		dwc_udelay(10);++		gpwrdn.d32 = core_if->gr_backup->gpwrdn_local;+		if (gpwrdn.b.dis_vbus == 1) {+			gpwrdn.d32 = 0;+			gpwrdn.b.dis_vbus = 1;+			DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+		}++		if (gpwrdn_temp.b.idsts) {+			core_if->op_state = B_PERIPHERAL;+			dwc_otg_core_init(core_if);+			dwc_otg_enable_global_interrupts(core_if);+			cil_pcd_start(core_if);+		} else {+			core_if->op_state = A_HOST;+			dwc_otg_core_init(core_if);+			dwc_otg_enable_global_interrupts(core_if);+			cil_hcd_start(core_if);+		}+	}++	if (core_if->adp_enable) {+		uint8_t is_host = 0;+		DWC_SPINUNLOCK(core_if->lock);+		/* Change the core_if's lock to hcd/pcd lock depend on mode? */+#ifndef DWC_HOST_ONLY+		if (gpwrdn_temp.b.idsts)+			core_if->lock = otg_dev->pcd->lock;+#endif+#ifndef DWC_DEVICE_ONLY+		if (!gpwrdn_temp.b.idsts) {+				core_if->lock = otg_dev->hcd->lock;+				is_host = 1;+		}+#endif+		DWC_PRINTF("RESTART ADP\n");+		if (core_if->adp.probe_enabled)+			dwc_otg_adp_probe_stop(core_if);+		if (core_if->adp.sense_enabled)+			dwc_otg_adp_sense_stop(core_if);+		if (core_if->adp.sense_timer_started)+			DWC_TIMER_CANCEL(core_if->adp.sense_timer);+		if (core_if->adp.vbuson_timer_started)+			DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);+		core_if->adp.probe_timer_values[0] = -1;+		core_if->adp.probe_timer_values[1] = -1;+		core_if->adp.sense_timer_started = 0;+		core_if->adp.vbuson_timer_started = 0;+		core_if->adp.probe_counter = 0;+		core_if->adp.gpwrdn = 0;++		/* Disable PMU and restart ADP */+		gpwrdn_temp.d32 = 0;+		gpwrdn_temp.b.pmuactv = 1;+		gpwrdn_temp.b.pmuintsel = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+		DWC_PRINTF("Check point 1\n");+		dwc_mdelay(110);+		dwc_otg_adp_start(core_if, is_host);+		DWC_SPINLOCK(core_if->lock);+	}+++	return 1;+}++static int32_t dwc_otg_handle_pwrdn_session_change(dwc_otg_core_if_t * core_if)+{+	gpwrdn_data_t gpwrdn = {.d32 = 0 };+	int32_t otg_cap_param = core_if->core_params->otg_cap;+	DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);++	gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);+	if (core_if->power_down == 2) {+		if (!core_if->hibernation_suspend) {+			DWC_PRINTF("Already exited from Hibernation\n");+			return 1;+		}++		if ((otg_cap_param != DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||+			 otg_cap_param != DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) &&+			gpwrdn.b.bsessvld == 0) {+			/* Save gpwrdn register for further usage if stschng interrupt */+			core_if->gr_backup->gpwrdn_local =+				DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);+			/*Exit from ISR and wait for stschng interrupt with bsessvld = 1 */+			return 1;+		}++		/* Switch on the voltage to the core */+		gpwrdn.d32 = 0;+		gpwrdn.b.pwrdnswtch = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+		dwc_udelay(10);++		/* Reset the core */+		gpwrdn.d32 = 0;+		gpwrdn.b.pwrdnrstn = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+		dwc_udelay(10);++		/* Disable power clamps */+		gpwrdn.d32 = 0;+		gpwrdn.b.pwrdnclmp = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++		/* Remove reset the core signal */+		gpwrdn.d32 = 0;+		gpwrdn.b.pwrdnrstn = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);+		dwc_udelay(10);++		/* Disable PMU interrupt */+		gpwrdn.d32 = 0;+		gpwrdn.b.pmuintsel = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+		dwc_udelay(10);++		/*Indicates that we are exiting from hibernation */+		core_if->hibernation_suspend = 0;++		/* Disable PMU */+		gpwrdn.d32 = 0;+		gpwrdn.b.pmuactv = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+		dwc_udelay(10);++		core_if->op_state = B_PERIPHERAL;+		dwc_otg_core_init(core_if);+		dwc_otg_enable_global_interrupts(core_if);+		cil_pcd_start(core_if);++		if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||+			otg_cap_param == DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) {+			/*+			 * Initiate SRP after initial ADP probe.+			 */+			dwc_otg_initiate_srp(core_if);+		}+	}++	return 1;+}+/**+ * This interrupt indicates that the Wakeup Logic has detected a+ * status change either on IDDIG or BSessVld.+ */+static uint32_t dwc_otg_handle_pwrdn_stschng_intr(dwc_otg_device_t *otg_dev)+{+	int retval;+	gpwrdn_data_t gpwrdn = {.d32 = 0 };+	gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };+	dwc_otg_core_if_t *core_if = otg_dev->core_if;++	DWC_PRINTF("%s called\n", __FUNCTION__);++	if (core_if->power_down == 2) {+		if (core_if->hibernation_suspend <= 0) {+			DWC_PRINTF("Already exited from Hibernation\n");+			return 1;+		} else+			gpwrdn_temp.d32 = core_if->gr_backup->gpwrdn_local;++	} else {+		gpwrdn_temp.d32 = core_if->adp.gpwrdn;+	}++	gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);++	if (gpwrdn.b.idsts ^ gpwrdn_temp.b.idsts) {+		retval = dwc_otg_handle_pwrdn_idsts_change(otg_dev);+	} else if (gpwrdn.b.bsessvld ^ gpwrdn_temp.b.bsessvld) {+		retval = dwc_otg_handle_pwrdn_session_change(core_if);+	}++	return retval;+}++/**+ * This interrupt indicates that the Wakeup Logic has detected a+ * SRP.+ */+static int32_t dwc_otg_handle_pwrdn_srp_intr(dwc_otg_core_if_t * core_if)+{+	gpwrdn_data_t gpwrdn = {.d32 = 0 };++	DWC_PRINTF("%s called\n", __FUNCTION__);++	if (!core_if->hibernation_suspend) {+		DWC_PRINTF("Already exited from Hibernation\n");+		return 1;+	}+#ifdef DWC_DEV_SRPCAP+	if (core_if->pwron_timer_started) {+		core_if->pwron_timer_started = 0;+		DWC_TIMER_CANCEL(core_if->pwron_timer);+	}+#endif++	/* Switch on the voltage to the core */+	gpwrdn.b.pwrdnswtch = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+	dwc_udelay(10);++	/* Reset the core */+	gpwrdn.d32 = 0;+	gpwrdn.b.pwrdnrstn = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+	dwc_udelay(10);++	/* Disable power clamps */+	gpwrdn.d32 = 0;+	gpwrdn.b.pwrdnclmp = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++	/* Remove reset the core signal */+	gpwrdn.d32 = 0;+	gpwrdn.b.pwrdnrstn = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);+	dwc_udelay(10);++	/* Disable PMU interrupt */+	gpwrdn.d32 = 0;+	gpwrdn.b.pmuintsel = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++	/* Indicates that we are exiting from hibernation */+	core_if->hibernation_suspend = 0;++	/* Disable PMU */+	gpwrdn.d32 = 0;+	gpwrdn.b.pmuactv = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+	dwc_udelay(10);++	/* Programm Disable VBUS to 0 */+	gpwrdn.d32 = 0;+	gpwrdn.b.dis_vbus = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++	/*Initialize the core as Host */+	core_if->op_state = A_HOST;+	dwc_otg_core_init(core_if);+	dwc_otg_enable_global_interrupts(core_if);+	cil_hcd_start(core_if);++	return 1;+}++/** This interrupt indicates that restore command after Hibernation+ * was completed by the core. */+int32_t dwc_otg_handle_restore_done_intr(dwc_otg_core_if_t * core_if)+{+	pcgcctl_data_t pcgcctl;+	DWC_DEBUGPL(DBG_ANY, "++Restore Done Interrupt++\n");++	//TODO De-assert restore signal. 8.a+	pcgcctl.d32 = DWC_READ_REG32(core_if->pcgcctl);+	if (pcgcctl.b.restoremode == 1) {+		gintmsk_data_t gintmsk = {.d32 = 0 };+		/*+		 * If restore mode is Remote Wakeup,+		 * unmask Remote Wakeup interrupt.+		 */+		gintmsk.b.wkupintr = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,+				 0, gintmsk.d32);+	}++	return 1;+}++/**+ * This interrupt indicates that a device has been disconnected from+ * the root port.+ */+int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if)+{+	gintsts_data_t gintsts;++	DWC_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n",+		    (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"),+		    op_state_str(core_if));++/** @todo Consolidate this if statement. */+#ifndef DWC_HOST_ONLY+	if (core_if->op_state == B_HOST) {+		/* If in device mode Disconnect and stop the HCD, then+		 * start the PCD. */+		DWC_SPINUNLOCK(core_if->lock);+		cil_hcd_disconnect(core_if);+		cil_pcd_start(core_if);+		DWC_SPINLOCK(core_if->lock);+		core_if->op_state = B_PERIPHERAL;+	} else if (dwc_otg_is_device_mode(core_if)) {+		gotgctl_data_t gotgctl = {.d32 = 0 };+		gotgctl.d32 =+		    DWC_READ_REG32(&core_if->core_global_regs->gotgctl);+		if (gotgctl.b.hstsethnpen == 1) {+			/* Do nothing, if HNP in process the OTG+			 * interrupt "Host Negotiation Detected"+			 * interrupt will do the mode switch.+			 */+		} else if (gotgctl.b.devhnpen == 0) {+			/* If in device mode Disconnect and stop the HCD, then+			 * start the PCD. */+			DWC_SPINUNLOCK(core_if->lock);+			cil_hcd_disconnect(core_if);+			cil_pcd_start(core_if);+			DWC_SPINLOCK(core_if->lock);+			core_if->op_state = B_PERIPHERAL;+		} else {+			DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n");+		}+	} else {+		if (core_if->op_state == A_HOST) {+			/* A-Cable still connected but device disconnected. */+			cil_hcd_disconnect(core_if);+			if (core_if->adp_enable) {+				gpwrdn_data_t gpwrdn = { .d32 = 0 };+				cil_hcd_stop(core_if);+				/* Enable Power Down Logic */+				gpwrdn.b.pmuintsel = 1;+				gpwrdn.b.pmuactv = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, 0, gpwrdn.d32);+				dwc_otg_adp_probe_start(core_if);++				/* Power off the core */+				if (core_if->power_down == 2) {+					gpwrdn.d32 = 0;+					gpwrdn.b.pwrdnswtch = 1;+					DWC_MODIFY_REG32+					    (&core_if->core_global_regs->gpwrdn,+					     gpwrdn.d32, 0);+				}+			}+		}+	}+#endif+	/* Change to L3(OFF) state */+	core_if->lx_state = DWC_OTG_L3;++	gintsts.d32 = 0;+	gintsts.b.disconnect = 1;+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);+	return 1;+}++/**+ * This interrupt indicates that SUSPEND state has been detected on+ * the USB.+ *+ * For HNP the USB Suspend interrupt signals the change from+ * "a_peripheral" to "a_host".+ *+ * When power management is enabled the core will be put in low power+ * mode.+ */+int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if)+{+	dsts_data_t dsts;+	gintsts_data_t gintsts;+	dcfg_data_t dcfg;++	DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n");++	if (dwc_otg_is_device_mode(core_if)) {+		/* Check the Device status register to determine if the Suspend+		 * state is active. */+		dsts.d32 =+		    DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);+		DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32);+		DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d "+			    "HWCFG4.power Optimize=%d\n",+			    dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz);++#ifdef PARTIAL_POWER_DOWN+/** @todo Add a module parameter for power management. */++		if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) {+			pcgcctl_data_t power = {.d32 = 0 };+			DWC_DEBUGPL(DBG_CIL, "suspend\n");++			power.b.pwrclmp = 1;+			DWC_WRITE_REG32(core_if->pcgcctl, power.d32);++			power.b.rstpdwnmodule = 1;+			DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);++			power.b.stoppclk = 1;+			DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);++		} else {+			DWC_DEBUGPL(DBG_ANY, "disconnect?\n");+		}+#endif+		/* PCD callback for suspend. Release the lock inside of callback function */+		cil_pcd_suspend(core_if);+		if (core_if->power_down == 2)+		{+			dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);+			DWC_DEBUGPL(DBG_ANY,"lx_state = %08x\n",core_if->lx_state);+			DWC_DEBUGPL(DBG_ANY," device address = %08d\n",dcfg.b.devaddr);++			if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) {+				pcgcctl_data_t pcgcctl = {.d32 = 0 };+				gpwrdn_data_t gpwrdn = {.d32 = 0 };+				gusbcfg_data_t gusbcfg = {.d32 = 0 };++				/* Change to L2(suspend) state */+				core_if->lx_state = DWC_OTG_L2;++				/* Clear interrupt in gintsts */+				gintsts.d32 = 0;+				gintsts.b.usbsuspend = 1;+				DWC_WRITE_REG32(&core_if->core_global_regs->+						gintsts, gintsts.d32);+				DWC_PRINTF("Start of hibernation completed\n");+				dwc_otg_save_global_regs(core_if);+				dwc_otg_save_dev_regs(core_if);++				gusbcfg.d32 =+				    DWC_READ_REG32(&core_if->core_global_regs->+						   gusbcfg);+				if (gusbcfg.b.ulpi_utmi_sel == 1) {+					/* ULPI interface */+					/* Suspend the Phy Clock */+					pcgcctl.d32 = 0;+					pcgcctl.b.stoppclk = 1;+					DWC_MODIFY_REG32(core_if->pcgcctl, 0,+							 pcgcctl.d32);+					dwc_udelay(10);+					gpwrdn.b.pmuactv = 1;+					DWC_MODIFY_REG32(&core_if->+							 core_global_regs->+							 gpwrdn, 0, gpwrdn.d32);+				} else {+					/* UTMI+ Interface */+					gpwrdn.b.pmuactv = 1;+					DWC_MODIFY_REG32(&core_if->+							 core_global_regs->+							 gpwrdn, 0, gpwrdn.d32);+					dwc_udelay(10);+					pcgcctl.b.stoppclk = 1;+					DWC_MODIFY_REG32(core_if->pcgcctl, 0,+							 pcgcctl.d32);+					dwc_udelay(10);+				}++				/* Set flag to indicate that we are in hibernation */+				core_if->hibernation_suspend = 1;+				/* Enable interrupts from wake up logic */+				gpwrdn.d32 = 0;+				gpwrdn.b.pmuintsel = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, 0, gpwrdn.d32);+				dwc_udelay(10);++				/* Unmask device mode interrupts in GPWRDN */+				gpwrdn.d32 = 0;+				gpwrdn.b.rst_det_msk = 1;+				gpwrdn.b.lnstchng_msk = 1;+				gpwrdn.b.sts_chngint_msk = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, 0, gpwrdn.d32);+				dwc_udelay(10);++				/* Enable Power Down Clamp */+				gpwrdn.d32 = 0;+				gpwrdn.b.pwrdnclmp = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, 0, gpwrdn.d32);+				dwc_udelay(10);++				/* Switch off VDD */+				gpwrdn.d32 = 0;+				gpwrdn.b.pwrdnswtch = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, 0, gpwrdn.d32);++				/* Save gpwrdn register for further usage if stschng interrupt */+				core_if->gr_backup->gpwrdn_local =+							DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);+				DWC_PRINTF("Hibernation completed\n");++				return 1;+			}+		} else if (core_if->power_down == 3) {+			pcgcctl_data_t pcgcctl = {.d32 = 0 };+			dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);+			DWC_DEBUGPL(DBG_ANY, "lx_state = %08x\n",core_if->lx_state);+			DWC_DEBUGPL(DBG_ANY, " device address = %08d\n",dcfg.b.devaddr);++			if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) {+				DWC_DEBUGPL(DBG_ANY, "Start entering to extended hibernation\n");+				core_if->xhib = 1;++				/* Clear interrupt in gintsts */+				gintsts.d32 = 0;+				gintsts.b.usbsuspend = 1;+				DWC_WRITE_REG32(&core_if->core_global_regs->+					gintsts, gintsts.d32);++				dwc_otg_save_global_regs(core_if);+				dwc_otg_save_dev_regs(core_if);++				/* Wait for 10 PHY clocks */+				dwc_udelay(10);++				/* Program GPIO register while entering to xHib */+				DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x1);++				pcgcctl.b.enbl_extnd_hiber = 1;+				DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);+				DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);++				pcgcctl.d32 = 0;+				pcgcctl.b.extnd_hiber_pwrclmp = 1;+				DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);++				pcgcctl.d32 = 0;+				pcgcctl.b.extnd_hiber_switch = 1;+				core_if->gr_backup->xhib_gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);+				core_if->gr_backup->xhib_pcgcctl = DWC_READ_REG32(core_if->pcgcctl) | pcgcctl.d32;+				DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);++				DWC_DEBUGPL(DBG_ANY, "Finished entering to extended hibernation\n");++				return 1;+			}+		}+	} else {+		if (core_if->op_state == A_PERIPHERAL) {+			DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n");+			/* Clear the a_peripheral flag, back to a_host. */+			DWC_SPINUNLOCK(core_if->lock);+			cil_pcd_stop(core_if);+			cil_hcd_start(core_if);+			DWC_SPINLOCK(core_if->lock);+			core_if->op_state = A_HOST;+		}+	}++	/* Change to L2(suspend) state */+	core_if->lx_state = DWC_OTG_L2;++	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.usbsuspend = 1;+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);++	return 1;+}++static int32_t dwc_otg_handle_xhib_exit_intr(dwc_otg_core_if_t * core_if)+{+	gpwrdn_data_t gpwrdn = {.d32 = 0 };+	pcgcctl_data_t pcgcctl = {.d32 = 0 };+	gahbcfg_data_t gahbcfg = {.d32 = 0 };++	dwc_udelay(10);++	/* Program GPIO register while entering to xHib */+	DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x0);++	pcgcctl.d32 = core_if->gr_backup->xhib_pcgcctl;+	pcgcctl.b.extnd_hiber_pwrclmp = 0;+	DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);+	dwc_udelay(10);++	gpwrdn.d32 = core_if->gr_backup->xhib_gpwrdn;+	gpwrdn.b.restore = 1;+	DWC_WRITE_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32);+	dwc_udelay(10);++	restore_lpm_i2c_regs(core_if);++	pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);+	pcgcctl.b.max_xcvrselect = 1;+	pcgcctl.b.ess_reg_restored = 0;+	pcgcctl.b.extnd_hiber_switch = 0;+	pcgcctl.b.extnd_hiber_pwrclmp = 0;+	pcgcctl.b.enbl_extnd_hiber = 1;+	DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);++	gahbcfg.d32 = core_if->gr_backup->gahbcfg_local;+	gahbcfg.b.glblintrmsk = 1;+	DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32);++	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);+	DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0x1 << 16);++	DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,+			core_if->gr_backup->gusbcfg_local);+	DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,+			core_if->dr_backup->dcfg);++	pcgcctl.d32 = 0;+	pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);+	pcgcctl.b.max_xcvrselect = 1;+	pcgcctl.d32 |= 0x608;+	DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);+	dwc_udelay(10);++	pcgcctl.d32 = 0;+	pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);+	pcgcctl.b.max_xcvrselect = 1;+	pcgcctl.b.ess_reg_restored = 1;+	pcgcctl.b.enbl_extnd_hiber = 1;+	pcgcctl.b.rstpdwnmodule = 1;+	pcgcctl.b.restoremode = 1;+	DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);++	DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);++	return 1;+}++#ifdef CONFIG_USB_DWC_OTG_LPM+/**+ * This function hadles LPM transaction received interrupt.+ */+static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if)+{+	glpmcfg_data_t lpmcfg;+	gintsts_data_t gintsts;++	if (!core_if->core_params->lpm_enable) {+		DWC_PRINTF("Unexpected LPM interrupt\n");+	}++	lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);+	DWC_PRINTF("LPM config register = 0x%08x\n", lpmcfg.d32);++	if (dwc_otg_is_host_mode(core_if)) {+		cil_hcd_sleep(core_if);+	} else {+		lpmcfg.b.hird_thres |= (1 << 4);+		DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,+				lpmcfg.d32);+	}++	/* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */+	dwc_udelay(10);+	lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);+	if (lpmcfg.b.prt_sleep_sts) {+		/* Save the current state */+		core_if->lx_state = DWC_OTG_L1;+	}++	/* Clear interrupt  */+	gintsts.d32 = 0;+	gintsts.b.lpmtranrcvd = 1;+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);+	return 1;+}+#endif /* CONFIG_USB_DWC_OTG_LPM */++/**+ * This function returns the Core Interrupt register.+ */+static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gintmsk_data_t *reenable_gintmsk)+{+	gahbcfg_data_t gahbcfg = {.d32 = 0 };+	gintsts_data_t gintsts;+	gintmsk_data_t gintmsk;+	gintmsk_data_t gintmsk_common = {.d32 = 0 };+	gintmsk_common.b.wkupintr = 1;+	gintmsk_common.b.sessreqintr = 1;+	gintmsk_common.b.conidstschng = 1;+	gintmsk_common.b.otgintr = 1;+	gintmsk_common.b.modemismatch = 1;+	gintmsk_common.b.disconnect = 1;+	gintmsk_common.b.usbsuspend = 1;+#ifdef CONFIG_USB_DWC_OTG_LPM+	gintmsk_common.b.lpmtranrcvd = 1;+#endif+	gintmsk_common.b.restoredone = 1;+	if(dwc_otg_is_device_mode(core_if))+	{+		/** @todo: The port interrupt occurs while in device+		 * mode. Added code to CIL to clear the interrupt for now!+		 */+		gintmsk_common.b.portintr = 1;+	}+	gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);+	gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);+	{+		unsigned long flags;++		// Re-enable the saved interrupts+		local_irq_save(flags);+		local_fiq_disable();+		gintmsk.d32 |= gintmsk_common.d32;+		gintsts_saved.d32 &= ~gintmsk_common.d32;+		reenable_gintmsk->d32 = gintmsk.d32;+		local_irq_restore(flags);+	}++	gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);++#ifdef DEBUG+	/* if any common interrupts set */+	if (gintsts.d32 & gintmsk_common.d32) {+		DWC_DEBUGPL(DBG_ANY, "common_intr: gintsts=%08x  gintmsk=%08x\n",+			    gintsts.d32, gintmsk.d32);+	}+#endif+	if (!fiq_fix_enable){+		if (gahbcfg.b.glblintrmsk)+			return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);+		else+			return 0;+	}+	else {+		return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);+	}++}++/* MACRO for clearing interupt bits in GPWRDN register */+#define CLEAR_GPWRDN_INTR(__core_if,__intr) \+do { \+		gpwrdn_data_t gpwrdn = {.d32=0}; \+		gpwrdn.b.__intr = 1; \+		DWC_MODIFY_REG32(&__core_if->core_global_regs->gpwrdn, \+		0, gpwrdn.d32); \+} while (0)++/**+ * Common interrupt handler.+ *+ * The common interrupts are those that occur in both Host and Device mode.+ * This handler handles the following interrupts:+ * - Mode Mismatch Interrupt+ * - Disconnect Interrupt+ * - OTG Interrupt+ * - Connector ID Status Change Interrupt+ * - Session Request Interrupt.+ * - Resume / Remote Wakeup Detected Interrupt.+ * - LPM Transaction Received Interrupt+ * - ADP Transaction Received Interrupt+ *+ */+int32_t dwc_otg_handle_common_intr(void *dev)+{+	int retval = 0;+	gintsts_data_t gintsts;+	gintmsk_data_t reenable_gintmsk;+	gpwrdn_data_t gpwrdn = {.d32 = 0 };+	dwc_otg_device_t *otg_dev = dev;+	dwc_otg_core_if_t *core_if = otg_dev->core_if;+	gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);+	if (dwc_otg_is_device_mode(core_if))+		core_if->frame_num = dwc_otg_get_frame_number(core_if);++	if (core_if->lock)+		DWC_SPINLOCK(core_if->lock);++	if (core_if->power_down == 3 && core_if->xhib == 1) {+		DWC_DEBUGPL(DBG_ANY, "Exiting from xHIB state\n");+		retval |= dwc_otg_handle_xhib_exit_intr(core_if);+		core_if->xhib = 2;+		if (core_if->lock)+			DWC_SPINUNLOCK(core_if->lock);++		return retval;+	}++	if (core_if->hibernation_suspend <= 0) {+		gintsts.d32 = dwc_otg_read_common_intr(core_if, &reenable_gintmsk);++		if (gintsts.b.modemismatch) {+			retval |= dwc_otg_handle_mode_mismatch_intr(core_if);+		}+		if (gintsts.b.otgintr) {+			retval |= dwc_otg_handle_otg_intr(core_if);+		}+		if (gintsts.b.conidstschng) {+			retval |=+			    dwc_otg_handle_conn_id_status_change_intr(core_if);+		}+		if (gintsts.b.disconnect) {+			retval |= dwc_otg_handle_disconnect_intr(core_if);+		}+		if (gintsts.b.sessreqintr) {+			retval |= dwc_otg_handle_session_req_intr(core_if);+		}+		if (gintsts.b.wkupintr) {+			retval |= dwc_otg_handle_wakeup_detected_intr(core_if);+		}+		if (gintsts.b.usbsuspend) {+			retval |= dwc_otg_handle_usb_suspend_intr(core_if);+		}+#ifdef CONFIG_USB_DWC_OTG_LPM+		if (gintsts.b.lpmtranrcvd) {+			retval |= dwc_otg_handle_lpm_intr(core_if);+		}+#endif+		if (gintsts.b.restoredone) {+			gintsts.d32 = 0;+	                if (core_if->power_down == 2)+				core_if->hibernation_suspend = -1;+			else if (core_if->power_down == 3 && core_if->xhib == 2) {+				gpwrdn_data_t gpwrdn = {.d32 = 0 };+				pcgcctl_data_t pcgcctl = {.d32 = 0 };+				dctl_data_t dctl = {.d32 = 0 };++				DWC_WRITE_REG32(&core_if->core_global_regs->+						gintsts, 0xFFFFFFFF);++				DWC_DEBUGPL(DBG_ANY,+					    "RESTORE DONE generated\n");++				gpwrdn.b.restore = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+				dwc_udelay(10);++				pcgcctl.b.rstpdwnmodule = 1;+				DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);++				DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, core_if->gr_backup->gusbcfg_local);+				DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, core_if->dr_backup->dcfg);+				DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, core_if->dr_backup->dctl);+				dwc_udelay(50);++				dctl.b.pwronprgdone = 1;+				DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);+				dwc_udelay(10);++				dwc_otg_restore_global_regs(core_if);+				dwc_otg_restore_dev_regs(core_if, 0);++				dctl.d32 = 0;+				dctl.b.pwronprgdone = 1;+				DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);+				dwc_udelay(10);++				pcgcctl.d32 = 0;+				pcgcctl.b.enbl_extnd_hiber = 1;+				DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);++				/* The core will be in ON STATE */+				core_if->lx_state = DWC_OTG_L0;+				core_if->xhib = 0;++				DWC_SPINUNLOCK(core_if->lock);+				if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {+					core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);+				}+				DWC_SPINLOCK(core_if->lock);++			}++			gintsts.b.restoredone = 1;+			DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);+			DWC_PRINTF(" --Restore done interrupt received-- \n");+			retval |= 1;+		}+		if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) {+			/* The port interrupt occurs while in device mode with HPRT0+			 * Port Enable/Disable.+			 */+			gintsts.d32 = 0;+			gintsts.b.portintr = 1;+			DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);+			retval |= 1;+			reenable_gintmsk.b.portintr = 1;++		}++		DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, reenable_gintmsk.d32);++	} else {+		DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32);++		if (gpwrdn.b.disconn_det && gpwrdn.b.disconn_det_msk) {+			CLEAR_GPWRDN_INTR(core_if, disconn_det);+			if (gpwrdn.b.linestate == 0) {+				dwc_otg_handle_pwrdn_disconnect_intr(core_if);+			} else {+				DWC_PRINTF("Disconnect detected while linestate is not 0\n");+			}++			retval |= 1;+		}+		if (gpwrdn.b.lnstschng && gpwrdn.b.lnstchng_msk) {+			CLEAR_GPWRDN_INTR(core_if, lnstschng);+			/* remote wakeup from hibernation */+			if (gpwrdn.b.linestate == 2 || gpwrdn.b.linestate == 1) {+				dwc_otg_handle_pwrdn_wakeup_detected_intr(core_if);+			} else {+				DWC_PRINTF("gpwrdn.linestate = %d\n", gpwrdn.b.linestate);+			}+			retval |= 1;+		}+		if (gpwrdn.b.rst_det && gpwrdn.b.rst_det_msk) {+			CLEAR_GPWRDN_INTR(core_if, rst_det);+			if (gpwrdn.b.linestate == 0) {+				DWC_PRINTF("Reset detected\n");+				retval |= dwc_otg_device_hibernation_restore(core_if, 0, 1);+			}+		}+		if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) {+			CLEAR_GPWRDN_INTR(core_if, srp_det);+			dwc_otg_handle_pwrdn_srp_intr(core_if);+			retval |= 1;+		}+	}+	/* Handle ADP interrupt here */+	if (gpwrdn.b.adp_int) {+		DWC_PRINTF("ADP interrupt\n");+		CLEAR_GPWRDN_INTR(core_if, adp_int);+		dwc_otg_adp_handle_intr(core_if);+		retval |= 1;+	}+	if (gpwrdn.b.sts_chngint && gpwrdn.b.sts_chngint_msk) {+		DWC_PRINTF("STS CHNG interrupt asserted\n");+		CLEAR_GPWRDN_INTR(core_if, sts_chngint);+		dwc_otg_handle_pwrdn_stschng_intr(otg_dev);++		retval |= 1;+	}+	if (core_if->lock)+		DWC_SPINUNLOCK(core_if->lock);++	return retval;+}diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_core_if.h--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_core_if.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_core_if.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,705 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $+ * $Revision: #13 $+ * $Date: 2012/08/10 $+ * $Change: 2047372 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */+#if !defined(__DWC_CORE_IF_H__)+#define __DWC_CORE_IF_H__++#include "dwc_os.h"++/** @file+ * This file defines DWC_OTG Core API+ */++struct dwc_otg_core_if;+typedef struct dwc_otg_core_if dwc_otg_core_if_t;++/** Maximum number of Periodic FIFOs */+#define MAX_PERIO_FIFOS 15+/** Maximum number of Periodic FIFOs */+#define MAX_TX_FIFOS 15++/** Maximum number of Endpoints/HostChannels */+#define MAX_EPS_CHANNELS 16++extern dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * _reg_base_addr);+extern void dwc_otg_core_init(dwc_otg_core_if_t * _core_if);+extern void dwc_otg_cil_remove(dwc_otg_core_if_t * _core_if);++extern void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * _core_if);+extern void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * _core_if);++extern uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if);+extern uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if);++extern uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if);++/** This function should be called on every hardware interrupt. */+extern int32_t dwc_otg_handle_common_intr(void *otg_dev);++/** @name OTG Core Parameters */+/** @{ */++/**+ * Specifies the OTG capabilities. The driver will automatically+ * detect the value for this parameter if none is specified.+ * 0 - HNP and SRP capable (default)+ * 1 - SRP Only capable+ * 2 - No HNP/SRP capable+ */+extern int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val);+extern int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if);+#define DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE 0+#define DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE 1+#define DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE 2+#define dwc_param_otg_cap_default DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE++extern int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val);+extern int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if);+#define dwc_param_opt_default 1++/**+ * Specifies whether to use slave or DMA mode for accessing the data+ * FIFOs. The driver will automatically detect the value for this+ * parameter if none is specified.+ * 0 - Slave+ * 1 - DMA (default, if available)+ */+extern int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if,+					int32_t val);+extern int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if);+#define dwc_param_dma_enable_default 1++/**+ * When DMA mode is enabled specifies whether to use+ * address DMA or DMA Descritor mode for accessing the data+ * FIFOs in device mode. The driver will automatically detect+ * the value for this parameter if none is specified.+ * 0 - address DMA+ * 1 - DMA Descriptor(default, if available)+ */+extern int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if,+					     int32_t val);+extern int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if);+//#define dwc_param_dma_desc_enable_default 1+#define dwc_param_dma_desc_enable_default 0 // Broadcom BCM2708++/** The DMA Burst size (applicable only for External DMA+ * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)+ */+extern int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if,+					    int32_t val);+extern int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if);+#define dwc_param_dma_burst_size_default 32++/**+ * Specifies the maximum speed of operation in host and device mode.+ * The actual speed depends on the speed of the attached device and+ * the value of phy_type. The actual speed depends on the speed of the+ * attached device.+ * 0 - High Speed (default)+ * 1 - Full Speed+ */+extern int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val);+extern int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if);+#define dwc_param_speed_default 0+#define DWC_SPEED_PARAM_HIGH 0+#define DWC_SPEED_PARAM_FULL 1++/** Specifies whether low power mode is supported when attached+ *	to a Full Speed or Low Speed device in host mode.+ * 0 - Don't support low power mode (default)+ * 1 - Support low power mode+ */+extern int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *+							  core_if, int32_t val);+extern int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t+							      * core_if);+#define dwc_param_host_support_fs_ls_low_power_default 0++/** Specifies the PHY clock rate in low power mode when connected to a+ * Low Speed device in host mode. This parameter is applicable only if+ * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS+ * then defaults to 6 MHZ otherwise 48 MHZ.+ *+ * 0 - 48 MHz+ * 1 - 6 MHz+ */+extern int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *+						       core_if, int32_t val);+extern int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *+							   core_if);+#define dwc_param_host_ls_low_power_phy_clk_default 0+#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0+#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1++/**+ * 0 - Use cC FIFO size parameters+ * 1 - Allow dynamic FIFO sizing (default)+ */+extern int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if,+						 int32_t val);+extern int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t *+						     core_if);+#define dwc_param_enable_dynamic_fifo_default 1++/** Total number of 4-byte words in the data FIFO memory. This+ * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic+ * Tx FIFOs.+ * 32 to 32768 (default 8192)+ * Note: The total FIFO memory depth in the FPGA configuration is 8192.+ */+extern int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if,+					    int32_t val);+extern int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if);+//#define dwc_param_data_fifo_size_default 8192+#define dwc_param_data_fifo_size_default 0xFF0 // Broadcom BCM2708++/** Number of 4-byte words in the Rx FIFO in device mode when dynamic+ * FIFO sizing is enabled.+ * 16 to 32768 (default 1064)+ */+extern int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if,+					      int32_t val);+extern int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if);+#define dwc_param_dev_rx_fifo_size_default 1064++/** Number of 4-byte words in the non-periodic Tx FIFO in device mode+ * when dynamic FIFO sizing is enabled.+ * 16 to 32768 (default 1024)+ */+extern int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *+						     core_if, int32_t val);+extern int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *+							 core_if);+#define dwc_param_dev_nperio_tx_fifo_size_default 1024++/** Number of 4-byte words in each of the periodic Tx FIFOs in device+ * mode when dynamic FIFO sizing is enabled.+ * 4 to 768 (default 256)+ */+extern int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,+						    int32_t val, int fifo_num);+extern int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *+							core_if, int fifo_num);+#define dwc_param_dev_perio_tx_fifo_size_default 256++/** Number of 4-byte words in the Rx FIFO in host mode when dynamic+ * FIFO sizing is enabled.+ * 16 to 32768 (default 1024)+ */+extern int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if,+					       int32_t val);+extern int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if);+//#define dwc_param_host_rx_fifo_size_default 1024+#define dwc_param_host_rx_fifo_size_default 774 // Broadcom BCM2708++/** Number of 4-byte words in the non-periodic Tx FIFO in host mode+ * when Dynamic FIFO sizing is enabled in the core.+ * 16 to 32768 (default 1024)+ */+extern int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *+						      core_if, int32_t val);+extern int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *+							  core_if);+//#define dwc_param_host_nperio_tx_fifo_size_default 1024+#define dwc_param_host_nperio_tx_fifo_size_default 0x100 // Broadcom BCM2708++/** Number of 4-byte words in the host periodic Tx FIFO when dynamic+ * FIFO sizing is enabled.+ * 16 to 32768 (default 1024)+ */+extern int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *+						     core_if, int32_t val);+extern int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *+							 core_if);+//#define dwc_param_host_perio_tx_fifo_size_default 1024+#define dwc_param_host_perio_tx_fifo_size_default 0x200 // Broadcom BCM2708++/** The maximum transfer size supported in bytes.+ * 2047 to 65,535  (default 65,535)+ */+extern int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if,+					       int32_t val);+extern int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if);+#define dwc_param_max_transfer_size_default 65535++/** The maximum number of packets in a transfer.+ * 15 to 511  (default 511)+ */+extern int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if,+					      int32_t val);+extern int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if);+#define dwc_param_max_packet_count_default 511++/** The number of host channel registers to use.+ * 1 to 16 (default 12)+ * Note: The FPGA configuration supports a maximum of 12 host channels.+ */+extern int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if,+					   int32_t val);+extern int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if);+//#define dwc_param_host_channels_default 12+#define dwc_param_host_channels_default 8 // Broadcom BCM2708++/** The number of endpoints in addition to EP0 available for device+ * mode operations.+ * 1 to 15 (default 6 IN and OUT)+ * Note: The FPGA configuration supports a maximum of 6 IN and OUT+ * endpoints in addition to EP0.+ */+extern int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if,+					   int32_t val);+extern int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if);+#define dwc_param_dev_endpoints_default 6++/**+ * Specifies the type of PHY interface to use. By default, the driver+ * will automatically detect the phy_type.+ *+ * 0 - Full Speed PHY+ * 1 - UTMI+ (default)+ * 2 - ULPI+ */+extern int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val);+extern int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if);+#define DWC_PHY_TYPE_PARAM_FS 0+#define DWC_PHY_TYPE_PARAM_UTMI 1+#define DWC_PHY_TYPE_PARAM_ULPI 2+#define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI++/**+ * Specifies the UTMI+ Data Width. This parameter is+ * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI+ * PHY_TYPE, this parameter indicates the data width between+ * the MAC and the ULPI Wrapper.) Also, this parameter is+ * applicable only if the OTG_HSPHY_WIDTH cC parameter was set+ * to "8 and 16 bits", meaning that the core has been+ * configured to work at either data path width.+ *+ * 8 or 16 bits (default 16)+ */+extern int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if,+					    int32_t val);+extern int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if);+//#define dwc_param_phy_utmi_width_default 16+#define dwc_param_phy_utmi_width_default 8 // Broadcom BCM2708++/**+ * Specifies whether the ULPI operates at double or single+ * data rate. This parameter is only applicable if PHY_TYPE is+ * ULPI.+ *+ * 0 - single data rate ULPI interface with 8 bit wide data+ * bus (default)+ * 1 - double data rate ULPI interface with 4 bit wide data+ * bus+ */+extern int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if,+					  int32_t val);+extern int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if);+#define dwc_param_phy_ulpi_ddr_default 0++/**+ * Specifies whether to use the internal or external supply to+ * drive the vbus with a ULPI phy.+ */+extern int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if,+					       int32_t val);+extern int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if);+#define DWC_PHY_ULPI_INTERNAL_VBUS 0+#define DWC_PHY_ULPI_EXTERNAL_VBUS 1+#define dwc_param_phy_ulpi_ext_vbus_default DWC_PHY_ULPI_INTERNAL_VBUS++/**+ * Specifies whether to use the I2Cinterface for full speed PHY. This+ * parameter is only applicable if PHY_TYPE is FS.+ * 0 - No (default)+ * 1 - Yes+ */+extern int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if,+					int32_t val);+extern int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if);+#define dwc_param_i2c_enable_default 0++extern int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if,+					int32_t val);+extern int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if);+#define dwc_param_ulpi_fs_ls_default 0++extern int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val);+extern int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if);+#define dwc_param_ts_dline_default 0++/**+ * Specifies whether dedicated transmit FIFOs are+ * enabled for non periodic IN endpoints in device mode+ * 0 - No+ * 1 - Yes+ */+extern int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if,+						 int32_t val);+extern int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t *+						     core_if);+#define dwc_param_en_multiple_tx_fifo_default 1++/** Number of 4-byte words in each of the Tx FIFOs in device+ * mode when dynamic FIFO sizing is enabled.+ * 4 to 768 (default 256)+ */+extern int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,+					      int fifo_num, int32_t val);+extern int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,+						  int fifo_num);+#define dwc_param_dev_tx_fifo_size_default 768++/** Thresholding enable flag-+ * bit 0 - enable non-ISO Tx thresholding+ * bit 1 - enable ISO Tx thresholding+ * bit 2 - enable Rx thresholding+ */+extern int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val);+extern int32_t dwc_otg_get_thr_ctl(dwc_otg_core_if_t * core_if, int fifo_num);+#define dwc_param_thr_ctl_default 0++/** Thresholding length for Tx+ * FIFOs in 32 bit DWORDs+ */+extern int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if,+					   int32_t val);+extern int32_t dwc_otg_get_tx_thr_length(dwc_otg_core_if_t * core_if);+#define dwc_param_tx_thr_length_default 64++/** Thresholding length for Rx+ *	FIFOs in 32 bit DWORDs+ */+extern int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if,+					   int32_t val);+extern int32_t dwc_otg_get_rx_thr_length(dwc_otg_core_if_t * core_if);+#define dwc_param_rx_thr_length_default 64++/**+ * Specifies whether LPM (Link Power Management) support is enabled+ */+extern int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if,+					int32_t val);+extern int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if);+#define dwc_param_lpm_enable_default 1++/**+ * Specifies whether PTI enhancement is enabled+ */+extern int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if,+					int32_t val);+extern int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if);+#define dwc_param_pti_enable_default 0++/**+ * Specifies whether MPI enhancement is enabled+ */+extern int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if,+					int32_t val);+extern int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if);+#define dwc_param_mpi_enable_default 0++/**+ * Specifies whether ADP capability is enabled+ */+extern int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if,+					int32_t val);+extern int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if);+#define dwc_param_adp_enable_default 0++/**+ * Specifies whether IC_USB capability is enabled+ */++extern int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if,+					int32_t val);+extern int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if);+#define dwc_param_ic_usb_cap_default 0++extern int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if,+					   int32_t val);+extern int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if);+#define dwc_param_ahb_thr_ratio_default 0++extern int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if,+					int32_t val);+extern int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if);+#define dwc_param_power_down_default 0++extern int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if,+					int32_t val);+extern int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if);+#define dwc_param_reload_ctl_default 0++extern int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if,+										int32_t val);+extern int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if);+#define dwc_param_dev_out_nak_default 0++extern int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if,+										 int32_t val);+extern int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if);+#define dwc_param_cont_on_bna_default 0++extern int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if,+										 int32_t val);+extern int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if);+#define dwc_param_ahb_single_default 0++extern int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val);+extern int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if);+#define dwc_param_otg_ver_default 0++/** @} */++/** @name Access to registers and bit-fields */++/**+ * Dump core registers and SPRAM+ */+extern void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * _core_if);+extern void dwc_otg_dump_spram(dwc_otg_core_if_t * _core_if);+extern void dwc_otg_dump_host_registers(dwc_otg_core_if_t * _core_if);+extern void dwc_otg_dump_global_registers(dwc_otg_core_if_t * _core_if);++/**+ * Get host negotiation status.+ */+extern uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if);++/**+ * Get srp status+ */+extern uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if);++/**+ * Set hnpreq bit in the GOTGCTL register.+ */+extern void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * Get Content of SNPSID register.+ */+extern uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if);++/**+ * Get current mode.+ * Returns 0 if in device mode, and 1 if in host mode.+ */+extern uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if);++/**+ * Get value of hnpcapable field in the GUSBCFG register+ */+extern uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if);+/**+ * Set value of hnpcapable field in the GUSBCFG register+ */+extern void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * Get value of srpcapable field in the GUSBCFG register+ */+extern uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if);+/**+ * Set value of srpcapable field in the GUSBCFG register+ */+extern void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * Get value of devspeed field in the DCFG register+ */+extern uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if);+/**+ * Set value of devspeed field in the DCFG register+ */+extern void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * Get the value of busconnected field from the HPRT0 register+ */+extern uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if);++/**+ * Gets the device enumeration Speed.+ */+extern uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if);++/**+ * Get value of prtpwr field from the HPRT0 register+ */+extern uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if);++/**+ * Get value of flag indicating core state - hibernated or not+ */+extern uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if);++/**+ * Set value of prtpwr field from the HPRT0 register+ */+extern void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * Get value of prtsusp field from the HPRT0 regsiter+ */+extern uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if);+/**+ * Set value of prtpwr field from the HPRT0 register+ */+extern void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * Get value of ModeChTimEn field from the HCFG regsiter+ */+extern uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if);+/**+ * Set value of ModeChTimEn field from the HCFG regsiter+ */+extern void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * Get value of Fram Interval field from the HFIR regsiter+ */+extern uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if);+/**+ * Set value of Frame Interval field from the HFIR regsiter+ */+extern void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * Set value of prtres field from the HPRT0 register+ *FIXME Remove?+ */+extern void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * Get value of rmtwkupsig bit in DCTL register+ */+extern uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if);++/**+ * Get value of prt_sleep_sts field from the GLPMCFG register+ */+extern uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if);++/**+ * Get value of rem_wkup_en field from the GLPMCFG register+ */+extern uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if);++/**+ * Get value of appl_resp field from the GLPMCFG register+ */+extern uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if);+/**+ * Set value of appl_resp field from the GLPMCFG register+ */+extern void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * Get value of hsic_connect field from the GLPMCFG register+ */+extern uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if);+/**+ * Set value of hsic_connect field from the GLPMCFG register+ */+extern void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * Get value of inv_sel_hsic field from the GLPMCFG register.+ */+extern uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if);+/**+ * Set value of inv_sel_hsic field from the GLPMFG register.+ */+extern void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val);++/*+ * Some functions for accessing registers+ */++/**+ *  GOTGCTL register+ */+extern uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if);+extern void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * GUSBCFG register+ */+extern uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if);+extern void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * GRXFSIZ register+ */+extern uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if);+extern void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * GNPTXFSIZ register+ */+extern uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if);+extern void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val);++extern uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if);+extern void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * GGPIO register+ */+extern uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if);+extern void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * GUID register+ */+extern uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if);+extern void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * HPRT0 register+ */+extern uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if);+extern void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val);++/**+ * GHPTXFSIZE+ */+extern uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if);++/** @} */++#endif				/* __DWC_CORE_IF_H__ */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_dbg.h linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_dbg.h--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_dbg.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_dbg.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,117 @@+/* ==========================================================================+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */++#ifndef __DWC_OTG_DBG_H__+#define __DWC_OTG_DBG_H__++/** @file+ * This file defines debug levels.+ * Debugging support vanishes in non-debug builds.+ */++/**+ * The Debug Level bit-mask variable.+ */+extern uint32_t g_dbg_lvl;+/**+ * Set the Debug Level variable.+ */+static inline uint32_t SET_DEBUG_LEVEL(const uint32_t new)+{+	uint32_t old = g_dbg_lvl;+	g_dbg_lvl = new;+	return old;+}++#define DBG_USER	(0x1)+/** When debug level has the DBG_CIL bit set, display CIL Debug messages. */+#define DBG_CIL		(0x2)+/** When debug level has the DBG_CILV bit set, display CIL Verbose debug+ * messages */+#define DBG_CILV	(0x20)+/**  When debug level has the DBG_PCD bit set, display PCD (Device) debug+ *  messages */+#define DBG_PCD		(0x4)+/** When debug level has the DBG_PCDV set, display PCD (Device) Verbose debug+ * messages */+#define DBG_PCDV	(0x40)+/** When debug level has the DBG_HCD bit set, display Host debug messages */+#define DBG_HCD		(0x8)+/** When debug level has the DBG_HCDV bit set, display Verbose Host debug+ * messages */+#define DBG_HCDV	(0x80)+/** When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host+ *  mode. */+#define DBG_HCD_URB	(0x800)+/** When debug level has the DBG_HCDI bit set, display host interrupt+ *  messages. */+#define DBG_HCDI	(0x1000)++/** When debug level has any bit set, display debug messages */+#define DBG_ANY		(0xFF)++/** All debug messages off */+#define DBG_OFF		0++/** Prefix string for DWC_DEBUG print macros. */+#define USB_DWC "DWC_otg: "++/**+ * Print a debug message when the Global debug level variable contains+ * the bit defined in <code>lvl</code>.+ *+ * @param[in] lvl - Debug level, use one of the DBG_ constants above.+ * @param[in] x - like printf+ *+ *    Example:<p>+ * <code>+ *      DWC_DEBUGPL( DBG_ANY, "%s(%p)\n", __func__, _reg_base_addr);+ * </code>+ * <br>+ * results in:<br>+ * <code>+ * usb-DWC_otg: dwc_otg_cil_init(ca867000)+ * </code>+ */+#ifdef DEBUG++# define DWC_DEBUGPL(lvl, x...) do{ if ((lvl)&g_dbg_lvl)__DWC_DEBUG(USB_DWC x ); }while(0)+# define DWC_DEBUGP(x...)	DWC_DEBUGPL(DBG_ANY, x )++# define CHK_DEBUG_LEVEL(level) ((level) & g_dbg_lvl)++#else++# define DWC_DEBUGPL(lvl, x...) do{}while(0)+# define DWC_DEBUGP(x...)++# define CHK_DEBUG_LEVEL(level) (0)++#endif /*DEBUG*/+#endifdiff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_driver.c--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_driver.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_driver.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,1742 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $+ * $Revision: #92 $+ * $Date: 2012/08/10 $+ * $Change: 2047372 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */++/** @file+ * The dwc_otg_driver module provides the initialization and cleanup entry+ * points for the DWC_otg driver. This module will be dynamically installed+ * after Linux is booted using the insmod command. When the module is+ * installed, the dwc_otg_driver_init function is called. When the module is+ * removed (using rmmod), the dwc_otg_driver_cleanup function is called.+ *+ * This module also defines a data structure for the dwc_otg_driver, which is+ * used in conjunction with the standard ARM lm_device structure. These+ * structures allow the OTG driver to comply with the standard Linux driver+ * model in which devices and drivers are registered with a bus driver. This+ * has the benefit that Linux can expose attributes of the driver and device+ * in its special sysfs file system. Users can then read or write files in+ * this file system to perform diagnostics on the driver components or the+ * device.+ */++#include "dwc_otg_os_dep.h"+#include "dwc_os.h"+#include "dwc_otg_dbg.h"+#include "dwc_otg_driver.h"+#include "dwc_otg_attr.h"+#include "dwc_otg_core_if.h"+#include "dwc_otg_pcd_if.h"+#include "dwc_otg_hcd_if.h"++#define DWC_DRIVER_VERSION	"3.00a 10-AUG-2012"+#define DWC_DRIVER_DESC		"HS OTG USB Controller driver"++bool microframe_schedule=true;++static const char dwc_driver_name[] = "dwc_otg";++extern void* dummy_send;++extern int pcd_init(+#ifdef LM_INTERFACE+			   struct lm_device *_dev+#elif  defined(PCI_INTERFACE)+			   struct pci_dev *_dev+#elif  defined(PLATFORM_INTERFACE)+	struct platform_device *dev+#endif+    );+extern int hcd_init(+#ifdef LM_INTERFACE+			   struct lm_device *_dev+#elif  defined(PCI_INTERFACE)+			   struct pci_dev *_dev+#elif  defined(PLATFORM_INTERFACE)+	struct platform_device *dev+#endif+    );++extern int pcd_remove(+#ifdef LM_INTERFACE+			     struct lm_device *_dev+#elif  defined(PCI_INTERFACE)+			     struct pci_dev *_dev+#elif  defined(PLATFORM_INTERFACE)+	struct platform_device *_dev+#endif+    );++extern void hcd_remove(+#ifdef LM_INTERFACE+			      struct lm_device *_dev+#elif  defined(PCI_INTERFACE)+			      struct pci_dev *_dev+#elif  defined(PLATFORM_INTERFACE)+	struct platform_device *_dev+#endif+    );++extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host);++/*-------------------------------------------------------------------------*/+/* Encapsulate the module parameter settings */++struct dwc_otg_driver_module_params {+	int32_t opt;+	int32_t otg_cap;+	int32_t dma_enable;+	int32_t dma_desc_enable;+	int32_t dma_burst_size;+	int32_t speed;+	int32_t host_support_fs_ls_low_power;+	int32_t host_ls_low_power_phy_clk;+	int32_t enable_dynamic_fifo;+	int32_t data_fifo_size;+	int32_t dev_rx_fifo_size;+	int32_t dev_nperio_tx_fifo_size;+	uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];+	int32_t host_rx_fifo_size;+	int32_t host_nperio_tx_fifo_size;+	int32_t host_perio_tx_fifo_size;+	int32_t max_transfer_size;+	int32_t max_packet_count;+	int32_t host_channels;+	int32_t dev_endpoints;+	int32_t phy_type;+	int32_t phy_utmi_width;+	int32_t phy_ulpi_ddr;+	int32_t phy_ulpi_ext_vbus;+	int32_t i2c_enable;+	int32_t ulpi_fs_ls;+	int32_t ts_dline;+	int32_t en_multiple_tx_fifo;+	uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];+	uint32_t thr_ctl;+	uint32_t tx_thr_length;+	uint32_t rx_thr_length;+	int32_t pti_enable;+	int32_t mpi_enable;+	int32_t lpm_enable;+	int32_t ic_usb_cap;+	int32_t ahb_thr_ratio;+	int32_t power_down;+	int32_t reload_ctl;+	int32_t dev_out_nak;+	int32_t cont_on_bna;+	int32_t ahb_single;+	int32_t otg_ver;+	int32_t adp_enable;+};++static struct dwc_otg_driver_module_params dwc_otg_module_params = {+	.opt = -1,+	.otg_cap = -1,+	.dma_enable = -1,+	.dma_desc_enable = -1,+	.dma_burst_size = -1,+	.speed = -1,+	.host_support_fs_ls_low_power = -1,+	.host_ls_low_power_phy_clk = -1,+	.enable_dynamic_fifo = -1,+	.data_fifo_size = -1,+	.dev_rx_fifo_size = -1,+	.dev_nperio_tx_fifo_size = -1,+	.dev_perio_tx_fifo_size = {+				   /* dev_perio_tx_fifo_size_1 */+				   -1,+				   -1,+				   -1,+				   -1,+				   -1,+				   -1,+				   -1,+				   -1,+				   -1,+				   -1,+				   -1,+				   -1,+				   -1,+				   -1,+				   -1+				   /* 15 */+				   },+	.host_rx_fifo_size = -1,+	.host_nperio_tx_fifo_size = -1,+	.host_perio_tx_fifo_size = -1,+	.max_transfer_size = -1,+	.max_packet_count = -1,+	.host_channels = -1,+	.dev_endpoints = -1,+	.phy_type = -1,+	.phy_utmi_width = -1,+	.phy_ulpi_ddr = -1,+	.phy_ulpi_ext_vbus = -1,+	.i2c_enable = -1,+	.ulpi_fs_ls = -1,+	.ts_dline = -1,+	.en_multiple_tx_fifo = -1,+	.dev_tx_fifo_size = {+			     /* dev_tx_fifo_size */+			     -1,+			     -1,+			     -1,+			     -1,+			     -1,+			     -1,+			     -1,+			     -1,+			     -1,+			     -1,+			     -1,+			     -1,+			     -1,+			     -1,+			     -1+			     /* 15 */+			     },+	.thr_ctl = -1,+	.tx_thr_length = -1,+	.rx_thr_length = -1,+	.pti_enable = -1,+	.mpi_enable = -1,+	.lpm_enable = 0,+	.ic_usb_cap = -1,+	.ahb_thr_ratio = -1,+	.power_down = -1,+	.reload_ctl = -1,+	.dev_out_nak = -1,+	.cont_on_bna = -1,+	.ahb_single = -1,+	.otg_ver = -1,+	.adp_enable = -1,+};++//Global variable to switch the fiq fix on or off (declared in bcm2708.c)+extern bool fiq_fix_enable;+// Global variable to enable the split transaction fix+bool fiq_split_enable = true;+//Global variable to switch the nak holdoff on or off+bool nak_holdoff_enable = true;+++/**+ * This function shows the Driver Version.+ */+static ssize_t version_show(struct device_driver *dev, char *buf)+{+	return snprintf(buf, sizeof(DWC_DRIVER_VERSION) + 2, "%s\n",+			DWC_DRIVER_VERSION);+}++static DRIVER_ATTR(version, S_IRUGO, version_show, NULL);++/**+ * Global Debug Level Mask.+ */+uint32_t g_dbg_lvl = 0;		/* OFF */++/**+ * This function shows the driver Debug Level.+ */+static ssize_t dbg_level_show(struct device_driver *drv, char *buf)+{+	return sprintf(buf, "0x%0x\n", g_dbg_lvl);+}++/**+ * This function stores the driver Debug Level.+ */+static ssize_t dbg_level_store(struct device_driver *drv, const char *buf,+			       size_t count)+{+	g_dbg_lvl = simple_strtoul(buf, NULL, 16);+	return count;+}++static DRIVER_ATTR(debuglevel, S_IRUGO | S_IWUSR, dbg_level_show,+		   dbg_level_store);++/**+ * This function is called during module intialization+ * to pass module parameters to the DWC_OTG CORE.+ */+static int set_parameters(dwc_otg_core_if_t * core_if)+{+	int retval = 0;+	int i;++	if (dwc_otg_module_params.otg_cap != -1) {+		retval +=+		    dwc_otg_set_param_otg_cap(core_if,+					      dwc_otg_module_params.otg_cap);+	}+	if (dwc_otg_module_params.dma_enable != -1) {+		retval +=+		    dwc_otg_set_param_dma_enable(core_if,+						 dwc_otg_module_params.+						 dma_enable);+	}+	if (dwc_otg_module_params.dma_desc_enable != -1) {+		retval +=+		    dwc_otg_set_param_dma_desc_enable(core_if,+						      dwc_otg_module_params.+						      dma_desc_enable);+	}+	if (dwc_otg_module_params.opt != -1) {+		retval +=+		    dwc_otg_set_param_opt(core_if, dwc_otg_module_params.opt);+	}+	if (dwc_otg_module_params.dma_burst_size != -1) {+		retval +=+		    dwc_otg_set_param_dma_burst_size(core_if,+						     dwc_otg_module_params.+						     dma_burst_size);+	}+	if (dwc_otg_module_params.host_support_fs_ls_low_power != -1) {+		retval +=+		    dwc_otg_set_param_host_support_fs_ls_low_power(core_if,+								   dwc_otg_module_params.+								   host_support_fs_ls_low_power);+	}+	if (dwc_otg_module_params.enable_dynamic_fifo != -1) {+		retval +=+		    dwc_otg_set_param_enable_dynamic_fifo(core_if,+							  dwc_otg_module_params.+							  enable_dynamic_fifo);+	}+	if (dwc_otg_module_params.data_fifo_size != -1) {+		retval +=+		    dwc_otg_set_param_data_fifo_size(core_if,+						     dwc_otg_module_params.+						     data_fifo_size);+	}+	if (dwc_otg_module_params.dev_rx_fifo_size != -1) {+		retval +=+		    dwc_otg_set_param_dev_rx_fifo_size(core_if,+						       dwc_otg_module_params.+						       dev_rx_fifo_size);+	}+	if (dwc_otg_module_params.dev_nperio_tx_fifo_size != -1) {+		retval +=+		    dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,+							      dwc_otg_module_params.+							      dev_nperio_tx_fifo_size);+	}+	if (dwc_otg_module_params.host_rx_fifo_size != -1) {+		retval +=+		    dwc_otg_set_param_host_rx_fifo_size(core_if,+							dwc_otg_module_params.host_rx_fifo_size);+	}+	if (dwc_otg_module_params.host_nperio_tx_fifo_size != -1) {+		retval +=+		    dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,+							       dwc_otg_module_params.+							       host_nperio_tx_fifo_size);+	}+	if (dwc_otg_module_params.host_perio_tx_fifo_size != -1) {+		retval +=+		    dwc_otg_set_param_host_perio_tx_fifo_size(core_if,+							      dwc_otg_module_params.+							      host_perio_tx_fifo_size);+	}+	if (dwc_otg_module_params.max_transfer_size != -1) {+		retval +=+		    dwc_otg_set_param_max_transfer_size(core_if,+							dwc_otg_module_params.+							max_transfer_size);+	}+	if (dwc_otg_module_params.max_packet_count != -1) {+		retval +=+		    dwc_otg_set_param_max_packet_count(core_if,+						       dwc_otg_module_params.+						       max_packet_count);+	}+	if (dwc_otg_module_params.host_channels != -1) {+		retval +=+		    dwc_otg_set_param_host_channels(core_if,+						    dwc_otg_module_params.+						    host_channels);+	}+	if (dwc_otg_module_params.dev_endpoints != -1) {+		retval +=+		    dwc_otg_set_param_dev_endpoints(core_if,+						    dwc_otg_module_params.+						    dev_endpoints);+	}+	if (dwc_otg_module_params.phy_type != -1) {+		retval +=+		    dwc_otg_set_param_phy_type(core_if,+					       dwc_otg_module_params.phy_type);+	}+	if (dwc_otg_module_params.speed != -1) {+		retval +=+		    dwc_otg_set_param_speed(core_if,+					    dwc_otg_module_params.speed);+	}+	if (dwc_otg_module_params.host_ls_low_power_phy_clk != -1) {+		retval +=+		    dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,+								dwc_otg_module_params.+								host_ls_low_power_phy_clk);+	}+	if (dwc_otg_module_params.phy_ulpi_ddr != -1) {+		retval +=+		    dwc_otg_set_param_phy_ulpi_ddr(core_if,+						   dwc_otg_module_params.+						   phy_ulpi_ddr);+	}+	if (dwc_otg_module_params.phy_ulpi_ext_vbus != -1) {+		retval +=+		    dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,+							dwc_otg_module_params.+							phy_ulpi_ext_vbus);+	}+	if (dwc_otg_module_params.phy_utmi_width != -1) {+		retval +=+		    dwc_otg_set_param_phy_utmi_width(core_if,+						     dwc_otg_module_params.+						     phy_utmi_width);+	}+	if (dwc_otg_module_params.ulpi_fs_ls != -1) {+		retval +=+		    dwc_otg_set_param_ulpi_fs_ls(core_if,+						 dwc_otg_module_params.ulpi_fs_ls);+	}+	if (dwc_otg_module_params.ts_dline != -1) {+		retval +=+		    dwc_otg_set_param_ts_dline(core_if,+					       dwc_otg_module_params.ts_dline);+	}+	if (dwc_otg_module_params.i2c_enable != -1) {+		retval +=+		    dwc_otg_set_param_i2c_enable(core_if,+						 dwc_otg_module_params.+						 i2c_enable);+	}+	if (dwc_otg_module_params.en_multiple_tx_fifo != -1) {+		retval +=+		    dwc_otg_set_param_en_multiple_tx_fifo(core_if,+							  dwc_otg_module_params.+							  en_multiple_tx_fifo);+	}+	for (i = 0; i < 15; i++) {+		if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] != -1) {+			retval +=+			    dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,+								     dwc_otg_module_params.+								     dev_perio_tx_fifo_size+								     [i], i);+		}+	}++	for (i = 0; i < 15; i++) {+		if (dwc_otg_module_params.dev_tx_fifo_size[i] != -1) {+			retval += dwc_otg_set_param_dev_tx_fifo_size(core_if,+								     dwc_otg_module_params.+								     dev_tx_fifo_size+								     [i], i);+		}+	}+	if (dwc_otg_module_params.thr_ctl != -1) {+		retval +=+		    dwc_otg_set_param_thr_ctl(core_if,+					      dwc_otg_module_params.thr_ctl);+	}+	if (dwc_otg_module_params.mpi_enable != -1) {+		retval +=+		    dwc_otg_set_param_mpi_enable(core_if,+						 dwc_otg_module_params.+						 mpi_enable);+	}+	if (dwc_otg_module_params.pti_enable != -1) {+		retval +=+		    dwc_otg_set_param_pti_enable(core_if,+						 dwc_otg_module_params.+						 pti_enable);+	}+	if (dwc_otg_module_params.lpm_enable != -1) {+		retval +=+		    dwc_otg_set_param_lpm_enable(core_if,+						 dwc_otg_module_params.+						 lpm_enable);+	}+	if (dwc_otg_module_params.ic_usb_cap != -1) {+		retval +=+		    dwc_otg_set_param_ic_usb_cap(core_if,+						 dwc_otg_module_params.+						 ic_usb_cap);+	}+	if (dwc_otg_module_params.tx_thr_length != -1) {+		retval +=+		    dwc_otg_set_param_tx_thr_length(core_if,+						    dwc_otg_module_params.tx_thr_length);+	}+	if (dwc_otg_module_params.rx_thr_length != -1) {+		retval +=+		    dwc_otg_set_param_rx_thr_length(core_if,+						    dwc_otg_module_params.+						    rx_thr_length);+	}+	if (dwc_otg_module_params.ahb_thr_ratio != -1) {+		retval +=+		    dwc_otg_set_param_ahb_thr_ratio(core_if,+						    dwc_otg_module_params.ahb_thr_ratio);+	}+	if (dwc_otg_module_params.power_down != -1) {+		retval +=+		    dwc_otg_set_param_power_down(core_if,+						 dwc_otg_module_params.power_down);+	}+	if (dwc_otg_module_params.reload_ctl != -1) {+		retval +=+		    dwc_otg_set_param_reload_ctl(core_if,+						 dwc_otg_module_params.reload_ctl);+	}++	if (dwc_otg_module_params.dev_out_nak != -1) {+		retval +=+			dwc_otg_set_param_dev_out_nak(core_if,+			dwc_otg_module_params.dev_out_nak);+	}++	if (dwc_otg_module_params.cont_on_bna != -1) {+		retval +=+			dwc_otg_set_param_cont_on_bna(core_if,+			dwc_otg_module_params.cont_on_bna);+	}++	if (dwc_otg_module_params.ahb_single != -1) {+		retval +=+			dwc_otg_set_param_ahb_single(core_if,+			dwc_otg_module_params.ahb_single);+	}++	if (dwc_otg_module_params.otg_ver != -1) {+		retval +=+		    dwc_otg_set_param_otg_ver(core_if,+					      dwc_otg_module_params.otg_ver);+	}+	if (dwc_otg_module_params.adp_enable != -1) {+		retval +=+		    dwc_otg_set_param_adp_enable(core_if,+						 dwc_otg_module_params.+						 adp_enable);+	}+	return retval;+}++/**+ * This function is the top level interrupt handler for the Common+ * (Device and host modes) interrupts.+ */+static irqreturn_t dwc_otg_common_irq(int irq, void *dev)+{+	int32_t retval = IRQ_NONE;++	retval = dwc_otg_handle_common_intr(dev);+	if (retval != 0) {+		S3C2410X_CLEAR_EINTPEND();+	}+	return IRQ_RETVAL(retval);+}++/**+ * This function is called when a lm_device is unregistered with the+ * dwc_otg_driver. This happens, for example, when the rmmod command is+ * executed. The device may or may not be electrically present. If it is+ * present, the driver stops device processing. Any resources used on behalf+ * of this device are freed.+ *+ * @param _dev+ */+#ifdef LM_INTERFACE+#define REM_RETVAL(n)+static void dwc_otg_driver_remove(	 struct lm_device *_dev )+{       dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);+#elif  defined(PCI_INTERFACE)+#define REM_RETVAL(n)+static void dwc_otg_driver_remove(	 struct pci_dev *_dev )+{	dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);+#elif  defined(PLATFORM_INTERFACE)+#define REM_RETVAL(n) n+static int dwc_otg_driver_remove(        struct platform_device *_dev )+{       dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev);+#endif++	DWC_DEBUGPL(DBG_ANY, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev);++	if (!otg_dev) {+		/* Memory allocation for the dwc_otg_device failed. */+		DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);+                return REM_RETVAL(-ENOMEM);+	}+#ifndef DWC_DEVICE_ONLY+	if (otg_dev->hcd) {+		hcd_remove(_dev);+	} else {+		DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);+                return REM_RETVAL(-EINVAL);+	}+#endif++#ifndef DWC_HOST_ONLY+	if (otg_dev->pcd) {+		pcd_remove(_dev);+	} else {+		DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->pcd NULL!\n", __func__);+                return REM_RETVAL(-EINVAL);+	}+#endif+	/*+	 * Free the IRQ+	 */+	if (otg_dev->common_irq_installed) {+#ifdef PLATFORM_INTERFACE+		free_irq(platform_get_irq(_dev, 0), otg_dev);+#else+		free_irq(_dev->irq, otg_dev);+#endif+        } else {+		DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__);+		return REM_RETVAL(-ENXIO);+	}++	if (otg_dev->core_if) {+		dwc_otg_cil_remove(otg_dev->core_if);+	} else {+		DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->core_if NULL!\n", __func__);+		return REM_RETVAL(-ENXIO);+	}++	/*+	 * Remove the device attributes+	 */+	dwc_otg_attr_remove(_dev);++	/*+	 * Return the memory.+	 */+	if (otg_dev->os_dep.base) {+		iounmap(otg_dev->os_dep.base);+	}+	DWC_FREE(otg_dev);++	/*+	 * Clear the drvdata pointer.+	 */+#ifdef LM_INTERFACE+	lm_set_drvdata(_dev, 0);+#elif defined(PCI_INTERFACE)+        release_mem_region(otg_dev->os_dep.rsrc_start,+                           otg_dev->os_dep.rsrc_len);+	pci_set_drvdata(_dev, 0);+#elif  defined(PLATFORM_INTERFACE)+        platform_set_drvdata(_dev, 0);+#endif+        return REM_RETVAL(0);+}++/**+ * This function is called when an lm_device is bound to a+ * dwc_otg_driver. It creates the driver components required to+ * control the device (CIL, HCD, and PCD) and it initializes the+ * device. The driver components are stored in a dwc_otg_device+ * structure. A reference to the dwc_otg_device is saved in the+ * lm_device. This allows the driver to access the dwc_otg_device+ * structure on subsequent calls to driver methods for this device.+ *+ * @param _dev Bus device+ */+static int dwc_otg_driver_probe(+#ifdef LM_INTERFACE+				       struct lm_device *_dev+#elif defined(PCI_INTERFACE)+				       struct pci_dev *_dev,+				       const struct pci_device_id *id+#elif  defined(PLATFORM_INTERFACE)+                                       struct platform_device *_dev+#endif+    )+{+	int retval = 0;+	dwc_otg_device_t *dwc_otg_device;+        int devirq;++	dev_dbg(&_dev->dev, "dwc_otg_driver_probe(%p)\n", _dev);+#ifdef LM_INTERFACE+	dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)_dev->resource.start);+#elif defined(PCI_INTERFACE)+	if (!id) {+		DWC_ERROR("Invalid pci_device_id %p", id);+		return -EINVAL;+	}++	if (!_dev || (pci_enable_device(_dev) < 0)) {+		DWC_ERROR("Invalid pci_device %p", _dev);+		return -ENODEV;+	}+	dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)pci_resource_start(_dev,0));+	/* other stuff needed as well? */++#elif  defined(PLATFORM_INTERFACE)+	dev_dbg(&_dev->dev, "start=0x%08x (len 0x%x)\n",+                (unsigned)_dev->resource->start,+                (unsigned)(_dev->resource->end - _dev->resource->start));+#endif++	dwc_otg_device = DWC_ALLOC(sizeof(dwc_otg_device_t));++	if (!dwc_otg_device) {+		dev_err(&_dev->dev, "kmalloc of dwc_otg_device failed\n");+		return -ENOMEM;+	}++	memset(dwc_otg_device, 0, sizeof(*dwc_otg_device));+	dwc_otg_device->os_dep.reg_offset = 0xFFFFFFFF;++	/*+	 * Map the DWC_otg Core memory into virtual address space.+	 */+#ifdef LM_INTERFACE+	dwc_otg_device->os_dep.base = ioremap(_dev->resource.start, SZ_256K);++	if (!dwc_otg_device->os_dep.base) {+		dev_err(&_dev->dev, "ioremap() failed\n");+		DWC_FREE(dwc_otg_device);+		return -ENOMEM;+	}+	dev_dbg(&_dev->dev, "base=0x%08x\n",+		(unsigned)dwc_otg_device->os_dep.base);+#elif defined(PCI_INTERFACE)+	_dev->current_state = PCI_D0;+	_dev->dev.power.power_state = PMSG_ON;++	if (!_dev->irq) {+		DWC_ERROR("Found HC with no IRQ. Check BIOS/PCI %s setup!",+			  pci_name(_dev));+		iounmap(dwc_otg_device->os_dep.base);+		DWC_FREE(dwc_otg_device);+		return -ENODEV;+	}++	dwc_otg_device->os_dep.rsrc_start = pci_resource_start(_dev, 0);+	dwc_otg_device->os_dep.rsrc_len = pci_resource_len(_dev, 0);+	DWC_DEBUGPL(DBG_ANY, "PCI resource: start=%08x, len=%08x\n",+		    (unsigned)dwc_otg_device->os_dep.rsrc_start,+		    (unsigned)dwc_otg_device->os_dep.rsrc_len);+	if (!request_mem_region+	    (dwc_otg_device->os_dep.rsrc_start, dwc_otg_device->os_dep.rsrc_len,+	     "dwc_otg")) {+		dev_dbg(&_dev->dev, "error requesting memory\n");+		iounmap(dwc_otg_device->os_dep.base);+		DWC_FREE(dwc_otg_device);+		return -EFAULT;+	}++	dwc_otg_device->os_dep.base =+	    ioremap_nocache(dwc_otg_device->os_dep.rsrc_start,+			    dwc_otg_device->os_dep.rsrc_len);+	if (dwc_otg_device->os_dep.base == NULL) {+		dev_dbg(&_dev->dev, "error mapping memory\n");+		release_mem_region(dwc_otg_device->os_dep.rsrc_start,+				   dwc_otg_device->os_dep.rsrc_len);+		iounmap(dwc_otg_device->os_dep.base);+		DWC_FREE(dwc_otg_device);+		return -EFAULT;+	}+	dev_dbg(&_dev->dev, "base=0x%p (before adjust) \n",+		dwc_otg_device->os_dep.base);+	dwc_otg_device->os_dep.base = (char *)dwc_otg_device->os_dep.base;+	dev_dbg(&_dev->dev, "base=0x%p (after adjust) \n",+		dwc_otg_device->os_dep.base);+	dev_dbg(&_dev->dev, "%s: mapped PA 0x%x to VA 0x%p\n", __func__,+		(unsigned)dwc_otg_device->os_dep.rsrc_start,+		dwc_otg_device->os_dep.base);++	pci_set_master(_dev);+	pci_set_drvdata(_dev, dwc_otg_device);+#elif defined(PLATFORM_INTERFACE)+        DWC_DEBUGPL(DBG_ANY,"Platform resource: start=%08x, len=%08x\n",+                    _dev->resource->start,+                    _dev->resource->end - _dev->resource->start + 1);+#if 1+        if (!request_mem_region(_dev->resource[0].start,+                                _dev->resource[0].end - _dev->resource[0].start + 1,+                                "dwc_otg")) {+          dev_dbg(&_dev->dev, "error reserving mapped memory\n");+          retval = -EFAULT;+          goto fail;+        }++	dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource[0].start,+                                                      _dev->resource[0].end -+                                                      _dev->resource[0].start+1);+	if (fiq_fix_enable)+	{+		if (!request_mem_region(_dev->resource[1].start,+	                                _dev->resource[1].end - _dev->resource[1].start + 1,+	                                "dwc_otg")) {+	          dev_dbg(&_dev->dev, "error reserving mapped memory\n");+	          retval = -EFAULT;+	          goto fail;+	}++		dwc_otg_device->os_dep.mphi_base = ioremap_nocache(_dev->resource[1].start,+							    _dev->resource[1].end -+							    _dev->resource[1].start + 1);+		dummy_send = (void *) kmalloc(16, GFP_ATOMIC);+	}++#else+        {+                struct map_desc desc = {+                    .virtual = IO_ADDRESS((unsigned)_dev->resource->start),+                    .pfn     = __phys_to_pfn((unsigned)_dev->resource->start),+                    .length  = SZ_128K,+                    .type    = MT_DEVICE+                };+                iotable_init(&desc, 1);+                dwc_otg_device->os_dep.base = (void *)desc.virtual;+        }+#endif+	if (!dwc_otg_device->os_dep.base) {+		dev_err(&_dev->dev, "ioremap() failed\n");+		retval = -ENOMEM;+		goto fail;+	}+	dev_dbg(&_dev->dev, "base=0x%08x\n",+                (unsigned)dwc_otg_device->os_dep.base);+#endif++	/*+	 * Initialize driver data to point to the global DWC_otg+	 * Device structure.+	 */+#ifdef LM_INTERFACE+	lm_set_drvdata(_dev, dwc_otg_device);+#elif defined(PLATFORM_INTERFACE)+	platform_set_drvdata(_dev, dwc_otg_device);+#endif+	dev_dbg(&_dev->dev, "dwc_otg_device=0x%p\n", dwc_otg_device);++	dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->os_dep.base);+        DWC_DEBUGPL(DBG_HCDV, "probe of device %p given core_if %p\n",+                    dwc_otg_device, dwc_otg_device->core_if);//GRAYG++	if (!dwc_otg_device->core_if) {+		dev_err(&_dev->dev, "CIL initialization failed!\n");+		retval = -ENOMEM;+		goto fail;+	}++	dev_dbg(&_dev->dev, "Calling get_gsnpsid\n");+	/*+	 * Attempt to ensure this device is really a DWC_otg Controller.+	 * Read and verify the SNPSID register contents. The value should be+	 * 0x45F42XXX or 0x45F42XXX, which corresponds to either "OT2" or "OTG3",+	 * as in "OTG version 2.XX" or "OTG version 3.XX".+	 */++	if (((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) !=	0x4F542000) &&+		((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) {+		dev_err(&_dev->dev, "Bad value for SNPSID: 0x%08x\n",+			dwc_otg_get_gsnpsid(dwc_otg_device->core_if));+		retval = -EINVAL;+		goto fail;+	}++	/*+	 * Validate parameter values.+	 */+	dev_dbg(&_dev->dev, "Calling set_parameters\n");+	if (set_parameters(dwc_otg_device->core_if)) {+		retval = -EINVAL;+		goto fail;+	}++	/*+	 * Create Device Attributes in sysfs+	 */+	dev_dbg(&_dev->dev, "Calling attr_create\n");+	dwc_otg_attr_create(_dev);++	/*+	 * Disable the global interrupt until all the interrupt+	 * handlers are installed.+	 */+	dev_dbg(&_dev->dev, "Calling disable_global_interrupts\n");+	dwc_otg_disable_global_interrupts(dwc_otg_device->core_if);++	/*+	 * Install the interrupt handler for the common interrupts before+	 * enabling common interrupts in core_init below.+	 */++#if defined(PLATFORM_INTERFACE)+        devirq = platform_get_irq(_dev, 0);+#else+        devirq = _dev->irq;+#endif+	DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n",+		    devirq);+	dev_dbg(&_dev->dev, "Calling request_irq(%d)\n", devirq);+	retval = request_irq(devirq, dwc_otg_common_irq,+                             IRQF_SHARED,+                             "dwc_otg", dwc_otg_device);+	if (retval) {+		DWC_ERROR("request of irq%d failed\n", devirq);+		retval = -EBUSY;+		goto fail;+	} else {+		dwc_otg_device->common_irq_installed = 1;+	}++#ifndef IRQF_TRIGGER_LOW+#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)+	dev_dbg(&_dev->dev, "Calling set_irq_type\n");+	set_irq_type(devirq,+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))+                     IRQT_LOW+#else+                     IRQ_TYPE_LEVEL_LOW+#endif+                    );+#endif+#endif /*IRQF_TRIGGER_LOW*/++	/*+	 * Initialize the DWC_otg core.+	 */+	dev_dbg(&_dev->dev, "Calling dwc_otg_core_init\n");+	dwc_otg_core_init(dwc_otg_device->core_if);++#ifndef DWC_HOST_ONLY+	/*+	 * Initialize the PCD+	 */+	dev_dbg(&_dev->dev, "Calling pcd_init\n");+	retval = pcd_init(_dev);+	if (retval != 0) {+		DWC_ERROR("pcd_init failed\n");+		dwc_otg_device->pcd = NULL;+		goto fail;+	}+#endif+#ifndef DWC_DEVICE_ONLY+	/*+	 * Initialize the HCD+	 */+	dev_dbg(&_dev->dev, "Calling hcd_init\n");+	retval = hcd_init(_dev);+	if (retval != 0) {+		DWC_ERROR("hcd_init failed\n");+		dwc_otg_device->hcd = NULL;+		goto fail;+	}+#endif+        /* Recover from drvdata having been overwritten by hcd_init() */+#ifdef LM_INTERFACE+	lm_set_drvdata(_dev, dwc_otg_device);+#elif defined(PLATFORM_INTERFACE)+	platform_set_drvdata(_dev, dwc_otg_device);+#elif defined(PCI_INTERFACE)+	pci_set_drvdata(_dev, dwc_otg_device);+	dwc_otg_device->os_dep.pcidev = _dev;+#endif++	/*+	 * Enable the global interrupt after all the interrupt+	 * handlers are installed if there is no ADP support else+	 * perform initial actions required for Internal ADP logic.+	 */+	if (!dwc_otg_get_param_adp_enable(dwc_otg_device->core_if)) {+	        dev_dbg(&_dev->dev, "Calling enable_global_interrupts\n");+		dwc_otg_enable_global_interrupts(dwc_otg_device->core_if);+	        dev_dbg(&_dev->dev, "Done\n");+	} else+		dwc_otg_adp_start(dwc_otg_device->core_if,+							dwc_otg_is_host_mode(dwc_otg_device->core_if));++	return 0;++fail:+	dwc_otg_driver_remove(_dev);+	return retval;+}++/**+ * This structure defines the methods to be called by a bus driver+ * during the lifecycle of a device on that bus. Both drivers and+ * devices are registered with a bus driver. The bus driver matches+ * devices to drivers based on information in the device and driver+ * structures.+ *+ * The probe function is called when the bus driver matches a device+ * to this driver. The remove function is called when a device is+ * unregistered with the bus driver.+ */+#ifdef LM_INTERFACE+static struct lm_driver dwc_otg_driver = {+	.drv = {.name = (char *)dwc_driver_name,},+	.probe = dwc_otg_driver_probe,+	.remove = dwc_otg_driver_remove,+        // 'suspend' and 'resume' absent+};+#elif defined(PCI_INTERFACE)+static const struct pci_device_id pci_ids[] = { {+						 PCI_DEVICE(0x16c3, 0xabcd),+						 .driver_data =+						 (unsigned long)0xdeadbeef,+						 }, { /* end: all zeroes */ }+};++MODULE_DEVICE_TABLE(pci, pci_ids);++/* pci driver glue; this is a "new style" PCI driver module */+static struct pci_driver dwc_otg_driver = {+	.name = "dwc_otg",+	.id_table = pci_ids,++	.probe = dwc_otg_driver_probe,+	.remove = dwc_otg_driver_remove,++	.driver = {+		   .name = (char *)dwc_driver_name,+		   },+};+#elif defined(PLATFORM_INTERFACE)+static struct platform_device_id platform_ids[] = {+        {+              .name = "bcm2708_usb",+              .driver_data = (kernel_ulong_t) 0xdeadbeef,+        },+        { /* end: all zeroes */ }+};+MODULE_DEVICE_TABLE(platform, platform_ids);++static struct platform_driver dwc_otg_driver = {+	.driver = {+		.name = (char *)dwc_driver_name,+		},+        .id_table = platform_ids,++	.probe = dwc_otg_driver_probe,+	.remove = dwc_otg_driver_remove,+        // no 'shutdown', 'suspend', 'resume', 'suspend_late' or 'resume_early'+};+#endif++/**+ * This function is called when the dwc_otg_driver is installed with the+ * insmod command. It registers the dwc_otg_driver structure with the+ * appropriate bus driver. This will cause the dwc_otg_driver_probe function+ * to be called. In addition, the bus driver will automatically expose+ * attributes defined for the device and driver in the special sysfs file+ * system.+ *+ * @return+ */+static int __init dwc_otg_driver_init(void)+{+	int retval = 0;+	int error;+        struct device_driver *drv;++	if(fiq_split_enable && !fiq_fix_enable) {+		printk(KERN_WARNING "dwc_otg: fiq_split_enable was set without fiq_fix_enable! Correcting.\n");+		fiq_fix_enable = 1;+	}++	printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name,+	       DWC_DRIVER_VERSION,+#ifdef LM_INTERFACE+               "logicmodule");+	retval = lm_driver_register(&dwc_otg_driver);+        drv = &dwc_otg_driver.drv;+#elif defined(PCI_INTERFACE)+               "pci");+	retval = pci_register_driver(&dwc_otg_driver);+        drv = &dwc_otg_driver.driver;+#elif defined(PLATFORM_INTERFACE)+               "platform");+	retval = platform_driver_register(&dwc_otg_driver);+        drv = &dwc_otg_driver.driver;+#endif+	if (retval < 0) {+		printk(KERN_ERR "%s retval=%d\n", __func__, retval);+		return retval;+	}+	printk(KERN_DEBUG "dwc_otg: FIQ %s\n", fiq_fix_enable ? "enabled":"disabled");+	printk(KERN_DEBUG "dwc_otg: NAK holdoff %s\n", nak_holdoff_enable ? "enabled":"disabled");+	printk(KERN_DEBUG "dwc_otg: FIQ split fix %s\n", fiq_split_enable ? "enabled":"disabled");++	error = driver_create_file(drv, &driver_attr_version);+#ifdef DEBUG+	error = driver_create_file(drv, &driver_attr_debuglevel);+#endif+	return retval;+}++module_init(dwc_otg_driver_init);++/**+ * This function is called when the driver is removed from the kernel+ * with the rmmod command. The driver unregisters itself with its bus+ * driver.+ *+ */+static void __exit dwc_otg_driver_cleanup(void)+{+	printk(KERN_DEBUG "dwc_otg_driver_cleanup()\n");++#ifdef LM_INTERFACE+	driver_remove_file(&dwc_otg_driver.drv, &driver_attr_debuglevel);+	driver_remove_file(&dwc_otg_driver.drv, &driver_attr_version);+	lm_driver_unregister(&dwc_otg_driver);+#elif defined(PCI_INTERFACE)+	driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);+	driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);+	pci_unregister_driver(&dwc_otg_driver);+#elif defined(PLATFORM_INTERFACE)+	driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);+	driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);+	platform_driver_unregister(&dwc_otg_driver);+#endif++	printk(KERN_INFO "%s module removed\n", dwc_driver_name);+}++module_exit(dwc_otg_driver_cleanup);++MODULE_DESCRIPTION(DWC_DRIVER_DESC);+MODULE_AUTHOR("Synopsys Inc.");+MODULE_LICENSE("GPL");++module_param_named(otg_cap, dwc_otg_module_params.otg_cap, int, 0444);+MODULE_PARM_DESC(otg_cap, "OTG Capabilities 0=HNP&SRP 1=SRP Only 2=None");+module_param_named(opt, dwc_otg_module_params.opt, int, 0444);+MODULE_PARM_DESC(opt, "OPT Mode");+module_param_named(dma_enable, dwc_otg_module_params.dma_enable, int, 0444);+MODULE_PARM_DESC(dma_enable, "DMA Mode 0=Slave 1=DMA enabled");++module_param_named(dma_desc_enable, dwc_otg_module_params.dma_desc_enable, int,+		   0444);+MODULE_PARM_DESC(dma_desc_enable,+		 "DMA Desc Mode 0=Address DMA 1=DMA Descriptor enabled");++module_param_named(dma_burst_size, dwc_otg_module_params.dma_burst_size, int,+		   0444);+MODULE_PARM_DESC(dma_burst_size,+		 "DMA Burst Size 1, 4, 8, 16, 32, 64, 128, 256");+module_param_named(speed, dwc_otg_module_params.speed, int, 0444);+MODULE_PARM_DESC(speed, "Speed 0=High Speed 1=Full Speed");+module_param_named(host_support_fs_ls_low_power,+		   dwc_otg_module_params.host_support_fs_ls_low_power, int,+		   0444);+MODULE_PARM_DESC(host_support_fs_ls_low_power,+		 "Support Low Power w/FS or LS 0=Support 1=Don't Support");+module_param_named(host_ls_low_power_phy_clk,+		   dwc_otg_module_params.host_ls_low_power_phy_clk, int, 0444);+MODULE_PARM_DESC(host_ls_low_power_phy_clk,+		 "Low Speed Low Power Clock 0=48Mhz 1=6Mhz");+module_param_named(enable_dynamic_fifo,+		   dwc_otg_module_params.enable_dynamic_fifo, int, 0444);+MODULE_PARM_DESC(enable_dynamic_fifo, "0=cC Setting 1=Allow Dynamic Sizing");+module_param_named(data_fifo_size, dwc_otg_module_params.data_fifo_size, int,+		   0444);+MODULE_PARM_DESC(data_fifo_size,+		 "Total number of words in the data FIFO memory 32-32768");+module_param_named(dev_rx_fifo_size, dwc_otg_module_params.dev_rx_fifo_size,+		   int, 0444);+MODULE_PARM_DESC(dev_rx_fifo_size, "Number of words in the Rx FIFO 16-32768");+module_param_named(dev_nperio_tx_fifo_size,+		   dwc_otg_module_params.dev_nperio_tx_fifo_size, int, 0444);+MODULE_PARM_DESC(dev_nperio_tx_fifo_size,+		 "Number of words in the non-periodic Tx FIFO 16-32768");+module_param_named(dev_perio_tx_fifo_size_1,+		   dwc_otg_module_params.dev_perio_tx_fifo_size[0], int, 0444);+MODULE_PARM_DESC(dev_perio_tx_fifo_size_1,+		 "Number of words in the periodic Tx FIFO 4-768");+module_param_named(dev_perio_tx_fifo_size_2,+		   dwc_otg_module_params.dev_perio_tx_fifo_size[1], int, 0444);+MODULE_PARM_DESC(dev_perio_tx_fifo_size_2,+		 "Number of words in the periodic Tx FIFO 4-768");+module_param_named(dev_perio_tx_fifo_size_3,+		   dwc_otg_module_params.dev_perio_tx_fifo_size[2], int, 0444);+MODULE_PARM_DESC(dev_perio_tx_fifo_size_3,+		 "Number of words in the periodic Tx FIFO 4-768");+module_param_named(dev_perio_tx_fifo_size_4,+		   dwc_otg_module_params.dev_perio_tx_fifo_size[3], int, 0444);+MODULE_PARM_DESC(dev_perio_tx_fifo_size_4,+		 "Number of words in the periodic Tx FIFO 4-768");+module_param_named(dev_perio_tx_fifo_size_5,+		   dwc_otg_module_params.dev_perio_tx_fifo_size[4], int, 0444);+MODULE_PARM_DESC(dev_perio_tx_fifo_size_5,+		 "Number of words in the periodic Tx FIFO 4-768");+module_param_named(dev_perio_tx_fifo_size_6,+		   dwc_otg_module_params.dev_perio_tx_fifo_size[5], int, 0444);+MODULE_PARM_DESC(dev_perio_tx_fifo_size_6,+		 "Number of words in the periodic Tx FIFO 4-768");+module_param_named(dev_perio_tx_fifo_size_7,+		   dwc_otg_module_params.dev_perio_tx_fifo_size[6], int, 0444);+MODULE_PARM_DESC(dev_perio_tx_fifo_size_7,+		 "Number of words in the periodic Tx FIFO 4-768");+module_param_named(dev_perio_tx_fifo_size_8,+		   dwc_otg_module_params.dev_perio_tx_fifo_size[7], int, 0444);+MODULE_PARM_DESC(dev_perio_tx_fifo_size_8,+		 "Number of words in the periodic Tx FIFO 4-768");+module_param_named(dev_perio_tx_fifo_size_9,+		   dwc_otg_module_params.dev_perio_tx_fifo_size[8], int, 0444);+MODULE_PARM_DESC(dev_perio_tx_fifo_size_9,+		 "Number of words in the periodic Tx FIFO 4-768");+module_param_named(dev_perio_tx_fifo_size_10,+		   dwc_otg_module_params.dev_perio_tx_fifo_size[9], int, 0444);+MODULE_PARM_DESC(dev_perio_tx_fifo_size_10,+		 "Number of words in the periodic Tx FIFO 4-768");+module_param_named(dev_perio_tx_fifo_size_11,+		   dwc_otg_module_params.dev_perio_tx_fifo_size[10], int, 0444);+MODULE_PARM_DESC(dev_perio_tx_fifo_size_11,+		 "Number of words in the periodic Tx FIFO 4-768");+module_param_named(dev_perio_tx_fifo_size_12,+		   dwc_otg_module_params.dev_perio_tx_fifo_size[11], int, 0444);+MODULE_PARM_DESC(dev_perio_tx_fifo_size_12,+		 "Number of words in the periodic Tx FIFO 4-768");+module_param_named(dev_perio_tx_fifo_size_13,+		   dwc_otg_module_params.dev_perio_tx_fifo_size[12], int, 0444);+MODULE_PARM_DESC(dev_perio_tx_fifo_size_13,+		 "Number of words in the periodic Tx FIFO 4-768");+module_param_named(dev_perio_tx_fifo_size_14,+		   dwc_otg_module_params.dev_perio_tx_fifo_size[13], int, 0444);+MODULE_PARM_DESC(dev_perio_tx_fifo_size_14,+		 "Number of words in the periodic Tx FIFO 4-768");+module_param_named(dev_perio_tx_fifo_size_15,+		   dwc_otg_module_params.dev_perio_tx_fifo_size[14], int, 0444);+MODULE_PARM_DESC(dev_perio_tx_fifo_size_15,+		 "Number of words in the periodic Tx FIFO 4-768");+module_param_named(host_rx_fifo_size, dwc_otg_module_params.host_rx_fifo_size,+		   int, 0444);+MODULE_PARM_DESC(host_rx_fifo_size, "Number of words in the Rx FIFO 16-32768");+module_param_named(host_nperio_tx_fifo_size,+		   dwc_otg_module_params.host_nperio_tx_fifo_size, int, 0444);+MODULE_PARM_DESC(host_nperio_tx_fifo_size,+		 "Number of words in the non-periodic Tx FIFO 16-32768");+module_param_named(host_perio_tx_fifo_size,+		   dwc_otg_module_params.host_perio_tx_fifo_size, int, 0444);+MODULE_PARM_DESC(host_perio_tx_fifo_size,+		 "Number of words in the host periodic Tx FIFO 16-32768");+module_param_named(max_transfer_size, dwc_otg_module_params.max_transfer_size,+		   int, 0444);+/** @todo Set the max to 512K, modify checks */+MODULE_PARM_DESC(max_transfer_size,+		 "The maximum transfer size supported in bytes 2047-65535");+module_param_named(max_packet_count, dwc_otg_module_params.max_packet_count,+		   int, 0444);+MODULE_PARM_DESC(max_packet_count,+		 "The maximum number of packets in a transfer 15-511");+module_param_named(host_channels, dwc_otg_module_params.host_channels, int,+		   0444);+MODULE_PARM_DESC(host_channels,+		 "The number of host channel registers to use 1-16");+module_param_named(dev_endpoints, dwc_otg_module_params.dev_endpoints, int,+		   0444);+MODULE_PARM_DESC(dev_endpoints,+		 "The number of endpoints in addition to EP0 available for device mode 1-15");+module_param_named(phy_type, dwc_otg_module_params.phy_type, int, 0444);+MODULE_PARM_DESC(phy_type, "0=Reserved 1=UTMI+ 2=ULPI");+module_param_named(phy_utmi_width, dwc_otg_module_params.phy_utmi_width, int,+		   0444);+MODULE_PARM_DESC(phy_utmi_width, "Specifies the UTMI+ Data Width 8 or 16 bits");+module_param_named(phy_ulpi_ddr, dwc_otg_module_params.phy_ulpi_ddr, int, 0444);+MODULE_PARM_DESC(phy_ulpi_ddr,+		 "ULPI at double or single data rate 0=Single 1=Double");+module_param_named(phy_ulpi_ext_vbus, dwc_otg_module_params.phy_ulpi_ext_vbus,+		   int, 0444);+MODULE_PARM_DESC(phy_ulpi_ext_vbus,+		 "ULPI PHY using internal or external vbus 0=Internal");+module_param_named(i2c_enable, dwc_otg_module_params.i2c_enable, int, 0444);+MODULE_PARM_DESC(i2c_enable, "FS PHY Interface");+module_param_named(ulpi_fs_ls, dwc_otg_module_params.ulpi_fs_ls, int, 0444);+MODULE_PARM_DESC(ulpi_fs_ls, "ULPI PHY FS/LS mode only");+module_param_named(ts_dline, dwc_otg_module_params.ts_dline, int, 0444);+MODULE_PARM_DESC(ts_dline, "Term select Dline pulsing for all PHYs");+module_param_named(debug, g_dbg_lvl, int, 0444);+MODULE_PARM_DESC(debug, "");++module_param_named(en_multiple_tx_fifo,+		   dwc_otg_module_params.en_multiple_tx_fifo, int, 0444);+MODULE_PARM_DESC(en_multiple_tx_fifo,+		 "Dedicated Non Periodic Tx FIFOs 0=disabled 1=enabled");+module_param_named(dev_tx_fifo_size_1,+		   dwc_otg_module_params.dev_tx_fifo_size[0], int, 0444);+MODULE_PARM_DESC(dev_tx_fifo_size_1, "Number of words in the Tx FIFO 4-768");+module_param_named(dev_tx_fifo_size_2,+		   dwc_otg_module_params.dev_tx_fifo_size[1], int, 0444);+MODULE_PARM_DESC(dev_tx_fifo_size_2, "Number of words in the Tx FIFO 4-768");+module_param_named(dev_tx_fifo_size_3,+		   dwc_otg_module_params.dev_tx_fifo_size[2], int, 0444);+MODULE_PARM_DESC(dev_tx_fifo_size_3, "Number of words in the Tx FIFO 4-768");+module_param_named(dev_tx_fifo_size_4,+		   dwc_otg_module_params.dev_tx_fifo_size[3], int, 0444);+MODULE_PARM_DESC(dev_tx_fifo_size_4, "Number of words in the Tx FIFO 4-768");+module_param_named(dev_tx_fifo_size_5,+		   dwc_otg_module_params.dev_tx_fifo_size[4], int, 0444);+MODULE_PARM_DESC(dev_tx_fifo_size_5, "Number of words in the Tx FIFO 4-768");+module_param_named(dev_tx_fifo_size_6,+		   dwc_otg_module_params.dev_tx_fifo_size[5], int, 0444);+MODULE_PARM_DESC(dev_tx_fifo_size_6, "Number of words in the Tx FIFO 4-768");+module_param_named(dev_tx_fifo_size_7,+		   dwc_otg_module_params.dev_tx_fifo_size[6], int, 0444);+MODULE_PARM_DESC(dev_tx_fifo_size_7, "Number of words in the Tx FIFO 4-768");+module_param_named(dev_tx_fifo_size_8,+		   dwc_otg_module_params.dev_tx_fifo_size[7], int, 0444);+MODULE_PARM_DESC(dev_tx_fifo_size_8, "Number of words in the Tx FIFO 4-768");+module_param_named(dev_tx_fifo_size_9,+		   dwc_otg_module_params.dev_tx_fifo_size[8], int, 0444);+MODULE_PARM_DESC(dev_tx_fifo_size_9, "Number of words in the Tx FIFO 4-768");+module_param_named(dev_tx_fifo_size_10,+		   dwc_otg_module_params.dev_tx_fifo_size[9], int, 0444);+MODULE_PARM_DESC(dev_tx_fifo_size_10, "Number of words in the Tx FIFO 4-768");+module_param_named(dev_tx_fifo_size_11,+		   dwc_otg_module_params.dev_tx_fifo_size[10], int, 0444);+MODULE_PARM_DESC(dev_tx_fifo_size_11, "Number of words in the Tx FIFO 4-768");+module_param_named(dev_tx_fifo_size_12,+		   dwc_otg_module_params.dev_tx_fifo_size[11], int, 0444);+MODULE_PARM_DESC(dev_tx_fifo_size_12, "Number of words in the Tx FIFO 4-768");+module_param_named(dev_tx_fifo_size_13,+		   dwc_otg_module_params.dev_tx_fifo_size[12], int, 0444);+MODULE_PARM_DESC(dev_tx_fifo_size_13, "Number of words in the Tx FIFO 4-768");+module_param_named(dev_tx_fifo_size_14,+		   dwc_otg_module_params.dev_tx_fifo_size[13], int, 0444);+MODULE_PARM_DESC(dev_tx_fifo_size_14, "Number of words in the Tx FIFO 4-768");+module_param_named(dev_tx_fifo_size_15,+		   dwc_otg_module_params.dev_tx_fifo_size[14], int, 0444);+MODULE_PARM_DESC(dev_tx_fifo_size_15, "Number of words in the Tx FIFO 4-768");++module_param_named(thr_ctl, dwc_otg_module_params.thr_ctl, int, 0444);+MODULE_PARM_DESC(thr_ctl,+		 "Thresholding enable flag bit 0 - non ISO Tx thr., 1 - ISO Tx thr., 2 - Rx thr.- bit 0=disabled 1=enabled");+module_param_named(tx_thr_length, dwc_otg_module_params.tx_thr_length, int,+		   0444);+MODULE_PARM_DESC(tx_thr_length, "Tx Threshold length in 32 bit DWORDs");+module_param_named(rx_thr_length, dwc_otg_module_params.rx_thr_length, int,+		   0444);+MODULE_PARM_DESC(rx_thr_length, "Rx Threshold length in 32 bit DWORDs");++module_param_named(pti_enable, dwc_otg_module_params.pti_enable, int, 0444);+module_param_named(mpi_enable, dwc_otg_module_params.mpi_enable, int, 0444);+module_param_named(lpm_enable, dwc_otg_module_params.lpm_enable, int, 0444);+MODULE_PARM_DESC(lpm_enable, "LPM Enable 0=LPM Disabled 1=LPM Enabled");+module_param_named(ic_usb_cap, dwc_otg_module_params.ic_usb_cap, int, 0444);+MODULE_PARM_DESC(ic_usb_cap,+		 "IC_USB Capability 0=IC_USB Disabled 1=IC_USB Enabled");+module_param_named(ahb_thr_ratio, dwc_otg_module_params.ahb_thr_ratio, int,+		   0444);+MODULE_PARM_DESC(ahb_thr_ratio, "AHB Threshold Ratio");+module_param_named(power_down, dwc_otg_module_params.power_down, int, 0444);+MODULE_PARM_DESC(power_down, "Power Down Mode");+module_param_named(reload_ctl, dwc_otg_module_params.reload_ctl, int, 0444);+MODULE_PARM_DESC(reload_ctl, "HFIR Reload Control");+module_param_named(dev_out_nak, dwc_otg_module_params.dev_out_nak, int, 0444);+MODULE_PARM_DESC(dev_out_nak, "Enable Device OUT NAK");+module_param_named(cont_on_bna, dwc_otg_module_params.cont_on_bna, int, 0444);+MODULE_PARM_DESC(cont_on_bna, "Enable Enable Continue on BNA");+module_param_named(ahb_single, dwc_otg_module_params.ahb_single, int, 0444);+MODULE_PARM_DESC(ahb_single, "Enable AHB Single Support");+module_param_named(adp_enable, dwc_otg_module_params.adp_enable, int, 0444);+MODULE_PARM_DESC(adp_enable, "ADP Enable 0=ADP Disabled 1=ADP Enabled");+module_param_named(otg_ver, dwc_otg_module_params.otg_ver, int, 0444);+MODULE_PARM_DESC(otg_ver, "OTG revision supported 0=OTG 1.3 1=OTG 2.0");+module_param(microframe_schedule, bool, 0444);+MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler");++module_param(fiq_fix_enable, bool, 0444);+MODULE_PARM_DESC(fiq_fix_enable, "Enable the fiq fix");+module_param(nak_holdoff_enable, bool, 0444);+MODULE_PARM_DESC(nak_holdoff_enable, "Enable the NAK holdoff");+module_param(fiq_split_enable, bool, 0444);+MODULE_PARM_DESC(fiq_split_enable, "Enable the FIQ fix on split transactions");++/** @page "Module Parameters"+ *+ * The following parameters may be specified when starting the module.+ * These parameters define how the DWC_otg controller should be+ * configured. Parameter values are passed to the CIL initialization+ * function dwc_otg_cil_init+ *+ * Example: <code>modprobe dwc_otg speed=1 otg_cap=1</code>+ *++ <table>+ <tr><td>Parameter Name</td><td>Meaning</td></tr>++ <tr>+ <td>otg_cap</td>+ <td>Specifies the OTG capabilities. The driver will automatically detect the+ value for this parameter if none is specified.+ - 0: HNP and SRP capable (default, if available)+ - 1: SRP Only capable+ - 2: No HNP/SRP capable+ </td></tr>++ <tr>+ <td>dma_enable</td>+ <td>Specifies whether to use slave or DMA mode for accessing the data FIFOs.+ The driver will automatically detect the value for this parameter if none is+ specified.+ - 0: Slave+ - 1: DMA (default, if available)+ </td></tr>++ <tr>+ <td>dma_burst_size</td>+ <td>The DMA Burst size (applicable only for External DMA Mode).+ - Values: 1, 4, 8 16, 32, 64, 128, 256 (default 32)+ </td></tr>++ <tr>+ <td>speed</td>+ <td>Specifies the maximum speed of operation in host and device mode. The+ actual speed depends on the speed of the attached device and the value of+ phy_type.+ - 0: High Speed (default)+ - 1: Full Speed+ </td></tr>++ <tr>+ <td>host_support_fs_ls_low_power</td>+ <td>Specifies whether low power mode is supported when attached to a Full+ Speed or Low Speed device in host mode.+ - 0: Don't support low power mode (default)+ - 1: Support low power mode+ </td></tr>++ <tr>+ <td>host_ls_low_power_phy_clk</td>+ <td>Specifies the PHY clock rate in low power mode when connected to a Low+ Speed device in host mode. This parameter is applicable only if+ HOST_SUPPORT_FS_LS_LOW_POWER is enabled.+ - 0: 48 MHz (default)+ - 1: 6 MHz+ </td></tr>++ <tr>+ <td>enable_dynamic_fifo</td>+ <td> Specifies whether FIFOs may be resized by the driver software.+ - 0: Use cC FIFO size parameters+ - 1: Allow dynamic FIFO sizing (default)+ </td></tr>++ <tr>+ <td>data_fifo_size</td>+ <td>Total number of 4-byte words in the data FIFO memory. This memory+ includes the Rx FIFO, non-periodic Tx FIFO, and periodic Tx FIFOs.+ - Values: 32 to 32768 (default 8192)++ Note: The total FIFO memory depth in the FPGA configuration is 8192.+ </td></tr>++ <tr>+ <td>dev_rx_fifo_size</td>+ <td>Number of 4-byte words in the Rx FIFO in device mode when dynamic+ FIFO sizing is enabled.+ - Values: 16 to 32768 (default 1064)+ </td></tr>++ <tr>+ <td>dev_nperio_tx_fifo_size</td>+ <td>Number of 4-byte words in the non-periodic Tx FIFO in device mode when+ dynamic FIFO sizing is enabled.+ - Values: 16 to 32768 (default 1024)+ </td></tr>++ <tr>+ <td>dev_perio_tx_fifo_size_n (n = 1 to 15)</td>+ <td>Number of 4-byte words in each of the periodic Tx FIFOs in device mode+ when dynamic FIFO sizing is enabled.+ - Values: 4 to 768 (default 256)+ </td></tr>++ <tr>+ <td>host_rx_fifo_size</td>+ <td>Number of 4-byte words in the Rx FIFO in host mode when dynamic FIFO+ sizing is enabled.+ - Values: 16 to 32768 (default 1024)+ </td></tr>++ <tr>+ <td>host_nperio_tx_fifo_size</td>+ <td>Number of 4-byte words in the non-periodic Tx FIFO in host mode when+ dynamic FIFO sizing is enabled in the core.+ - Values: 16 to 32768 (default 1024)+ </td></tr>++ <tr>+ <td>host_perio_tx_fifo_size</td>+ <td>Number of 4-byte words in the host periodic Tx FIFO when dynamic FIFO+ sizing is enabled.+ - Values: 16 to 32768 (default 1024)+ </td></tr>++ <tr>+ <td>max_transfer_size</td>+ <td>The maximum transfer size supported in bytes.+ - Values: 2047 to 65,535 (default 65,535)+ </td></tr>++ <tr>+ <td>max_packet_count</td>+ <td>The maximum number of packets in a transfer.+ - Values: 15 to 511 (default 511)+ </td></tr>++ <tr>+ <td>host_channels</td>+ <td>The number of host channel registers to use.+ - Values: 1 to 16 (default 12)++ Note: The FPGA configuration supports a maximum of 12 host channels.+ </td></tr>++ <tr>+ <td>dev_endpoints</td>+ <td>The number of endpoints in addition to EP0 available for device mode+ operations.+ - Values: 1 to 15 (default 6 IN and OUT)++ Note: The FPGA configuration supports a maximum of 6 IN and OUT endpoints in+ addition to EP0.+ </td></tr>++ <tr>+ <td>phy_type</td>+ <td>Specifies the type of PHY interface to use. By default, the driver will+ automatically detect the phy_type.+ - 0: Full Speed+ - 1: UTMI+ (default, if available)+ - 2: ULPI+ </td></tr>++ <tr>+ <td>phy_utmi_width</td>+ <td>Specifies the UTMI+ Data Width. This parameter is applicable for a+ phy_type of UTMI+. Also, this parameter is applicable only if the+ OTG_HSPHY_WIDTH cC parameter was set to "8 and 16 bits", meaning that the+ core has been configured to work at either data path width.+ - Values: 8 or 16 bits (default 16)+ </td></tr>++ <tr>+ <td>phy_ulpi_ddr</td>+ <td>Specifies whether the ULPI operates at double or single data rate. This+ parameter is only applicable if phy_type is ULPI.+ - 0: single data rate ULPI interface with 8 bit wide data bus (default)+ - 1: double data rate ULPI interface with 4 bit wide data bus+ </td></tr>++ <tr>+ <td>i2c_enable</td>+ <td>Specifies whether to use the I2C interface for full speed PHY. This+ parameter is only applicable if PHY_TYPE is FS.+ - 0: Disabled (default)+ - 1: Enabled+ </td></tr>++ <tr>+ <td>ulpi_fs_ls</td>+ <td>Specifies whether to use ULPI FS/LS mode only.+ - 0: Disabled (default)+ - 1: Enabled+ </td></tr>++ <tr>+ <td>ts_dline</td>+ <td>Specifies whether term select D-Line pulsing for all PHYs is enabled.+ - 0: Disabled (default)+ - 1: Enabled+ </td></tr>++ <tr>+ <td>en_multiple_tx_fifo</td>+ <td>Specifies whether dedicatedto tx fifos are enabled for non periodic IN EPs.+ The driver will automatically detect the value for this parameter if none is+ specified.+ - 0: Disabled+ - 1: Enabled (default, if available)+ </td></tr>++ <tr>+ <td>dev_tx_fifo_size_n (n = 1 to 15)</td>+ <td>Number of 4-byte words in each of the Tx FIFOs in device mode+ when dynamic FIFO sizing is enabled.+ - Values: 4 to 768 (default 256)+ </td></tr>++ <tr>+ <td>tx_thr_length</td>+ <td>Transmit Threshold length in 32 bit double words+ - Values: 8 to 128 (default 64)+ </td></tr>++ <tr>+ <td>rx_thr_length</td>+ <td>Receive Threshold length in 32 bit double words+ - Values: 8 to 128 (default 64)+ </td></tr>++<tr>+ <td>thr_ctl</td>+ <td>Specifies whether to enable Thresholding for Device mode. Bits 0, 1, 2 of+ this parmater specifies if thresholding is enabled for non-Iso Tx, Iso Tx and+ Rx transfers accordingly.+ The driver will automatically detect the value for this parameter if none is+ specified.+ - Values: 0 to 7 (default 0)+ Bit values indicate:+ - 0: Thresholding disabled+ - 1: Thresholding enabled+ </td></tr>++<tr>+ <td>dma_desc_enable</td>+ <td>Specifies whether to enable Descriptor DMA mode.+ The driver will automatically detect the value for this parameter if none is+ specified.+ - 0: Descriptor DMA disabled+ - 1: Descriptor DMA (default, if available)+ </td></tr>++<tr>+ <td>mpi_enable</td>+ <td>Specifies whether to enable MPI enhancement mode.+ The driver will automatically detect the value for this parameter if none is+ specified.+ - 0: MPI disabled (default)+ - 1: MPI enable+ </td></tr>++<tr>+ <td>pti_enable</td>+ <td>Specifies whether to enable PTI enhancement support.+ The driver will automatically detect the value for this parameter if none is+ specified.+ - 0: PTI disabled (default)+ - 1: PTI enable+ </td></tr>++<tr>+ <td>lpm_enable</td>+ <td>Specifies whether to enable LPM support.+ The driver will automatically detect the value for this parameter if none is+ specified.+ - 0: LPM disabled+ - 1: LPM enable (default, if available)+ </td></tr>++<tr>+ <td>ic_usb_cap</td>+ <td>Specifies whether to enable IC_USB capability.+ The driver will automatically detect the value for this parameter if none is+ specified.+ - 0: IC_USB disabled (default, if available)+ - 1: IC_USB enable+ </td></tr>++<tr>+ <td>ahb_thr_ratio</td>+ <td>Specifies AHB Threshold ratio.+ - Values: 0 to 3 (default 0)+ </td></tr>++<tr>+ <td>power_down</td>+ <td>Specifies Power Down(Hibernation) Mode.+ The driver will automatically detect the value for this parameter if none is+ specified.+ - 0: Power Down disabled (default)+ - 2: Power Down enabled+ </td></tr>++ <tr>+ <td>reload_ctl</td>+ <td>Specifies whether dynamic reloading of the HFIR register is allowed during+ run time. The driver will automatically detect the value for this parameter if+ none is specified. In case the HFIR value is reloaded when HFIR.RldCtrl == 1'b0+ the core might misbehave.+ - 0: Reload Control disabled (default)+ - 1: Reload Control enabled+ </td></tr>++ <tr>+ <td>dev_out_nak</td>+ <td>Specifies whether  Device OUT NAK enhancement enabled or no.+ The driver will automatically detect the value for this parameter if+ none is specified. This parameter is valid only when OTG_EN_DESC_DMA == 1b1.+ - 0: The core does not set NAK after Bulk OUT transfer complete (default)+ - 1: The core sets NAK after Bulk OUT transfer complete+ </td></tr>++ <tr>+ <td>cont_on_bna</td>+ <td>Specifies whether Enable Continue on BNA enabled or no.+ After receiving BNA interrupt the core disables the endpoint,when the+ endpoint is re-enabled by the application the+ - 0: Core starts processing from the DOEPDMA descriptor (default)+ - 1: Core starts processing from the descriptor which received the BNA.+ This parameter is valid only when OTG_EN_DESC_DMA == 1b1.+ </td></tr>++ <tr>+ <td>ahb_single</td>+ <td>This bit when programmed supports SINGLE transfers for remainder data+ in a transfer for DMA mode of operation.+ - 0: The remainder data will be sent using INCR burst size (default)+ - 1: The remainder data will be sent using SINGLE burst size.+ </td></tr>++<tr>+ <td>adp_enable</td>+ <td>Specifies whether ADP feature is enabled.+ The driver will automatically detect the value for this parameter if none is+ specified.+ - 0: ADP feature disabled (default)+ - 1: ADP feature enabled+ </td></tr>++  <tr>+ <td>otg_ver</td>+ <td>Specifies whether OTG is performing as USB OTG Revision 2.0 or Revision 1.3+ USB OTG device.+ - 0: OTG 2.0 support disabled (default)+ - 1: OTG 2.0 support enabled+ </td></tr>++*/diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_driver.h linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_driver.h--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_driver.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_driver.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,86 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $+ * $Revision: #19 $+ * $Date: 2010/11/15 $+ * $Change: 1627671 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */++#ifndef __DWC_OTG_DRIVER_H__+#define __DWC_OTG_DRIVER_H__++/** @file+ * This file contains the interface to the Linux driver.+ */+#include "dwc_otg_os_dep.h"+#include "dwc_otg_core_if.h"++/* Type declarations */+struct dwc_otg_pcd;+struct dwc_otg_hcd;++/**+ * This structure is a wrapper that encapsulates the driver components used to+ * manage a single DWC_otg controller.+ */+typedef struct dwc_otg_device {+	/** Structure containing OS-dependent stuff. KEEP THIS STRUCT AT THE+	 * VERY BEGINNING OF THE DEVICE STRUCT. OSes such as FreeBSD and NetBSD+	 * require this. */+	struct os_dependent os_dep;++	/** Pointer to the core interface structure. */+	dwc_otg_core_if_t *core_if;++	/** Pointer to the PCD structure. */+	struct dwc_otg_pcd *pcd;++	/** Pointer to the HCD structure. */+	struct dwc_otg_hcd *hcd;++	/** Flag to indicate whether the common IRQ handler is installed. */+	uint8_t common_irq_installed;++} dwc_otg_device_t;++/*We must clear S3C24XX_EINTPEND external interrupt register+ * because after clearing in this register trigerred IRQ from+ * H/W core in kernel interrupt can be occured again before OTG+ * handlers clear all IRQ sources of Core registers because of+ * timing latencies and Low Level IRQ Type.+ */+#ifdef CONFIG_MACH_IPMATE+#define  S3C2410X_CLEAR_EINTPEND()   \+do { \+	__raw_writel(1UL << 11,S3C24XX_EINTPEND); \+} while (0)+#else+#define  S3C2410X_CLEAR_EINTPEND()   do { } while (0)+#endif++#endifdiff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_hcd.c--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_hcd.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,3674 @@++/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $+ * $Revision: #104 $+ * $Date: 2011/10/24 $+ * $Change: 1871159 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */+#ifndef DWC_DEVICE_ONLY++/** @file+ * This file implements HCD Core. All code in this file is portable and doesn't+ * use any OS specific functions.+ * Interface provided by HCD Core is defined in <code><hcd_if.h></code>+ * header file.+ */++#include <linux/usb.h>+#include <linux/usb/hcd.h>++#include "dwc_otg_hcd.h"+#include "dwc_otg_regs.h"+#include "dwc_otg_mphi_fix.h"++extern bool microframe_schedule, nak_holdoff_enable;++//#define DEBUG_HOST_CHANNELS+#ifdef DEBUG_HOST_CHANNELS+static int last_sel_trans_num_per_scheduled = 0;+static int last_sel_trans_num_nonper_scheduled = 0;+static int last_sel_trans_num_avail_hc_at_start = 0;+static int last_sel_trans_num_avail_hc_at_end = 0;+#endif /* DEBUG_HOST_CHANNELS */++extern int g_next_sched_frame, g_np_count, g_np_sent;++extern haint_data_t haint_saved;+extern hcintmsk_data_t hcintmsk_saved[MAX_EPS_CHANNELS];+extern hcint_data_t hcint_saved[MAX_EPS_CHANNELS];+extern gintsts_data_t ginsts_saved;++dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)+{+	return DWC_ALLOC(sizeof(dwc_otg_hcd_t));+}++/**+ * Connection timeout function.  An OTG host is required to display a+ * message if the device does not connect within 10 seconds.+ */+void dwc_otg_hcd_connect_timeout(void *ptr)+{+	DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, ptr);+	DWC_PRINTF("Connect Timeout\n");+	__DWC_ERROR("Device Not Connected/Responding\n");+}++#if defined(DEBUG)+static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)+{+	if (qh->channel != NULL) {+		dwc_hc_t *hc = qh->channel;+		dwc_list_link_t *item;+		dwc_otg_qh_t *qh_item;+		int num_channels = hcd->core_if->core_params->host_channels;+		int i;++		dwc_otg_hc_regs_t *hc_regs;+		hcchar_data_t hcchar;+		hcsplt_data_t hcsplt;+		hctsiz_data_t hctsiz;+		uint32_t hcdma;++		hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num];+		hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+		hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);+		hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);+		hcdma = DWC_READ_REG32(&hc_regs->hcdma);++		DWC_PRINTF("  Assigned to channel %p:\n", hc);+		DWC_PRINTF("    hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32,+			   hcsplt.d32);+		DWC_PRINTF("    hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32,+			   hcdma);+		DWC_PRINTF("    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",+			   hc->dev_addr, hc->ep_num, hc->ep_is_in);+		DWC_PRINTF("    ep_type: %d\n", hc->ep_type);+		DWC_PRINTF("    max_packet: %d\n", hc->max_packet);+		DWC_PRINTF("    data_pid_start: %d\n", hc->data_pid_start);+		DWC_PRINTF("    xfer_started: %d\n", hc->xfer_started);+		DWC_PRINTF("    halt_status: %d\n", hc->halt_status);+		DWC_PRINTF("    xfer_buff: %p\n", hc->xfer_buff);+		DWC_PRINTF("    xfer_len: %d\n", hc->xfer_len);+		DWC_PRINTF("    qh: %p\n", hc->qh);+		DWC_PRINTF("  NP inactive sched:\n");+		DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_inactive) {+			qh_item =+			    DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);+			DWC_PRINTF("    %p\n", qh_item);+		}+		DWC_PRINTF("  NP active sched:\n");+		DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_active) {+			qh_item =+			    DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);+			DWC_PRINTF("    %p\n", qh_item);+		}+		DWC_PRINTF("  Channels: \n");+		for (i = 0; i < num_channels; i++) {+			dwc_hc_t *hc = hcd->hc_ptr_array[i];+			DWC_PRINTF("    %2d: %p\n", i, hc);+		}+	}+}+#else+#define dump_channel_info(hcd, qh)+#endif /* DEBUG */++/**+ * Work queue function for starting the HCD when A-Cable is connected.+ * The hcd_start() must be called in a process context.+ */+static void hcd_start_func(void *_vp)+{+	dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) _vp;++	DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, hcd);+	if (hcd) {+		hcd->fops->start(hcd);+	}+}++static void del_xfer_timers(dwc_otg_hcd_t * hcd)+{+#ifdef DEBUG+	int i;+	int num_channels = hcd->core_if->core_params->host_channels;+	for (i = 0; i < num_channels; i++) {+		DWC_TIMER_CANCEL(hcd->core_if->hc_xfer_timer[i]);+	}+#endif+}++static void del_timers(dwc_otg_hcd_t * hcd)+{+	del_xfer_timers(hcd);+	DWC_TIMER_CANCEL(hcd->conn_timer);+}++/**+ * Processes all the URBs in a single list of QHs. Completes them with+ * -ESHUTDOWN and frees the QTD.+ */+static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)+{+	dwc_list_link_t *qh_item, *qh_tmp;+	dwc_otg_qh_t *qh;+	dwc_otg_qtd_t *qtd, *qtd_tmp;++	DWC_LIST_FOREACH_SAFE(qh_item, qh_tmp, qh_list) {+		qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry);+		DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp,+					 &qh->qtd_list, qtd_list_entry) {+			qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);+			if (qtd->urb != NULL) {+				hcd->fops->complete(hcd, qtd->urb->priv,+						    qtd->urb, -DWC_E_SHUTDOWN);+				dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);+			}++		}+		if(qh->channel) {+			/* Using hcchar.chen == 1 is not a reliable test.+			 * It is possible that the channel has already halted+			 * but not yet been through the IRQ handler.+			 */+			dwc_otg_hc_halt(hcd->core_if, qh->channel,+				DWC_OTG_HC_XFER_URB_DEQUEUE);+			if(microframe_schedule)+				hcd->available_host_channels++;+			qh->channel = NULL;+		}+		dwc_otg_hcd_qh_remove(hcd, qh);+	}+}++/**+ * Responds with an error status of ESHUTDOWN to all URBs in the non-periodic+ * and periodic schedules. The QTD associated with each URB is removed from+ * the schedule and freed. This function may be called when a disconnect is+ * detected or when the HCD is being stopped.+ */+static void kill_all_urbs(dwc_otg_hcd_t * hcd)+{+	kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive);+	kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active);+	kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive);+	kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready);+	kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned);+	kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued);+}++/**+ * Start the connection timer.  An OTG host is required to display a+ * message if the device does not connect within 10 seconds.  The+ * timer is deleted if a port connect interrupt occurs before the+ * timer expires.+ */+static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t * hcd)+{+	DWC_TIMER_SCHEDULE(hcd->conn_timer, 10000 /* 10 secs */ );+}++/**+ * HCD Callback function for disconnect of the HCD.+ *+ * @param p void pointer to the <code>struct usb_hcd</code>+ */+static int32_t dwc_otg_hcd_session_start_cb(void *p)+{+	dwc_otg_hcd_t *dwc_otg_hcd;+	DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);+	dwc_otg_hcd = p;+	dwc_otg_hcd_start_connect_timer(dwc_otg_hcd);+	return 1;+}++/**+ * HCD Callback function for starting the HCD when A-Cable is+ * connected.+ *+ * @param p void pointer to the <code>struct usb_hcd</code>+ */+static int32_t dwc_otg_hcd_start_cb(void *p)+{+	dwc_otg_hcd_t *dwc_otg_hcd = p;+	dwc_otg_core_if_t *core_if;+	hprt0_data_t hprt0;++	core_if = dwc_otg_hcd->core_if;++	if (core_if->op_state == B_HOST) {+		/*+		 * Reset the port.  During a HNP mode switch the reset+		 * needs to occur within 1ms and have a duration of at+		 * least 50ms.+		 */+		hprt0.d32 = dwc_otg_read_hprt0(core_if);+		hprt0.b.prtrst = 1;+		DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+	}+	DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg,+				   hcd_start_func, dwc_otg_hcd, 50,+				   "start hcd");++	return 1;+}++/**+ * HCD Callback function for disconnect of the HCD.+ *+ * @param p void pointer to the <code>struct usb_hcd</code>+ */+static int32_t dwc_otg_hcd_disconnect_cb(void *p)+{+	gintsts_data_t intr;+	dwc_otg_hcd_t *dwc_otg_hcd = p;++	/*+	 * Set status flags for the hub driver.+	 */+	dwc_otg_hcd->flags.b.port_connect_status_change = 1;+	dwc_otg_hcd->flags.b.port_connect_status = 0;+	if(fiq_fix_enable)+		local_fiq_disable();+	/*+	 * Shutdown any transfers in process by clearing the Tx FIFO Empty+	 * interrupt mask and status bits and disabling subsequent host+	 * channel interrupts.+	 */+	intr.d32 = 0;+	intr.b.nptxfempty = 1;+	intr.b.ptxfempty = 1;+	intr.b.hcintr = 1;+	DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk,+			 intr.d32, 0);+	DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintsts,+			 intr.d32, 0);++	del_timers(dwc_otg_hcd);++	/*+	 * Turn off the vbus power only if the core has transitioned to device+	 * mode. If still in host mode, need to keep power on to detect a+	 * reconnection.+	 */+	if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) {+		if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) {+			hprt0_data_t hprt0 = {.d32 = 0 };+			DWC_PRINTF("Disconnect: PortPower off\n");+			hprt0.b.prtpwr = 0;+			DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0,+					hprt0.d32);+		}++		dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if);+	}++	/* Respond with an error status to all URBs in the schedule. */+	kill_all_urbs(dwc_otg_hcd);++	if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) {+		/* Clean up any host channels that were in use. */+		int num_channels;+		int i;+		dwc_hc_t *channel;+		dwc_otg_hc_regs_t *hc_regs;+		hcchar_data_t hcchar;++		num_channels = dwc_otg_hcd->core_if->core_params->host_channels;++		if (!dwc_otg_hcd->core_if->dma_enable) {+			/* Flush out any channel requests in slave mode. */+			for (i = 0; i < num_channels; i++) {+				channel = dwc_otg_hcd->hc_ptr_array[i];+				if (DWC_CIRCLEQ_EMPTY_ENTRY+				    (channel, hc_list_entry)) {+					hc_regs =+					    dwc_otg_hcd->core_if->+					    host_if->hc_regs[i];+					hcchar.d32 =+					    DWC_READ_REG32(&hc_regs->hcchar);+					if (hcchar.b.chen) {+						hcchar.b.chen = 0;+						hcchar.b.chdis = 1;+						hcchar.b.epdir = 0;+						DWC_WRITE_REG32+						    (&hc_regs->hcchar,+						     hcchar.d32);+					}+				}+			}+		}++		for (i = 0; i < num_channels; i++) {+			channel = dwc_otg_hcd->hc_ptr_array[i];+			if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) {+				hc_regs =+				    dwc_otg_hcd->core_if->host_if->hc_regs[i];+				hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+				if (hcchar.b.chen) {+					/* Halt the channel. */+					hcchar.b.chdis = 1;+					DWC_WRITE_REG32(&hc_regs->hcchar,+							hcchar.d32);+				}++				dwc_otg_hc_cleanup(dwc_otg_hcd->core_if,+						   channel);+				DWC_CIRCLEQ_INSERT_TAIL+				    (&dwc_otg_hcd->free_hc_list, channel,+				     hc_list_entry);+				/*+				 * Added for Descriptor DMA to prevent channel double cleanup+				 * in release_channel_ddma(). Which called from ep_disable+				 * when device disconnect.+				 */+				channel->qh = NULL;+			}+		}+		if(fiq_split_enable) {+			for(i=0; i < 128; i++) {+				dwc_otg_hcd->hub_port[i] = 0;+			}+			haint_saved.d32 = 0;+			for(i=0; i < MAX_EPS_CHANNELS; i++) {+				hcint_saved[i].d32 = 0;+				hcintmsk_saved[i].d32 = 0;+			}+		}++	}++	if(fiq_fix_enable)+		local_fiq_enable();++	if (dwc_otg_hcd->fops->disconnect) {+		dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);+	}++	return 1;+}++/**+ * HCD Callback function for stopping the HCD.+ *+ * @param p void pointer to the <code>struct usb_hcd</code>+ */+static int32_t dwc_otg_hcd_stop_cb(void *p)+{+	dwc_otg_hcd_t *dwc_otg_hcd = p;++	DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);+	dwc_otg_hcd_stop(dwc_otg_hcd);+	return 1;+}++#ifdef CONFIG_USB_DWC_OTG_LPM+/**+ * HCD Callback function for sleep of HCD.+ *+ * @param p void pointer to the <code>struct usb_hcd</code>+ */+static int dwc_otg_hcd_sleep_cb(void *p)+{+	dwc_otg_hcd_t *hcd = p;++	dwc_otg_hcd_free_hc_from_lpm(hcd);++	return 0;+}+#endif+++/**+ * HCD Callback function for Remote Wakeup.+ *+ * @param p void pointer to the <code>struct usb_hcd</code>+ */+static int dwc_otg_hcd_rem_wakeup_cb(void *p)+{+	dwc_otg_hcd_t *hcd = p;++	if (hcd->core_if->lx_state == DWC_OTG_L2) {+		hcd->flags.b.port_suspend_change = 1;+	}+#ifdef CONFIG_USB_DWC_OTG_LPM+	else {+		hcd->flags.b.port_l1_change = 1;+	}+#endif+	return 0;+}++/**+ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are+ * stopped.+ */+void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd)+{+	hprt0_data_t hprt0 = {.d32 = 0 };++	DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n");++	/*+	 * The root hub should be disconnected before this function is called.+	 * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue)+	 * and the QH lists (via ..._hcd_endpoint_disable).+	 */++	/* Turn off all host-specific interrupts. */+	dwc_otg_disable_host_interrupts(hcd->core_if);++	/* Turn off the vbus power */+	DWC_PRINTF("PortPower off\n");+	hprt0.b.prtpwr = 0;+	DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32);+	dwc_mdelay(1);+}++int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd,+			    dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle,+			    int atomic_alloc)+{+	int retval = 0;+	uint8_t needs_scheduling = 0;+	dwc_otg_transaction_type_e tr_type;+	dwc_otg_qtd_t *qtd;+	gintmsk_data_t intr_mask = {.d32 = 0 };++#ifdef DEBUG /* integrity checks (Broadcom) */+	if (NULL == hcd->core_if) {+		DWC_ERROR("**** DWC OTG HCD URB Enqueue - HCD has NULL core_if\n");+		/* No longer connected. */+		return -DWC_E_INVALID;+	}+#endif+	if (!hcd->flags.b.port_connect_status) {+		/* No longer connected. */+		DWC_ERROR("Not connected\n");+		return -DWC_E_NO_DEVICE;+	}++	qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc);+	if (qtd == NULL) {+		DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");+		return -DWC_E_NO_MEMORY;+	}+#ifdef DEBUG /* integrity checks (Broadcom) */+	if (qtd->urb == NULL) {+		DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD with no URBs\n");+		return -DWC_E_NO_MEMORY;+	}+	if (qtd->urb->priv == NULL) {+		DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD URB with no URB handle\n");+		return -DWC_E_NO_MEMORY;+	}+#endif+	intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);+	if(!intr_mask.b.sofintr) needs_scheduling = 1;+	if((((dwc_otg_qh_t *)ep_handle)->ep_type == UE_BULK) && !(qtd->urb->flags & URB_GIVEBACK_ASAP))+		/* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */+		needs_scheduling = 0;++	retval = dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc);+            // creates a new queue in ep_handle if it doesn't exist already+	if (retval < 0) {+		DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "+			  "Error status %d\n", retval);+		dwc_otg_hcd_qtd_free(qtd);+		return retval;+	}++	if(needs_scheduling) {+		tr_type = dwc_otg_hcd_select_transactions(hcd);+		if (tr_type != DWC_OTG_TRANSACTION_NONE) {+			dwc_otg_hcd_queue_transactions(hcd, tr_type);+		}+	}+	return retval;+}++int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,+			    dwc_otg_hcd_urb_t * dwc_otg_urb)+{+	dwc_otg_qh_t *qh;+	dwc_otg_qtd_t *urb_qtd;+	BUG_ON(!hcd);+	BUG_ON(!dwc_otg_urb);++#ifdef DEBUG /* integrity checks (Broadcom) */++	if (hcd == NULL) {+		DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL HCD\n");+		return -DWC_E_INVALID;+	}+	if (dwc_otg_urb == NULL) {+		DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL URB\n");+		return -DWC_E_INVALID;+	}+	if (dwc_otg_urb->qtd == NULL) {+		DWC_ERROR("**** DWC OTG HCD URB Dequeue with NULL QTD\n");+		return -DWC_E_INVALID;+	}+	urb_qtd = dwc_otg_urb->qtd;+	BUG_ON(!urb_qtd);+	if (urb_qtd->qh == NULL) {+		DWC_ERROR("**** DWC OTG HCD URB Dequeue with QTD with NULL Q handler\n");+		return -DWC_E_INVALID;+	}+#else+	urb_qtd = dwc_otg_urb->qtd;+	BUG_ON(!urb_qtd);+#endif+	qh = urb_qtd->qh;+	BUG_ON(!qh);+	if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {+		if (urb_qtd->in_process) {+			dump_channel_info(hcd, qh);+		}+	}+#ifdef DEBUG /* integrity checks (Broadcom) */+	if (hcd->core_if == NULL) {+		DWC_ERROR("**** DWC OTG HCD URB Dequeue HCD has NULL core_if\n");+		return -DWC_E_INVALID;+	}+#endif+	if (urb_qtd->in_process && qh->channel) {+		/* The QTD is in process (it has been assigned to a channel). */+		if (hcd->flags.b.port_connect_status) {+			/*+			 * If still connected (i.e. in host mode), halt the+			 * channel so it can be used for other transfers. If+			 * no longer connected, the host registers can't be+			 * written to halt the channel since the core is in+			 * device mode.+			 */+			dwc_otg_hc_halt(hcd->core_if, qh->channel,+					DWC_OTG_HC_XFER_URB_DEQUEUE);++			dwc_otg_hcd_release_port(hcd, qh);+		}+	}++	/*+	 * Free the QTD and clean up the associated QH. Leave the QH in the+	 * schedule if it has any remaining QTDs.+	 */++	DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue - "+                    "delete %sQueue handler\n",+                    hcd->core_if->dma_desc_enable?"DMA ":"");+	if (!hcd->core_if->dma_desc_enable) {+		uint8_t b = urb_qtd->in_process;+		dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);+		if (b) {+			dwc_otg_hcd_qh_deactivate(hcd, qh, 0);+			qh->channel = NULL;+		} else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {+			dwc_otg_hcd_qh_remove(hcd, qh);+		}+	} else {+		dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);+	}+	return 0;+}++int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,+				 int retry)+{+	dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;+	int retval = 0;+	dwc_irqflags_t flags;++	if (retry < 0) {+		retval = -DWC_E_INVALID;+		goto done;+	}++	if (!qh) {+		retval = -DWC_E_INVALID;+		goto done;+	}++	DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);++	while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) {+		DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);+		retry--;+		dwc_msleep(5);+		DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);+	}++	dwc_otg_hcd_qh_remove(hcd, qh);++	DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);+	/*+	 * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove+	 * and qh_free to prevent stack dump on DWC_DMA_FREE() with+	 * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free()+	 * and dwc_otg_hcd_frame_list_alloc().+	 */+	dwc_otg_hcd_qh_free(hcd, qh);++done:+	return retval;+}++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)+int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle)+{+	int retval = 0;+	dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;+	if (!qh)+		return -DWC_E_INVALID;++	qh->data_toggle = DWC_OTG_HC_PID_DATA0;+	return retval;+}+#endif++/**+ * HCD Callback structure for handling mode switching.+ */+static dwc_otg_cil_callbacks_t hcd_cil_callbacks = {+	.start = dwc_otg_hcd_start_cb,+	.stop = dwc_otg_hcd_stop_cb,+	.disconnect = dwc_otg_hcd_disconnect_cb,+	.session_start = dwc_otg_hcd_session_start_cb,+	.resume_wakeup = dwc_otg_hcd_rem_wakeup_cb,+#ifdef CONFIG_USB_DWC_OTG_LPM+	.sleep = dwc_otg_hcd_sleep_cb,+#endif+	.p = 0,+};++/**+ * Reset tasklet function+ */+static void reset_tasklet_func(void *data)+{+	dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *) data;+	dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;+	hprt0_data_t hprt0;++	DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n");++	hprt0.d32 = dwc_otg_read_hprt0(core_if);+	hprt0.b.prtrst = 1;+	DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+	dwc_mdelay(60);++	hprt0.b.prtrst = 0;+	DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+	dwc_otg_hcd->flags.b.port_reset_change = 1;+}++static void completion_tasklet_func(void *ptr)+{+	dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) ptr;+	struct urb *urb;+	urb_tq_entry_t *item;+	dwc_irqflags_t flags;++	/* This could just be spin_lock_irq */+	DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);+	while (!DWC_TAILQ_EMPTY(&hcd->completed_urb_list)) {+		item = DWC_TAILQ_FIRST(&hcd->completed_urb_list);+		urb = item->urb;+		DWC_TAILQ_REMOVE(&hcd->completed_urb_list, item,+				urb_tq_entries);+		DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);+		DWC_FREE(item);++		usb_hcd_giveback_urb(hcd->priv, urb, urb->status);++		fiq_print(FIQDBG_PORTHUB, "COMPLETE");++		DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);+	}+	DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);+	return;+}++static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)+{+	dwc_list_link_t *item;+	dwc_otg_qh_t *qh;+	dwc_irqflags_t flags;++	if (!qh_list->next) {+		/* The list hasn't been initialized yet. */+		return;+	}+	/*+	 * Hold spinlock here. Not needed in that case if bellow+	 * function is being called from ISR+	 */+	DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);+	/* Ensure there are no QTDs or URBs left. */+	kill_urbs_in_qh_list(hcd, qh_list);+	DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);++	DWC_LIST_FOREACH(item, qh_list) {+		qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);+		dwc_otg_hcd_qh_remove_and_free(hcd, qh);+	}+}++/**+ * Exit from Hibernation if Host did not detect SRP from connected SRP capable+ * Device during SRP time by host power up.+ */+void dwc_otg_hcd_power_up(void *ptr)+{+	gpwrdn_data_t gpwrdn = {.d32 = 0 };+	dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;++	DWC_PRINTF("%s called\n", __FUNCTION__);++	if (!core_if->hibernation_suspend) {+		DWC_PRINTF("Already exited from Hibernation\n");+		return;+	}++	/* Switch on the voltage to the core */+	gpwrdn.b.pwrdnswtch = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+	dwc_udelay(10);++	/* Reset the core */+	gpwrdn.d32 = 0;+	gpwrdn.b.pwrdnrstn = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+	dwc_udelay(10);++	/* Disable power clamps */+	gpwrdn.d32 = 0;+	gpwrdn.b.pwrdnclmp = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++	/* Remove reset the core signal */+	gpwrdn.d32 = 0;+	gpwrdn.b.pwrdnrstn = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);+	dwc_udelay(10);++	/* Disable PMU interrupt */+	gpwrdn.d32 = 0;+	gpwrdn.b.pmuintsel = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++	core_if->hibernation_suspend = 0;++	/* Disable PMU */+	gpwrdn.d32 = 0;+	gpwrdn.b.pmuactv = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);+	dwc_udelay(10);++	/* Enable VBUS */+	gpwrdn.d32 = 0;+	gpwrdn.b.dis_vbus = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);++	core_if->op_state = A_HOST;+	dwc_otg_core_init(core_if);+	dwc_otg_enable_global_interrupts(core_if);+	cil_hcd_start(core_if);+}++/**+ * Frees secondary storage associated with the dwc_otg_hcd structure contained+ * in the struct usb_hcd field.+ */+static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd)+{+	int i;++	DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n");++	del_timers(dwc_otg_hcd);++	/* Free memory for QH/QTD lists */+	qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive);+	qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active);+	qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive);+	qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready);+	qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned);+	qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued);++	/* Free memory for the host channels. */+	for (i = 0; i < MAX_EPS_CHANNELS; i++) {+		dwc_hc_t *hc = dwc_otg_hcd->hc_ptr_array[i];++#ifdef DEBUG+		if (dwc_otg_hcd->core_if->hc_xfer_timer[i]) {+			DWC_TIMER_FREE(dwc_otg_hcd->core_if->hc_xfer_timer[i]);+		}+#endif+		if (hc != NULL) {+			DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n",+				    i, hc);+			DWC_FREE(hc);+		}+	}++	if (dwc_otg_hcd->core_if->dma_enable) {+		if (dwc_otg_hcd->status_buf_dma) {+			DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE,+				     dwc_otg_hcd->status_buf,+				     dwc_otg_hcd->status_buf_dma);+		}+	} else if (dwc_otg_hcd->status_buf != NULL) {+		DWC_FREE(dwc_otg_hcd->status_buf);+	}+	DWC_SPINLOCK_FREE(dwc_otg_hcd->channel_lock);+	DWC_SPINLOCK_FREE(dwc_otg_hcd->lock);+	/* Set core_if's lock pointer to NULL */+	dwc_otg_hcd->core_if->lock = NULL;++	DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);+	DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);+	DWC_TASK_FREE(dwc_otg_hcd->completion_tasklet);++#ifdef DWC_DEV_SRPCAP+	if (dwc_otg_hcd->core_if->power_down == 2 &&+	    dwc_otg_hcd->core_if->pwron_timer) {+		DWC_TIMER_FREE(dwc_otg_hcd->core_if->pwron_timer);+	}+#endif+	DWC_FREE(dwc_otg_hcd);+}++int init_hcd_usecs(dwc_otg_hcd_t *_hcd);++int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)+{+	int retval = 0;+	int num_channels;+	int i;+	dwc_hc_t *channel;++	hcd->lock = DWC_SPINLOCK_ALLOC();+	hcd->channel_lock = DWC_SPINLOCK_ALLOC();+        DWC_DEBUGPL(DBG_HCDV, "init of HCD %p given core_if %p\n",+                    hcd, core_if);+	if (!hcd->lock) {+		DWC_ERROR("Could not allocate lock for pcd");+		DWC_FREE(hcd);+		retval = -DWC_E_NO_MEMORY;+		goto out;+	}+	hcd->core_if = core_if;++	/* Register the HCD CIL Callbacks */+	dwc_otg_cil_register_hcd_callbacks(hcd->core_if,+					   &hcd_cil_callbacks, hcd);++	/* Initialize the non-periodic schedule. */+	DWC_LIST_INIT(&hcd->non_periodic_sched_inactive);+	DWC_LIST_INIT(&hcd->non_periodic_sched_active);++	/* Initialize the periodic schedule. */+	DWC_LIST_INIT(&hcd->periodic_sched_inactive);+	DWC_LIST_INIT(&hcd->periodic_sched_ready);+	DWC_LIST_INIT(&hcd->periodic_sched_assigned);+	DWC_LIST_INIT(&hcd->periodic_sched_queued);+	DWC_TAILQ_INIT(&hcd->completed_urb_list);+	/*+	 * Create a host channel descriptor for each host channel implemented+	 * in the controller. Initialize the channel descriptor array.+	 */+	DWC_CIRCLEQ_INIT(&hcd->free_hc_list);+	num_channels = hcd->core_if->core_params->host_channels;+	DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array));+	for (i = 0; i < num_channels; i++) {+		channel = DWC_ALLOC(sizeof(dwc_hc_t));+		if (channel == NULL) {+			retval = -DWC_E_NO_MEMORY;+			DWC_ERROR("%s: host channel allocation failed\n",+				  __func__);+			dwc_otg_hcd_free(hcd);+			goto out;+		}+		channel->hc_num = i;+		hcd->hc_ptr_array[i] = channel;+#ifdef DEBUG+		hcd->core_if->hc_xfer_timer[i] =+		    DWC_TIMER_ALLOC("hc timer", hc_xfer_timeout,+				    &hcd->core_if->hc_xfer_info[i]);+#endif+		DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i,+			    channel);+	}++	/* Initialize the Connection timeout timer. */+	hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer",+					  dwc_otg_hcd_connect_timeout, 0);++	printk(KERN_DEBUG "dwc_otg: Microframe scheduler %s\n", microframe_schedule ? "enabled":"disabled");+	if (microframe_schedule)+		init_hcd_usecs(hcd);++	/* Initialize reset tasklet. */+	hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd);++	hcd->completion_tasklet = DWC_TASK_ALLOC("completion_tasklet",+						completion_tasklet_func, hcd);+#ifdef DWC_DEV_SRPCAP+	if (hcd->core_if->power_down == 2) {+		/* Initialize Power on timer for Host power up in case hibernation */+		hcd->core_if->pwron_timer = DWC_TIMER_ALLOC("PWRON TIMER",+									dwc_otg_hcd_power_up, core_if);+	}+#endif++	/*+	 * Allocate space for storing data on status transactions. Normally no+	 * data is sent, but this space acts as a bit bucket. This must be+	 * done after usb_add_hcd since that function allocates the DMA buffer+	 * pool.+	 */+	if (hcd->core_if->dma_enable) {+		hcd->status_buf =+		    DWC_DMA_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE,+				  &hcd->status_buf_dma);+	} else {+		hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE);+	}+	if (!hcd->status_buf) {+		retval = -DWC_E_NO_MEMORY;+		DWC_ERROR("%s: status_buf allocation failed\n", __func__);+		dwc_otg_hcd_free(hcd);+		goto out;+	}++	hcd->otg_port = 1;+	hcd->frame_list = NULL;+	hcd->frame_list_dma = 0;+	hcd->periodic_qh_count = 0;++	DWC_MEMSET(hcd->hub_port, 0, sizeof(hcd->hub_port));+#ifdef FIQ_DEBUG+	DWC_MEMSET(hcd->hub_port_alloc, -1, sizeof(hcd->hub_port_alloc));+#endif++out:+	return retval;+}++void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd)+{+	/* Turn off all host-specific interrupts. */+	dwc_otg_disable_host_interrupts(hcd->core_if);++	dwc_otg_hcd_free(hcd);+}++/**+ * Initializes dynamic portions of the DWC_otg HCD state.+ */+static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd)+{+	int num_channels;+	int i;+	dwc_hc_t *channel;+	dwc_hc_t *channel_tmp;++	hcd->flags.d32 = 0;++	hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active;+	if (!microframe_schedule) {+		hcd->non_periodic_channels = 0;+		hcd->periodic_channels = 0;+	} else {+		hcd->available_host_channels = hcd->core_if->core_params->host_channels;+	}+	/*+	 * Put all channels in the free channel list and clean up channel+	 * states.+	 */+	DWC_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp,+				 &hcd->free_hc_list, hc_list_entry) {+		DWC_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry);+	}++	num_channels = hcd->core_if->core_params->host_channels;+	for (i = 0; i < num_channels; i++) {+		channel = hcd->hc_ptr_array[i];+		DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel,+					hc_list_entry);+		dwc_otg_hc_cleanup(hcd->core_if, channel);+	}++	/* Initialize the DWC core for host mode operation. */+	dwc_otg_core_host_init(hcd->core_if);++	/* Set core_if's lock pointer to the hcd->lock */+	hcd->core_if->lock = hcd->lock;+}++/**+ * Assigns transactions from a QTD to a free host channel and initializes the+ * host channel to perform the transactions. The host channel is removed from+ * the free list.+ *+ * @param hcd The HCD state structure.+ * @param qh Transactions from the first QTD for this QH are selected and+ * assigned to a free host channel.+ */+static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)+{+	dwc_hc_t *hc;+	dwc_otg_qtd_t *qtd;+	dwc_otg_hcd_urb_t *urb;+	void* ptr = NULL;++	qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);++	urb = qtd->urb;++	DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p) - urb %x, actual_length %d\n", __func__, hcd, qh, (unsigned int)urb, urb->actual_length);++	if (((urb->actual_length < 0) || (urb->actual_length > urb->length)) && !dwc_otg_hcd_is_pipe_in(&urb->pipe_info))+		urb->actual_length = urb->length;+++	hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);++	/* Remove the host channel from the free list. */+	DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);++	qh->channel = hc;++	qtd->in_process = 1;++	/*+	 * Use usb_pipedevice to determine device address. This address is+	 * 0 before the SET_ADDRESS command and the correct address afterward.+	 */+	hc->dev_addr = dwc_otg_hcd_get_dev_addr(&urb->pipe_info);+	hc->ep_num = dwc_otg_hcd_get_ep_num(&urb->pipe_info);+	hc->speed = qh->dev_speed;+	hc->max_packet = dwc_max_packet(qh->maxp);++	hc->xfer_started = 0;+	hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS;+	hc->error_state = (qtd->error_count > 0);+	hc->halt_on_queue = 0;+	hc->halt_pending = 0;+	hc->requests = 0;++	/*+	 * The following values may be modified in the transfer type section+	 * below. The xfer_len value may be reduced when the transfer is+	 * started to accommodate the max widths of the XferSize and PktCnt+	 * fields in the HCTSIZn register.+	 */++	hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0);+	if (hc->ep_is_in) {+		hc->do_ping = 0;+	} else {+		hc->do_ping = qh->ping_state;+	}++	hc->data_pid_start = qh->data_toggle;+	hc->multi_count = 1;++	if (hcd->core_if->dma_enable) {+		hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length;++		/* For non-dword aligned case */+		if (((unsigned long)hc->xfer_buff & 0x3)+		    && !hcd->core_if->dma_desc_enable) {+			ptr = (uint8_t *) urb->buf + urb->actual_length;+		}+	} else {+		hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length;+	}+	hc->xfer_len = urb->length - urb->actual_length;+	hc->xfer_count = 0;++	/*+	 * Set the split attributes+	 */+	hc->do_split = 0;+	if (qh->do_split) {+		uint32_t hub_addr, port_addr;+		hc->do_split = 1;+		hc->xact_pos = qtd->isoc_split_pos;+		/* We don't need to do complete splits anymore */+		if(fiq_split_enable)+			hc->complete_split = qtd->complete_split = 0;+		else+			hc->complete_split = qtd->complete_split;++		hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr);+		hc->hub_addr = (uint8_t) hub_addr;+		hc->port_addr = (uint8_t) port_addr;+	}++	switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {+	case UE_CONTROL:+		hc->ep_type = DWC_OTG_EP_TYPE_CONTROL;+		switch (qtd->control_phase) {+		case DWC_OTG_CONTROL_SETUP:+			DWC_DEBUGPL(DBG_HCDV, "  Control setup transaction\n");+			hc->do_ping = 0;+			hc->ep_is_in = 0;+			hc->data_pid_start = DWC_OTG_HC_PID_SETUP;+			if (hcd->core_if->dma_enable) {+				hc->xfer_buff = (uint8_t *) urb->setup_dma;+			} else {+				hc->xfer_buff = (uint8_t *) urb->setup_packet;+			}+			hc->xfer_len = 8;+			ptr = NULL;+			break;+		case DWC_OTG_CONTROL_DATA:+			DWC_DEBUGPL(DBG_HCDV, "  Control data transaction\n");+			hc->data_pid_start = qtd->data_toggle;+			break;+		case DWC_OTG_CONTROL_STATUS:+			/*+			 * Direction is opposite of data direction or IN if no+			 * data.+			 */+			DWC_DEBUGPL(DBG_HCDV, "  Control status transaction\n");+			if (urb->length == 0) {+				hc->ep_is_in = 1;+			} else {+				hc->ep_is_in =+				    dwc_otg_hcd_is_pipe_out(&urb->pipe_info);+			}+			if (hc->ep_is_in) {+				hc->do_ping = 0;+			}++			hc->data_pid_start = DWC_OTG_HC_PID_DATA1;++			hc->xfer_len = 0;+			if (hcd->core_if->dma_enable) {+				hc->xfer_buff = (uint8_t *) hcd->status_buf_dma;+			} else {+				hc->xfer_buff = (uint8_t *) hcd->status_buf;+			}+			ptr = NULL;+			break;+		}+		break;+	case UE_BULK:+		hc->ep_type = DWC_OTG_EP_TYPE_BULK;+		break;+	case UE_INTERRUPT:+		hc->ep_type = DWC_OTG_EP_TYPE_INTR;+		break;+	case UE_ISOCHRONOUS:+		{+			struct dwc_otg_hcd_iso_packet_desc *frame_desc;++			hc->ep_type = DWC_OTG_EP_TYPE_ISOC;++			if (hcd->core_if->dma_desc_enable)+				break;++			frame_desc = &urb->iso_descs[qtd->isoc_frame_index];++			frame_desc->status = 0;++			if (hcd->core_if->dma_enable) {+				hc->xfer_buff = (uint8_t *) urb->dma;+			} else {+				hc->xfer_buff = (uint8_t *) urb->buf;+			}+			hc->xfer_buff +=+			    frame_desc->offset + qtd->isoc_split_offset;+			hc->xfer_len =+			    frame_desc->length - qtd->isoc_split_offset;++			/* For non-dword aligned buffers */+			if (((unsigned long)hc->xfer_buff & 0x3)+			    && hcd->core_if->dma_enable) {+				ptr =+				    (uint8_t *) urb->buf + frame_desc->offset ++				    qtd->isoc_split_offset;+			} else+				ptr = NULL;++			if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) {+				if (hc->xfer_len <= 188) {+					hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL;+				} else {+					hc->xact_pos =+					    DWC_HCSPLIT_XACTPOS_BEGIN;+				}+			}+		}+		break;+	}+	/* non DWORD-aligned buffer case */+	if (ptr) {+		uint32_t buf_size;+		if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {+			buf_size = hcd->core_if->core_params->max_transfer_size;+		} else {+			buf_size = 4096;+		}+		if (!qh->dw_align_buf) {+			qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size,+							 &qh->dw_align_buf_dma);+			if (!qh->dw_align_buf) {+				DWC_ERROR+				    ("%s: Failed to allocate memory to handle "+				     "non-dword aligned buffer case\n",+				     __func__);+				return;+			}+		}+		if (!hc->ep_is_in) {+			dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len);+		}+		hc->align_buff = qh->dw_align_buf_dma;+	} else {+		hc->align_buff = 0;+	}++	if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||+	    hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {+		/*+		 * This value may be modified when the transfer is started to+		 * reflect the actual transfer length.+		 */+		hc->multi_count = dwc_hb_mult(qh->maxp);+	}++	if (hcd->core_if->dma_desc_enable)+		hc->desc_list_addr = qh->desc_list_dma;++	dwc_otg_hc_init(hcd->core_if, hc);+	hc->qh = qh;+}++/*+** Check the transaction to see if the port / hub has already been assigned for+** a split transaction+**+** Return 0 - Port is already in use+*/+int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh)+{+	uint32_t hub_addr, port_addr;++	if(!fiq_split_enable)+		return 0;++	hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr);++	if(hcd->hub_port[hub_addr] & (1 << port_addr))+	{+		fiq_print(FIQDBG_PORTHUB, "H%dP%d:S%02d", hub_addr, port_addr, qh->skip_count);++		qh->skip_count++;++		if(qh->skip_count > 40000)+		{+			printk_once(KERN_ERR "Error: Having to skip port allocation");+			local_fiq_disable();+			BUG();+			return 0;+		}+		return 1;+	}+	else+	{+		qh->skip_count = 0;+		hcd->hub_port[hub_addr] |= 1 << port_addr;+		fiq_print(FIQDBG_PORTHUB, "H%dP%d:A %d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num);+#ifdef FIQ_DEBUG+		hcd->hub_port_alloc[hub_addr * 16 + port_addr] = dwc_otg_hcd_get_frame_number(hcd);+#endif+		return 0;+	}+}+void dwc_otg_hcd_release_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh)+{+	uint32_t hub_addr, port_addr;++	if(!fiq_split_enable)+		return;++	hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr);++	hcd->hub_port[hub_addr] &= ~(1 << port_addr);+#ifdef FIQ_DEBUG+	hcd->hub_port_alloc[hub_addr * 16 + port_addr] = -1;+#endif+	fiq_print(FIQDBG_PORTHUB, "H%dP%d:RO%d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num);++}+++/**+ * This function selects transactions from the HCD transfer schedule and+ * assigns them to available host channels. It is called from HCD interrupt+ * handler functions.+ *+ * @param hcd The HCD state structure.+ *+ * @return The types of new transactions that were assigned to host channels.+ */+dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)+{+	dwc_list_link_t *qh_ptr;+	dwc_otg_qh_t *qh;+	dwc_otg_qtd_t *qtd;+	int num_channels;+	dwc_irqflags_t flags;+	dwc_spinlock_t *channel_lock = hcd->channel_lock;+	dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;++#ifdef DEBUG_SOF+	DWC_DEBUGPL(DBG_HCD, "  Select Transactions\n");+#endif++#ifdef DEBUG_HOST_CHANNELS+	last_sel_trans_num_per_scheduled = 0;+	last_sel_trans_num_nonper_scheduled = 0;+	last_sel_trans_num_avail_hc_at_start = hcd->available_host_channels;+#endif /* DEBUG_HOST_CHANNELS */++	/* Process entries in the periodic ready list. */+	qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready);++	while (qh_ptr != &hcd->periodic_sched_ready &&+	       !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {++		qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);++		if(qh->do_split) {+			qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);+			if(!(qh->ep_type == UE_ISOCHRONOUS &&+					(qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||+					qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END))) {+				if(dwc_otg_hcd_allocate_port(hcd, qh))+				{+					qh_ptr = DWC_LIST_NEXT(qh_ptr);+					g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1);+					continue;+				}+			}+		}++		if (microframe_schedule) {+			// Make sure we leave one channel for non periodic transactions.+			DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);+			if (hcd->available_host_channels <= 1) {+				DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);+				if(qh->do_split) dwc_otg_hcd_release_port(hcd, qh);+				break;+			}+			hcd->available_host_channels--;+			DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);+#ifdef DEBUG_HOST_CHANNELS+			last_sel_trans_num_per_scheduled++;+#endif /* DEBUG_HOST_CHANNELS */+		}+		qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);+		assign_and_init_hc(hcd, qh);++		/*+		 * Move the QH from the periodic ready schedule to the+		 * periodic assigned schedule.+		 */+		qh_ptr = DWC_LIST_NEXT(qh_ptr);+		DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);+		DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,+				   &qh->qh_list_entry);+		DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);+	}++	/*+	 * Process entries in the inactive portion of the non-periodic+	 * schedule. Some free host channels may not be used if they are+	 * reserved for periodic transfers.+	 */+	qh_ptr = hcd->non_periodic_sched_inactive.next;+	num_channels = hcd->core_if->core_params->host_channels;+	while (qh_ptr != &hcd->non_periodic_sched_inactive &&+	       (microframe_schedule || hcd->non_periodic_channels <+		num_channels - hcd->periodic_channels) &&+	       !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {++		qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);++		/*+		 * Check to see if this is a NAK'd retransmit, in which case ignore for retransmission+		 * we hold off on bulk retransmissions to reduce NAK interrupt overhead for full-speed+		 * cheeky devices that just hold off using NAKs+		 */+		if (nak_holdoff_enable && qh->do_split) {+			if (qh->nak_frame != 0xffff &&+				dwc_full_frame_num(qh->nak_frame) ==+				dwc_full_frame_num(dwc_otg_hcd_get_frame_number(hcd))) {+				/*+				 * Revisit: Need to avoid trampling on periodic scheduling.+				 * Currently we are safe because g_np_count != g_np_sent whenever we hit this,+				 * but if this behaviour is changed then periodic endpoints will get a slower+				 * polling rate.+				 */+				g_next_sched_frame = ((qh->nak_frame + 8) & ~7) & DWC_HFNUM_MAX_FRNUM;+				qh_ptr = DWC_LIST_NEXT(qh_ptr);+				continue;+			} else {+				qh->nak_frame = 0xffff;+			}+		}++		if (microframe_schedule) {+				DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);+				if (hcd->available_host_channels < 1) {+					DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);+					break;+				}+				hcd->available_host_channels--;+				DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);+#ifdef DEBUG_HOST_CHANNELS+				last_sel_trans_num_nonper_scheduled++;+#endif /* DEBUG_HOST_CHANNELS */+		}++		assign_and_init_hc(hcd, qh);++		/*+		 * Move the QH from the non-periodic inactive schedule to the+		 * non-periodic active schedule.+		 */+		qh_ptr = DWC_LIST_NEXT(qh_ptr);+		DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);+		DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active,+				   &qh->qh_list_entry);+		DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);++		g_np_sent++;++		if (!microframe_schedule)+			hcd->non_periodic_channels++;+	}++	if(!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned))+		ret_val |= DWC_OTG_TRANSACTION_PERIODIC;++	if(!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active))+		ret_val |= DWC_OTG_TRANSACTION_NON_PERIODIC;+++#ifdef DEBUG_HOST_CHANNELS+	last_sel_trans_num_avail_hc_at_end = hcd->available_host_channels;+#endif /* DEBUG_HOST_CHANNELS */+	return ret_val;+}++/**+ * Attempts to queue a single transaction request for a host channel+ * associated with either a periodic or non-periodic transfer. This function+ * assumes that there is space available in the appropriate request queue. For+ * an OUT transfer or SETUP transaction in Slave mode, it checks whether space+ * is available in the appropriate Tx FIFO.+ *+ * @param hcd The HCD state structure.+ * @param hc Host channel descriptor associated with either a periodic or+ * non-periodic transfer.+ * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx+ * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic+ * transfers.+ *+ * @return 1 if a request is queued and more requests may be needed to+ * complete the transfer, 0 if no more requests are required for this+ * transfer, -1 if there is insufficient space in the Tx FIFO.+ */+static int queue_transaction(dwc_otg_hcd_t * hcd,+			     dwc_hc_t * hc, uint16_t fifo_dwords_avail)+{+	int retval;++	if (hcd->core_if->dma_enable) {+		if (hcd->core_if->dma_desc_enable) {+			if (!hc->xfer_started+			    || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) {+				dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh);+				hc->qh->ping_state = 0;+			}+		} else if (!hc->xfer_started) {+			dwc_otg_hc_start_transfer(hcd->core_if, hc);+			hc->qh->ping_state = 0;+		}+		retval = 0;+	} else if (hc->halt_pending) {+		/* Don't queue a request if the channel has been halted. */+		retval = 0;+	} else if (hc->halt_on_queue) {+		dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status);+		retval = 0;+	} else if (hc->do_ping) {+		if (!hc->xfer_started) {+			dwc_otg_hc_start_transfer(hcd->core_if, hc);+		}+		retval = 0;+	} else if (!hc->ep_is_in || hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {+		if ((fifo_dwords_avail * 4) >= hc->max_packet) {+			if (!hc->xfer_started) {+				dwc_otg_hc_start_transfer(hcd->core_if, hc);+				retval = 1;+			} else {+				retval =+				    dwc_otg_hc_continue_transfer(hcd->core_if,+								 hc);+			}+		} else {+			retval = -1;+		}+	} else {+		if (!hc->xfer_started) {+			dwc_otg_hc_start_transfer(hcd->core_if, hc);+			retval = 1;+		} else {+			retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc);+		}+	}++	return retval;+}++/**+ * Processes periodic channels for the next frame and queues transactions for+ * these channels to the DWC_otg controller. After queueing transactions, the+ * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions+ * to queue as Periodic Tx FIFO or request queue space becomes available.+ * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled.+ */+static void process_periodic_channels(dwc_otg_hcd_t * hcd)+{+	hptxsts_data_t tx_status;+	dwc_list_link_t *qh_ptr;+	dwc_otg_qh_t *qh;+	int status;+	int no_queue_space = 0;+	int no_fifo_space = 0;++	dwc_otg_host_global_regs_t *host_regs;+	host_regs = hcd->core_if->host_if->host_global_regs;++	DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n");+#ifdef DEBUG+	tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);+	DWC_DEBUGPL(DBG_HCDV,+		    "  P Tx Req Queue Space Avail (before queue): %d\n",+		    tx_status.b.ptxqspcavail);+	DWC_DEBUGPL(DBG_HCDV, "  P Tx FIFO Space Avail (before queue): %d\n",+		    tx_status.b.ptxfspcavail);+#endif++	qh_ptr = hcd->periodic_sched_assigned.next;+	while (qh_ptr != &hcd->periodic_sched_assigned) {+		tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);+		if (tx_status.b.ptxqspcavail == 0) {+			no_queue_space = 1;+			break;+		}++		qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);++		// Do not send a split start transaction any later than frame .6+		// Note, we have to schedule a periodic in .5 to make it go in .6+		if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6)+		{+			qh_ptr = qh_ptr->next;+			g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7;+			continue;+		}++		/*+		 * Set a flag if we're queuing high-bandwidth in slave mode.+		 * The flag prevents any halts to get into the request queue in+		 * the middle of multiple high-bandwidth packets getting queued.+		 */+		if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) {+			hcd->core_if->queuing_high_bandwidth = 1;+		}+		status =+		    queue_transaction(hcd, qh->channel,+				      tx_status.b.ptxfspcavail);+		if (status < 0) {+			no_fifo_space = 1;+			break;+		}++		/*+		 * In Slave mode, stay on the current transfer until there is+		 * nothing more to do or the high-bandwidth request count is+		 * reached. In DMA mode, only need to queue one request. The+		 * controller automatically handles multiple packets for+		 * high-bandwidth transfers.+		 */+		if (hcd->core_if->dma_enable || status == 0 ||+		    qh->channel->requests == qh->channel->multi_count) {+			qh_ptr = qh_ptr->next;+			/*+			 * Move the QH from the periodic assigned schedule to+			 * the periodic queued schedule.+			 */+			DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued,+					   &qh->qh_list_entry);++			/* done queuing high bandwidth */+			hcd->core_if->queuing_high_bandwidth = 0;+		}+	}++	if (!hcd->core_if->dma_enable) {+		dwc_otg_core_global_regs_t *global_regs;+		gintmsk_data_t intr_mask = {.d32 = 0 };++		global_regs = hcd->core_if->core_global_regs;+		intr_mask.b.ptxfempty = 1;+#ifdef DEBUG+		tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);+		DWC_DEBUGPL(DBG_HCDV,+			    "  P Tx Req Queue Space Avail (after queue): %d\n",+			    tx_status.b.ptxqspcavail);+		DWC_DEBUGPL(DBG_HCDV,+			    "  P Tx FIFO Space Avail (after queue): %d\n",+			    tx_status.b.ptxfspcavail);+#endif+		if (!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned) ||+		    no_queue_space || no_fifo_space) {+			/*+			 * May need to queue more transactions as the request+			 * queue or Tx FIFO empties. Enable the periodic Tx+			 * FIFO empty interrupt. (Always use the half-empty+			 * level to ensure that new requests are loaded as+			 * soon as possible.)+			 */+			DWC_MODIFY_REG32(&global_regs->gintmsk, 0,+					 intr_mask.d32);+		} else {+			/*+			 * Disable the Tx FIFO empty interrupt since there are+			 * no more transactions that need to be queued right+			 * now. This function is called from interrupt+			 * handlers to queue more transactions as transfer+			 * states change.+			 */+			DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,+					 0);+		}+	}+}++/**+ * Processes active non-periodic channels and queues transactions for these+ * channels to the DWC_otg controller. After queueing transactions, the NP Tx+ * FIFO Empty interrupt is enabled if there are more transactions to queue as+ * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx+ * FIFO Empty interrupt is disabled.+ */+static void process_non_periodic_channels(dwc_otg_hcd_t * hcd)+{+	gnptxsts_data_t tx_status;+	dwc_list_link_t *orig_qh_ptr;+	dwc_otg_qh_t *qh;+	int status;+	int no_queue_space = 0;+	int no_fifo_space = 0;+	int more_to_do = 0;++	dwc_otg_core_global_regs_t *global_regs =+	    hcd->core_if->core_global_regs;++	DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n");+#ifdef DEBUG+	tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);+	DWC_DEBUGPL(DBG_HCDV,+		    "  NP Tx Req Queue Space Avail (before queue): %d\n",+		    tx_status.b.nptxqspcavail);+	DWC_DEBUGPL(DBG_HCDV, "  NP Tx FIFO Space Avail (before queue): %d\n",+		    tx_status.b.nptxfspcavail);+#endif+	/*+	 * Keep track of the starting point. Skip over the start-of-list+	 * entry.+	 */+	if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {+		hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;+	}+	orig_qh_ptr = hcd->non_periodic_qh_ptr;++	/*+	 * Process once through the active list or until no more space is+	 * available in the request queue or the Tx FIFO.+	 */+	do {+		tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);+		if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) {+			no_queue_space = 1;+			break;+		}++		qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,+				    qh_list_entry);++		// Do not send a split start transaction any later than frame .5+		// non periodic transactions will start immediately in this uframe+		if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6)+		{+			g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7;+			break;+		}++		status =+		    queue_transaction(hcd, qh->channel,+				      tx_status.b.nptxfspcavail);++		if (status > 0) {+			more_to_do = 1;+		} else if (status < 0) {+			no_fifo_space = 1;+			break;+		}++		/* Advance to next QH, skipping start-of-list entry. */+		hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;+		if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {+			hcd->non_periodic_qh_ptr =+			    hcd->non_periodic_qh_ptr->next;+		}++	} while (hcd->non_periodic_qh_ptr != orig_qh_ptr);++	if (!hcd->core_if->dma_enable) {+		gintmsk_data_t intr_mask = {.d32 = 0 };+		intr_mask.b.nptxfempty = 1;++#ifdef DEBUG+		tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);+		DWC_DEBUGPL(DBG_HCDV,+			    "  NP Tx Req Queue Space Avail (after queue): %d\n",+			    tx_status.b.nptxqspcavail);+		DWC_DEBUGPL(DBG_HCDV,+			    "  NP Tx FIFO Space Avail (after queue): %d\n",+			    tx_status.b.nptxfspcavail);+#endif+		if (more_to_do || no_queue_space || no_fifo_space) {+			/*+			 * May need to queue more transactions as the request+			 * queue or Tx FIFO empties. Enable the non-periodic+			 * Tx FIFO empty interrupt. (Always use the half-empty+			 * level to ensure that new requests are loaded as+			 * soon as possible.)+			 */+			DWC_MODIFY_REG32(&global_regs->gintmsk, 0,+					 intr_mask.d32);+		} else {+			/*+			 * Disable the Tx FIFO empty interrupt since there are+			 * no more transactions that need to be queued right+			 * now. This function is called from interrupt+			 * handlers to queue more transactions as transfer+			 * states change.+			 */+			DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,+					 0);+		}+	}+}++/**+ * This function processes the currently active host channels and queues+ * transactions for these channels to the DWC_otg controller. It is called+ * from HCD interrupt handler functions.+ *+ * @param hcd The HCD state structure.+ * @param tr_type The type(s) of transactions to queue (non-periodic,+ * periodic, or both).+ */+void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,+				    dwc_otg_transaction_type_e tr_type)+{+#ifdef DEBUG_SOF+	DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n");+#endif+	/* Process host channels associated with periodic transfers. */+	if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC ||+	     tr_type == DWC_OTG_TRANSACTION_ALL) &&+	    !DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) {++		process_periodic_channels(hcd);+	}++	/* Process host channels associated with non-periodic transfers. */+	if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC ||+	    tr_type == DWC_OTG_TRANSACTION_ALL) {+		if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) {+			process_non_periodic_channels(hcd);+		} else {+			/*+			 * Ensure NP Tx FIFO empty interrupt is disabled when+			 * there are no non-periodic transfers to process.+			 */+			gintmsk_data_t gintmsk = {.d32 = 0 };+			gintmsk.b.nptxfempty = 1;+			DWC_MODIFY_REG32(&hcd->core_if->+					 core_global_regs->gintmsk, gintmsk.d32,+					 0);+		}+	}+}++#ifdef DWC_HS_ELECT_TST+/*+ * Quick and dirty hack to implement the HS Electrical Test+ * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature.+ *+ * This code was copied from our userspace app "hset". It sends a+ * Get Device Descriptor control sequence in two parts, first the+ * Setup packet by itself, followed some time later by the In and+ * Ack packets. Rather than trying to figure out how to add this+ * functionality to the normal driver code, we just hijack the+ * hardware, using these two function to drive the hardware+ * directly.+ */++static dwc_otg_core_global_regs_t *global_regs;+static dwc_otg_host_global_regs_t *hc_global_regs;+static dwc_otg_hc_regs_t *hc_regs;+static uint32_t *data_fifo;++static void do_setup(void)+{+	gintsts_data_t gintsts;+	hctsiz_data_t hctsiz;+	hcchar_data_t hcchar;+	haint_data_t haint;+	hcint_data_t hcint;++	/* Enable HAINTs */+	DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);++	/* Enable HCINTs */+	DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);++	/* Read GINTSTS */+	gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);++	/* Read HAINT */+	haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);++	/* Read HCINT */+	hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);++	/* Read HCCHAR */+	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);++	/* Clear HCINT */+	DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);++	/* Clear HAINT */+	DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);++	/* Clear GINTSTS */+	DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);++	/* Read GINTSTS */+	gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);++	/*+	 * Send Setup packet (Get Device Descriptor)+	 */++	/* Make sure channel is disabled */+	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+	if (hcchar.b.chen) {+		hcchar.b.chdis = 1;+//              hcchar.b.chen = 1;+		DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);+		//sleep(1);+		dwc_mdelay(1000);++		/* Read GINTSTS */+		gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);++		/* Read HAINT */+		haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);++		/* Read HCINT */+		hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);++		/* Read HCCHAR */+		hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);++		/* Clear HCINT */+		DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);++		/* Clear HAINT */+		DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);++		/* Clear GINTSTS */+		DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);++		hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+	}++	/* Set HCTSIZ */+	hctsiz.d32 = 0;+	hctsiz.b.xfersize = 8;+	hctsiz.b.pktcnt = 1;+	hctsiz.b.pid = DWC_OTG_HC_PID_SETUP;+	DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);++	/* Set HCCHAR */+	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+	hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;+	hcchar.b.epdir = 0;+	hcchar.b.epnum = 0;+	hcchar.b.mps = 8;+	hcchar.b.chen = 1;+	DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);++	/* Fill FIFO with Setup data for Get Device Descriptor */+	data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);+	DWC_WRITE_REG32(data_fifo++, 0x01000680);+	DWC_WRITE_REG32(data_fifo++, 0x00080000);++	gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);++	/* Wait for host channel interrupt */+	do {+		gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);+	} while (gintsts.b.hcintr == 0);++	/* Disable HCINTs */+	DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);++	/* Disable HAINTs */+	DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);++	/* Read HAINT */+	haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);++	/* Read HCINT */+	hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);++	/* Read HCCHAR */+	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);++	/* Clear HCINT */+	DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);++	/* Clear HAINT */+	DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);++	/* Clear GINTSTS */+	DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);++	/* Read GINTSTS */+	gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);+}++static void do_in_ack(void)+{+	gintsts_data_t gintsts;+	hctsiz_data_t hctsiz;+	hcchar_data_t hcchar;+	haint_data_t haint;+	hcint_data_t hcint;+	host_grxsts_data_t grxsts;++	/* Enable HAINTs */+	DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);++	/* Enable HCINTs */+	DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);++	/* Read GINTSTS */+	gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);++	/* Read HAINT */+	haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);++	/* Read HCINT */+	hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);++	/* Read HCCHAR */+	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);++	/* Clear HCINT */+	DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);++	/* Clear HAINT */+	DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);++	/* Clear GINTSTS */+	DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);++	/* Read GINTSTS */+	gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);++	/*+	 * Receive Control In packet+	 */++	/* Make sure channel is disabled */+	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+	if (hcchar.b.chen) {+		hcchar.b.chdis = 1;+		hcchar.b.chen = 1;+		DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);+		//sleep(1);+		dwc_mdelay(1000);++		/* Read GINTSTS */+		gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);++		/* Read HAINT */+		haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);++		/* Read HCINT */+		hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);++		/* Read HCCHAR */+		hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);++		/* Clear HCINT */+		DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);++		/* Clear HAINT */+		DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);++		/* Clear GINTSTS */+		DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);++		hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+	}++	/* Set HCTSIZ */+	hctsiz.d32 = 0;+	hctsiz.b.xfersize = 8;+	hctsiz.b.pktcnt = 1;+	hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;+	DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);++	/* Set HCCHAR */+	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+	hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;+	hcchar.b.epdir = 1;+	hcchar.b.epnum = 0;+	hcchar.b.mps = 8;+	hcchar.b.chen = 1;+	DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);++	gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);++	/* Wait for receive status queue interrupt */+	do {+		gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);+	} while (gintsts.b.rxstsqlvl == 0);++	/* Read RXSTS */+	grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);++	/* Clear RXSTSQLVL in GINTSTS */+	gintsts.d32 = 0;+	gintsts.b.rxstsqlvl = 1;+	DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);++	switch (grxsts.b.pktsts) {+	case DWC_GRXSTS_PKTSTS_IN:+		/* Read the data into the host buffer */+		if (grxsts.b.bcnt > 0) {+			int i;+			int word_count = (grxsts.b.bcnt + 3) / 4;++			data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);++			for (i = 0; i < word_count; i++) {+				(void)DWC_READ_REG32(data_fifo++);+			}+		}+		break;++	default:+		break;+	}++	gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);++	/* Wait for receive status queue interrupt */+	do {+		gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);+	} while (gintsts.b.rxstsqlvl == 0);++	/* Read RXSTS */+	grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);++	/* Clear RXSTSQLVL in GINTSTS */+	gintsts.d32 = 0;+	gintsts.b.rxstsqlvl = 1;+	DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);++	switch (grxsts.b.pktsts) {+	case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:+		break;++	default:+		break;+	}++	gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);++	/* Wait for host channel interrupt */+	do {+		gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);+	} while (gintsts.b.hcintr == 0);++	/* Read HAINT */+	haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);++	/* Read HCINT */+	hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);++	/* Read HCCHAR */+	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);++	/* Clear HCINT */+	DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);++	/* Clear HAINT */+	DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);++	/* Clear GINTSTS */+	DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);++	/* Read GINTSTS */+	gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);++//      usleep(100000);+//      mdelay(100);+	dwc_mdelay(1);++	/*+	 * Send handshake packet+	 */++	/* Read HAINT */+	haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);++	/* Read HCINT */+	hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);++	/* Read HCCHAR */+	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);++	/* Clear HCINT */+	DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);++	/* Clear HAINT */+	DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);++	/* Clear GINTSTS */+	DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);++	/* Read GINTSTS */+	gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);++	/* Make sure channel is disabled */+	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+	if (hcchar.b.chen) {+		hcchar.b.chdis = 1;+		hcchar.b.chen = 1;+		DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);+		//sleep(1);+		dwc_mdelay(1000);++		/* Read GINTSTS */+		gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);++		/* Read HAINT */+		haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);++		/* Read HCINT */+		hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);++		/* Read HCCHAR */+		hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);++		/* Clear HCINT */+		DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);++		/* Clear HAINT */+		DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);++		/* Clear GINTSTS */+		DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);++		hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+	}++	/* Set HCTSIZ */+	hctsiz.d32 = 0;+	hctsiz.b.xfersize = 0;+	hctsiz.b.pktcnt = 1;+	hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;+	DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);++	/* Set HCCHAR */+	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+	hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;+	hcchar.b.epdir = 0;+	hcchar.b.epnum = 0;+	hcchar.b.mps = 8;+	hcchar.b.chen = 1;+	DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);++	gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);++	/* Wait for host channel interrupt */+	do {+		gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);+	} while (gintsts.b.hcintr == 0);++	/* Disable HCINTs */+	DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);++	/* Disable HAINTs */+	DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);++	/* Read HAINT */+	haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);++	/* Read HCINT */+	hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);++	/* Read HCCHAR */+	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);++	/* Clear HCINT */+	DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);++	/* Clear HAINT */+	DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);++	/* Clear GINTSTS */+	DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);++	/* Read GINTSTS */+	gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);+}+#endif++/** Handles hub class-specific requests. */+int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,+			    uint16_t typeReq,+			    uint16_t wValue,+			    uint16_t wIndex, uint8_t * buf, uint16_t wLength)+{+	int retval = 0;++	dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;+	usb_hub_descriptor_t *hub_desc;+	hprt0_data_t hprt0 = {.d32 = 0 };++	uint32_t port_status;++	switch (typeReq) {+	case UCR_CLEAR_HUB_FEATURE:+		DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "+			    "ClearHubFeature 0x%x\n", wValue);+		switch (wValue) {+		case UHF_C_HUB_LOCAL_POWER:+		case UHF_C_HUB_OVER_CURRENT:+			/* Nothing required here */+			break;+		default:+			retval = -DWC_E_INVALID;+			DWC_ERROR("DWC OTG HCD - "+				  "ClearHubFeature request %xh unknown\n",+				  wValue);+		}+		break;+	case UCR_CLEAR_PORT_FEATURE:+#ifdef CONFIG_USB_DWC_OTG_LPM+		if (wValue != UHF_PORT_L1)+#endif+			if (!wIndex || wIndex > 1)+				goto error;++		switch (wValue) {+		case UHF_PORT_ENABLE:+			DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - "+				    "ClearPortFeature USB_PORT_FEAT_ENABLE\n");+			hprt0.d32 = dwc_otg_read_hprt0(core_if);+			hprt0.b.prtena = 1;+			DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+			break;+		case UHF_PORT_SUSPEND:+			DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "+				    "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");++			if (core_if->power_down == 2) {+				dwc_otg_host_hibernation_restore(core_if, 0, 0);+			} else {+				DWC_WRITE_REG32(core_if->pcgcctl, 0);+				dwc_mdelay(5);++				hprt0.d32 = dwc_otg_read_hprt0(core_if);+				hprt0.b.prtres = 1;+				DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+				hprt0.b.prtsusp = 0;+				/* Clear Resume bit */+				dwc_mdelay(100);+				hprt0.b.prtres = 0;+				DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+			}+			break;+#ifdef CONFIG_USB_DWC_OTG_LPM+		case UHF_PORT_L1:+			{+				pcgcctl_data_t pcgcctl = {.d32 = 0 };+				glpmcfg_data_t lpmcfg = {.d32 = 0 };++				lpmcfg.d32 =+				    DWC_READ_REG32(&core_if->+						   core_global_regs->glpmcfg);+				lpmcfg.b.en_utmi_sleep = 0;+				lpmcfg.b.hird_thres &= (~(1 << 4));+				lpmcfg.b.prt_sleep_sts = 1;+				DWC_WRITE_REG32(&core_if->+						core_global_regs->glpmcfg,+						lpmcfg.d32);++				/* Clear Enbl_L1Gating bit. */+				pcgcctl.b.enbl_sleep_gating = 1;+				DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,+						 0);++				dwc_mdelay(5);++				hprt0.d32 = dwc_otg_read_hprt0(core_if);+				hprt0.b.prtres = 1;+				DWC_WRITE_REG32(core_if->host_if->hprt0,+						hprt0.d32);+				/* This bit will be cleared in wakeup interrupt handle */+				break;+			}+#endif+		case UHF_PORT_POWER:+			DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "+				    "ClearPortFeature USB_PORT_FEAT_POWER\n");+			hprt0.d32 = dwc_otg_read_hprt0(core_if);+			hprt0.b.prtpwr = 0;+			DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+			break;+		case UHF_PORT_INDICATOR:+			DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "+				    "ClearPortFeature USB_PORT_FEAT_INDICATOR\n");+			/* Port inidicator not supported */+			break;+		case UHF_C_PORT_CONNECTION:+			/* Clears drivers internal connect status change+			 * flag */+			DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "+				    "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");+			dwc_otg_hcd->flags.b.port_connect_status_change = 0;+			break;+		case UHF_C_PORT_RESET:+			/* Clears the driver's internal Port Reset Change+			 * flag */+			DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "+				    "ClearPortFeature USB_PORT_FEAT_C_RESET\n");+			dwc_otg_hcd->flags.b.port_reset_change = 0;+			break;+		case UHF_C_PORT_ENABLE:+			/* Clears the driver's internal Port+			 * Enable/Disable Change flag */+			DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "+				    "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");+			dwc_otg_hcd->flags.b.port_enable_change = 0;+			break;+		case UHF_C_PORT_SUSPEND:+			/* Clears the driver's internal Port Suspend+			 * Change flag, which is set when resume signaling on+			 * the host port is complete */+			DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "+				    "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");+			dwc_otg_hcd->flags.b.port_suspend_change = 0;+			break;+#ifdef CONFIG_USB_DWC_OTG_LPM+		case UHF_C_PORT_L1:+			dwc_otg_hcd->flags.b.port_l1_change = 0;+			break;+#endif+		case UHF_C_PORT_OVER_CURRENT:+			DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "+				    "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");+			dwc_otg_hcd->flags.b.port_over_current_change = 0;+			break;+		default:+			retval = -DWC_E_INVALID;+			DWC_ERROR("DWC OTG HCD - "+				  "ClearPortFeature request %xh "+				  "unknown or unsupported\n", wValue);+		}+		break;+	case UCR_GET_HUB_DESCRIPTOR:+		DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "+			    "GetHubDescriptor\n");+		hub_desc = (usb_hub_descriptor_t *) buf;+		hub_desc->bDescLength = 9;+		hub_desc->bDescriptorType = 0x29;+		hub_desc->bNbrPorts = 1;+		USETW(hub_desc->wHubCharacteristics, 0x08);+		hub_desc->bPwrOn2PwrGood = 1;+		hub_desc->bHubContrCurrent = 0;+		hub_desc->DeviceRemovable[0] = 0;+		hub_desc->DeviceRemovable[1] = 0xff;+		break;+	case UCR_GET_HUB_STATUS:+		DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "+			    "GetHubStatus\n");+		DWC_MEMSET(buf, 0, 4);+		break;+	case UCR_GET_PORT_STATUS:+		DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "+			    "GetPortStatus wIndex = 0x%04x FLAGS=0x%08x\n",+			    wIndex, dwc_otg_hcd->flags.d32);+		if (!wIndex || wIndex > 1)+			goto error;++		port_status = 0;++		if (dwc_otg_hcd->flags.b.port_connect_status_change)+			port_status |= (1 << UHF_C_PORT_CONNECTION);++		if (dwc_otg_hcd->flags.b.port_enable_change)+			port_status |= (1 << UHF_C_PORT_ENABLE);++		if (dwc_otg_hcd->flags.b.port_suspend_change)+			port_status |= (1 << UHF_C_PORT_SUSPEND);++		if (dwc_otg_hcd->flags.b.port_l1_change)+			port_status |= (1 << UHF_C_PORT_L1);++		if (dwc_otg_hcd->flags.b.port_reset_change) {+			port_status |= (1 << UHF_C_PORT_RESET);+		}++		if (dwc_otg_hcd->flags.b.port_over_current_change) {+			DWC_WARN("Overcurrent change detected\n");+			port_status |= (1 << UHF_C_PORT_OVER_CURRENT);+		}++		if (!dwc_otg_hcd->flags.b.port_connect_status) {+			/*+			 * The port is disconnected, which means the core is+			 * either in device mode or it soon will be. Just+			 * return 0's for the remainder of the port status+			 * since the port register can't be read if the core+			 * is in device mode.+			 */+			*((__le32 *) buf) = dwc_cpu_to_le32(&port_status);+			break;+		}++		hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);+		DWC_DEBUGPL(DBG_HCDV, "  HPRT0: 0x%08x\n", hprt0.d32);++		if (hprt0.b.prtconnsts)+			port_status |= (1 << UHF_PORT_CONNECTION);++		if (hprt0.b.prtena)+			port_status |= (1 << UHF_PORT_ENABLE);++		if (hprt0.b.prtsusp)+			port_status |= (1 << UHF_PORT_SUSPEND);++		if (hprt0.b.prtovrcurract)+			port_status |= (1 << UHF_PORT_OVER_CURRENT);++		if (hprt0.b.prtrst)+			port_status |= (1 << UHF_PORT_RESET);++		if (hprt0.b.prtpwr)+			port_status |= (1 << UHF_PORT_POWER);++		if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED)+			port_status |= (1 << UHF_PORT_HIGH_SPEED);+		else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED)+			port_status |= (1 << UHF_PORT_LOW_SPEED);++		if (hprt0.b.prttstctl)+			port_status |= (1 << UHF_PORT_TEST);+		if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) {+			port_status |= (1 << UHF_PORT_L1);+		}+		/*+		   For Synopsys HW emulation of Power down wkup_control asserts the+		   hreset_n and prst_n on suspned. This causes the HPRT0 to be zero.+		   We intentionally tell the software that port is in L2Suspend state.+		   Only for STE.+		*/+		if ((core_if->power_down == 2)+		    && (core_if->hibernation_suspend == 1)) {+			port_status |= (1 << UHF_PORT_SUSPEND);+		}+		/* USB_PORT_FEAT_INDICATOR unsupported always 0 */++		*((__le32 *) buf) = dwc_cpu_to_le32(&port_status);++		break;+	case UCR_SET_HUB_FEATURE:+		DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "+			    "SetHubFeature\n");+		/* No HUB features supported */+		break;+	case UCR_SET_PORT_FEATURE:+		if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1))+			goto error;++		if (!dwc_otg_hcd->flags.b.port_connect_status) {+			/*+			 * The port is disconnected, which means the core is+			 * either in device mode or it soon will be. Just+			 * return without doing anything since the port+			 * register can't be written if the core is in device+			 * mode.+			 */+			break;+		}++		switch (wValue) {+		case UHF_PORT_SUSPEND:+			DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "+				    "SetPortFeature - USB_PORT_FEAT_SUSPEND\n");+			if (dwc_otg_hcd_otg_port(dwc_otg_hcd) != wIndex) {+				goto error;+			}+			if (core_if->power_down == 2) {+				int timeout = 300;+				dwc_irqflags_t flags;+				pcgcctl_data_t pcgcctl = {.d32 = 0 };+				gpwrdn_data_t gpwrdn = {.d32 = 0 };+				gusbcfg_data_t gusbcfg = {.d32 = 0 };+#ifdef DWC_DEV_SRPCAP+				int32_t otg_cap_param = core_if->core_params->otg_cap;+#endif+				DWC_PRINTF("Preparing for complete power-off\n");++				/* Save registers before hibernation */+				dwc_otg_save_global_regs(core_if);+				dwc_otg_save_host_regs(core_if);++				hprt0.d32 = dwc_otg_read_hprt0(core_if);+				hprt0.b.prtsusp = 1;+				hprt0.b.prtena = 0;+				DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+				/* Spin hprt0.b.prtsusp to became 1 */+				do {+					hprt0.d32 = dwc_otg_read_hprt0(core_if);+					if (hprt0.b.prtsusp) {+						break;+					}+					dwc_mdelay(1);+				} while (--timeout);+				if (!timeout) {+					DWC_WARN("Suspend wasn't genereted\n");+				}+				dwc_udelay(10);++				/*+				 * We need to disable interrupts to prevent servicing of any IRQ+				 * during going to hibernation+				 */+				DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);+				core_if->lx_state = DWC_OTG_L2;+#ifdef DWC_DEV_SRPCAP+				hprt0.d32 = dwc_otg_read_hprt0(core_if);+				hprt0.b.prtpwr = 0;+				hprt0.b.prtena = 0;+				DWC_WRITE_REG32(core_if->host_if->hprt0,+						hprt0.d32);+#endif+				gusbcfg.d32 =+				    DWC_READ_REG32(&core_if->core_global_regs->+						   gusbcfg);+				if (gusbcfg.b.ulpi_utmi_sel == 1) {+					/* ULPI interface */+					/* Suspend the Phy Clock */+					pcgcctl.d32 = 0;+					pcgcctl.b.stoppclk = 1;+					DWC_MODIFY_REG32(core_if->pcgcctl, 0,+							 pcgcctl.d32);+					dwc_udelay(10);+					gpwrdn.b.pmuactv = 1;+					DWC_MODIFY_REG32(&core_if->+							 core_global_regs->+							 gpwrdn, 0, gpwrdn.d32);+				} else {+					/* UTMI+ Interface */+					gpwrdn.b.pmuactv = 1;+					DWC_MODIFY_REG32(&core_if->+							 core_global_regs->+							 gpwrdn, 0, gpwrdn.d32);+					dwc_udelay(10);+					pcgcctl.b.stoppclk = 1;+					DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);+					dwc_udelay(10);+				}+#ifdef DWC_DEV_SRPCAP+				gpwrdn.d32 = 0;+				gpwrdn.b.dis_vbus = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, 0, gpwrdn.d32);+#endif+				gpwrdn.d32 = 0;+				gpwrdn.b.pmuintsel = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, 0, gpwrdn.d32);+				dwc_udelay(10);++				gpwrdn.d32 = 0;+#ifdef DWC_DEV_SRPCAP+				gpwrdn.b.srp_det_msk = 1;+#endif+				gpwrdn.b.disconn_det_msk = 1;+				gpwrdn.b.lnstchng_msk = 1;+				gpwrdn.b.sts_chngint_msk = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, 0, gpwrdn.d32);+				dwc_udelay(10);++				/* Enable Power Down Clamp and all interrupts in GPWRDN */+				gpwrdn.d32 = 0;+				gpwrdn.b.pwrdnclmp = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, 0, gpwrdn.d32);+				dwc_udelay(10);++				/* Switch off VDD */+				gpwrdn.d32 = 0;+				gpwrdn.b.pwrdnswtch = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, 0, gpwrdn.d32);++#ifdef DWC_DEV_SRPCAP+				if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE)+				{+					core_if->pwron_timer_started = 1;+					DWC_TIMER_SCHEDULE(core_if->pwron_timer, 6000 /* 6 secs */ );+				}+#endif+				/* Save gpwrdn register for further usage if stschng interrupt */+				core_if->gr_backup->gpwrdn_local =+						DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);++				/* Set flag to indicate that we are in hibernation */+				core_if->hibernation_suspend = 1;+				DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,flags);++				DWC_PRINTF("Host hibernation completed\n");+				// Exit from case statement+				break;++			}+			if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex &&+			    dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {+				gotgctl_data_t gotgctl = {.d32 = 0 };+				gotgctl.b.hstsethnpen = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gotgctl, 0, gotgctl.d32);+				core_if->op_state = A_SUSPEND;+			}+			hprt0.d32 = dwc_otg_read_hprt0(core_if);+			hprt0.b.prtsusp = 1;+			DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+			{+				dwc_irqflags_t flags;+				/* Update lx_state */+				DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);+				core_if->lx_state = DWC_OTG_L2;+				DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);+			}+			/* Suspend the Phy Clock */+			{+				pcgcctl_data_t pcgcctl = {.d32 = 0 };+				pcgcctl.b.stoppclk = 1;+				DWC_MODIFY_REG32(core_if->pcgcctl, 0,+						 pcgcctl.d32);+				dwc_udelay(10);+			}++			/* For HNP the bus must be suspended for at least 200ms. */+			if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {+				pcgcctl_data_t pcgcctl = {.d32 = 0 };+				pcgcctl.b.stoppclk = 1;+                DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);+				dwc_mdelay(200);+			}++			/** @todo - check how sw can wait for 1 sec to check asesvld??? */+#if 0 //vahrama !!!!!!!!!!!!!!!!!!+			if (core_if->adp_enable) {+				gotgctl_data_t gotgctl = {.d32 = 0 };+				gpwrdn_data_t gpwrdn;++				while (gotgctl.b.asesvld == 1) {+					gotgctl.d32 =+					    DWC_READ_REG32(&core_if->+							   core_global_regs->+							   gotgctl);+					dwc_mdelay(100);+				}++				/* Enable Power Down Logic */+				gpwrdn.d32 = 0;+				gpwrdn.b.pmuactv = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, 0, gpwrdn.d32);++				/* Unmask SRP detected interrupt from Power Down Logic */+				gpwrdn.d32 = 0;+				gpwrdn.b.srp_det_msk = 1;+				DWC_MODIFY_REG32(&core_if->core_global_regs->+						 gpwrdn, 0, gpwrdn.d32);++				dwc_otg_adp_probe_start(core_if);+			}+#endif+			break;+		case UHF_PORT_POWER:+			DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "+				    "SetPortFeature - USB_PORT_FEAT_POWER\n");+			hprt0.d32 = dwc_otg_read_hprt0(core_if);+			hprt0.b.prtpwr = 1;+			DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+			break;+		case UHF_PORT_RESET:+			if ((core_if->power_down == 2)+			    && (core_if->hibernation_suspend == 1)) {+				/* If we are going to exit from Hibernated+				 * state via USB RESET.+				 */+				dwc_otg_host_hibernation_restore(core_if, 0, 1);+			} else {+				hprt0.d32 = dwc_otg_read_hprt0(core_if);++				DWC_DEBUGPL(DBG_HCD,+					    "DWC OTG HCD HUB CONTROL - "+					    "SetPortFeature - USB_PORT_FEAT_RESET\n");+				{+					pcgcctl_data_t pcgcctl = {.d32 = 0 };+					pcgcctl.b.enbl_sleep_gating = 1;+					pcgcctl.b.stoppclk = 1;+					DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);+					DWC_WRITE_REG32(core_if->pcgcctl, 0);+				}+#ifdef CONFIG_USB_DWC_OTG_LPM+				{+					glpmcfg_data_t lpmcfg;+					lpmcfg.d32 =+						DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);+					if (lpmcfg.b.prt_sleep_sts) {+						lpmcfg.b.en_utmi_sleep = 0;+						lpmcfg.b.hird_thres &= (~(1 << 4));+						DWC_WRITE_REG32+						    (&core_if->core_global_regs->glpmcfg,+						     lpmcfg.d32);+						dwc_mdelay(1);+					}+				}+#endif+				hprt0.d32 = dwc_otg_read_hprt0(core_if);+				/* Clear suspend bit if resetting from suspended state. */+				hprt0.b.prtsusp = 0;+				/* When B-Host the Port reset bit is set in+				 * the Start HCD Callback function, so that+				 * the reset is started within 1ms of the HNP+				 * success interrupt. */+				if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) {+					hprt0.b.prtpwr = 1;+					hprt0.b.prtrst = 1;+					DWC_PRINTF("Indeed it is in host mode hprt0 = %08x\n",hprt0.d32);+					DWC_WRITE_REG32(core_if->host_if->hprt0,+							hprt0.d32);+				}+				/* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */+				dwc_mdelay(60);+				hprt0.b.prtrst = 0;+				DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+				core_if->lx_state = DWC_OTG_L0;	/* Now back to the on state */+			}+			break;+#ifdef DWC_HS_ELECT_TST+		case UHF_PORT_TEST:+			{+				uint32_t t;+				gintmsk_data_t gintmsk;++				t = (wIndex >> 8);	/* MSB wIndex USB */+				DWC_DEBUGPL(DBG_HCD,+					    "DWC OTG HCD HUB CONTROL - "+					    "SetPortFeature - USB_PORT_FEAT_TEST %d\n",+					    t);+				DWC_WARN("USB_PORT_FEAT_TEST %d\n", t);+				if (t < 6) {+					hprt0.d32 = dwc_otg_read_hprt0(core_if);+					hprt0.b.prttstctl = t;+					DWC_WRITE_REG32(core_if->host_if->hprt0,+							hprt0.d32);+				} else {+					/* Setup global vars with reg addresses (quick and+					 * dirty hack, should be cleaned up)+					 */+					global_regs = core_if->core_global_regs;+					hc_global_regs =+					    core_if->host_if->host_global_regs;+					hc_regs =+					    (dwc_otg_hc_regs_t *) ((char *)+								   global_regs ++								   0x500);+					data_fifo =+					    (uint32_t *) ((char *)global_regs ++							  0x1000);++					if (t == 6) {	/* HS_HOST_PORT_SUSPEND_RESUME */+						/* Save current interrupt mask */+						gintmsk.d32 =+						    DWC_READ_REG32+						    (&global_regs->gintmsk);++						/* Disable all interrupts while we muck with+						 * the hardware directly+						 */+						DWC_WRITE_REG32(&global_regs->gintmsk, 0);++						/* 15 second delay per the test spec */+						dwc_mdelay(15000);++						/* Drive suspend on the root port */+						hprt0.d32 =+						    dwc_otg_read_hprt0(core_if);+						hprt0.b.prtsusp = 1;+						hprt0.b.prtres = 0;+						DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);++						/* 15 second delay per the test spec */+						dwc_mdelay(15000);++						/* Drive resume on the root port */+						hprt0.d32 =+						    dwc_otg_read_hprt0(core_if);+						hprt0.b.prtsusp = 0;+						hprt0.b.prtres = 1;+						DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);+						dwc_mdelay(100);++						/* Clear the resume bit */+						hprt0.b.prtres = 0;+						DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);++						/* Restore interrupts */+						DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);+					} else if (t == 7) {	/* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */+						/* Save current interrupt mask */+						gintmsk.d32 =+						    DWC_READ_REG32+						    (&global_regs->gintmsk);++						/* Disable all interrupts while we muck with+						 * the hardware directly+						 */+						DWC_WRITE_REG32(&global_regs->gintmsk, 0);++						/* 15 second delay per the test spec */+						dwc_mdelay(15000);++						/* Send the Setup packet */+						do_setup();++						/* 15 second delay so nothing else happens for awhile */+						dwc_mdelay(15000);++						/* Restore interrupts */+						DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);+					} else if (t == 8) {	/* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */+						/* Save current interrupt mask */+						gintmsk.d32 =+						    DWC_READ_REG32+						    (&global_regs->gintmsk);++						/* Disable all interrupts while we muck with+						 * the hardware directly+						 */+						DWC_WRITE_REG32(&global_regs->gintmsk, 0);++						/* Send the Setup packet */+						do_setup();++						/* 15 second delay so nothing else happens for awhile */+						dwc_mdelay(15000);++						/* Send the In and Ack packets */+						do_in_ack();++						/* 15 second delay so nothing else happens for awhile */+						dwc_mdelay(15000);++						/* Restore interrupts */+						DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);+					}+				}+				break;+			}+#endif /* DWC_HS_ELECT_TST */++		case UHF_PORT_INDICATOR:+			DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "+				    "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");+			/* Not supported */+			break;+		default:+			retval = -DWC_E_INVALID;+			DWC_ERROR("DWC OTG HCD - "+				  "SetPortFeature request %xh "+				  "unknown or unsupported\n", wValue);+			break;+		}+		break;+#ifdef CONFIG_USB_DWC_OTG_LPM+	case UCR_SET_AND_TEST_PORT_FEATURE:+		if (wValue != UHF_PORT_L1) {+			goto error;+		}+		{+			int portnum, hird, devaddr, remwake;+			glpmcfg_data_t lpmcfg;+			uint32_t time_usecs;+			gintsts_data_t gintsts;+			gintmsk_data_t gintmsk;++			if (!dwc_otg_get_param_lpm_enable(core_if)) {+				goto error;+			}+			if (wValue != UHF_PORT_L1 || wLength != 1) {+				goto error;+			}+			/* Check if the port currently is in SLEEP state */+			lpmcfg.d32 =+			    DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);+			if (lpmcfg.b.prt_sleep_sts) {+				DWC_INFO("Port is already in sleep mode\n");+				buf[0] = 0;	/* Return success */+				break;+			}++			portnum = wIndex & 0xf;+			hird = (wIndex >> 4) & 0xf;+			devaddr = (wIndex >> 8) & 0x7f;+			remwake = (wIndex >> 15);++			if (portnum != 1) {+				retval = -DWC_E_INVALID;+				DWC_WARN+				    ("Wrong port number(%d) in SetandTestPortFeature request\n",+				     portnum);+				break;+			}++			DWC_PRINTF+			    ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n",+			     portnum, hird, devaddr, remwake);+			/* Disable LPM interrupt */+			gintmsk.d32 = 0;+			gintmsk.b.lpmtranrcvd = 1;+			DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,+					 gintmsk.d32, 0);++			if (dwc_otg_hcd_send_lpm+			    (dwc_otg_hcd, devaddr, hird, remwake)) {+				retval = -DWC_E_INVALID;+				break;+			}++			time_usecs = 10 * (lpmcfg.b.retry_count + 1);+			/* We will consider timeout if time_usecs microseconds pass,+			 * and we don't receive LPM transaction status.+			 * After receiving non-error responce(ACK/NYET/STALL) from device,+			 *  core will set lpmtranrcvd bit.+			 */+			do {+				gintsts.d32 =+				    DWC_READ_REG32(&core_if->core_global_regs->gintsts);+				if (gintsts.b.lpmtranrcvd) {+					break;+				}+				dwc_udelay(1);+			} while (--time_usecs);+			/* lpm_int bit will be cleared in LPM interrupt handler */++			/* Now fill status+			 * 0x00 - Success+			 * 0x10 - NYET+			 * 0x11 - Timeout+			 */+			if (!gintsts.b.lpmtranrcvd) {+				buf[0] = 0x3;	/* Completion code is Timeout */+				dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd);+			} else {+				lpmcfg.d32 =+				    DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);+				if (lpmcfg.b.lpm_resp == 0x3) {+					/* ACK responce from the device */+					buf[0] = 0x00;	/* Success */+				} else if (lpmcfg.b.lpm_resp == 0x2) {+					/* NYET responce from the device */+					buf[0] = 0x2;+				} else {+					/* Otherwise responce with Timeout */+					buf[0] = 0x3;+				}+			}+			DWC_PRINTF("Device responce to LPM trans is %x\n",+				   lpmcfg.b.lpm_resp);+			DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0,+					 gintmsk.d32);++			break;+		}+#endif /* CONFIG_USB_DWC_OTG_LPM */+	default:+error:+		retval = -DWC_E_INVALID;+		DWC_WARN("DWC OTG HCD - "+			 "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n",+			 typeReq, wIndex, wValue);+		break;+	}++	return retval;+}++#ifdef CONFIG_USB_DWC_OTG_LPM+/** Returns index of host channel to perform LPM transaction. */+int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, uint8_t devaddr)+{+	dwc_otg_core_if_t *core_if = hcd->core_if;+	dwc_hc_t *hc;+	hcchar_data_t hcchar;+	gintmsk_data_t gintmsk = {.d32 = 0 };++	if (DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {+		DWC_PRINTF("No free channel to select for LPM transaction\n");+		return -1;+	}++	hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);++	/* Mask host channel interrupts. */+	gintmsk.b.hcintr = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);++	/* Fill fields that core needs for LPM transaction */+	hcchar.b.devaddr = devaddr;+	hcchar.b.epnum = 0;+	hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;+	hcchar.b.mps = 64;+	hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);+	hcchar.b.epdir = 0;	/* OUT */+	DWC_WRITE_REG32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar,+			hcchar.d32);++	/* Remove the host channel from the free list. */+	DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);++	DWC_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr);++	return hc->hc_num;+}++/** Release hc after performing LPM transaction */+void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd)+{+	dwc_hc_t *hc;+	glpmcfg_data_t lpmcfg;+	uint8_t hc_num;++	lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);+	hc_num = lpmcfg.b.lpm_chan_index;++	hc = hcd->hc_ptr_array[hc_num];++	DWC_PRINTF("Freeing channel %d after LPM\n", hc_num);+	/* Return host channel to free list */+	DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);+}++int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird,+			 uint8_t bRemoteWake)+{+	glpmcfg_data_t lpmcfg;+	pcgcctl_data_t pcgcctl = {.d32 = 0 };+	int channel;++	channel = dwc_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr);+	if (channel < 0) {+		return channel;+	}++	pcgcctl.b.enbl_sleep_gating = 1;+	DWC_MODIFY_REG32(hcd->core_if->pcgcctl, 0, pcgcctl.d32);++	/* Read LPM config register */+	lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);++	/* Program LPM transaction fields */+	lpmcfg.b.rem_wkup_en = bRemoteWake;+	lpmcfg.b.hird = hird;+	lpmcfg.b.hird_thres = 0x1c;+	lpmcfg.b.lpm_chan_index = channel;+	lpmcfg.b.en_utmi_sleep = 1;+	/* Program LPM config register */+	DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);++	/* Send LPM transaction */+	lpmcfg.b.send_lpm = 1;+	DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);++	return 0;+}++#endif /* CONFIG_USB_DWC_OTG_LPM */++int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port)+{+	int retval;++	if (port != 1) {+		return -DWC_E_INVALID;+	}++	retval = (hcd->flags.b.port_connect_status_change ||+		  hcd->flags.b.port_reset_change ||+		  hcd->flags.b.port_enable_change ||+		  hcd->flags.b.port_suspend_change ||+		  hcd->flags.b.port_over_current_change);+#ifdef DEBUG+	if (retval) {+		DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:"+			    " Root port status changed\n");+		DWC_DEBUGPL(DBG_HCDV, "  port_connect_status_change: %d\n",+			    hcd->flags.b.port_connect_status_change);+		DWC_DEBUGPL(DBG_HCDV, "  port_reset_change: %d\n",+			    hcd->flags.b.port_reset_change);+		DWC_DEBUGPL(DBG_HCDV, "  port_enable_change: %d\n",+			    hcd->flags.b.port_enable_change);+		DWC_DEBUGPL(DBG_HCDV, "  port_suspend_change: %d\n",+			    hcd->flags.b.port_suspend_change);+		DWC_DEBUGPL(DBG_HCDV, "  port_over_current_change: %d\n",+			    hcd->flags.b.port_over_current_change);+	}+#endif+	return retval;+}++int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * dwc_otg_hcd)+{+	hfnum_data_t hfnum;+	hfnum.d32 =+	    DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->+			   hfnum);++#ifdef DEBUG_SOF+	DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n",+		    hfnum.b.frnum);+#endif+	return hfnum.b.frnum;+}++int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,+		      struct dwc_otg_hcd_function_ops *fops)+{+	int retval = 0;++	hcd->fops = fops;+	if (!dwc_otg_is_device_mode(hcd->core_if) &&+		(!hcd->core_if->adp_enable || hcd->core_if->adp.adp_started)) {+		dwc_otg_hcd_reinit(hcd);+	} else {+		retval = -DWC_E_NO_DEVICE;+	}++	return retval;+}++void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd)+{+	return hcd->priv;+}++void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data)+{+	hcd->priv = priv_data;+}++uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd)+{+	return hcd->otg_port;+}++uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd)+{+	uint32_t is_b_host;+	if (hcd->core_if->op_state == B_HOST) {+		is_b_host = 1;+	} else {+		is_b_host = 0;+	}++	return is_b_host;+}++dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,+					 int iso_desc_count, int atomic_alloc)+{+	dwc_otg_hcd_urb_t *dwc_otg_urb;+	uint32_t size;++	size =+	    sizeof(*dwc_otg_urb) ++	    iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc);+	if (atomic_alloc)+		dwc_otg_urb = DWC_ALLOC_ATOMIC(size);+	else+		dwc_otg_urb = DWC_ALLOC(size);++        if (dwc_otg_urb)+		dwc_otg_urb->packet_count = iso_desc_count;+        else {+		DWC_ERROR("**** DWC OTG HCD URB alloc - "+			"%salloc of %db failed\n",+			atomic_alloc?"atomic ":"", size);+	}+	return dwc_otg_urb;+}++void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * dwc_otg_urb,+				  uint8_t dev_addr, uint8_t ep_num,+				  uint8_t ep_type, uint8_t ep_dir, uint16_t mps)+{+	dwc_otg_hcd_fill_pipe(&dwc_otg_urb->pipe_info, dev_addr, ep_num,+			      ep_type, ep_dir, mps);+#if 0+	DWC_PRINTF+	    ("addr = %d, ep_num = %d, ep_dir = 0x%x, ep_type = 0x%x, mps = %d\n",+	     dev_addr, ep_num, ep_dir, ep_type, mps);+#endif+}++void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * dwc_otg_urb,+				void *urb_handle, void *buf, dwc_dma_t dma,+				uint32_t buflen, void *setup_packet,+				dwc_dma_t setup_dma, uint32_t flags,+				uint16_t interval)+{+	dwc_otg_urb->priv = urb_handle;+	dwc_otg_urb->buf = buf;+	dwc_otg_urb->dma = dma;+	dwc_otg_urb->length = buflen;+	dwc_otg_urb->setup_packet = setup_packet;+	dwc_otg_urb->setup_dma = setup_dma;+	dwc_otg_urb->flags = flags;+	dwc_otg_urb->interval = interval;+	dwc_otg_urb->status = -DWC_E_IN_PROGRESS;+}++uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb)+{+	return dwc_otg_urb->status;+}++uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * dwc_otg_urb)+{+	return dwc_otg_urb->actual_length;+}++uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * dwc_otg_urb)+{+	return dwc_otg_urb->error_count;+}++void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,+					 int desc_num, uint32_t offset,+					 uint32_t length)+{+	dwc_otg_urb->iso_descs[desc_num].offset = offset;+	dwc_otg_urb->iso_descs[desc_num].length = length;+}++uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * dwc_otg_urb,+					     int desc_num)+{+	return dwc_otg_urb->iso_descs[desc_num].status;+}++uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *+						    dwc_otg_urb, int desc_num)+{+	return dwc_otg_urb->iso_descs[desc_num].actual_length;+}++int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, void *ep_handle)+{+	int allocated = 0;+	dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;++	if (qh) {+		if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {+			allocated = 1;+		}+	}+	return allocated;+}++int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle)+{+	dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;+	int freed = 0;+	DWC_ASSERT(qh, "qh is not allocated\n");++	if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {+		freed = 1;+	}++	return freed;+}++uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, void *ep_handle)+{+	dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;+	DWC_ASSERT(qh, "qh is not allocated\n");+	return qh->usecs;+}++void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd)+{+#ifdef DEBUG+	int num_channels;+	int i;+	gnptxsts_data_t np_tx_status;+	hptxsts_data_t p_tx_status;++	num_channels = hcd->core_if->core_params->host_channels;+	DWC_PRINTF("\n");+	DWC_PRINTF+	    ("************************************************************\n");+	DWC_PRINTF("HCD State:\n");+	DWC_PRINTF("  Num channels: %d\n", num_channels);+	for (i = 0; i < num_channels; i++) {+		dwc_hc_t *hc = hcd->hc_ptr_array[i];+		DWC_PRINTF("  Channel %d:\n", i);+		DWC_PRINTF("    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",+			   hc->dev_addr, hc->ep_num, hc->ep_is_in);+		DWC_PRINTF("    speed: %d\n", hc->speed);+		DWC_PRINTF("    ep_type: %d\n", hc->ep_type);+		DWC_PRINTF("    max_packet: %d\n", hc->max_packet);+		DWC_PRINTF("    data_pid_start: %d\n", hc->data_pid_start);+		DWC_PRINTF("    multi_count: %d\n", hc->multi_count);+		DWC_PRINTF("    xfer_started: %d\n", hc->xfer_started);+		DWC_PRINTF("    xfer_buff: %p\n", hc->xfer_buff);+		DWC_PRINTF("    xfer_len: %d\n", hc->xfer_len);+		DWC_PRINTF("    xfer_count: %d\n", hc->xfer_count);+		DWC_PRINTF("    halt_on_queue: %d\n", hc->halt_on_queue);+		DWC_PRINTF("    halt_pending: %d\n", hc->halt_pending);+		DWC_PRINTF("    halt_status: %d\n", hc->halt_status);+		DWC_PRINTF("    do_split: %d\n", hc->do_split);+		DWC_PRINTF("    complete_split: %d\n", hc->complete_split);+		DWC_PRINTF("    hub_addr: %d\n", hc->hub_addr);+		DWC_PRINTF("    port_addr: %d\n", hc->port_addr);+		DWC_PRINTF("    xact_pos: %d\n", hc->xact_pos);+		DWC_PRINTF("    requests: %d\n", hc->requests);+		DWC_PRINTF("    qh: %p\n", hc->qh);+		if (hc->xfer_started) {+			hfnum_data_t hfnum;+			hcchar_data_t hcchar;+			hctsiz_data_t hctsiz;+			hcint_data_t hcint;+			hcintmsk_data_t hcintmsk;+			hfnum.d32 =+			    DWC_READ_REG32(&hcd->core_if->+					   host_if->host_global_regs->hfnum);+			hcchar.d32 =+			    DWC_READ_REG32(&hcd->core_if->host_if->+					   hc_regs[i]->hcchar);+			hctsiz.d32 =+			    DWC_READ_REG32(&hcd->core_if->host_if->+					   hc_regs[i]->hctsiz);+			hcint.d32 =+			    DWC_READ_REG32(&hcd->core_if->host_if->+					   hc_regs[i]->hcint);+			hcintmsk.d32 =+			    DWC_READ_REG32(&hcd->core_if->host_if->+					   hc_regs[i]->hcintmsk);+			DWC_PRINTF("    hfnum: 0x%08x\n", hfnum.d32);+			DWC_PRINTF("    hcchar: 0x%08x\n", hcchar.d32);+			DWC_PRINTF("    hctsiz: 0x%08x\n", hctsiz.d32);+			DWC_PRINTF("    hcint: 0x%08x\n", hcint.d32);+			DWC_PRINTF("    hcintmsk: 0x%08x\n", hcintmsk.d32);+		}+		if (hc->xfer_started && hc->qh) {+			dwc_otg_qtd_t *qtd;+			dwc_otg_hcd_urb_t *urb;++			DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) {+				if (!qtd->in_process)+					break;++				urb = qtd->urb;+			DWC_PRINTF("    URB Info:\n");+			DWC_PRINTF("      qtd: %p, urb: %p\n", qtd, urb);+			if (urb) {+				DWC_PRINTF("      Dev: %d, EP: %d %s\n",+					   dwc_otg_hcd_get_dev_addr(&urb->+								    pipe_info),+					   dwc_otg_hcd_get_ep_num(&urb->+								  pipe_info),+					   dwc_otg_hcd_is_pipe_in(&urb->+								  pipe_info) ?+					   "IN" : "OUT");+				DWC_PRINTF("      Max packet size: %d\n",+					   dwc_otg_hcd_get_mps(&urb->+							       pipe_info));+				DWC_PRINTF("      transfer_buffer: %p\n",+					   urb->buf);+				DWC_PRINTF("      transfer_dma: %p\n",+					   (void *)urb->dma);+				DWC_PRINTF("      transfer_buffer_length: %d\n",+					   urb->length);+					DWC_PRINTF("      actual_length: %d\n",+						   urb->actual_length);+				}+			}+		}+	}+	DWC_PRINTF("  non_periodic_channels: %d\n", hcd->non_periodic_channels);+	DWC_PRINTF("  periodic_channels: %d\n", hcd->periodic_channels);+	DWC_PRINTF("  periodic_usecs: %d\n", hcd->periodic_usecs);+	np_tx_status.d32 =+	    DWC_READ_REG32(&hcd->core_if->core_global_regs->gnptxsts);+	DWC_PRINTF("  NP Tx Req Queue Space Avail: %d\n",+		   np_tx_status.b.nptxqspcavail);+	DWC_PRINTF("  NP Tx FIFO Space Avail: %d\n",+		   np_tx_status.b.nptxfspcavail);+	p_tx_status.d32 =+	    DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hptxsts);+	DWC_PRINTF("  P Tx Req Queue Space Avail: %d\n",+		   p_tx_status.b.ptxqspcavail);+	DWC_PRINTF("  P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail);+	dwc_otg_hcd_dump_frrem(hcd);+	dwc_otg_dump_global_registers(hcd->core_if);+	dwc_otg_dump_host_registers(hcd->core_if);+	DWC_PRINTF+	    ("************************************************************\n");+	DWC_PRINTF("\n");+#endif+}++#ifdef DEBUG+void dwc_print_setup_data(uint8_t * setup)+{+	int i;+	if (CHK_DEBUG_LEVEL(DBG_HCD)) {+		DWC_PRINTF("Setup Data = MSB ");+		for (i = 7; i >= 0; i--)+			DWC_PRINTF("%02x ", setup[i]);+		DWC_PRINTF("\n");+		DWC_PRINTF("  bmRequestType Tranfer = %s\n",+			   (setup[0] & 0x80) ? "Device-to-Host" :+			   "Host-to-Device");+		DWC_PRINTF("  bmRequestType Type = ");+		switch ((setup[0] & 0x60) >> 5) {+		case 0:+			DWC_PRINTF("Standard\n");+			break;+		case 1:+			DWC_PRINTF("Class\n");+			break;+		case 2:+			DWC_PRINTF("Vendor\n");+			break;+		case 3:+			DWC_PRINTF("Reserved\n");+			break;+		}+		DWC_PRINTF("  bmRequestType Recipient = ");+		switch (setup[0] & 0x1f) {+		case 0:+			DWC_PRINTF("Device\n");+			break;+		case 1:+			DWC_PRINTF("Interface\n");+			break;+		case 2:+			DWC_PRINTF("Endpoint\n");+			break;+		case 3:+			DWC_PRINTF("Other\n");+			break;+		default:+			DWC_PRINTF("Reserved\n");+			break;+		}+		DWC_PRINTF("  bRequest = 0x%0x\n", setup[1]);+		DWC_PRINTF("  wValue = 0x%0x\n", *((uint16_t *) & setup[2]));+		DWC_PRINTF("  wIndex = 0x%0x\n", *((uint16_t *) & setup[4]));+		DWC_PRINTF("  wLength = 0x%0x\n\n", *((uint16_t *) & setup[6]));+	}+}+#endif++void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd)+{+#if 0+	DWC_PRINTF("Frame remaining at SOF:\n");+	DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",+		   hcd->frrem_samples, hcd->frrem_accum,+		   (hcd->frrem_samples > 0) ?+		   hcd->frrem_accum / hcd->frrem_samples : 0);++	DWC_PRINTF("\n");+	DWC_PRINTF("Frame remaining at start_transfer (uframe 7):\n");+	DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",+		   hcd->core_if->hfnum_7_samples,+		   hcd->core_if->hfnum_7_frrem_accum,+		   (hcd->core_if->hfnum_7_samples >+		    0) ? hcd->core_if->hfnum_7_frrem_accum /+		   hcd->core_if->hfnum_7_samples : 0);+	DWC_PRINTF("Frame remaining at start_transfer (uframe 0):\n");+	DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",+		   hcd->core_if->hfnum_0_samples,+		   hcd->core_if->hfnum_0_frrem_accum,+		   (hcd->core_if->hfnum_0_samples >+		    0) ? hcd->core_if->hfnum_0_frrem_accum /+		   hcd->core_if->hfnum_0_samples : 0);+	DWC_PRINTF("Frame remaining at start_transfer (uframe 1-6):\n");+	DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",+		   hcd->core_if->hfnum_other_samples,+		   hcd->core_if->hfnum_other_frrem_accum,+		   (hcd->core_if->hfnum_other_samples >+		    0) ? hcd->core_if->hfnum_other_frrem_accum /+		   hcd->core_if->hfnum_other_samples : 0);++	DWC_PRINTF("\n");+	DWC_PRINTF("Frame remaining at sample point A (uframe 7):\n");+	DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",+		   hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a,+		   (hcd->hfnum_7_samples_a > 0) ?+		   hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0);+	DWC_PRINTF("Frame remaining at sample point A (uframe 0):\n");+	DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",+		   hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a,+		   (hcd->hfnum_0_samples_a > 0) ?+		   hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0);+	DWC_PRINTF("Frame remaining at sample point A (uframe 1-6):\n");+	DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",+		   hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a,+		   (hcd->hfnum_other_samples_a > 0) ?+		   hcd->hfnum_other_frrem_accum_a /+		   hcd->hfnum_other_samples_a : 0);++	DWC_PRINTF("\n");+	DWC_PRINTF("Frame remaining at sample point B (uframe 7):\n");+	DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",+		   hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b,+		   (hcd->hfnum_7_samples_b > 0) ?+		   hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0);+	DWC_PRINTF("Frame remaining at sample point B (uframe 0):\n");+	DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",+		   hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b,+		   (hcd->hfnum_0_samples_b > 0) ?+		   hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0);+	DWC_PRINTF("Frame remaining at sample point B (uframe 1-6):\n");+	DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",+		   hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b,+		   (hcd->hfnum_other_samples_b > 0) ?+		   hcd->hfnum_other_frrem_accum_b /+		   hcd->hfnum_other_samples_b : 0);+#endif+}++#endif /* DWC_DEVICE_ONLY */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,1132 @@+/*==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $+ * $Revision: #10 $+ * $Date: 2011/10/20 $+ * $Change: 1869464 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */+#ifndef DWC_DEVICE_ONLY++/** @file+ * This file contains Descriptor DMA support implementation for host mode.+ */++#include "dwc_otg_hcd.h"+#include "dwc_otg_regs.h"++extern bool microframe_schedule;++static inline uint8_t frame_list_idx(uint16_t frame)+{+	return (frame & (MAX_FRLIST_EN_NUM - 1));+}++static inline uint16_t desclist_idx_inc(uint16_t idx, uint16_t inc, uint8_t speed)+{+	return (idx + inc) &+	    (((speed ==+	       DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC :+	      MAX_DMA_DESC_NUM_GENERIC) - 1);+}++static inline uint16_t desclist_idx_dec(uint16_t idx, uint16_t inc, uint8_t speed)+{+	return (idx - inc) &+	    (((speed ==+	       DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC :+	      MAX_DMA_DESC_NUM_GENERIC) - 1);+}++static inline uint16_t max_desc_num(dwc_otg_qh_t * qh)+{+	return (((qh->ep_type == UE_ISOCHRONOUS)+		 && (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH))+		? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC);+}+static inline uint16_t frame_incr_val(dwc_otg_qh_t * qh)+{+	return ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH)+		? ((qh->interval + 8 - 1) / 8)+		: qh->interval);+}++static int desc_list_alloc(dwc_otg_qh_t * qh)+{+	int retval = 0;++	qh->desc_list = (dwc_otg_host_dma_desc_t *)+	    DWC_DMA_ALLOC(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh),+			  &qh->desc_list_dma);++	if (!qh->desc_list) {+		retval = -DWC_E_NO_MEMORY;+		DWC_ERROR("%s: DMA descriptor list allocation failed\n", __func__);++	}++	dwc_memset(qh->desc_list, 0x00,+		   sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));++	qh->n_bytes =+	    (uint32_t *) DWC_ALLOC(sizeof(uint32_t) * max_desc_num(qh));++	if (!qh->n_bytes) {+		retval = -DWC_E_NO_MEMORY;+		DWC_ERROR+		    ("%s: Failed to allocate array for descriptors' size actual values\n",+		     __func__);++	}+	return retval;++}++static void desc_list_free(dwc_otg_qh_t * qh)+{+	if (qh->desc_list) {+		DWC_DMA_FREE(max_desc_num(qh), qh->desc_list,+			     qh->desc_list_dma);+		qh->desc_list = NULL;+	}++	if (qh->n_bytes) {+		DWC_FREE(qh->n_bytes);+		qh->n_bytes = NULL;+	}+}++static int frame_list_alloc(dwc_otg_hcd_t * hcd)+{+	int retval = 0;+	if (hcd->frame_list)+		return 0;++	hcd->frame_list = DWC_DMA_ALLOC(4 * MAX_FRLIST_EN_NUM,+					&hcd->frame_list_dma);+	if (!hcd->frame_list) {+		retval = -DWC_E_NO_MEMORY;+		DWC_ERROR("%s: Frame List allocation failed\n", __func__);+	}++	dwc_memset(hcd->frame_list, 0x00, 4 * MAX_FRLIST_EN_NUM);++	return retval;+}++static void frame_list_free(dwc_otg_hcd_t * hcd)+{+	if (!hcd->frame_list)+		return;++	DWC_DMA_FREE(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma);+	hcd->frame_list = NULL;+}++static void per_sched_enable(dwc_otg_hcd_t * hcd, uint16_t fr_list_en)+{++	hcfg_data_t hcfg;++	hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg);++	if (hcfg.b.perschedena) {+		/* already enabled */+		return;+	}++	DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hflbaddr,+			hcd->frame_list_dma);++	switch (fr_list_en) {+	case 64:+		hcfg.b.frlisten = 3;+		break;+	case 32:+		hcfg.b.frlisten = 2;+		break;+	case 16:+		hcfg.b.frlisten = 1;+		break;+	case 8:+		hcfg.b.frlisten = 0;+		break;+	default:+		break;+	}++	hcfg.b.perschedena = 1;++	DWC_DEBUGPL(DBG_HCD, "Enabling Periodic schedule\n");+	DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32);++}++static void per_sched_disable(dwc_otg_hcd_t * hcd)+{+	hcfg_data_t hcfg;++	hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg);++	if (!hcfg.b.perschedena) {+		/* already disabled */+		return;+	}+	hcfg.b.perschedena = 0;++	DWC_DEBUGPL(DBG_HCD, "Disabling Periodic schedule\n");+	DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32);+}++/*+ * Activates/Deactivates FrameList entries for the channel+ * based on endpoint servicing period.+ */+void update_frame_list(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t enable)+{+	uint16_t i, j, inc;+	dwc_hc_t *hc = NULL;++	if (!qh->channel) {+		DWC_ERROR("qh->channel = %p", qh->channel);+		return;+	}++	if (!hcd) {+		DWC_ERROR("------hcd = %p", hcd);+		return;+	}++	if (!hcd->frame_list) {+		DWC_ERROR("-------hcd->frame_list = %p", hcd->frame_list);+		return;+	}++	hc = qh->channel;+	inc = frame_incr_val(qh);+	if (qh->ep_type == UE_ISOCHRONOUS)+		i = frame_list_idx(qh->sched_frame);+	else+		i = 0;++	j = i;+	do {+		if (enable)+			hcd->frame_list[j] |= (1 << hc->hc_num);+		else+			hcd->frame_list[j] &= ~(1 << hc->hc_num);+		j = (j + inc) & (MAX_FRLIST_EN_NUM - 1);+	}+	while (j != i);+	if (!enable)+		return;+	hc->schinfo = 0;+	if (qh->channel->speed == DWC_OTG_EP_SPEED_HIGH) {+		j = 1;+		/* TODO - check this */+		inc = (8 + qh->interval - 1) / qh->interval;+		for (i = 0; i < inc; i++) {+			hc->schinfo |= j;+			j = j << qh->interval;+		}+	} else {+		hc->schinfo = 0xff;+	}+}++#if 1+void dump_frame_list(dwc_otg_hcd_t * hcd)+{+	int i = 0;+	DWC_PRINTF("--FRAME LIST (hex) --\n");+	for (i = 0; i < MAX_FRLIST_EN_NUM; i++) {+		DWC_PRINTF("%x\t", hcd->frame_list[i]);+		if (!(i % 8) && i)+			DWC_PRINTF("\n");+	}+	DWC_PRINTF("\n----\n");++}+#endif++static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)+{+	dwc_irqflags_t flags;+	dwc_spinlock_t *channel_lock = hcd->channel_lock;++	dwc_hc_t *hc = qh->channel;+	if (dwc_qh_is_non_per(qh)) {+		DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);+		if (!microframe_schedule)+			hcd->non_periodic_channels--;+		else+			hcd->available_host_channels++;+		DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);+	} else+		update_frame_list(hcd, qh, 0);++	/*+	 * The condition is added to prevent double cleanup try in case of device+	 * disconnect. See channel cleanup in dwc_otg_hcd_disconnect_cb().+	 */+	if (hc->qh) {+		dwc_otg_hc_cleanup(hcd->core_if, hc);+		DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);+		hc->qh = NULL;+	}++	qh->channel = NULL;+	qh->ntd = 0;++	if (qh->desc_list) {+		dwc_memset(qh->desc_list, 0x00,+			   sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));+	}+}++/**+ * Initializes a QH structure's Descriptor DMA related members.+ * Allocates memory for descriptor list.+ * On first periodic QH, allocates memory for FrameList+ * and enables periodic scheduling.+ *+ * @param hcd The HCD state structure for the DWC OTG controller.+ * @param qh The QH to init.+ *+ * @return 0 if successful, negative error code otherwise.+ */+int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)+{+	int retval = 0;++	if (qh->do_split) {+		DWC_ERROR("SPLIT Transfers are not supported in Descriptor DMA.\n");+		return -1;+	}++	retval = desc_list_alloc(qh);++	if ((retval == 0)+	    && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) {+		if (!hcd->frame_list) {+			retval = frame_list_alloc(hcd);+			/* Enable periodic schedule on first periodic QH */+			if (retval == 0)+				per_sched_enable(hcd, MAX_FRLIST_EN_NUM);+		}+	}++	qh->ntd = 0;++	return retval;+}++/**+ * Frees descriptor list memory associated with the QH.+ * If QH is periodic and the last, frees FrameList memory+ * and disables periodic scheduling.+ *+ * @param hcd The HCD state structure for the DWC OTG controller.+ * @param qh The QH to init.+ */+void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)+{+	desc_list_free(qh);++	/*+	 * Channel still assigned due to some reasons.+	 * Seen on Isoc URB dequeue. Channel halted but no subsequent+	 * ChHalted interrupt to release the channel. Afterwards+	 * when it comes here from endpoint disable routine+	 * channel remains assigned.+	 */+	if (qh->channel)+		release_channel_ddma(hcd, qh);++	if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)+	    && (microframe_schedule || !hcd->periodic_channels) && hcd->frame_list) {++		per_sched_disable(hcd);+		frame_list_free(hcd);+	}+}++static uint8_t frame_to_desc_idx(dwc_otg_qh_t * qh, uint16_t frame_idx)+{+	if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) {+		/*+		 * Descriptor set(8 descriptors) index+		 * which is 8-aligned.+		 */+		return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8;+	} else {+		return (frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1));+	}+}++/*+ * Determine starting frame for Isochronous transfer.+ * Few frames skipped to prevent race condition with HC.+ */+static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,+				   uint8_t * skip_frames)+{+	uint16_t frame = 0;+	hcd->frame_number = dwc_otg_hcd_get_frame_number(hcd);++	/* sched_frame is always frame number(not uFrame) both in FS and HS !! */++	/*+	 * skip_frames is used to limit activated descriptors number+	 * to avoid the situation when HC services the last activated+	 * descriptor firstly.+	 * Example for FS:+	 * Current frame is 1, scheduled frame is 3. Since HC always fetches the descriptor+	 * corresponding to curr_frame+1, the descriptor corresponding to frame 2+	 * will be fetched. If the number of descriptors is max=64 (or greather) the+	 * list will be fully programmed with Active descriptors and it is possible+	 * case(rare) that the latest descriptor(considering rollback) corresponding+	 * to frame 2 will be serviced first. HS case is more probable because, in fact,+	 * up to 11 uframes(16 in the code) may be skipped.+	 */+	if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) {+		/*+		 * Consider uframe counter also, to start xfer asap.+		 * If half of the frame elapsed skip 2 frames otherwise+		 * just 1 frame.+		 * Starting descriptor index must be 8-aligned, so+		 * if the current frame is near to complete the next one+		 * is skipped as well.+		 */++		if (dwc_micro_frame_num(hcd->frame_number) >= 5) {+			*skip_frames = 2 * 8;+			frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames);+		} else {+			*skip_frames = 1 * 8;+			frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames);+		}++		frame = dwc_full_frame_num(frame);+	} else {+		/*+		 * Two frames are skipped for FS - the current and the next.+		 * But for descriptor programming, 1 frame(descriptor) is enough,+		 * see example above.+		 */+		*skip_frames = 1;+		frame = dwc_frame_num_inc(hcd->frame_number, 2);+	}++	return frame;+}++/*+ * Calculate initial descriptor index for isochronous transfer+ * based on scheduled frame.+ */+static uint8_t recalc_initial_desc_idx(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)+{+	uint16_t frame = 0, fr_idx, fr_idx_tmp;+	uint8_t skip_frames = 0;+	/*+	 * With current ISOC processing algorithm the channel is being+	 * released when no more QTDs in the list(qh->ntd == 0).+	 * Thus this function is called only when qh->ntd == 0 and qh->channel == 0.+	 *+	 * So qh->channel != NULL branch is not used and just not removed from the+	 * source file. It is required for another possible approach which is,+	 * do not disable and release the channel when ISOC session completed,+	 * just move QH to inactive schedule until new QTD arrives.+	 * On new QTD, the QH moved back to 'ready' schedule,+	 * starting frame and therefore starting desc_index are recalculated.+	 * In this case channel is released only on ep_disable.+	 */++	/* Calculate starting descriptor index. For INTERRUPT endpoint it is always 0. */+	if (qh->channel) {+		frame = calc_starting_frame(hcd, qh, &skip_frames);+		/*+		 * Calculate initial descriptor index based on FrameList current bitmap+		 * and servicing period.+		 */+		fr_idx_tmp = frame_list_idx(frame);+		fr_idx =+		    (MAX_FRLIST_EN_NUM + frame_list_idx(qh->sched_frame) -+		     fr_idx_tmp)+		    % frame_incr_val(qh);+		fr_idx = (fr_idx + fr_idx_tmp) % MAX_FRLIST_EN_NUM;+	} else {+		qh->sched_frame = calc_starting_frame(hcd, qh, &skip_frames);+		fr_idx = frame_list_idx(qh->sched_frame);+	}++	qh->td_first = qh->td_last = frame_to_desc_idx(qh, fr_idx);++	return skip_frames;+}++#define	ISOC_URB_GIVEBACK_ASAP++#define MAX_ISOC_XFER_SIZE_FS 1023+#define MAX_ISOC_XFER_SIZE_HS 3072+#define DESCNUM_THRESHOLD 4++static void init_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,+			       uint8_t skip_frames)+{+	struct dwc_otg_hcd_iso_packet_desc *frame_desc;+	dwc_otg_qtd_t *qtd;+	dwc_otg_host_dma_desc_t *dma_desc;+	uint16_t idx, inc, n_desc, ntd_max, max_xfer_size;++	idx = qh->td_last;+	inc = qh->interval;+	n_desc = 0;++	ntd_max = (max_desc_num(qh) + qh->interval - 1) / qh->interval;+	if (skip_frames && !qh->channel)+		ntd_max = ntd_max - skip_frames / qh->interval;++	max_xfer_size =+	    (qh->dev_speed ==+	     DWC_OTG_EP_SPEED_HIGH) ? MAX_ISOC_XFER_SIZE_HS :+	    MAX_ISOC_XFER_SIZE_FS;++	DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) {+		while ((qh->ntd < ntd_max)+		       && (qtd->isoc_frame_index_last <+			   qtd->urb->packet_count)) {++			dma_desc = &qh->desc_list[idx];+			dwc_memset(dma_desc, 0x00, sizeof(dwc_otg_host_dma_desc_t));++			frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last];++			if (frame_desc->length > max_xfer_size)+				qh->n_bytes[idx] = max_xfer_size;+			else+				qh->n_bytes[idx] = frame_desc->length;+			dma_desc->status.b_isoc.n_bytes = qh->n_bytes[idx];+			dma_desc->status.b_isoc.a = 1;+			dma_desc->status.b_isoc.sts = 0;++			dma_desc->buf = qtd->urb->dma + frame_desc->offset;++			qh->ntd++;++			qtd->isoc_frame_index_last++;++#ifdef	ISOC_URB_GIVEBACK_ASAP+			/*+			 * Set IOC for each descriptor corresponding to the+			 * last frame of the URB.+			 */+			if (qtd->isoc_frame_index_last ==+			    qtd->urb->packet_count)+				dma_desc->status.b_isoc.ioc = 1;++#endif+			idx = desclist_idx_inc(idx, inc, qh->dev_speed);+			n_desc++;++		}+		qtd->in_process = 1;+	}++	qh->td_last = idx;++#ifdef	ISOC_URB_GIVEBACK_ASAP+	/* Set IOC for the last descriptor if descriptor list is full */+	if (qh->ntd == ntd_max) {+		idx = desclist_idx_dec(qh->td_last, inc, qh->dev_speed);+		qh->desc_list[idx].status.b_isoc.ioc = 1;+	}+#else+	/*+	 * Set IOC bit only for one descriptor.+	 * Always try to be ahead of HW processing,+	 * i.e. on IOC generation driver activates next descriptors but+	 * core continues to process descriptors followed the one with IOC set.+	 */++	if (n_desc > DESCNUM_THRESHOLD) {+		/*+		 * Move IOC "up". Required even if there is only one QTD+		 * in the list, cause QTDs migth continue to be queued,+		 * but during the activation it was only one queued.+		 * Actually more than one QTD might be in the list if this function called+		 * from XferCompletion - QTDs was queued during HW processing of the previous+		 * descriptor chunk.+		 */+		idx = dwc_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2), qh->dev_speed);+	} else {+		/*+		 * Set the IOC for the latest descriptor+		 * if either number of descriptor is not greather than threshold+		 * or no more new descriptors activated.+		 */+		idx = dwc_desclist_idx_dec(qh->td_last, inc, qh->dev_speed);+	}++	qh->desc_list[idx].status.b_isoc.ioc = 1;+#endif+}++static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)+{++	dwc_hc_t *hc;+	dwc_otg_host_dma_desc_t *dma_desc;+	dwc_otg_qtd_t *qtd;+	int num_packets, len, n_desc = 0;++	hc = qh->channel;++	/*+	 * Start with hc->xfer_buff initialized in+	 * assign_and_init_hc(), then if SG transfer consists of multiple URBs,+	 * this pointer re-assigned to the buffer of the currently processed QTD.+	 * For non-SG request there is always one QTD active.+	 */++	DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) {++		if (n_desc) {+			/* SG request - more than 1 QTDs */+			hc->xfer_buff = (uint8_t *)qtd->urb->dma + qtd->urb->actual_length;+			hc->xfer_len = qtd->urb->length - qtd->urb->actual_length;+		}++		qtd->n_desc = 0;++		do {+			dma_desc = &qh->desc_list[n_desc];+			len = hc->xfer_len;++			if (len > MAX_DMA_DESC_SIZE)+				len = MAX_DMA_DESC_SIZE - hc->max_packet + 1;++			if (hc->ep_is_in) {+				if (len > 0) {+					num_packets = (len + hc->max_packet - 1) / hc->max_packet;+				} else {+					/* Need 1 packet for transfer length of 0. */+					num_packets = 1;+				}+				/* Always program an integral # of max packets for IN transfers. */+				len = num_packets * hc->max_packet;+			}++			dma_desc->status.b.n_bytes = len;++			qh->n_bytes[n_desc] = len;++			if ((qh->ep_type == UE_CONTROL)+			    && (qtd->control_phase == DWC_OTG_CONTROL_SETUP))+				dma_desc->status.b.sup = 1;	/* Setup Packet */++			dma_desc->status.b.a = 1;	/* Active descriptor */+			dma_desc->status.b.sts = 0;++			dma_desc->buf =+			    ((unsigned long)hc->xfer_buff & 0xffffffff);++			/*+			 * Last descriptor(or single) of IN transfer+			 * with actual size less than MaxPacket.+			 */+			if (len > hc->xfer_len) {+				hc->xfer_len = 0;+			} else {+				hc->xfer_buff += len;+				hc->xfer_len -= len;+			}++			qtd->n_desc++;+			n_desc++;+		}+		while ((hc->xfer_len > 0) && (n_desc != MAX_DMA_DESC_NUM_GENERIC));+++		qtd->in_process = 1;++		if (qh->ep_type == UE_CONTROL)+			break;++		if (n_desc == MAX_DMA_DESC_NUM_GENERIC)+			break;+	}++	if (n_desc) {+		/* Request Transfer Complete interrupt for the last descriptor */+		qh->desc_list[n_desc - 1].status.b.ioc = 1;+		/* End of List indicator */+		qh->desc_list[n_desc - 1].status.b.eol = 1;++		hc->ntd = n_desc;+	}+}++/**+ * For Control and Bulk endpoints initializes descriptor list+ * and starts the transfer.+ *+ * For Interrupt and Isochronous endpoints initializes descriptor list+ * then updates FrameList, marking appropriate entries as active.+ * In case of Isochronous, the starting descriptor index is calculated based+ * on the scheduled frame, but only on the first transfer descriptor within a session.+ * Then starts the transfer via enabling the channel.+ * For Isochronous endpoint the channel is not halted on XferComplete+ * interrupt so remains assigned to the endpoint(QH) until session is done.+ *+ * @param hcd The HCD state structure for the DWC OTG controller.+ * @param qh The QH to init.+ *+ * @return 0 if successful, negative error code otherwise.+ */+void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)+{+	/* Channel is already assigned */+	dwc_hc_t *hc = qh->channel;+	uint8_t skip_frames = 0;++	switch (hc->ep_type) {+	case DWC_OTG_EP_TYPE_CONTROL:+	case DWC_OTG_EP_TYPE_BULK:+		init_non_isoc_dma_desc(hcd, qh);++		dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);+		break;+	case DWC_OTG_EP_TYPE_INTR:+		init_non_isoc_dma_desc(hcd, qh);++		update_frame_list(hcd, qh, 1);++		dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);+		break;+	case DWC_OTG_EP_TYPE_ISOC:++		if (!qh->ntd)+			skip_frames = recalc_initial_desc_idx(hcd, qh);++		init_isoc_dma_desc(hcd, qh, skip_frames);++		if (!hc->xfer_started) {++			update_frame_list(hcd, qh, 1);++			/*+			 * Always set to max, instead of actual size.+			 * Otherwise ntd will be changed with+			 * channel being enabled. Not recommended.+			 *+			 */+			hc->ntd = max_desc_num(qh);+			/* Enable channel only once for ISOC */+			dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);+		}++		break;+	default:++		break;+	}+}++static void complete_isoc_xfer_ddma(dwc_otg_hcd_t * hcd,+				    dwc_hc_t * hc,+				    dwc_otg_hc_regs_t * hc_regs,+				    dwc_otg_halt_status_e halt_status)+{+	struct dwc_otg_hcd_iso_packet_desc *frame_desc;+	dwc_otg_qtd_t *qtd, *qtd_tmp;+	dwc_otg_qh_t *qh;+	dwc_otg_host_dma_desc_t *dma_desc;+	uint16_t idx, remain;+	uint8_t urb_compl;++	qh = hc->qh;+	idx = qh->td_first;++	if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {+		DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry)+		    qtd->in_process = 0;+		return;+	} else if ((halt_status == DWC_OTG_HC_XFER_AHB_ERR) ||+		   (halt_status == DWC_OTG_HC_XFER_BABBLE_ERR)) {+		/*+		 * Channel is halted in these error cases.+		 * Considered as serious issues.+		 * Complete all URBs marking all frames as failed,+		 * irrespective whether some of the descriptors(frames) succeeded or no.+		 * Pass error code to completion routine as well, to+		 * update urb->status, some of class drivers might use it to stop+		 * queing transfer requests.+		 */+		int err = (halt_status == DWC_OTG_HC_XFER_AHB_ERR)+		    ? (-DWC_E_IO)+		    : (-DWC_E_OVERFLOW);++		DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {+			for (idx = 0; idx < qtd->urb->packet_count; idx++) {+				frame_desc = &qtd->urb->iso_descs[idx];+				frame_desc->status = err;+			}+			hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, err);+			dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);+		}+		return;+	}++	DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {++		if (!qtd->in_process)+			break;++		urb_compl = 0;++		do {++			dma_desc = &qh->desc_list[idx];++			frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];+			remain = hc->ep_is_in ? dma_desc->status.b_isoc.n_bytes : 0;++			if (dma_desc->status.b_isoc.sts == DMA_DESC_STS_PKTERR) {+				/*+				 * XactError or, unable to complete all the transactions+				 * in the scheduled micro-frame/frame,+				 * both indicated by DMA_DESC_STS_PKTERR.+				 */+				qtd->urb->error_count++;+				frame_desc->actual_length = qh->n_bytes[idx] - remain;+				frame_desc->status = -DWC_E_PROTOCOL;+			} else {+				/* Success */++				frame_desc->actual_length = qh->n_bytes[idx] - remain;+				frame_desc->status = 0;+			}++			if (++qtd->isoc_frame_index == qtd->urb->packet_count) {+				/*+				 * urb->status is not used for isoc transfers here.+				 * The individual frame_desc status are used instead.+				 */++				hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);+				dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);++				/*+				 * This check is necessary because urb_dequeue can be called+				 * from urb complete callback(sound driver example).+				 * All pending URBs are dequeued there, so no need for+				 * further processing.+				 */+				if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {+					return;+				}++				urb_compl = 1;++			}++			qh->ntd--;++			/* Stop if IOC requested descriptor reached */+			if (dma_desc->status.b_isoc.ioc) {+				idx = desclist_idx_inc(idx, qh->interval, hc->speed);+				goto stop_scan;+			}++			idx = desclist_idx_inc(idx, qh->interval, hc->speed);++			if (urb_compl)+				break;+		}+		while (idx != qh->td_first);+	}+stop_scan:+	qh->td_first = idx;+}++uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd,+				       dwc_hc_t * hc,+				       dwc_otg_qtd_t * qtd,+				       dwc_otg_host_dma_desc_t * dma_desc,+				       dwc_otg_halt_status_e halt_status,+				       uint32_t n_bytes, uint8_t * xfer_done)+{++	uint16_t remain = hc->ep_is_in ? dma_desc->status.b.n_bytes : 0;+	dwc_otg_hcd_urb_t *urb = qtd->urb;++	if (halt_status == DWC_OTG_HC_XFER_AHB_ERR) {+		urb->status = -DWC_E_IO;+		return 1;+	}+	if (dma_desc->status.b.sts == DMA_DESC_STS_PKTERR) {+		switch (halt_status) {+		case DWC_OTG_HC_XFER_STALL:+			urb->status = -DWC_E_PIPE;+			break;+		case DWC_OTG_HC_XFER_BABBLE_ERR:+			urb->status = -DWC_E_OVERFLOW;+			break;+		case DWC_OTG_HC_XFER_XACT_ERR:+			urb->status = -DWC_E_PROTOCOL;+			break;+		default:+			DWC_ERROR("%s: Unhandled descriptor error status (%d)\n", __func__,+				  halt_status);+			break;+		}+		return 1;+	}++	if (dma_desc->status.b.a == 1) {+		DWC_DEBUGPL(DBG_HCDV,+			    "Active descriptor encountered on channel %d\n",+			    hc->hc_num);+		return 0;+	}++	if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL) {+		if (qtd->control_phase == DWC_OTG_CONTROL_DATA) {+			urb->actual_length += n_bytes - remain;+			if (remain || urb->actual_length == urb->length) {+				/*+				 * For Control Data stage do not set urb->status=0 to prevent+				 * URB callback. Set it when Status phase done. See below.+				 */+				*xfer_done = 1;+			}++		} else if (qtd->control_phase == DWC_OTG_CONTROL_STATUS) {+			urb->status = 0;+			*xfer_done = 1;+		}+		/* No handling for SETUP stage */+	} else {+		/* BULK and INTR */+		urb->actual_length += n_bytes - remain;+		if (remain || urb->actual_length == urb->length) {+			urb->status = 0;+			*xfer_done = 1;+		}+	}++	return 0;+}++static void complete_non_isoc_xfer_ddma(dwc_otg_hcd_t * hcd,+					dwc_hc_t * hc,+					dwc_otg_hc_regs_t * hc_regs,+					dwc_otg_halt_status_e halt_status)+{+	dwc_otg_hcd_urb_t *urb = NULL;+	dwc_otg_qtd_t *qtd, *qtd_tmp;+	dwc_otg_qh_t *qh;+	dwc_otg_host_dma_desc_t *dma_desc;+	uint32_t n_bytes, n_desc, i;+	uint8_t failed = 0, xfer_done;++	n_desc = 0;++	qh = hc->qh;++	if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {+		DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {+			qtd->in_process = 0;+		}+		return;+	}++	DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {++		urb = qtd->urb;++		n_bytes = 0;+		xfer_done = 0;++		for (i = 0; i < qtd->n_desc; i++) {+			dma_desc = &qh->desc_list[n_desc];++			n_bytes = qh->n_bytes[n_desc];++			failed =+			    update_non_isoc_urb_state_ddma(hcd, hc, qtd,+							   dma_desc,+							   halt_status, n_bytes,+							   &xfer_done);++			if (failed+			    || (xfer_done+				&& (urb->status != -DWC_E_IN_PROGRESS))) {++				hcd->fops->complete(hcd, urb->priv, urb,+						    urb->status);+				dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);++				if (failed)+					goto stop_scan;+			} else if (qh->ep_type == UE_CONTROL) {+				if (qtd->control_phase == DWC_OTG_CONTROL_SETUP) {+					if (urb->length > 0) {+						qtd->control_phase = DWC_OTG_CONTROL_DATA;+					} else {+						qtd->control_phase = DWC_OTG_CONTROL_STATUS;+					}+					DWC_DEBUGPL(DBG_HCDV, "  Control setup transaction done\n");+				} else if (qtd->control_phase == DWC_OTG_CONTROL_DATA) {+					if (xfer_done) {+						qtd->control_phase = DWC_OTG_CONTROL_STATUS;+						DWC_DEBUGPL(DBG_HCDV, "  Control data transfer done\n");+					} else if (i + 1 == qtd->n_desc) {+						/*+						 * Last descriptor for Control data stage which is+						 * not completed yet.+						 */+						dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);+					}+				}+			}++			n_desc++;+		}++	}++stop_scan:++	if (qh->ep_type != UE_CONTROL) {+		/*+		 * Resetting the data toggle for bulk+		 * and interrupt endpoints in case of stall. See handle_hc_stall_intr()+		 */+		if (halt_status == DWC_OTG_HC_XFER_STALL)+			qh->data_toggle = DWC_OTG_HC_PID_DATA0;+		else+			dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);+	}++	if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {+		hcint_data_t hcint;+		hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);+		if (hcint.b.nyet) {+			/*+			 * Got a NYET on the last transaction of the transfer. It+			 * means that the endpoint should be in the PING state at the+			 * beginning of the next transfer.+			 */+			qh->ping_state = 1;+			clear_hc_int(hc_regs, nyet);+		}++	}++}++/**+ * This function is called from interrupt handlers.+ * Scans the descriptor list, updates URB's status and+ * calls completion routine for the URB if it's done.+ * Releases the channel to be used by other transfers.+ * In case of Isochronous endpoint the channel is not halted until+ * the end of the session, i.e. QTD list is empty.+ * If periodic channel released the FrameList is updated accordingly.+ *+ * Calls transaction selection routines to activate pending transfers.+ *+ * @param hcd The HCD state structure for the DWC OTG controller.+ * @param hc Host channel, the transfer is completed on.+ * @param hc_regs Host channel registers.+ * @param halt_status Reason the channel is being halted,+ *		      or just XferComplete for isochronous transfer+ */+void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,+				    dwc_hc_t * hc,+				    dwc_otg_hc_regs_t * hc_regs,+				    dwc_otg_halt_status_e halt_status)+{+	uint8_t continue_isoc_xfer = 0;+	dwc_otg_transaction_type_e tr_type;+	dwc_otg_qh_t *qh = hc->qh;++	if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {++		complete_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status);++		/* Release the channel if halted or session completed */+		if (halt_status != DWC_OTG_HC_XFER_COMPLETE ||+		    DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {++			/* Halt the channel if session completed */+			if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {+				dwc_otg_hc_halt(hcd->core_if, hc, halt_status);+			}++			release_channel_ddma(hcd, qh);+			dwc_otg_hcd_qh_remove(hcd, qh);+		} else {+			/* Keep in assigned schedule to continue transfer */+			DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,+					   &qh->qh_list_entry);+			continue_isoc_xfer = 1;++		}+		/** @todo Consider the case when period exceeds FrameList size.+		 *  Frame Rollover interrupt should be used.+		 */+	} else {+		/* Scan descriptor list to complete the URB(s), then release the channel */+		complete_non_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status);++		release_channel_ddma(hcd, qh);+		dwc_otg_hcd_qh_remove(hcd, qh);++		if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {+			/* Add back to inactive non-periodic schedule on normal completion */+			dwc_otg_hcd_qh_add(hcd, qh);+		}++	}+	tr_type = dwc_otg_hcd_select_transactions(hcd);+	if (tr_type != DWC_OTG_TRANSACTION_NONE || continue_isoc_xfer) {+		if (continue_isoc_xfer) {+			if (tr_type == DWC_OTG_TRANSACTION_NONE) {+				tr_type = DWC_OTG_TRANSACTION_PERIODIC;+			} else if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC) {+				tr_type = DWC_OTG_TRANSACTION_ALL;+			}+		}+		dwc_otg_hcd_queue_transactions(hcd, tr_type);+	}+}++#endif /* DWC_DEVICE_ONLY */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_hcd.h--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_hcd.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,851 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $+ * $Revision: #58 $+ * $Date: 2011/09/15 $+ * $Change: 1846647 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */+#ifndef DWC_DEVICE_ONLY+#ifndef __DWC_HCD_H__+#define __DWC_HCD_H__++#include "dwc_otg_os_dep.h"+#include "usb.h"+#include "dwc_otg_hcd_if.h"+#include "dwc_otg_core_if.h"+#include "dwc_list.h"+#include "dwc_otg_cil.h"++/**+ * @file+ *+ * This file contains the structures, constants, and interfaces for+ * the Host Contoller Driver (HCD).+ *+ * The Host Controller Driver (HCD) is responsible for translating requests+ * from the USB Driver into the appropriate actions on the DWC_otg controller.+ * It isolates the USBD from the specifics of the controller by providing an+ * API to the USBD.+ */++struct dwc_otg_hcd_pipe_info {+	uint8_t dev_addr;+	uint8_t ep_num;+	uint8_t pipe_type;+	uint8_t pipe_dir;+	uint16_t mps;+};++struct dwc_otg_hcd_iso_packet_desc {+	uint32_t offset;+	uint32_t length;+	uint32_t actual_length;+	uint32_t status;+};++struct dwc_otg_qtd;++struct dwc_otg_hcd_urb {+	void *priv;+	struct dwc_otg_qtd *qtd;+	void *buf;+	dwc_dma_t dma;+	void *setup_packet;+	dwc_dma_t setup_dma;+	uint32_t length;+	uint32_t actual_length;+	uint32_t status;+	uint32_t error_count;+	uint32_t packet_count;+	uint32_t flags;+	uint16_t interval;+	struct dwc_otg_hcd_pipe_info pipe_info;+	struct dwc_otg_hcd_iso_packet_desc iso_descs[0];+};++static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe)+{+	return pipe->ep_num;+}++static inline uint8_t dwc_otg_hcd_get_pipe_type(struct dwc_otg_hcd_pipe_info+						*pipe)+{+	return pipe->pipe_type;+}++static inline uint16_t dwc_otg_hcd_get_mps(struct dwc_otg_hcd_pipe_info *pipe)+{+	return pipe->mps;+}++static inline uint8_t dwc_otg_hcd_get_dev_addr(struct dwc_otg_hcd_pipe_info+					       *pipe)+{+	return pipe->dev_addr;+}++static inline uint8_t dwc_otg_hcd_is_pipe_isoc(struct dwc_otg_hcd_pipe_info+					       *pipe)+{+	return (pipe->pipe_type == UE_ISOCHRONOUS);+}++static inline uint8_t dwc_otg_hcd_is_pipe_int(struct dwc_otg_hcd_pipe_info+					      *pipe)+{+	return (pipe->pipe_type == UE_INTERRUPT);+}++static inline uint8_t dwc_otg_hcd_is_pipe_bulk(struct dwc_otg_hcd_pipe_info+					       *pipe)+{+	return (pipe->pipe_type == UE_BULK);+}++static inline uint8_t dwc_otg_hcd_is_pipe_control(struct dwc_otg_hcd_pipe_info+						  *pipe)+{+	return (pipe->pipe_type == UE_CONTROL);+}++static inline uint8_t dwc_otg_hcd_is_pipe_in(struct dwc_otg_hcd_pipe_info *pipe)+{+	return (pipe->pipe_dir == UE_DIR_IN);+}++static inline uint8_t dwc_otg_hcd_is_pipe_out(struct dwc_otg_hcd_pipe_info+					      *pipe)+{+	return (!dwc_otg_hcd_is_pipe_in(pipe));+}++static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe,+					 uint8_t devaddr, uint8_t ep_num,+					 uint8_t pipe_type, uint8_t pipe_dir,+					 uint16_t mps)+{+	pipe->dev_addr = devaddr;+	pipe->ep_num = ep_num;+	pipe->pipe_type = pipe_type;+	pipe->pipe_dir = pipe_dir;+	pipe->mps = mps;+}++/**+ * Phases for control transfers.+ */+typedef enum dwc_otg_control_phase {+	DWC_OTG_CONTROL_SETUP,+	DWC_OTG_CONTROL_DATA,+	DWC_OTG_CONTROL_STATUS+} dwc_otg_control_phase_e;++/** Transaction types. */+typedef enum dwc_otg_transaction_type {+	DWC_OTG_TRANSACTION_NONE          = 0,+	DWC_OTG_TRANSACTION_PERIODIC      = 1,+	DWC_OTG_TRANSACTION_NON_PERIODIC  = 2,+	DWC_OTG_TRANSACTION_ALL           = DWC_OTG_TRANSACTION_PERIODIC + DWC_OTG_TRANSACTION_NON_PERIODIC+} dwc_otg_transaction_type_e;++struct dwc_otg_qh;++/**+ * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control,+ * interrupt, or isochronous transfer. A single QTD is created for each URB+ * (of one of these types) submitted to the HCD. The transfer associated with+ * a QTD may require one or multiple transactions.+ *+ * A QTD is linked to a Queue Head, which is entered in either the+ * non-periodic or periodic schedule for execution. When a QTD is chosen for+ * execution, some or all of its transactions may be executed. After+ * execution, the state of the QTD is updated. The QTD may be retired if all+ * its transactions are complete or if an error occurred. Otherwise, it+ * remains in the schedule so more transactions can be executed later.+ */+typedef struct dwc_otg_qtd {+	/**+	 * Determines the PID of the next data packet for the data phase of+	 * control transfers. Ignored for other transfer types.<br>+	 * One of the following values:+	 *	- DWC_OTG_HC_PID_DATA0+	 *	- DWC_OTG_HC_PID_DATA1+	 */+	uint8_t data_toggle;++	/** Current phase for control transfers (Setup, Data, or Status). */+	dwc_otg_control_phase_e control_phase;++	/** Keep track of the current split type+	 * for FS/LS endpoints on a HS Hub */+	uint8_t complete_split;++	/** How many bytes transferred during SSPLIT OUT */+	uint32_t ssplit_out_xfer_count;++	/**+	 * Holds the number of bus errors that have occurred for a transaction+	 * within this transfer.+	 */+	uint8_t error_count;++	/**+	 * Index of the next frame descriptor for an isochronous transfer. A+	 * frame descriptor describes the buffer position and length of the+	 * data to be transferred in the next scheduled (micro)frame of an+	 * isochronous transfer. It also holds status for that transaction.+	 * The frame index starts at 0.+	 */+	uint16_t isoc_frame_index;++	/** Position of the ISOC split on full/low speed */+	uint8_t isoc_split_pos;++	/** Position of the ISOC split in the buffer for the current frame */+	uint16_t isoc_split_offset;++	/** URB for this transfer */+	struct dwc_otg_hcd_urb *urb;++	struct dwc_otg_qh *qh;++	/** This list of QTDs */+	 DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry;++	/** Indicates if this QTD is currently processed by HW. */+	uint8_t in_process;++	/** Number of DMA descriptors for this QTD */+	uint8_t n_desc;++	/**+	 * Last activated frame(packet) index.+	 * Used in Descriptor DMA mode only.+	 */+	uint16_t isoc_frame_index_last;++} dwc_otg_qtd_t;++DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd);++/**+ * A Queue Head (QH) holds the static characteristics of an endpoint and+ * maintains a list of transfers (QTDs) for that endpoint. A QH structure may+ * be entered in either the non-periodic or periodic schedule.+ */+typedef struct dwc_otg_qh {+	/**+	 * Endpoint type.+	 * One of the following values:+	 *	- UE_CONTROL+	 *	- UE_BULK+	 *	- UE_INTERRUPT+	 *	- UE_ISOCHRONOUS+	 */+	uint8_t ep_type;+	uint8_t ep_is_in;++	/** wMaxPacketSize Field of Endpoint Descriptor. */+	uint16_t maxp;++	/**+	 * Device speed.+	 * One of the following values:+	 *	- DWC_OTG_EP_SPEED_LOW+	 *	- DWC_OTG_EP_SPEED_FULL+	 *	- DWC_OTG_EP_SPEED_HIGH+	 */+	uint8_t dev_speed;++	/**+	 * Determines the PID of the next data packet for non-control+	 * transfers. Ignored for control transfers.<br>+	 * One of the following values:+	 *	- DWC_OTG_HC_PID_DATA0+	 *	- DWC_OTG_HC_PID_DATA1+	 */+	uint8_t data_toggle;++	/** Ping state if 1. */+	uint8_t ping_state;++	/**+	 * List of QTDs for this QH.+	 */+	struct dwc_otg_qtd_list qtd_list;++	/** Host channel currently processing transfers for this QH. */+	struct dwc_hc *channel;++	/** Full/low speed endpoint on high-speed hub requires split. */+	uint8_t do_split;++	/** @name Periodic schedule information */+	/** @{ */++	/** Bandwidth in microseconds per (micro)frame. */+	uint16_t usecs;++	/** Interval between transfers in (micro)frames. */+	uint16_t interval;++	/**+	 * (micro)frame to initialize a periodic transfer. The transfer+	 * executes in the following (micro)frame.+	 */+	uint16_t sched_frame;++	/*+	** Frame a NAK was received on this queue head, used to minimise NAK retransmission+	*/+	uint16_t nak_frame;++	/** (micro)frame at which last start split was initialized. */+	uint16_t start_split_frame;++	/** @} */++	/**+	 * Used instead of original buffer if+	 * it(physical address) is not dword-aligned.+	 */+	uint8_t *dw_align_buf;+	dwc_dma_t dw_align_buf_dma;++	/** Entry for QH in either the periodic or non-periodic schedule. */+	dwc_list_link_t qh_list_entry;++	/** @name Descriptor DMA support */+	/** @{ */++	/** Descriptor List. */+	dwc_otg_host_dma_desc_t *desc_list;++	/** Descriptor List physical address. */+	dwc_dma_t desc_list_dma;++	/**+	 * Xfer Bytes array.+	 * Each element corresponds to a descriptor and indicates+	 * original XferSize size value for the descriptor.+	 */+	uint32_t *n_bytes;++	/** Actual number of transfer descriptors in a list. */+	uint16_t ntd;++	/** First activated isochronous transfer descriptor index. */+	uint8_t td_first;+	/** Last activated isochronous transfer descriptor index. */+	uint8_t td_last;++	/** @} */+++	uint16_t speed;+	uint16_t frame_usecs[8];++	uint32_t skip_count;+} dwc_otg_qh_t;++DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);++typedef struct urb_tq_entry {+	struct urb *urb;+	DWC_TAILQ_ENTRY(urb_tq_entry) urb_tq_entries;+} urb_tq_entry_t;++DWC_TAILQ_HEAD(urb_list, urb_tq_entry);++/**+ * This structure holds the state of the HCD, including the non-periodic and+ * periodic schedules.+ */+struct dwc_otg_hcd {+	/** The DWC otg device pointer */+	struct dwc_otg_device *otg_dev;+	/** DWC OTG Core Interface Layer */+	dwc_otg_core_if_t *core_if;++	/** Function HCD driver callbacks */+	struct dwc_otg_hcd_function_ops *fops;++	/** Internal DWC HCD Flags */+	volatile union dwc_otg_hcd_internal_flags {+		uint32_t d32;+		struct {+			unsigned port_connect_status_change:1;+			unsigned port_connect_status:1;+			unsigned port_reset_change:1;+			unsigned port_enable_change:1;+			unsigned port_suspend_change:1;+			unsigned port_over_current_change:1;+			unsigned port_l1_change:1;+			unsigned reserved:26;+		} b;+	} flags;++	/**+	 * Inactive items in the non-periodic schedule. This is a list of+	 * Queue Heads. Transfers associated with these Queue Heads are not+	 * currently assigned to a host channel.+	 */+	dwc_list_link_t non_periodic_sched_inactive;++	/**+	 * Active items in the non-periodic schedule. This is a list of+	 * Queue Heads. Transfers associated with these Queue Heads are+	 * currently assigned to a host channel.+	 */+	dwc_list_link_t non_periodic_sched_active;++	/**+	 * Pointer to the next Queue Head to process in the active+	 * non-periodic schedule.+	 */+	dwc_list_link_t *non_periodic_qh_ptr;++	/**+	 * Inactive items in the periodic schedule. This is a list of QHs for+	 * periodic transfers that are _not_ scheduled for the next frame.+	 * Each QH in the list has an interval counter that determines when it+	 * needs to be scheduled for execution. This scheduling mechanism+	 * allows only a simple calculation for periodic bandwidth used (i.e.+	 * must assume that all periodic transfers may need to execute in the+	 * same frame). However, it greatly simplifies scheduling and should+	 * be sufficient for the vast majority of OTG hosts, which need to+	 * connect to a small number of peripherals at one time.+	 *+	 * Items move from this list to periodic_sched_ready when the QH+	 * interval counter is 0 at SOF.+	 */+	dwc_list_link_t periodic_sched_inactive;++	/**+	 * List of periodic QHs that are ready for execution in the next+	 * frame, but have not yet been assigned to host channels.+	 *+	 * Items move from this list to periodic_sched_assigned as host+	 * channels become available during the current frame.+	 */+	dwc_list_link_t periodic_sched_ready;++	/**+	 * List of periodic QHs to be executed in the next frame that are+	 * assigned to host channels.+	 *+	 * Items move from this list to periodic_sched_queued as the+	 * transactions for the QH are queued to the DWC_otg controller.+	 */+	dwc_list_link_t periodic_sched_assigned;++	/**+	 * List of periodic QHs that have been queued for execution.+	 *+	 * Items move from this list to either periodic_sched_inactive or+	 * periodic_sched_ready when the channel associated with the transfer+	 * is released. If the interval for the QH is 1, the item moves to+	 * periodic_sched_ready because it must be rescheduled for the next+	 * frame. Otherwise, the item moves to periodic_sched_inactive.+	 */+	dwc_list_link_t periodic_sched_queued;++	/**+	 * Total bandwidth claimed so far for periodic transfers. This value+	 * is in microseconds per (micro)frame. The assumption is that all+	 * periodic transfers may occur in the same (micro)frame.+	 */+	uint16_t periodic_usecs;++	/**+	 * Total bandwidth claimed so far for all periodic transfers+	 * in a frame.+	 * This will include a mixture of HS and FS transfers.+	 * Units are microseconds per (micro)frame.+	 * We have a budget per frame and have to schedule+	 * transactions accordingly.+	 * Watch out for the fact that things are actually scheduled for the+	 * "next frame".+	 */+	uint16_t                frame_usecs[8];+++	/**+	 * Frame number read from the core at SOF. The value ranges from 0 to+	 * DWC_HFNUM_MAX_FRNUM.+	 */+	uint16_t frame_number;++	/**+	 * Count of periodic QHs, if using several eps. For SOF enable/disable.+	 */+	uint16_t periodic_qh_count;++	/**+	 * Free host channels in the controller. This is a list of+	 * dwc_hc_t items.+	 */+	struct hc_list free_hc_list;+	/**+	 * Number of host channels assigned to periodic transfers. Currently+	 * assuming that there is a dedicated host channel for each periodic+	 * transaction and at least one host channel available for+	 * non-periodic transactions.+	 */+	int periodic_channels; /* microframe_schedule==0 */++	/**+	 * Number of host channels assigned to non-periodic transfers.+	 */+	int non_periodic_channels; /* microframe_schedule==0 */++	/**+	 * Number of host channels assigned to non-periodic transfers.+	 */+	int available_host_channels;++	/**+	 * Array of pointers to the host channel descriptors. Allows accessing+	 * a host channel descriptor given the host channel number. This is+	 * useful in interrupt handlers.+	 */+	struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS];++	/**+	 * Buffer to use for any data received during the status phase of a+	 * control transfer. Normally no data is transferred during the status+	 * phase. This buffer is used as a bit bucket.+	 */+	uint8_t *status_buf;++	/**+	 * DMA address for status_buf.+	 */+	dma_addr_t status_buf_dma;+#define DWC_OTG_HCD_STATUS_BUF_SIZE 64++	/**+	 * Connection timer. An OTG host must display a message if the device+	 * does not connect. Started when the VBus power is turned on via+	 * sysfs attribute "buspower".+	 */+	dwc_timer_t *conn_timer;++	/* Tasket to do a reset */+	dwc_tasklet_t *reset_tasklet;++	dwc_tasklet_t *completion_tasklet;+	struct urb_list completed_urb_list;++	/*  */+	dwc_spinlock_t *lock;+	dwc_spinlock_t *channel_lock;+	/**+	 * Private data that could be used by OS wrapper.+	 */+	void *priv;++	uint8_t otg_port;++	/** Frame List */+	uint32_t *frame_list;++	/** Hub - Port assignment */+	int hub_port[128];+#ifdef FIQ_DEBUG+	int hub_port_alloc[2048];+#endif++	/** Frame List DMA address */+	dma_addr_t frame_list_dma;++#ifdef DEBUG+	uint32_t frrem_samples;+	uint64_t frrem_accum;++	uint32_t hfnum_7_samples_a;+	uint64_t hfnum_7_frrem_accum_a;+	uint32_t hfnum_0_samples_a;+	uint64_t hfnum_0_frrem_accum_a;+	uint32_t hfnum_other_samples_a;+	uint64_t hfnum_other_frrem_accum_a;++	uint32_t hfnum_7_samples_b;+	uint64_t hfnum_7_frrem_accum_b;+	uint32_t hfnum_0_samples_b;+	uint64_t hfnum_0_frrem_accum_b;+	uint32_t hfnum_other_samples_b;+	uint64_t hfnum_other_frrem_accum_b;+#endif+};++/** @name Transaction Execution Functions */+/** @{ */+extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t+								  * hcd);+extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,+					   dwc_otg_transaction_type_e tr_type);++int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh);+void dwc_otg_hcd_release_port(dwc_otg_hcd_t * dwc_otg_hcd, dwc_otg_qh_t *qh);+++/** @} */++/** @name Interrupt Handler Functions */+/** @{ */+extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);+extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd);+extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *+							 dwc_otg_hcd);+extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *+							dwc_otg_hcd);+extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t *+							   dwc_otg_hcd);+extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t *+							   dwc_otg_hcd);+extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd);+extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t *+							     dwc_otg_hcd);+extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t * dwc_otg_hcd);+extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd);+extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd,+					    uint32_t num);+extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t * dwc_otg_hcd);+extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t *+						       dwc_otg_hcd);+/** @} */++/** @name Schedule Queue Functions */+/** @{ */++/* Implemented in dwc_otg_hcd_queue.c */+extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,+					   dwc_otg_hcd_urb_t * urb, int atomic_alloc);+extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);+extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);+extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);+extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,+				      int sched_csplit);++/** Remove and free a QH */+static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd,+						  dwc_otg_qh_t * qh)+{+	dwc_irqflags_t flags;+	DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);+	dwc_otg_hcd_qh_remove(hcd, qh);+	DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);+	dwc_otg_hcd_qh_free(hcd, qh);+}++/** Allocates memory for a QH structure.+ * @return Returns the memory allocate or NULL on error. */+static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(int atomic_alloc)+{+	if (atomic_alloc)+		return (dwc_otg_qh_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qh_t));+	else+		return (dwc_otg_qh_t *) DWC_ALLOC(sizeof(dwc_otg_qh_t));+}++extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb,+					     int atomic_alloc);+extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb);+extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd,+			       dwc_otg_qh_t ** qh, int atomic_alloc);++/** Allocates memory for a QTD structure.+ * @return Returns the memory allocate or NULL on error. */+static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(int atomic_alloc)+{+	if (atomic_alloc)+		return (dwc_otg_qtd_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qtd_t));+	else+		return (dwc_otg_qtd_t *) DWC_ALLOC(sizeof(dwc_otg_qtd_t));+}++/** Frees the memory for a QTD structure.  QTD should already be removed from+ * list.+ * @param qtd QTD to free.*/+static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd)+{+	DWC_FREE(qtd);+}++/** Removes a QTD from list.+ * @param hcd HCD instance.+ * @param qtd QTD to remove from list.+ * @param qh QTD belongs to.+ */+static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd,+					  dwc_otg_qtd_t * qtd,+					  dwc_otg_qh_t * qh)+{+	DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);+}++/** Remove and free a QTD+  * Need to disable IRQ and hold hcd lock while calling this function out of+  * interrupt servicing chain */+static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd,+						   dwc_otg_qtd_t * qtd,+						   dwc_otg_qh_t * qh)+{+	dwc_otg_hcd_qtd_remove(hcd, qtd, qh);+	dwc_otg_hcd_qtd_free(qtd);+}++/** @} */++/** @name Descriptor DMA Supporting Functions */+/** @{ */++extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);+extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,+					   dwc_hc_t * hc,+					   dwc_otg_hc_regs_t * hc_regs,+					   dwc_otg_halt_status_e halt_status);++extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);+extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);++/** @} */++/** @name Internal Functions */+/** @{ */+dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb);+/** @} */++#ifdef CONFIG_USB_DWC_OTG_LPM+extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd,+					   uint8_t devaddr);+extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd);+#endif++/** Gets the QH that contains the list_head */+#define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry)++/** Gets the QTD that contains the list_head */+#define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry)++/** Check if QH is non-periodic  */+#define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \+				     (_qh_ptr_->ep_type == UE_CONTROL))++/** High bandwidth multiplier as encoded in highspeed endpoint descriptors */+#define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))++/** Packet size for any kind of endpoint descriptor */+#define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)++/**+ * Returns true if _frame1 is less than or equal to _frame2. The comparison is+ * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the+ * frame number when the max frame number is reached.+ */+static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2)+{+	return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <=+	    (DWC_HFNUM_MAX_FRNUM >> 1);+}++/**+ * Returns true if _frame1 is greater than _frame2. The comparison is done+ * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame+ * number when the max frame number is reached.+ */+static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2)+{+	return (frame1 != frame2) &&+	    (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) <+	     (DWC_HFNUM_MAX_FRNUM >> 1));+}++/**+ * Increments _frame by the amount specified by _inc. The addition is done+ * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value.+ */+static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc)+{+	return (frame + inc) & DWC_HFNUM_MAX_FRNUM;+}++static inline uint16_t dwc_full_frame_num(uint16_t frame)+{+	return (frame & DWC_HFNUM_MAX_FRNUM) >> 3;+}++static inline uint16_t dwc_micro_frame_num(uint16_t frame)+{+	return frame & 0x7;+}++void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,+				  dwc_otg_hc_regs_t * hc_regs,+				  dwc_otg_qtd_t * qtd);++#ifdef DEBUG+/**+ * Macro to sample the remaining PHY clocks left in the current frame. This+ * may be used during debugging to determine the average time it takes to+ * execute sections of code. There are two possible sample points, "a" and+ * "b", so the _letter argument must be one of these values.+ *+ * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For+ * example, "cat /sys/devices/lm0/hcd_frrem".+ */+#define dwc_sample_frrem(_hcd, _qh, _letter) \+{ \+	hfnum_data_t hfnum; \+	dwc_otg_qtd_t *qtd; \+	qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \+	if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \+		hfnum.d32 = DWC_READ_REG32(&_hcd->core_if->host_if->host_global_regs->hfnum); \+		switch (hfnum.b.frnum & 0x7) { \+		case 7: \+			_hcd->hfnum_7_samples_##_letter++; \+			_hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \+			break; \+		case 0: \+			_hcd->hfnum_0_samples_##_letter++; \+			_hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \+			break; \+		default: \+			_hcd->hfnum_other_samples_##_letter++; \+			_hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \+			break; \+		} \+	} \+}+#else+#define dwc_sample_frrem(_hcd, _qh, _letter)+#endif+#endif+#endif /* DWC_DEVICE_ONLY */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,417 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $+ * $Revision: #12 $+ * $Date: 2011/10/26 $+ * $Change: 1873028 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */+#ifndef DWC_DEVICE_ONLY+#ifndef __DWC_HCD_IF_H__+#define __DWC_HCD_IF_H__++#include "dwc_otg_core_if.h"++/** @file+ * This file defines DWC_OTG HCD Core API.+ */++struct dwc_otg_hcd;+typedef struct dwc_otg_hcd dwc_otg_hcd_t;++struct dwc_otg_hcd_urb;+typedef struct dwc_otg_hcd_urb dwc_otg_hcd_urb_t;++/** @name HCD Function Driver Callbacks */+/** @{ */++/** This function is called whenever core switches to host mode. */+typedef int (*dwc_otg_hcd_start_cb_t) (dwc_otg_hcd_t * hcd);++/** This function is called when device has been disconnected */+typedef int (*dwc_otg_hcd_disconnect_cb_t) (dwc_otg_hcd_t * hcd);++/** Wrapper provides this function to HCD to core, so it can get hub information to which device is connected */+typedef int (*dwc_otg_hcd_hub_info_from_urb_cb_t) (dwc_otg_hcd_t * hcd,+						   void *urb_handle,+						   uint32_t * hub_addr,+						   uint32_t * port_addr);+/** Via this function HCD core gets device speed */+typedef int (*dwc_otg_hcd_speed_from_urb_cb_t) (dwc_otg_hcd_t * hcd,+						void *urb_handle);++/** This function is called when urb is completed */+typedef int (*dwc_otg_hcd_complete_urb_cb_t) (dwc_otg_hcd_t * hcd,+					      void *urb_handle,+					      dwc_otg_hcd_urb_t * dwc_otg_urb,+					      int32_t status);++/** Via this function HCD core gets b_hnp_enable parameter */+typedef int (*dwc_otg_hcd_get_b_hnp_enable) (dwc_otg_hcd_t * hcd);++struct dwc_otg_hcd_function_ops {+	dwc_otg_hcd_start_cb_t start;+	dwc_otg_hcd_disconnect_cb_t disconnect;+	dwc_otg_hcd_hub_info_from_urb_cb_t hub_info;+	dwc_otg_hcd_speed_from_urb_cb_t speed;+	dwc_otg_hcd_complete_urb_cb_t complete;+	dwc_otg_hcd_get_b_hnp_enable get_b_hnp_enable;+};+/** @} */++/** @name HCD Core API */+/** @{ */+/** This function allocates dwc_otg_hcd structure and returns pointer on it. */+extern dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void);++/** This function should be called to initiate HCD Core.+ *+ * @param hcd The HCD+ * @param core_if The DWC_OTG Core+ *+ * Returns -DWC_E_NO_MEMORY if no enough memory.+ * Returns 0 on success+ */+extern int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if);++/** Frees HCD+ *+ * @param hcd The HCD+ */+extern void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd);++/** This function should be called on every hardware interrupt.+ *+ * @param dwc_otg_hcd The HCD+ *+ * Returns non zero if interrupt is handled+ * Return 0 if interrupt is not handled+ */+extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);++/** This function is used to handle the fast interrupt+ *+ */+extern void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void);++/**+ * Returns private data set by+ * dwc_otg_hcd_set_priv_data function.+ *+ * @param hcd The HCD+ */+extern void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd);++/**+ * Set private data.+ *+ * @param hcd The HCD+ * @param priv_data pointer to be stored in private data+ */+extern void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data);++/**+ * This function initializes the HCD Core.+ *+ * @param hcd The HCD+ * @param fops The Function Driver Operations data structure containing pointers to all callbacks.+ *+ * Returns -DWC_E_NO_DEVICE if Core is currently is in device mode.+ * Returns 0 on success+ */+extern int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,+			     struct dwc_otg_hcd_function_ops *fops);++/**+ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are+ * stopped.+ *+ * @param hcd The HCD+ */+extern void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd);++/**+ * Handles hub class-specific requests.+ *+ * @param dwc_otg_hcd The HCD+ * @param typeReq Request Type+ * @param wValue wValue from control request+ * @param wIndex wIndex from control request+ * @param buf data buffer+ * @param wLength data buffer length+ *+ * Returns -DWC_E_INVALID if invalid argument is passed+ * Returns 0 on success+ */+extern int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,+				   uint16_t typeReq, uint16_t wValue,+				   uint16_t wIndex, uint8_t * buf,+				   uint16_t wLength);++/**+ * Returns otg port number.+ *+ * @param hcd The HCD+ */+extern uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd);++/**+ * Returns OTG version - either 1.3 or 2.0.+ *+ * @param core_if The core_if structure pointer+ */+extern uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if);++/**+ * Returns 1 if currently core is acting as B host, and 0 otherwise.+ *+ * @param hcd The HCD+ */+extern uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd);++/**+ * Returns current frame number.+ *+ * @param hcd The HCD+ */+extern int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * hcd);++/**+ * Dumps hcd state.+ *+ * @param hcd The HCD+ */+extern void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd);++/**+ * Dump the average frame remaining at SOF. This can be used to+ * determine average interrupt latency. Frame remaining is also shown for+ * start transfer and two additional sample points.+ * Currently this function is not implemented.+ *+ * @param hcd The HCD+ */+extern void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd);++/**+ * Sends LPM transaction to the local device.+ *+ * @param hcd The HCD+ * @param devaddr Device Address+ * @param hird Host initiated resume duration+ * @param bRemoteWake Value of bRemoteWake field in LPM transaction+ *+ * Returns negative value if sending LPM transaction was not succeeded.+ * Returns 0 on success.+ */+extern int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr,+				uint8_t hird, uint8_t bRemoteWake);++/* URB interface */++/**+ * Allocates memory for dwc_otg_hcd_urb structure.+ * Allocated memory should be freed by call of DWC_FREE.+ *+ * @param hcd The HCD+ * @param iso_desc_count Count of ISOC descriptors+ * @param atomic_alloc Specefies whether to perform atomic allocation.+ */+extern dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,+						int iso_desc_count,+						int atomic_alloc);++/**+ * Set pipe information in URB.+ *+ * @param hcd_urb DWC_OTG URB+ * @param devaddr Device Address+ * @param ep_num Endpoint Number+ * @param ep_type Endpoint Type+ * @param ep_dir Endpoint Direction+ * @param mps Max Packet Size+ */+extern void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * hcd_urb,+					 uint8_t devaddr, uint8_t ep_num,+					 uint8_t ep_type, uint8_t ep_dir,+					 uint16_t mps);++/* Transfer flags */+#define URB_GIVEBACK_ASAP 0x1+#define URB_SEND_ZERO_PACKET 0x2++/**+ * Sets dwc_otg_hcd_urb parameters.+ *+ * @param urb DWC_OTG URB allocated by dwc_otg_hcd_urb_alloc function.+ * @param urb_handle Unique handle for request, this will be passed back+ * to function driver in completion callback.+ * @param buf The buffer for the data+ * @param dma The DMA buffer for the data+ * @param buflen Transfer length+ * @param sp Buffer for setup data+ * @param sp_dma DMA address of setup data buffer+ * @param flags Transfer flags+ * @param interval Polling interval for interrupt or isochronous transfers.+ */+extern void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * urb,+				       void *urb_handle, void *buf,+				       dwc_dma_t dma, uint32_t buflen, void *sp,+				       dwc_dma_t sp_dma, uint32_t flags,+				       uint16_t interval);++/** Gets status from dwc_otg_hcd_urb+ *+ * @param dwc_otg_urb DWC_OTG URB+ */+extern uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb);++/** Gets actual length from dwc_otg_hcd_urb+ *+ * @param dwc_otg_urb DWC_OTG URB+ */+extern uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t *+						  dwc_otg_urb);++/** Gets error count from dwc_otg_hcd_urb. Only for ISOC URBs+ *+ * @param dwc_otg_urb DWC_OTG URB+ */+extern uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t *+						dwc_otg_urb);++/** Set ISOC descriptor offset and length+ *+ * @param dwc_otg_urb DWC_OTG URB+ * @param desc_num ISOC descriptor number+ * @param offset Offset from beginig of buffer.+ * @param length Transaction length+ */+extern void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,+						int desc_num, uint32_t offset,+						uint32_t length);++/** Get status of ISOC descriptor, specified by desc_num+ *+ * @param dwc_otg_urb DWC_OTG URB+ * @param desc_num ISOC descriptor number+ */+extern uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t *+						    dwc_otg_urb, int desc_num);++/** Get actual length of ISOC descriptor, specified by desc_num+ *+ * @param dwc_otg_urb DWC_OTG URB+ * @param desc_num ISOC descriptor number+ */+extern uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *+							   dwc_otg_urb,+							   int desc_num);++/** Queue URB. After transfer is completes, the complete callback will be called with the URB status+ *+ * @param dwc_otg_hcd The HCD+ * @param dwc_otg_urb DWC_OTG URB+ * @param ep_handle Out parameter for returning endpoint handle+ * @param atomic_alloc Flag to do atomic allocation if needed+ *+ * Returns -DWC_E_NO_DEVICE if no device is connected.+ * Returns -DWC_E_NO_MEMORY if there is no enough memory.+ * Returns 0 on success.+ */+extern int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * dwc_otg_hcd,+				   dwc_otg_hcd_urb_t * dwc_otg_urb,+				   void **ep_handle, int atomic_alloc);++/** De-queue the specified URB+ *+ * @param dwc_otg_hcd The HCD+ * @param dwc_otg_urb DWC_OTG URB+ */+extern int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * dwc_otg_hcd,+				   dwc_otg_hcd_urb_t * dwc_otg_urb);++/** Frees resources in the DWC_otg controller related to a given endpoint.+ * Any URBs for the endpoint must already be dequeued.+ *+ * @param hcd The HCD+ * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function+ * @param retry Number of retries if there are queued transfers.+ *+ * Returns -DWC_E_INVALID if invalid arguments are passed.+ * Returns 0 on success+ */+extern int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,+					int retry);++/* Resets the data toggle in qh structure. This function can be called from+ * usb_clear_halt routine.+ *+ * @param hcd The HCD+ * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function+ *+ * Returns -DWC_E_INVALID if invalid arguments are passed.+ * Returns 0 on success+ */+extern int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle);++/** Returns 1 if status of specified port is changed and 0 otherwise.+ *+ * @param hcd The HCD+ * @param port Port number+ */+extern int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port);++/** Call this function to check if bandwidth was allocated for specified endpoint.+ * Only for ISOC and INTERRUPT endpoints.+ *+ * @param hcd The HCD+ * @param ep_handle Endpoint handle+ */+extern int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd,+					      void *ep_handle);++/** Call this function to check if bandwidth was freed for specified endpoint.+ *+ * @param hcd The HCD+ * @param ep_handle Endpoint handle+ */+extern int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle);++/** Returns bandwidth allocated for specified endpoint in microseconds.+ * Only for ISOC and INTERRUPT endpoints.+ *+ * @param hcd The HCD+ * @param ep_handle Endpoint handle+ */+extern uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd,+					    void *ep_handle);++/** @} */++#endif /* __DWC_HCD_IF_H__ */+#endif /* DWC_DEVICE_ONLY */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,2741 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $+ * $Revision: #89 $+ * $Date: 2011/10/20 $+ * $Change: 1869487 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */+#ifndef DWC_DEVICE_ONLY++#include "dwc_otg_hcd.h"+#include "dwc_otg_regs.h"+#include "dwc_otg_mphi_fix.h"++#include <linux/jiffies.h>+#include <mach/hardware.h>+#include <asm/fiq.h>+++extern bool microframe_schedule;++/** @file+ * This file contains the implementation of the HCD Interrupt handlers.+ */++/*+ * Some globals to communicate between the FIQ and INTERRUPT+ */++void * dummy_send;+mphi_regs_t c_mphi_regs;+volatile void *dwc_regs_base;+int fiq_done, int_done;++gintsts_data_t  gintsts_saved = {.d32 = 0};+hcint_data_t    hcint_saved[MAX_EPS_CHANNELS];+hcintmsk_data_t hcintmsk_saved[MAX_EPS_CHANNELS];+int             split_out_xfersize[MAX_EPS_CHANNELS];+haint_data_t    haint_saved;++int g_next_sched_frame, g_np_count, g_np_sent;+static int mphi_int_count = 0 ;++hcchar_data_t nak_hcchar;+hctsiz_data_t nak_hctsiz;+hcsplt_data_t nak_hcsplt;+int nak_count;++int complete_sched[MAX_EPS_CHANNELS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};+int split_start_frame[MAX_EPS_CHANNELS];+int queued_port[MAX_EPS_CHANNELS];++#ifdef FIQ_DEBUG+char buffer[1000*16];+int wptr;+void notrace _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...)+{+	FIQDBG_T dbg_lvl_req = FIQDBG_PORTHUB;+	va_list args;+	char text[17];+	hfnum_data_t hfnum = { .d32 = FIQ_READ(dwc_regs_base + 0x408) };+	unsigned long flags;++	local_irq_save(flags);+	local_fiq_disable();+	if(dbg_lvl & dbg_lvl_req || dbg_lvl == FIQDBG_ERR)+	{+		snprintf(text, 9, "%4d%d:%d ", hfnum.b.frnum/8, hfnum.b.frnum%8, 8 - hfnum.b.frrem/937);+		va_start(args, fmt);+		vsnprintf(text+8, 9, fmt, args);+		va_end(args);++		memcpy(buffer + wptr, text, 16);+		wptr = (wptr + 16) % sizeof(buffer);+	}+	local_irq_restore(flags);+}+#endif++void notrace fiq_queue_request(int channel, int odd_frame)+{+	hcchar_data_t   hcchar   = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0)  };+	hcsplt_data_t   hcsplt   = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4)  };+	hctsiz_data_t   hctsiz   = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10) };++	if(hcsplt.b.spltena	== 0)+	{+		fiq_print(FIQDBG_ERR, "SPLTENA ");+		BUG();+	}++	if(hcchar.b.epdir == 1)+	{+		fiq_print(FIQDBG_SCHED, "IN  Ch %d", channel);+	}+	else+	{+		hctsiz.b.xfersize = 0;+		fiq_print(FIQDBG_SCHED, "OUT Ch %d", channel);+	}+	FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x10), hctsiz.d32);++	hcsplt.b.compsplt = 1;+	FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x4), hcsplt.d32);++	// Send the Split complete+	hcchar.b.chen = 1;+	hcchar.b.oddfrm = odd_frame ? 1 : 0;++	// Post this for transmit on the next frame for periodic or this frame for non-periodic+	fiq_print(FIQDBG_SCHED, "SND_%s", odd_frame ? "ODD " : "EVEN");++	FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x0), hcchar.d32);+}++static int last_sof = -1;++/*+** Function to handle the start of frame interrupt, choose whether we need to do anything and+** therefore trigger the main interrupt+**+** returns int != 0 - interrupt has been handled+*/+int diff;++int notrace fiq_sof_handle(hfnum_data_t hfnum)+{+	int handled = 0;+	int i;++	// Just check that once we're running we don't miss a SOF+	/*if(last_sof != -1 && (hfnum.b.frnum != ((last_sof + 1) & 0x3fff)))+	{+		fiq_print(FIQDBG_ERR, "LASTSOF ");+		fiq_print(FIQDBG_ERR, "%4d%d   ", last_sof / 8, last_sof & 7);+		fiq_print(FIQDBG_ERR, "%4d%d   ", hfnum.b.frnum / 8, hfnum.b.frnum & 7);+		BUG();+	}*/++	// Only start remembering the last sof when the interrupt has been+	// enabled (we don't check the mask to come in here...)+	if(last_sof != -1 || FIQ_READ(dwc_regs_base + 0x18) & (1<<3))+		last_sof = hfnum.b.frnum;++	for(i = 0; i < MAX_EPS_CHANNELS; i++)+	{+		if(complete_sched[i] != -1)+		{+			if(complete_sched[i] <= hfnum.b.frnum || (complete_sched[i] > 0x3f00 && hfnum.b.frnum < 0xf0))+			{+				fiq_queue_request(i, hfnum.b.frnum & 1);+				complete_sched[i] = -1;+			}+		}++		if(complete_sched[i] != -1)+		{+			// This is because we've seen a split complete occur with no start...+			// most likely because missed the complete 0x3fff frames ago!++			diff = (hfnum.b.frnum + 0x3fff - complete_sched[i]) & 0x3fff ;+			if(diff > 32 && diff < 0x3f00)+			{+				fiq_print(FIQDBG_ERR, "SPLTMISS");+				BUG();+			}+		}+	}++	if(g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))+	{+		/*+		 * If np_count != np_sent that means we need to queue non-periodic (bulk) packets this packet+		 * g_next_sched_frame is the next frame we have periodic packets for+		 *+		 * if neither of these are required for this frame then just clear the interrupt+		 */+		handled = 1;++	}++	return handled;+}++int notrace port_id(hcsplt_data_t hcsplt)+{+	return hcsplt.b.prtaddr + (hcsplt.b.hubaddr << 8);+}++int notrace fiq_hcintr_handle(int channel, hfnum_data_t hfnum)+{+	hcchar_data_t   hcchar   = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0) };+	hcsplt_data_t   hcsplt   = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4) };+	hcint_data_t    hcint    = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x8) };+	hcintmsk_data_t hcintmsk = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0xc) };+	hctsiz_data_t   hctsiz   = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10)};++	hcint_saved[channel].d32 |= hcint.d32;+	hcintmsk_saved[channel].d32 =  hcintmsk.d32;++	if(hcsplt.b.spltena)+	{+		fiq_print(FIQDBG_PORTHUB, "ph: %4x", port_id(hcsplt));+		if(hcint.b.chhltd)+		{+			fiq_print(FIQDBG_SCHED, "CH HLT %d", channel);+			fiq_print(FIQDBG_SCHED, "%08x", hcint_saved[channel]);+		}+		if(hcint.b.stall || hcint.b.xacterr || hcint.b.bblerr || hcint.b.frmovrun || hcint.b.datatglerr)+		{+			queued_port[channel] = 0;+			fiq_print(FIQDBG_ERR, "CHAN ERR");+		}+		if(hcint.b.xfercomp)+		{+			// Clear the port allocation and transmit anything also on this port+			queued_port[channel] = 0;+			fiq_print(FIQDBG_SCHED, "XFERCOMP");+		}+		if(hcint.b.nak)+		{+			queued_port[channel] = 0;+			fiq_print(FIQDBG_SCHED, "NAK");+		}+		if(hcint.b.ack && !hcsplt.b.compsplt)+		{+			int i;++			// Do not complete isochronous out transactions+			if(hcchar.b.eptype == 1 && hcchar.b.epdir == 0)+			{+				queued_port[channel] = 0;+				fiq_print(FIQDBG_SCHED, "ISOC_OUT");+			}+			else+			{+				// Make sure we check the port / hub combination that we sent this split on.+				// Do not queue a second request to the same port+				for(i = 0; i < MAX_EPS_CHANNELS; i++)+				{+					if(port_id(hcsplt) == queued_port[i])+					{+						fiq_print(FIQDBG_ERR, "PORTERR ");+						//BUG();+					}+				}++				split_start_frame[channel] = (hfnum.b.frnum + 1) & ~7;++				// Note, the size of an OUT is in the start split phase, not+				// the complete split+				split_out_xfersize[channel] = hctsiz.b.xfersize;++				hcint_saved[channel].b.chhltd = 0;+				hcint_saved[channel].b.ack = 0;++				queued_port[channel] = port_id(hcsplt);++				if(hcchar.b.eptype & 1)+				{+					// Send the periodic complete in the same oddness frame as the ACK went...+					fiq_queue_request(channel, !(hfnum.b.frnum & 1));+	//				complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1);+				}+				else+				{+					// Schedule the split complete to occur later+					complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 2);+					fiq_print(FIQDBG_SCHED, "ACK%04d%d", complete_sched[channel]/8, complete_sched[channel]%8);+				}+			}+		}+		if(hcint.b.nyet)+		{+			fiq_print(FIQDBG_ERR, "NYETERR1");+			//BUG();+			// Can transmit a split complete up to uframe .0 of the next frame+			if(hfnum.b.frnum <= dwc_frame_num_inc(split_start_frame[channel], 8))+			{+				// Send it next frame+				if(hcchar.b.eptype & 1) // type 1 & 3 are interrupt & isoc+				{+					fiq_print(FIQDBG_SCHED, "NYT:SEND");+					fiq_queue_request(channel, !(hfnum.b.frnum & 1));+				}+				else+				{+					// Schedule non-periodic access for next frame (the odd-even bit doesn't effect NP)+					complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1);+					fiq_print(FIQDBG_SCHED, "NYT%04d%d", complete_sched[channel]/8, complete_sched[channel]%8);+				}+				hcint_saved[channel].b.chhltd = 0;+				hcint_saved[channel].b.nyet = 0;+			}+			else+			{+				queued_port[channel] = 0;+				fiq_print(FIQDBG_ERR, "NYETERR2");+				//BUG();+			}+		}+	}+	else+	{+		/*+		 * If we have any of NAK, ACK, Datatlgerr active on a+		 * non-split channel, the sole reason is to reset error+		 * counts for a previously broken transaction. The FIQ+		 * will thrash on NAK IN and ACK OUT in particular so+		 * handle it "once" and allow the IRQ to do the rest.+		 */+		hcint.d32 &= hcintmsk.d32;+		if(hcint.b.nak)+		{+			hcintmsk.b.nak = 0;+			FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0xc), hcintmsk.d32);+		}+		if (hcint.b.ack)+		{+			hcintmsk.b.ack = 0;+			FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0xc), hcintmsk.d32);+		}+	}++	// Clear the interrupt, this will also clear the HAINT bit+	FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x8), hcint.d32);+	return hcint_saved[channel].d32 == 0;+}++gintsts_data_t gintsts;+gintmsk_data_t gintmsk;+// triggered: The set of interrupts that were triggered+// handled:   The set of interrupts that have been handled (no IRQ is+//            required)+// keep:      The set of interrupts we want to keep unmasked even though we+//            want to trigger an IRQ to handle it (SOF and HCINTR)+gintsts_data_t triggered, handled, keep;+hfnum_data_t hfnum;++void __attribute__ ((naked)) notrace dwc_otg_hcd_handle_fiq(void)+{++	/* entry takes care to store registers we will be treading on here */+	asm __volatile__ (+		"mov     ip, sp ;"+		/* stash FIQ and normal regs */+		"stmdb	sp!, {r0-r12,  lr};"+		/* !! THIS SETS THE FRAME, adjust to > sizeof locals */+		"sub     fp, ip, #512 ;"+		);++	// Cannot put local variables at the beginning of the function+	// because otherwise 'C' will play with the stack pointer. any locals+	// need to be inside the following block+	do+	{+		fiq_done++;+		gintsts.d32 = FIQ_READ(dwc_regs_base + 0x14);+		gintmsk.d32 = FIQ_READ(dwc_regs_base + 0x18);+		hfnum.d32 =   FIQ_READ(dwc_regs_base + 0x408);+		triggered.d32 = gintsts.d32 & gintmsk.d32;+		handled.d32 = 0;+		keep.d32 = 0;+		fiq_print(FIQDBG_INT, "FIQ     ");+		fiq_print(FIQDBG_INT, "%08x", gintsts.d32);+		fiq_print(FIQDBG_INT, "%08x", gintmsk.d32);+		if(gintsts.d32)+		{+			// If port enabled+			if((FIQ_READ(dwc_regs_base + 0x440) & 0xf) == 0x5)+			{+				if(gintsts.b.sofintr)+				{+					if(fiq_sof_handle(hfnum))+					{+						handled.b.sofintr = 1; /* Handled in FIQ */+					}+					else+					{+						/* Keer interrupt unmasked */+						keep.b.sofintr = 1;+					}+					{+						// Need to make sure the read and clearing of the SOF interrupt is as close as possible to avoid the possibility of missing+						// a start of frame interrupt+						gintsts_data_t gintsts = { .b.sofintr = 1 };+						FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32);+					}+				}++				if(fiq_split_enable && gintsts.b.hcintr)+				{+					int i;+					haint_data_t    haint;+					haintmsk_data_t haintmsk;++					haint.d32 = FIQ_READ(dwc_regs_base + 0x414);+					haintmsk.d32 = FIQ_READ(dwc_regs_base + 0x418);+					haint.d32 &= haintmsk.d32;+					haint_saved.d32 |= haint.d32;++					fiq_print(FIQDBG_INT, "hcintr");+					fiq_print(FIQDBG_INT, "%08x", FIQ_READ(dwc_regs_base + 0x414));++					// Go through each channel that has an enabled interrupt+					for(i = 0; i < 16; i++)+						if((haint.d32 >> i) & 1)+							if(fiq_hcintr_handle(i, hfnum))+								haint_saved.d32 &= ~(1 << i); /* this was handled */++					/* If we've handled all host channel interrupts then don't trigger the interrupt */+					if(haint_saved.d32 == 0)+					{+						handled.b.hcintr = 1;+					}+					else+					{+						/* Make sure we keep the channel interrupt unmasked when triggering the IRQ */+						keep.b.hcintr = 1;+					}++					{+						gintsts_data_t gintsts = { .b.hcintr = 1 };++						// Always clear the channel interrupt+						FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32);+					}+				}+			}+			else+			{+				last_sof = -1;+			}+		}++		// Mask out the interrupts triggered - those handled - don't mask out the ones we want to keep+		gintmsk.d32 = keep.d32 | (gintmsk.d32 & ~(triggered.d32 & ~handled.d32));+		// Save those that were triggered but not handled+		gintsts_saved.d32 |= triggered.d32 & ~handled.d32;+		FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32);++		// Clear and save any unhandled interrupts and trigger the interrupt+		if(gintsts_saved.d32)+		{+			/* To enable the MPHI interrupt  (INT 32)+			 */+			FIQ_WRITE( c_mphi_regs.outdda, (int) dummy_send);+			FIQ_WRITE( c_mphi_regs.outddb, (1 << 29));++			mphi_int_count++;+		}+	}+	while(0);++	mb();++	/* exit back to normal mode restoring everything */+	asm __volatile__ (+		/* return FIQ regs back to pristine state+		 * and get normal regs back+		 */+		"ldmia	sp!, {r0-r12, lr};"++		/* return */+		"subs	pc, lr, #4;"+	);+}++/** This function handles interrupts for the HCD. */+int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)+{+	int retval = 0;+	static int last_time;++	dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;+	gintsts_data_t gintsts;+	gintmsk_data_t gintmsk;+	hfnum_data_t hfnum;++#ifdef DEBUG+	dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;++#endif++	gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);+	gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);++	/* Exit from ISR if core is hibernated */+	if (core_if->hibernation_suspend == 1) {+		goto exit_handler_routine;+	}+	DWC_SPINLOCK(dwc_otg_hcd->lock);+	/* Check if HOST Mode */+	if (dwc_otg_is_host_mode(core_if)) {+		local_fiq_disable();+		gintmsk.d32 |= gintsts_saved.d32;+		gintsts.d32 |= gintsts_saved.d32;+		gintsts_saved.d32 = 0;+		local_fiq_enable();+		if (!gintsts.d32) {+			goto exit_handler_routine;+		}+		gintsts.d32 &= gintmsk.d32;++#ifdef DEBUG+		// We should be OK doing this because the common interrupts should already have been serviced+		/* Don't print debug message in the interrupt handler on SOF */+#ifndef DEBUG_SOF+		if (gintsts.d32 != DWC_SOF_INTR_MASK)+#endif+			DWC_DEBUGPL(DBG_HCDI, "\n");+#endif++#ifdef DEBUG+#ifndef DEBUG_SOF+		if (gintsts.d32 != DWC_SOF_INTR_MASK)+#endif+			DWC_DEBUGPL(DBG_HCDI,+				    "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n",+				    gintsts.d32, core_if);+#endif+		hfnum.d32 = DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->hfnum);+		if (gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))+		{+			/* Note, we should never get here if the FIQ is doing it's job properly*/+			retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);+		}+		else if (gintsts.b.sofintr) {+			retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);+		}++		if (gintsts.b.rxstsqlvl) {+			retval |=+			    dwc_otg_hcd_handle_rx_status_q_level_intr+			    (dwc_otg_hcd);+		}+		if (gintsts.b.nptxfempty) {+			retval |=+			    dwc_otg_hcd_handle_np_tx_fifo_empty_intr+			    (dwc_otg_hcd);+		}+		if (gintsts.b.i2cintr) {+			/** @todo Implement i2cintr handler. */+		}+		if (gintsts.b.portintr) {++			gintmsk_data_t gintmsk = { .b.portintr = 1};+			retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd);+			DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32);+		}+		if (gintsts.b.hcintr) {+			retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd);+		}+		if (gintsts.b.ptxfempty) {+			retval |=+			    dwc_otg_hcd_handle_perio_tx_fifo_empty_intr+			    (dwc_otg_hcd);+		}+#ifdef DEBUG+#ifndef DEBUG_SOF+		if (gintsts.d32 != DWC_SOF_INTR_MASK)+#endif+		{+			DWC_DEBUGPL(DBG_HCDI,+				    "DWC OTG HCD Finished Servicing Interrupts\n");+			DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n",+				    DWC_READ_REG32(&global_regs->gintsts));+			DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n",+				    DWC_READ_REG32(&global_regs->gintmsk));+		}+#endif++#ifdef DEBUG+#ifndef DEBUG_SOF+		if (gintsts.d32 != DWC_SOF_INTR_MASK)+#endif+			DWC_DEBUGPL(DBG_HCDI, "\n");+#endif++	}++exit_handler_routine:++	if (fiq_fix_enable)+	{+		local_fiq_disable();+		// Make sure that we don't clear the interrupt if we've still got pending work to do+		if(gintsts_saved.d32 == 0)+		{+			/* Clear the MPHI interrupt */+			DWC_WRITE_REG32(c_mphi_regs.intstat, (1<<16));+			if (mphi_int_count >= 60)+			{+				DWC_WRITE_REG32(c_mphi_regs.ctrl, ((1<<31) + (1<<16)));+				while(!(DWC_READ_REG32(c_mphi_regs.ctrl) & (1 << 17)))+					;+				DWC_WRITE_REG32(c_mphi_regs.ctrl, (1<<31));+				mphi_int_count = 0;+			}+			int_done++;+		}++		// Unmask handled interrupts+		FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32);+		//DWC_MODIFY_REG32((uint32_t *)IO_ADDRESS(USB_BASE + 0x8), 0 , 1);++		local_fiq_enable();++		if((jiffies / HZ) > last_time)+		{+			/* Once a second output the fiq and irq numbers, useful for debug */+			last_time = jiffies / HZ;+			DWC_DEBUGPL(DBG_USER, "int_done = %d fiq_done = %d\n", int_done, fiq_done);+		}+	}++	DWC_SPINUNLOCK(dwc_otg_hcd->lock);+	return retval;+}++#ifdef DWC_TRACK_MISSED_SOFS++#warning Compiling code to track missed SOFs+#define FRAME_NUM_ARRAY_SIZE 1000+/**+ * This function is for debug only.+ */+static inline void track_missed_sofs(uint16_t curr_frame_number)+{+	static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE];+	static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE];+	static int frame_num_idx = 0;+	static uint16_t last_frame_num = DWC_HFNUM_MAX_FRNUM;+	static int dumped_frame_num_array = 0;++	if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) {+		if (((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) !=+		    curr_frame_number) {+			frame_num_array[frame_num_idx] = curr_frame_number;+			last_frame_num_array[frame_num_idx++] = last_frame_num;+		}+	} else if (!dumped_frame_num_array) {+		int i;+		DWC_PRINTF("Frame     Last Frame\n");+		DWC_PRINTF("-----     ----------\n");+		for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) {+			DWC_PRINTF("0x%04x    0x%04x\n",+				   frame_num_array[i], last_frame_num_array[i]);+		}+		dumped_frame_num_array = 1;+	}+	last_frame_num = curr_frame_number;+}+#endif++/**+ * Handles the start-of-frame interrupt in host mode. Non-periodic+ * transactions may be queued to the DWC_otg controller for the current+ * (micro)frame. Periodic transactions may be queued to the controller for the+ * next (micro)frame.+ */+int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)+{+	hfnum_data_t hfnum;+	dwc_list_link_t *qh_entry;+	dwc_otg_qh_t *qh;+	dwc_otg_transaction_type_e tr_type;+	int did_something = 0;+	int32_t next_sched_frame = -1;++	hfnum.d32 =+	    DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);++#ifdef DEBUG_SOF+	DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n");+#endif+	hcd->frame_number = hfnum.b.frnum;++#ifdef DEBUG+	hcd->frrem_accum += hfnum.b.frrem;+	hcd->frrem_samples++;+#endif++#ifdef DWC_TRACK_MISSED_SOFS+	track_missed_sofs(hcd->frame_number);+#endif+	/* Determine whether any periodic QHs should be executed. */+	qh_entry = DWC_LIST_FIRST(&hcd->periodic_sched_inactive);+	while (qh_entry != &hcd->periodic_sched_inactive) {+		qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry);+		qh_entry = qh_entry->next;+		if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) {++			/*+			 * Move QH to the ready list to be executed next+			 * (micro)frame.+			 */+			DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,+					   &qh->qh_list_entry);++			did_something = 1;+		}+		else+		{+			if(next_sched_frame < 0 || dwc_frame_num_le(qh->sched_frame, next_sched_frame))+			{+				next_sched_frame = qh->sched_frame;+			}+		}+	}++	g_next_sched_frame = next_sched_frame;++	tr_type = dwc_otg_hcd_select_transactions(hcd);+	if (tr_type != DWC_OTG_TRANSACTION_NONE) {+		dwc_otg_hcd_queue_transactions(hcd, tr_type);+		did_something = 1;+	}++	/* Clear interrupt */+	gintsts.b.sofintr = 1;+	DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32);++	return 1;+}++/** Handles the Rx Status Queue Level Interrupt, which indicates that there is at+ * least one packet in the Rx FIFO.  The packets are moved from the FIFO to+ * memory if the DWC_otg controller is operating in Slave mode. */+int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * dwc_otg_hcd)+{+	host_grxsts_data_t grxsts;+	dwc_hc_t *hc = NULL;++	DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n");++	grxsts.d32 =+	    DWC_READ_REG32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp);++	hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum];+	if (!hc) {+		DWC_ERROR("Unable to get corresponding channel\n");+		return 0;+	}++	/* Packet Status */+	DWC_DEBUGPL(DBG_HCDV, "    Ch num = %d\n", grxsts.b.chnum);+	DWC_DEBUGPL(DBG_HCDV, "    Count = %d\n", grxsts.b.bcnt);+	DWC_DEBUGPL(DBG_HCDV, "    DPID = %d, hc.dpid = %d\n", grxsts.b.dpid,+		    hc->data_pid_start);+	DWC_DEBUGPL(DBG_HCDV, "    PStatus = %d\n", grxsts.b.pktsts);++	switch (grxsts.b.pktsts) {+	case DWC_GRXSTS_PKTSTS_IN:+		/* Read the data into the host buffer. */+		if (grxsts.b.bcnt > 0) {+			dwc_otg_read_packet(dwc_otg_hcd->core_if,+					    hc->xfer_buff, grxsts.b.bcnt);++			/* Update the HC fields for the next packet received. */+			hc->xfer_count += grxsts.b.bcnt;+			hc->xfer_buff += grxsts.b.bcnt;+		}++	case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:+	case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR:+	case DWC_GRXSTS_PKTSTS_CH_HALTED:+		/* Handled in interrupt, just ignore data */+		break;+	default:+		DWC_ERROR("RX_STS_Q Interrupt: Unknown status %d\n",+			  grxsts.b.pktsts);+		break;+	}++	return 1;+}++/** This interrupt occurs when the non-periodic Tx FIFO is half-empty. More+ * data packets may be written to the FIFO for OUT transfers. More requests+ * may be written to the non-periodic request queue for IN transfers. This+ * interrupt is enabled only in Slave mode. */+int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)+{+	DWC_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n");+	dwc_otg_hcd_queue_transactions(dwc_otg_hcd,+				       DWC_OTG_TRANSACTION_NON_PERIODIC);+	return 1;+}++/** This interrupt occurs when the periodic Tx FIFO is half-empty. More data+ * packets may be written to the FIFO for OUT transfers. More requests may be+ * written to the periodic request queue for IN transfers. This interrupt is+ * enabled only in Slave mode. */+int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)+{+	DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n");+	dwc_otg_hcd_queue_transactions(dwc_otg_hcd,+				       DWC_OTG_TRANSACTION_PERIODIC);+	return 1;+}++/** There are multiple conditions that can cause a port interrupt. This function+ * determines which interrupt conditions have occurred and handles them+ * appropriately. */+int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd)+{+	int retval = 0;+	hprt0_data_t hprt0;+	hprt0_data_t hprt0_modify;++	hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);+	hprt0_modify.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);++	/* Clear appropriate bits in HPRT0 to clear the interrupt bit in+	 * GINTSTS */++	hprt0_modify.b.prtena = 0;+	hprt0_modify.b.prtconndet = 0;+	hprt0_modify.b.prtenchng = 0;+	hprt0_modify.b.prtovrcurrchng = 0;++	/* Port Connect Detected+	 * Set flag and clear if detected */+	if (dwc_otg_hcd->core_if->hibernation_suspend == 1) {+		// Dont modify port status if we are in hibernation state+		hprt0_modify.b.prtconndet = 1;+		hprt0_modify.b.prtenchng = 1;+		DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);+		hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);+		return retval;+	}++	if (hprt0.b.prtconndet) {+		/** @todo - check if steps performed in 'else' block should be perfromed regardles adp */+		if (dwc_otg_hcd->core_if->adp_enable &&+				dwc_otg_hcd->core_if->adp.vbuson_timer_started == 1) {+			DWC_PRINTF("PORT CONNECT DETECTED ----------------\n");+			DWC_TIMER_CANCEL(dwc_otg_hcd->core_if->adp.vbuson_timer);+			dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0;+			/* TODO - check if this is required, as+			 * host initialization was already performed+			 * after initial ADP probing+			 */+			/*dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0;+			dwc_otg_core_init(dwc_otg_hcd->core_if);+			dwc_otg_enable_global_interrupts(dwc_otg_hcd->core_if);+			cil_hcd_start(dwc_otg_hcd->core_if);*/+		} else {++			DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x "+				    "Port Connect Detected--\n", hprt0.d32);+			dwc_otg_hcd->flags.b.port_connect_status_change = 1;+			dwc_otg_hcd->flags.b.port_connect_status = 1;+			hprt0_modify.b.prtconndet = 1;++			/* B-Device has connected, Delete the connection timer. */+			DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer);+		}+		/* The Hub driver asserts a reset when it sees port connect+		 * status change flag */+		retval |= 1;+	}++	/* Port Enable Changed+	 * Clear if detected - Set internal flag if disabled */+	if (hprt0.b.prtenchng) {+		DWC_DEBUGPL(DBG_HCD, "  --Port Interrupt HPRT0=0x%08x "+			    "Port Enable Changed--\n", hprt0.d32);+		hprt0_modify.b.prtenchng = 1;+		if (hprt0.b.prtena == 1) {+			hfir_data_t hfir;+			int do_reset = 0;+			dwc_otg_core_params_t *params =+			    dwc_otg_hcd->core_if->core_params;+			dwc_otg_core_global_regs_t *global_regs =+			    dwc_otg_hcd->core_if->core_global_regs;+			dwc_otg_host_if_t *host_if =+			    dwc_otg_hcd->core_if->host_if;++			/* Every time when port enables calculate+			 * HFIR.FrInterval+			 */+			hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir);+			hfir.b.frint = calc_frame_interval(dwc_otg_hcd->core_if);+			DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32);++			/* Check if we need to adjust the PHY clock speed for+			 * low power and adjust it */+			if (params->host_support_fs_ls_low_power) {+				gusbcfg_data_t usbcfg;++				usbcfg.d32 =+				    DWC_READ_REG32(&global_regs->gusbcfg);++				if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED+				    || hprt0.b.prtspd ==+				    DWC_HPRT0_PRTSPD_FULL_SPEED) {+					/*+					 * Low power+					 */+					hcfg_data_t hcfg;+					if (usbcfg.b.phylpwrclksel == 0) {+						/* Set PHY low power clock select for FS/LS devices */+						usbcfg.b.phylpwrclksel = 1;+						DWC_WRITE_REG32+						    (&global_regs->gusbcfg,+						     usbcfg.d32);+						do_reset = 1;+					}++					hcfg.d32 =+					    DWC_READ_REG32+					    (&host_if->host_global_regs->hcfg);++					if (hprt0.b.prtspd ==+					    DWC_HPRT0_PRTSPD_LOW_SPEED+					    && params->host_ls_low_power_phy_clk+					    ==+					    DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)+					{+						/* 6 MHZ */+						DWC_DEBUGPL(DBG_CIL,+							    "FS_PHY programming HCFG to 6 MHz (Low Power)\n");+						if (hcfg.b.fslspclksel !=+						    DWC_HCFG_6_MHZ) {+							hcfg.b.fslspclksel =+							    DWC_HCFG_6_MHZ;+							DWC_WRITE_REG32+							    (&host_if->host_global_regs->hcfg,+							     hcfg.d32);+							do_reset = 1;+						}+					} else {+						/* 48 MHZ */+						DWC_DEBUGPL(DBG_CIL,+							    "FS_PHY programming HCFG to 48 MHz ()\n");+						if (hcfg.b.fslspclksel !=+						    DWC_HCFG_48_MHZ) {+							hcfg.b.fslspclksel =+							    DWC_HCFG_48_MHZ;+							DWC_WRITE_REG32+							    (&host_if->host_global_regs->hcfg,+							     hcfg.d32);+							do_reset = 1;+						}+					}+				} else {+					/*+					 * Not low power+					 */+					if (usbcfg.b.phylpwrclksel == 1) {+						usbcfg.b.phylpwrclksel = 0;+						DWC_WRITE_REG32+						    (&global_regs->gusbcfg,+						     usbcfg.d32);+						do_reset = 1;+					}+				}++				if (do_reset) {+					DWC_TASK_SCHEDULE(dwc_otg_hcd->reset_tasklet);+				}+			}++			if (!do_reset) {+				/* Port has been enabled set the reset change flag */+				dwc_otg_hcd->flags.b.port_reset_change = 1;+			}+		} else {+			dwc_otg_hcd->flags.b.port_enable_change = 1;+		}+		retval |= 1;+	}++	/** Overcurrent Change Interrupt */+	if (hprt0.b.prtovrcurrchng) {+		DWC_DEBUGPL(DBG_HCD, "  --Port Interrupt HPRT0=0x%08x "+			    "Port Overcurrent Changed--\n", hprt0.d32);+		dwc_otg_hcd->flags.b.port_over_current_change = 1;+		hprt0_modify.b.prtovrcurrchng = 1;+		retval |= 1;+	}++	/* Clear Port Interrupts */+	DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);++	return retval;+}++/** This interrupt indicates that one or more host channels has a pending+ * interrupt. There are multiple conditions that can cause each host channel+ * interrupt. This function determines which conditions have occurred for each+ * host channel interrupt and handles them appropriately. */+int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd)+{+	int i;+	int retval = 0;+	haint_data_t haint;++	/* Clear appropriate bits in HCINTn to clear the interrupt bit in+	 * GINTSTS */++	haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if);++	// Overwrite with saved interrupts from fiq handler+	if(fiq_split_enable)+	{+		local_fiq_disable();+		haint.d32 = haint_saved.d32;+		haint_saved.d32 = 0;+		local_fiq_enable();+	}++	for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) {+		if (haint.b2.chint & (1 << i)) {+			retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i);+		}+	}++	return retval;+}++/**+ * Gets the actual length of a transfer after the transfer halts. _halt_status+ * holds the reason for the halt.+ *+ * For IN transfers where halt_status is DWC_OTG_HC_XFER_COMPLETE,+ * *short_read is set to 1 upon return if less than the requested+ * number of bytes were transferred. Otherwise, *short_read is set to 0 upon+ * return. short_read may also be NULL on entry, in which case it remains+ * unchanged.+ */+static uint32_t get_actual_xfer_length(dwc_hc_t * hc,+				       dwc_otg_hc_regs_t * hc_regs,+				       dwc_otg_qtd_t * qtd,+				       dwc_otg_halt_status_e halt_status,+				       int *short_read)+{+	hctsiz_data_t hctsiz;+	uint32_t length;++	if (short_read != NULL) {+		*short_read = 0;+	}+	hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);++	if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {+		if (hc->ep_is_in) {+			length = hc->xfer_len - hctsiz.b.xfersize;+			if (short_read != NULL) {+				*short_read = (hctsiz.b.xfersize != 0);+			}+		} else if (hc->qh->do_split) {+			if(fiq_split_enable)+				length = split_out_xfersize[hc->hc_num];+			else+				length = qtd->ssplit_out_xfer_count;+		} else {+			length = hc->xfer_len;+		}+	} else {+		/*+		 * Must use the hctsiz.pktcnt field to determine how much data+		 * has been transferred. This field reflects the number of+		 * packets that have been transferred via the USB. This is+		 * always an integral number of packets if the transfer was+		 * halted before its normal completion. (Can't use the+		 * hctsiz.xfersize field because that reflects the number of+		 * bytes transferred via the AHB, not the USB).+		 */+		length =+		    (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet;+	}++	return length;+}++/**+ * Updates the state of the URB after a Transfer Complete interrupt on the+ * host channel. Updates the actual_length field of the URB based on the+ * number of bytes transferred via the host channel. Sets the URB status+ * if the data transfer is finished.+ *+ * @return 1 if the data transfer specified by the URB is completely finished,+ * 0 otherwise.+ */+static int update_urb_state_xfer_comp(dwc_hc_t * hc,+				      dwc_otg_hc_regs_t * hc_regs,+				      dwc_otg_hcd_urb_t * urb,+				      dwc_otg_qtd_t * qtd)+{+	int xfer_done = 0;+	int short_read = 0;++	int xfer_length;++	xfer_length = get_actual_xfer_length(hc, hc_regs, qtd,+					     DWC_OTG_HC_XFER_COMPLETE,+					     &short_read);++	/* non DWORD-aligned buffer case handling. */+	if (hc->align_buff && xfer_length && hc->ep_is_in) {+		dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,+			   xfer_length);+	}++	urb->actual_length += xfer_length;++	if (xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) &&+	    (urb->flags & URB_SEND_ZERO_PACKET)+	    && (urb->actual_length == urb->length)+	    && !(urb->length % hc->max_packet)) {+		xfer_done = 0;+	} else if (short_read || urb->actual_length >= urb->length) {+		xfer_done = 1;+		urb->status = 0;+	}++#ifdef DEBUG+	{+		hctsiz_data_t hctsiz;+		hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);+		DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",+			    __func__, (hc->ep_is_in ? "IN" : "OUT"),+			    hc->hc_num);+		DWC_DEBUGPL(DBG_HCDV, "  hc->xfer_len %d\n", hc->xfer_len);+		DWC_DEBUGPL(DBG_HCDV, "  hctsiz.xfersize %d\n",+			    hctsiz.b.xfersize);+		DWC_DEBUGPL(DBG_HCDV, "  urb->transfer_buffer_length %d\n",+			    urb->length);+		DWC_DEBUGPL(DBG_HCDV, "  urb->actual_length %d\n",+			    urb->actual_length);+		DWC_DEBUGPL(DBG_HCDV, "  short_read %d, xfer_done %d\n",+			    short_read, xfer_done);+	}+#endif++	return xfer_done;+}++/*+ * Save the starting data toggle for the next transfer. The data toggle is+ * saved in the QH for non-control transfers and it's saved in the QTD for+ * control transfers.+ */+void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,+			     dwc_otg_hc_regs_t * hc_regs, dwc_otg_qtd_t * qtd)+{+	hctsiz_data_t hctsiz;+	hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);++	if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) {+		dwc_otg_qh_t *qh = hc->qh;+		if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {+			qh->data_toggle = DWC_OTG_HC_PID_DATA0;+		} else {+			qh->data_toggle = DWC_OTG_HC_PID_DATA1;+		}+	} else {+		if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {+			qtd->data_toggle = DWC_OTG_HC_PID_DATA0;+		} else {+			qtd->data_toggle = DWC_OTG_HC_PID_DATA1;+		}+	}+}++/**+ * Updates the state of an Isochronous URB when the transfer is stopped for+ * any reason. The fields of the current entry in the frame descriptor array+ * are set based on the transfer state and the input _halt_status. Completes+ * the Isochronous URB if all the URB frames have been completed.+ *+ * @return DWC_OTG_HC_XFER_COMPLETE if there are more frames remaining to be+ * transferred in the URB. Otherwise return DWC_OTG_HC_XFER_URB_COMPLETE.+ */+static dwc_otg_halt_status_e+update_isoc_urb_state(dwc_otg_hcd_t * hcd,+		      dwc_hc_t * hc,+		      dwc_otg_hc_regs_t * hc_regs,+		      dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)+{+	dwc_otg_hcd_urb_t *urb = qtd->urb;+	dwc_otg_halt_status_e ret_val = halt_status;+	struct dwc_otg_hcd_iso_packet_desc *frame_desc;++	frame_desc = &urb->iso_descs[qtd->isoc_frame_index];+	switch (halt_status) {+	case DWC_OTG_HC_XFER_COMPLETE:+		frame_desc->status = 0;+		frame_desc->actual_length =+		    get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);++		/* non DWORD-aligned buffer case handling. */+		if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {+			dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,+				   hc->qh->dw_align_buf, frame_desc->actual_length);+		}++		break;+	case DWC_OTG_HC_XFER_FRAME_OVERRUN:+		urb->error_count++;+		if (hc->ep_is_in) {+			frame_desc->status = -DWC_E_NO_STREAM_RES;+		} else {+			frame_desc->status = -DWC_E_COMMUNICATION;+		}+		frame_desc->actual_length = 0;+		break;+	case DWC_OTG_HC_XFER_BABBLE_ERR:+		urb->error_count++;+		frame_desc->status = -DWC_E_OVERFLOW;+		/* Don't need to update actual_length in this case. */+		break;+	case DWC_OTG_HC_XFER_XACT_ERR:+		urb->error_count++;+		frame_desc->status = -DWC_E_PROTOCOL;+		frame_desc->actual_length =+		    get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);++		/* non DWORD-aligned buffer case handling. */+		if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {+			dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,+				   hc->qh->dw_align_buf, frame_desc->actual_length);+		}+		/* Skip whole frame */+		if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) &&+		    hc->ep_is_in && hcd->core_if->dma_enable) {+			qtd->complete_split = 0;+			qtd->isoc_split_offset = 0;+		}++		break;+	default:+		DWC_ASSERT(1, "Unhandled _halt_status (%d)\n", halt_status);+		break;+	}+	if (++qtd->isoc_frame_index == urb->packet_count) {+		/*+		 * urb->status is not used for isoc transfers.+		 * The individual frame_desc statuses are used instead.+		 */+		hcd->fops->complete(hcd, urb->priv, urb, 0);+		ret_val = DWC_OTG_HC_XFER_URB_COMPLETE;+	} else {+		ret_val = DWC_OTG_HC_XFER_COMPLETE;+	}+	return ret_val;+}++/**+ * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic+ * QHs, removes the QH from the active non-periodic schedule. If any QTDs are+ * still linked to the QH, the QH is added to the end of the inactive+ * non-periodic schedule. For periodic QHs, removes the QH from the periodic+ * schedule if no more QTDs are linked to the QH.+ */+static void deactivate_qh(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, int free_qtd)+{+	int continue_split = 0;+	dwc_otg_qtd_t *qtd;++	DWC_DEBUGPL(DBG_HCDV, "  %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd);++	qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);++	if (qtd->complete_split) {+		continue_split = 1;+	} else if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||+		   qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END) {+		continue_split = 1;+	}++	if (free_qtd) {+		dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);+		continue_split = 0;+	}++	qh->channel = NULL;+	dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split);+}++/**+ * Releases a host channel for use by other transfers. Attempts to select and+ * queue more transactions since at least one host channel is available.+ *+ * @param hcd The HCD state structure.+ * @param hc The host channel to release.+ * @param qtd The QTD associated with the host channel. This QTD may be freed+ * if the transfer is complete or an error has occurred.+ * @param halt_status Reason the channel is being released. This status+ * determines the actions taken by this function.+ */+static void release_channel(dwc_otg_hcd_t * hcd,+			    dwc_hc_t * hc,+			    dwc_otg_qtd_t * qtd,+			    dwc_otg_halt_status_e halt_status)+{+	dwc_otg_transaction_type_e tr_type;+	int free_qtd;+	dwc_irqflags_t flags;+	dwc_spinlock_t *channel_lock = hcd->channel_lock;+#ifdef FIQ_DEBUG+	int endp = qtd->urb ? qtd->urb->pipe_info.ep_num : 0;+#endif+	int hog_port = 0;++	DWC_DEBUGPL(DBG_HCDV, "  %s: channel %d, halt_status %d, xfer_len %d\n",+		    __func__, hc->hc_num, halt_status, hc->xfer_len);++	if(fiq_split_enable && hc->do_split) {+		if(!hc->ep_is_in && hc->ep_type == UE_ISOCHRONOUS) {+			if(hc->xact_pos == DWC_HCSPLIT_XACTPOS_MID ||+					hc->xact_pos == DWC_HCSPLIT_XACTPOS_BEGIN) {+				hog_port = 1;+			}+		}+	}++	switch (halt_status) {+	case DWC_OTG_HC_XFER_URB_COMPLETE:+		free_qtd = 1;+		break;+	case DWC_OTG_HC_XFER_AHB_ERR:+	case DWC_OTG_HC_XFER_STALL:+	case DWC_OTG_HC_XFER_BABBLE_ERR:+		free_qtd = 1;+		break;+	case DWC_OTG_HC_XFER_XACT_ERR:+		if (qtd->error_count >= 3) {+			DWC_DEBUGPL(DBG_HCDV,+				    "  Complete URB with transaction error\n");+			free_qtd = 1;+			qtd->urb->status = -DWC_E_PROTOCOL;+			hcd->fops->complete(hcd, qtd->urb->priv,+					    qtd->urb, -DWC_E_PROTOCOL);+		} else {+			free_qtd = 0;+		}+		break;+	case DWC_OTG_HC_XFER_URB_DEQUEUE:+		/*+		 * The QTD has already been removed and the QH has been+		 * deactivated. Don't want to do anything except release the+		 * host channel and try to queue more transfers.+		 */+		goto cleanup;+	case DWC_OTG_HC_XFER_NO_HALT_STATUS:+		free_qtd = 0;+		break;+	case DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE:+		DWC_DEBUGPL(DBG_HCDV,+			"  Complete URB with I/O error\n");+		free_qtd = 1;+		qtd->urb->status = -DWC_E_IO;+		hcd->fops->complete(hcd, qtd->urb->priv,+			qtd->urb, -DWC_E_IO);+		break;+	default:+		free_qtd = 0;+		break;+	}++	deactivate_qh(hcd, hc->qh, free_qtd);++cleanup:+	/*+	 * Release the host channel for use by other transfers. The cleanup+	 * function clears the channel interrupt enables and conditions, so+	 * there's no need to clear the Channel Halted interrupt separately.+	 */+	dwc_otg_hc_cleanup(hcd->core_if, hc);+	DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);++	if (!microframe_schedule) {+		switch (hc->ep_type) {+		case DWC_OTG_EP_TYPE_CONTROL:+		case DWC_OTG_EP_TYPE_BULK:+			hcd->non_periodic_channels--;+			break;++		default:+			/*+			 * Don't release reservations for periodic channels here.+			 * That's done when a periodic transfer is descheduled (i.e.+			 * when the QH is removed from the periodic schedule).+			 */+			break;+		}+	} else {++		DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);+		hcd->available_host_channels++;+		fiq_print(FIQDBG_PORTHUB, "AHC = %d ", hcd->available_host_channels);+		DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);+	}++	if(fiq_split_enable && hc->do_split)+	{+		if(!(hcd->hub_port[hc->hub_addr] & (1 << hc->port_addr)))+		{+			fiq_print(FIQDBG_ERR, "PRTNOTAL");+			//BUG();+		}+		if(!hog_port && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC ||+				hc->ep_type == DWC_OTG_EP_TYPE_INTR)) {+			hcd->hub_port[hc->hub_addr] &= ~(1 << hc->port_addr);+#ifdef FIQ_DEBUG+			hcd->hub_port_alloc[hc->hub_addr * 16 + hc->port_addr] = -1;+#endif+			fiq_print(FIQDBG_PORTHUB, "H%dP%d:RR%d", hc->hub_addr, hc->port_addr, endp);+		}+	}++	/* Try to queue more transfers now that there's a free channel. */+	tr_type = dwc_otg_hcd_select_transactions(hcd);+	if (tr_type != DWC_OTG_TRANSACTION_NONE) {+		dwc_otg_hcd_queue_transactions(hcd, tr_type);+	}+}++/**+ * Halts a host channel. If the channel cannot be halted immediately because+ * the request queue is full, this function ensures that the FIFO empty+ * interrupt for the appropriate queue is enabled so that the halt request can+ * be queued when there is space in the request queue.+ *+ * This function may also be called in DMA mode. In that case, the channel is+ * simply released since the core always halts the channel automatically in+ * DMA mode.+ */+static void halt_channel(dwc_otg_hcd_t * hcd,+			 dwc_hc_t * hc,+			 dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)+{+	if (hcd->core_if->dma_enable) {+		release_channel(hcd, hc, qtd, halt_status);+		return;+	}++	/* Slave mode processing... */+	dwc_otg_hc_halt(hcd->core_if, hc, halt_status);++	if (hc->halt_on_queue) {+		gintmsk_data_t gintmsk = {.d32 = 0 };+		dwc_otg_core_global_regs_t *global_regs;+		global_regs = hcd->core_if->core_global_regs;++		if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||+		    hc->ep_type == DWC_OTG_EP_TYPE_BULK) {+			/*+			 * Make sure the Non-periodic Tx FIFO empty interrupt+			 * is enabled so that the non-periodic schedule will+			 * be processed.+			 */+			gintmsk.b.nptxfempty = 1;+			DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);+		} else {+			/*+			 * Move the QH from the periodic queued schedule to+			 * the periodic assigned schedule. This allows the+			 * halt to be queued when the periodic schedule is+			 * processed.+			 */+			DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,+					   &hc->qh->qh_list_entry);++			/*+			 * Make sure the Periodic Tx FIFO Empty interrupt is+			 * enabled so that the periodic schedule will be+			 * processed.+			 */+			gintmsk.b.ptxfempty = 1;+			DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);+		}+	}+}++/**+ * Performs common cleanup for non-periodic transfers after a Transfer+ * Complete interrupt. This function should be called after any endpoint type+ * specific handling is finished to release the host channel.+ */+static void complete_non_periodic_xfer(dwc_otg_hcd_t * hcd,+				       dwc_hc_t * hc,+				       dwc_otg_hc_regs_t * hc_regs,+				       dwc_otg_qtd_t * qtd,+				       dwc_otg_halt_status_e halt_status)+{+	hcint_data_t hcint;++	qtd->error_count = 0;++	hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);+	if (hcint.b.nyet) {+		/*+		 * Got a NYET on the last transaction of the transfer. This+		 * means that the endpoint should be in the PING state at the+		 * beginning of the next transfer.+		 */+		hc->qh->ping_state = 1;+		clear_hc_int(hc_regs, nyet);+	}++	/*+	 * Always halt and release the host channel to make it available for+	 * more transfers. There may still be more phases for a control+	 * transfer or more data packets for a bulk transfer at this point,+	 * but the host channel is still halted. A channel will be reassigned+	 * to the transfer when the non-periodic schedule is processed after+	 * the channel is released. This allows transactions to be queued+	 * properly via dwc_otg_hcd_queue_transactions, which also enables the+	 * Tx FIFO Empty interrupt if necessary.+	 */+	if (hc->ep_is_in) {+		/*+		 * IN transfers in Slave mode require an explicit disable to+		 * halt the channel. (In DMA mode, this call simply releases+		 * the channel.)+		 */+		halt_channel(hcd, hc, qtd, halt_status);+	} else {+		/*+		 * The channel is automatically disabled by the core for OUT+		 * transfers in Slave mode.+		 */+		release_channel(hcd, hc, qtd, halt_status);+	}+}++/**+ * Performs common cleanup for periodic transfers after a Transfer Complete+ * interrupt. This function should be called after any endpoint type specific+ * handling is finished to release the host channel.+ */+static void complete_periodic_xfer(dwc_otg_hcd_t * hcd,+				   dwc_hc_t * hc,+				   dwc_otg_hc_regs_t * hc_regs,+				   dwc_otg_qtd_t * qtd,+				   dwc_otg_halt_status_e halt_status)+{+	hctsiz_data_t hctsiz;+	qtd->error_count = 0;++	hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);+	if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) {+		/* Core halts channel in these cases. */+		release_channel(hcd, hc, qtd, halt_status);+	} else {+		/* Flush any outstanding requests from the Tx queue. */+		halt_channel(hcd, hc, qtd, halt_status);+	}+}++static int32_t handle_xfercomp_isoc_split_in(dwc_otg_hcd_t * hcd,+					     dwc_hc_t * hc,+					     dwc_otg_hc_regs_t * hc_regs,+					     dwc_otg_qtd_t * qtd)+{+	uint32_t len;+	struct dwc_otg_hcd_iso_packet_desc *frame_desc;+	frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];++	len = get_actual_xfer_length(hc, hc_regs, qtd,+				     DWC_OTG_HC_XFER_COMPLETE, NULL);++	if (!len) {+		qtd->complete_split = 0;+		qtd->isoc_split_offset = 0;+		return 0;+	}+	frame_desc->actual_length += len;++	if (hc->align_buff && len)+		dwc_memcpy(qtd->urb->buf + frame_desc->offset ++			   qtd->isoc_split_offset, hc->qh->dw_align_buf, len);+	qtd->isoc_split_offset += len;++	if (frame_desc->length == frame_desc->actual_length) {+		frame_desc->status = 0;+		qtd->isoc_frame_index++;+		qtd->complete_split = 0;+		qtd->isoc_split_offset = 0;+	}++	if (qtd->isoc_frame_index == qtd->urb->packet_count) {+		hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);+		release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);+	} else {+		release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);+	}++	return 1;		/* Indicates that channel released */+}++/**+ * Handles a host channel Transfer Complete interrupt. This handler may be+ * called in either DMA mode or Slave mode.+ */+static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t * hcd,+				       dwc_hc_t * hc,+				       dwc_otg_hc_regs_t * hc_regs,+				       dwc_otg_qtd_t * qtd)+{+	int urb_xfer_done;+	dwc_otg_halt_status_e halt_status = DWC_OTG_HC_XFER_COMPLETE;+	dwc_otg_hcd_urb_t *urb = qtd->urb;+	int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);++	DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "+		    "Transfer Complete--\n", hc->hc_num);++	if (hcd->core_if->dma_desc_enable) {+		dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, halt_status);+		if (pipe_type == UE_ISOCHRONOUS) {+			/* Do not disable the interrupt, just clear it */+			clear_hc_int(hc_regs, xfercomp);+			return 1;+		}+		goto handle_xfercomp_done;+	}++	/*+	 * Handle xfer complete on CSPLIT.+	 */++	if (hc->qh->do_split) {+		if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in+		    && hcd->core_if->dma_enable) {+			if (qtd->complete_split+			    && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs,+							     qtd))+				goto handle_xfercomp_done;+		} else {+			qtd->complete_split = 0;+		}+	}++	/* Update the QTD and URB states. */+	switch (pipe_type) {+	case UE_CONTROL:+		switch (qtd->control_phase) {+		case DWC_OTG_CONTROL_SETUP:+			if (urb->length > 0) {+				qtd->control_phase = DWC_OTG_CONTROL_DATA;+			} else {+				qtd->control_phase = DWC_OTG_CONTROL_STATUS;+			}+			DWC_DEBUGPL(DBG_HCDV,+				    "  Control setup transaction done\n");+			halt_status = DWC_OTG_HC_XFER_COMPLETE;+			break;+		case DWC_OTG_CONTROL_DATA:{+				urb_xfer_done =+				    update_urb_state_xfer_comp(hc, hc_regs, urb,+							       qtd);+				if (urb_xfer_done) {+					qtd->control_phase =+					    DWC_OTG_CONTROL_STATUS;+					DWC_DEBUGPL(DBG_HCDV,+						    "  Control data transfer done\n");+				} else {+					dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);+				}+				halt_status = DWC_OTG_HC_XFER_COMPLETE;+				break;+			}+		case DWC_OTG_CONTROL_STATUS:+			DWC_DEBUGPL(DBG_HCDV, "  Control transfer complete\n");+			if (urb->status == -DWC_E_IN_PROGRESS) {+				urb->status = 0;+			}+			hcd->fops->complete(hcd, urb->priv, urb, urb->status);+			halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;+			break;+		}++		complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);+		break;+	case UE_BULK:+		DWC_DEBUGPL(DBG_HCDV, "  Bulk transfer complete\n");+		urb_xfer_done =+		    update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);+		if (urb_xfer_done) {+			hcd->fops->complete(hcd, urb->priv, urb, urb->status);+			halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;+		} else {+			halt_status = DWC_OTG_HC_XFER_COMPLETE;+		}++		dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);+		complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);+		break;+	case UE_INTERRUPT:+		DWC_DEBUGPL(DBG_HCDV, "  Interrupt transfer complete\n");+		urb_xfer_done =+			update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);++		/*+		 * Interrupt URB is done on the first transfer complete+		 * interrupt.+		 */+		if (urb_xfer_done) {+				hcd->fops->complete(hcd, urb->priv, urb, urb->status);+				halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;+		} else {+				halt_status = DWC_OTG_HC_XFER_COMPLETE;+		}++		dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);+		complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);+		break;+	case UE_ISOCHRONOUS:+		DWC_DEBUGPL(DBG_HCDV, "  Isochronous transfer complete\n");+		if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) {+			halt_status =+			    update_isoc_urb_state(hcd, hc, hc_regs, qtd,+						  DWC_OTG_HC_XFER_COMPLETE);+		}+		complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);+		break;+	}++handle_xfercomp_done:+	disable_hc_int(hc_regs, xfercompl);++	return 1;+}++/**+ * Handles a host channel STALL interrupt. This handler may be called in+ * either DMA mode or Slave mode.+ */+static int32_t handle_hc_stall_intr(dwc_otg_hcd_t * hcd,+				    dwc_hc_t * hc,+				    dwc_otg_hc_regs_t * hc_regs,+				    dwc_otg_qtd_t * qtd)+{+	dwc_otg_hcd_urb_t *urb = qtd->urb;+	int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);++	DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "+		    "STALL Received--\n", hc->hc_num);++	if (hcd->core_if->dma_desc_enable) {+		dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_STALL);+		goto handle_stall_done;+	}++	if (pipe_type == UE_CONTROL) {+		hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);+	}++	if (pipe_type == UE_BULK || pipe_type == UE_INTERRUPT) {+		hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);+		/*+		 * USB protocol requires resetting the data toggle for bulk+		 * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT)+		 * setup command is issued to the endpoint. Anticipate the+		 * CLEAR_FEATURE command since a STALL has occurred and reset+		 * the data toggle now.+		 */+		hc->qh->data_toggle = 0;+	}++	halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL);++handle_stall_done:+	disable_hc_int(hc_regs, stall);++	return 1;+}++/*+ * Updates the state of the URB when a transfer has been stopped due to an+ * abnormal condition before the transfer completes. Modifies the+ * actual_length field of the URB to reflect the number of bytes that have+ * actually been transferred via the host channel.+ */+static void update_urb_state_xfer_intr(dwc_hc_t * hc,+				       dwc_otg_hc_regs_t * hc_regs,+				       dwc_otg_hcd_urb_t * urb,+				       dwc_otg_qtd_t * qtd,+				       dwc_otg_halt_status_e halt_status)+{+	uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd,+							    halt_status, NULL);+	/* non DWORD-aligned buffer case handling. */+	if (hc->align_buff && bytes_transferred && hc->ep_is_in) {+		dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,+			   bytes_transferred);+	}++	urb->actual_length += bytes_transferred;++#ifdef DEBUG+	{+		hctsiz_data_t hctsiz;+		hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);+		DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",+			    __func__, (hc->ep_is_in ? "IN" : "OUT"),+			    hc->hc_num);+		DWC_DEBUGPL(DBG_HCDV, "  hc->start_pkt_count %d\n",+			    hc->start_pkt_count);+		DWC_DEBUGPL(DBG_HCDV, "  hctsiz.pktcnt %d\n", hctsiz.b.pktcnt);+		DWC_DEBUGPL(DBG_HCDV, "  hc->max_packet %d\n", hc->max_packet);+		DWC_DEBUGPL(DBG_HCDV, "  bytes_transferred %d\n",+			    bytes_transferred);+		DWC_DEBUGPL(DBG_HCDV, "  urb->actual_length %d\n",+			    urb->actual_length);+		DWC_DEBUGPL(DBG_HCDV, "  urb->transfer_buffer_length %d\n",+			    urb->length);+	}+#endif+}++/**+ * Handles a host channel NAK interrupt. This handler may be called in either+ * DMA mode or Slave mode.+ */+static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd,+				  dwc_hc_t * hc,+				  dwc_otg_hc_regs_t * hc_regs,+				  dwc_otg_qtd_t * qtd)+{+	DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "+		    "NAK Received--\n", hc->hc_num);++	/*+	 * When we get bulk NAKs then remember this so we holdoff on this qh until+	 * the beginning of the next frame+	 */+	switch(dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {+		case UE_BULK:+		case UE_CONTROL:+		if (nak_holdoff_enable)+			hc->qh->nak_frame = dwc_otg_hcd_get_frame_number(hcd);+	}++	/*+	 * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and+	 * interrupt.  Re-start the SSPLIT transfer.+	 */+	if (hc->do_split) {+		if (hc->complete_split) {+			qtd->error_count = 0;+		}+		qtd->complete_split = 0;+		halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);+		goto handle_nak_done;+	}++	switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {+	case UE_CONTROL:+	case UE_BULK:+		if (hcd->core_if->dma_enable && hc->ep_is_in) {+			/*+			 * NAK interrupts are enabled on bulk/control IN+			 * transfers in DMA mode for the sole purpose of+			 * resetting the error count after a transaction error+			 * occurs. The core will continue transferring data.+			 * Disable other interrupts unmasked for the same+			 * reason.+			 */+			disable_hc_int(hc_regs, datatglerr);+			disable_hc_int(hc_regs, ack);+			qtd->error_count = 0;+			goto handle_nak_done;+		}++		/*+		 * NAK interrupts normally occur during OUT transfers in DMA+		 * or Slave mode. For IN transfers, more requests will be+		 * queued as request queue space is available.+		 */+		qtd->error_count = 0;++		if (!hc->qh->ping_state) {+			update_urb_state_xfer_intr(hc, hc_regs,+						   qtd->urb, qtd,+						   DWC_OTG_HC_XFER_NAK);+			dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);++			if (hc->speed == DWC_OTG_EP_SPEED_HIGH)+				hc->qh->ping_state = 1;+		}++		/*+		 * Halt the channel so the transfer can be re-started from+		 * the appropriate point or the PING protocol will+		 * start/continue.+		 */+		halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);+		break;+	case UE_INTERRUPT:+		qtd->error_count = 0;+		halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);+		break;+	case UE_ISOCHRONOUS:+		/* Should never get called for isochronous transfers. */+		DWC_ASSERT(1, "NACK interrupt for ISOC transfer\n");+		break;+	}++handle_nak_done:+	disable_hc_int(hc_regs, nak);++	return 1;+}++/**+ * Handles a host channel ACK interrupt. This interrupt is enabled when+ * performing the PING protocol in Slave mode, when errors occur during+ * either Slave mode or DMA mode, and during Start Split transactions.+ */+static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd,+				  dwc_hc_t * hc,+				  dwc_otg_hc_regs_t * hc_regs,+				  dwc_otg_qtd_t * qtd)+{+	DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "+		    "ACK Received--\n", hc->hc_num);++	if (hc->do_split) {+		/*+		 * Handle ACK on SSPLIT.+		 * ACK should not occur in CSPLIT.+		 */+		if (!hc->ep_is_in && hc->data_pid_start != DWC_OTG_HC_PID_SETUP) {+			qtd->ssplit_out_xfer_count = hc->xfer_len;+		}+		if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) {+			/* Don't need complete for isochronous out transfers. */+			qtd->complete_split = 1;+		}++		/* ISOC OUT */+		if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {+			switch (hc->xact_pos) {+			case DWC_HCSPLIT_XACTPOS_ALL:+				break;+			case DWC_HCSPLIT_XACTPOS_END:+				qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;+				qtd->isoc_split_offset = 0;+				break;+			case DWC_HCSPLIT_XACTPOS_BEGIN:+			case DWC_HCSPLIT_XACTPOS_MID:+				/*+				 * For BEGIN or MID, calculate the length for+				 * the next microframe to determine the correct+				 * SSPLIT token, either MID or END.+				 */+				{+					struct dwc_otg_hcd_iso_packet_desc+					*frame_desc;++					frame_desc =+					    &qtd->urb->+					    iso_descs[qtd->isoc_frame_index];+					qtd->isoc_split_offset += 188;++					if ((frame_desc->length -+					     qtd->isoc_split_offset) <= 188) {+						qtd->isoc_split_pos =+						    DWC_HCSPLIT_XACTPOS_END;+					} else {+						qtd->isoc_split_pos =+						    DWC_HCSPLIT_XACTPOS_MID;+					}++				}+				break;+			}+		} else {+			halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);+		}+	} else {+		/*+		 * An unmasked ACK on a non-split DMA transaction is+		 * for the sole purpose of resetting error counts. Disable other+		 * interrupts unmasked for the same reason.+		 */+		if(hcd->core_if->dma_enable) {+			disable_hc_int(hc_regs, datatglerr);+			disable_hc_int(hc_regs, nak);+		}+		qtd->error_count = 0;++		if (hc->qh->ping_state) {+			hc->qh->ping_state = 0;+			/*+			 * Halt the channel so the transfer can be re-started+			 * from the appropriate point. This only happens in+			 * Slave mode. In DMA mode, the ping_state is cleared+			 * when the transfer is started because the core+			 * automatically executes the PING, then the transfer.+			 */+			halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);+		}+	}++	/*+	 * If the ACK occurred when _not_ in the PING state, let the channel+	 * continue transferring data after clearing the error count.+	 */++	disable_hc_int(hc_regs, ack);++	return 1;+}++/**+ * Handles a host channel NYET interrupt. This interrupt should only occur on+ * Bulk and Control OUT endpoints and for complete split transactions. If a+ * NYET occurs at the same time as a Transfer Complete interrupt, it is+ * handled in the xfercomp interrupt handler, not here. This handler may be+ * called in either DMA mode or Slave mode.+ */+static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd,+				   dwc_hc_t * hc,+				   dwc_otg_hc_regs_t * hc_regs,+				   dwc_otg_qtd_t * qtd)+{+	DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "+		    "NYET Received--\n", hc->hc_num);++	/*+	 * NYET on CSPLIT+	 * re-do the CSPLIT immediately on non-periodic+	 */+	if (hc->do_split && hc->complete_split) {+		if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)+		    && hcd->core_if->dma_enable) {+			qtd->complete_split = 0;+			qtd->isoc_split_offset = 0;+			if (++qtd->isoc_frame_index == qtd->urb->packet_count) {+				hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);+				release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);+			}+			else+				release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);+			goto handle_nyet_done;+		}++		if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||+		    hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {+			int frnum = dwc_otg_hcd_get_frame_number(hcd);++			// With the FIQ running we only ever see the failed NYET+			if (dwc_full_frame_num(frnum) !=+			    dwc_full_frame_num(hc->qh->sched_frame) ||+			    fiq_split_enable) {+				/*+				 * No longer in the same full speed frame.+				 * Treat this as a transaction error.+				 */+#if 0+				/** @todo Fix system performance so this can+				 * be treated as an error. Right now complete+				 * splits cannot be scheduled precisely enough+				 * due to other system activity, so this error+				 * occurs regularly in Slave mode.+				 */+				qtd->error_count++;+#endif+				qtd->complete_split = 0;+				halt_channel(hcd, hc, qtd,+					     DWC_OTG_HC_XFER_XACT_ERR);+				/** @todo add support for isoc release */+				goto handle_nyet_done;+			}+		}++		halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);+		goto handle_nyet_done;+	}++	hc->qh->ping_state = 1;+	qtd->error_count = 0;++	update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd,+				   DWC_OTG_HC_XFER_NYET);+	dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);++	/*+	 * Halt the channel and re-start the transfer so the PING+	 * protocol will start.+	 */+	halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);++handle_nyet_done:+	disable_hc_int(hc_regs, nyet);+	return 1;+}++/**+ * Handles a host channel babble interrupt. This handler may be called in+ * either DMA mode or Slave mode.+ */+static int32_t handle_hc_babble_intr(dwc_otg_hcd_t * hcd,+				     dwc_hc_t * hc,+				     dwc_otg_hc_regs_t * hc_regs,+				     dwc_otg_qtd_t * qtd)+{+	DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "+		    "Babble Error--\n", hc->hc_num);++	if (hcd->core_if->dma_desc_enable) {+		dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,+					       DWC_OTG_HC_XFER_BABBLE_ERR);+		goto handle_babble_done;+	}++	if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {+		hcd->fops->complete(hcd, qtd->urb->priv,+				    qtd->urb, -DWC_E_OVERFLOW);+		halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR);+	} else {+		dwc_otg_halt_status_e halt_status;+		halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd,+						    DWC_OTG_HC_XFER_BABBLE_ERR);+		halt_channel(hcd, hc, qtd, halt_status);+	}++handle_babble_done:+	disable_hc_int(hc_regs, bblerr);+	return 1;+}++/**+ * Handles a host channel AHB error interrupt. This handler is only called in+ * DMA mode.+ */+static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t * hcd,+				     dwc_hc_t * hc,+				     dwc_otg_hc_regs_t * hc_regs,+				     dwc_otg_qtd_t * qtd)+{+	hcchar_data_t hcchar;+	hcsplt_data_t hcsplt;+	hctsiz_data_t hctsiz;+	uint32_t hcdma;+	char *pipetype, *speed;++	dwc_otg_hcd_urb_t *urb = qtd->urb;++	DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "+		    "AHB Error--\n", hc->hc_num);++	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+	hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);+	hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);+	hcdma = DWC_READ_REG32(&hc_regs->hcdma);++	DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num);+	DWC_ERROR("  hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32);+	DWC_ERROR("  hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma);+	DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n");+	DWC_ERROR("  Device address: %d\n",+		  dwc_otg_hcd_get_dev_addr(&urb->pipe_info));+	DWC_ERROR("  Endpoint: %d, %s\n",+		  dwc_otg_hcd_get_ep_num(&urb->pipe_info),+		  (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT"));++	switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {+	case UE_CONTROL:+		pipetype = "CONTROL";+		break;+	case UE_BULK:+		pipetype = "BULK";+		break;+	case UE_INTERRUPT:+		pipetype = "INTERRUPT";+		break;+	case UE_ISOCHRONOUS:+		pipetype = "ISOCHRONOUS";+		break;+	default:+		pipetype = "UNKNOWN";+		break;+	}++	DWC_ERROR("  Endpoint type: %s\n", pipetype);++	switch (hc->speed) {+	case DWC_OTG_EP_SPEED_HIGH:+		speed = "HIGH";+		break;+	case DWC_OTG_EP_SPEED_FULL:+		speed = "FULL";+		break;+	case DWC_OTG_EP_SPEED_LOW:+		speed = "LOW";+		break;+	default:+		speed = "UNKNOWN";+		break;+	};++	DWC_ERROR("  Speed: %s\n", speed);++	DWC_ERROR("  Max packet size: %d\n",+		  dwc_otg_hcd_get_mps(&urb->pipe_info));+	DWC_ERROR("  Data buffer length: %d\n", urb->length);+	DWC_ERROR("  Transfer buffer: %p, Transfer DMA: %p\n",+		  urb->buf, (void *)urb->dma);+	DWC_ERROR("  Setup buffer: %p, Setup DMA: %p\n",+		  urb->setup_packet, (void *)urb->setup_dma);+	DWC_ERROR("  Interval: %d\n", urb->interval);++	/* Core haltes the channel for Descriptor DMA mode */+	if (hcd->core_if->dma_desc_enable) {+		dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,+					       DWC_OTG_HC_XFER_AHB_ERR);+		goto handle_ahberr_done;+	}++	hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_IO);++	/*+	 * Force a channel halt. Don't call halt_channel because that won't+	 * write to the HCCHARn register in DMA mode to force the halt.+	 */+	dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR);+handle_ahberr_done:+	disable_hc_int(hc_regs, ahberr);+	return 1;+}++/**+ * Handles a host channel transaction error interrupt. This handler may be+ * called in either DMA mode or Slave mode.+ */+static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t * hcd,+				      dwc_hc_t * hc,+				      dwc_otg_hc_regs_t * hc_regs,+				      dwc_otg_qtd_t * qtd)+{+	DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "+		    "Transaction Error--\n", hc->hc_num);++	if (hcd->core_if->dma_desc_enable) {+		dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,+					       DWC_OTG_HC_XFER_XACT_ERR);+		goto handle_xacterr_done;+	}++	switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {+	case UE_CONTROL:+	case UE_BULK:+		qtd->error_count++;+		if (!hc->qh->ping_state) {++			update_urb_state_xfer_intr(hc, hc_regs,+						   qtd->urb, qtd,+						   DWC_OTG_HC_XFER_XACT_ERR);+			dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);+			if (!hc->ep_is_in && hc->speed == DWC_OTG_EP_SPEED_HIGH) {+				hc->qh->ping_state = 1;+			}+		}++		/*+		 * Halt the channel so the transfer can be re-started from+		 * the appropriate point or the PING protocol will start.+		 */+		halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);+		break;+	case UE_INTERRUPT:+		qtd->error_count++;+		if (hc->do_split && hc->complete_split) {+			qtd->complete_split = 0;+		}+		halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);+		break;+	case UE_ISOCHRONOUS:+		{+			dwc_otg_halt_status_e halt_status;+			halt_status =+			    update_isoc_urb_state(hcd, hc, hc_regs, qtd,+						  DWC_OTG_HC_XFER_XACT_ERR);++			halt_channel(hcd, hc, qtd, halt_status);+		}+		break;+	}+handle_xacterr_done:+	disable_hc_int(hc_regs, xacterr);++	return 1;+}++/**+ * Handles a host channel frame overrun interrupt. This handler may be called+ * in either DMA mode or Slave mode.+ */+static int32_t handle_hc_frmovrun_intr(dwc_otg_hcd_t * hcd,+				       dwc_hc_t * hc,+				       dwc_otg_hc_regs_t * hc_regs,+				       dwc_otg_qtd_t * qtd)+{+	DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "+		    "Frame Overrun--\n", hc->hc_num);++	switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {+	case UE_CONTROL:+	case UE_BULK:+		break;+	case UE_INTERRUPT:+		halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN);+		break;+	case UE_ISOCHRONOUS:+		{+			dwc_otg_halt_status_e halt_status;+			halt_status =+			    update_isoc_urb_state(hcd, hc, hc_regs, qtd,+						  DWC_OTG_HC_XFER_FRAME_OVERRUN);++			halt_channel(hcd, hc, qtd, halt_status);+		}+		break;+	}++	disable_hc_int(hc_regs, frmovrun);++	return 1;+}++/**+ * Handles a host channel data toggle error interrupt. This handler may be+ * called in either DMA mode or Slave mode.+ */+static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t * hcd,+					 dwc_hc_t * hc,+					 dwc_otg_hc_regs_t * hc_regs,+					 dwc_otg_qtd_t * qtd)+{+	DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "+		"Data Toggle Error on %s transfer--\n",+		hc->hc_num, (hc->ep_is_in ? "IN" : "OUT"));++	/* Data toggles on split transactions cause the hc to halt.+	 * restart transfer */+	if(hc->qh->do_split)+	{+		qtd->error_count++;+		dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);+		update_urb_state_xfer_intr(hc, hc_regs,+			qtd->urb, qtd, DWC_OTG_HC_XFER_XACT_ERR);+		halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);+	} else if (hc->ep_is_in) {+		/* An unmasked data toggle error on a non-split DMA transaction is+		 * for the sole purpose of resetting error counts. Disable other+		 * interrupts unmasked for the same reason.+		 */+		if(hcd->core_if->dma_enable) {+			disable_hc_int(hc_regs, ack);+			disable_hc_int(hc_regs, nak);+		}+		qtd->error_count = 0;+	}++	disable_hc_int(hc_regs, datatglerr);++	return 1;+}++#ifdef DEBUG+/**+ * This function is for debug only. It checks that a valid halt status is set+ * and that HCCHARn.chdis is clear. If there's a problem, corrective action is+ * taken and a warning is issued.+ * @return 1 if halt status is ok, 0 otherwise.+ */+static inline int halt_status_ok(dwc_otg_hcd_t * hcd,+				 dwc_hc_t * hc,+				 dwc_otg_hc_regs_t * hc_regs,+				 dwc_otg_qtd_t * qtd)+{+	hcchar_data_t hcchar;+	hctsiz_data_t hctsiz;+	hcint_data_t hcint;+	hcintmsk_data_t hcintmsk;+	hcsplt_data_t hcsplt;++	if (hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) {+		/*+		 * This code is here only as a check. This condition should+		 * never happen. Ignore the halt if it does occur.+		 */+		hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+		hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);+		hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);+		hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);+		hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);+		DWC_WARN+		    ("%s: hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, "+		     "channel %d, hcchar 0x%08x, hctsiz 0x%08x, "+		     "hcint 0x%08x, hcintmsk 0x%08x, "+		     "hcsplt 0x%08x, qtd->complete_split %d\n", __func__,+		     hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32,+		     hcintmsk.d32, hcsplt.d32, qtd->complete_split);++		DWC_WARN("%s: no halt status, channel %d, ignoring interrupt\n",+			 __func__, hc->hc_num);+		DWC_WARN("\n");+		clear_hc_int(hc_regs, chhltd);+		return 0;+	}++	/*+	 * This code is here only as a check. hcchar.chdis should+	 * never be set when the halt interrupt occurs. Halt the+	 * channel again if it does occur.+	 */+	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);+	if (hcchar.b.chdis) {+		DWC_WARN("%s: hcchar.chdis set unexpectedly, "+			 "hcchar 0x%08x, trying to halt again\n",+			 __func__, hcchar.d32);+		clear_hc_int(hc_regs, chhltd);+		hc->halt_pending = 0;+		halt_channel(hcd, hc, qtd, hc->halt_status);+		return 0;+	}++	return 1;+}+#endif++/**+ * Handles a host Channel Halted interrupt in DMA mode. This handler+ * determines the reason the channel halted and proceeds accordingly.+ */+static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,+				      dwc_hc_t * hc,+				      dwc_otg_hc_regs_t * hc_regs,+				      dwc_otg_qtd_t * qtd,+				      hcint_data_t hcint,+				      hcintmsk_data_t hcintmsk)+{+	int out_nak_enh = 0;++	/* For core with OUT NAK enhancement, the flow for high-+	 * speed CONTROL/BULK OUT is handled a little differently.+	 */+	if (hcd->core_if->snpsid >= OTG_CORE_REV_2_71a) {+		if (hc->speed == DWC_OTG_EP_SPEED_HIGH && !hc->ep_is_in &&+		    (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||+		     hc->ep_type == DWC_OTG_EP_TYPE_BULK)) {+			out_nak_enh = 1;+		}+	}++	if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||+	    (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR+	     && !hcd->core_if->dma_desc_enable)) {+		/*+		 * Just release the channel. A dequeue can happen on a+		 * transfer timeout. In the case of an AHB Error, the channel+		 * was forced to halt because there's no way to gracefully+		 * recover.+		 */+		if (hcd->core_if->dma_desc_enable)+			dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,+						       hc->halt_status);+		else+			release_channel(hcd, hc, qtd, hc->halt_status);+		return;+	}++	/* Read the HCINTn register to determine the cause for the halt. */+	if(!fiq_split_enable)+	{+		hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);+		hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);+	}++	if (hcint.b.xfercomp) {+		/** @todo This is here because of a possible hardware bug.  Spec+		 * says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT+		 * interrupt w/ACK bit set should occur, but I only see the+		 * XFERCOMP bit, even with it masked out.  This is a workaround+		 * for that behavior.  Should fix this when hardware is fixed.+		 */+		if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {+			handle_hc_ack_intr(hcd, hc, hc_regs, qtd);+		}+		handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd);+	} else if (hcint.b.stall) {+		handle_hc_stall_intr(hcd, hc, hc_regs, qtd);+	} else if (hcint.b.xacterr && !hcd->core_if->dma_desc_enable) {+		if (out_nak_enh) {+			if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) {+				DWC_DEBUGPL(DBG_HCD, "XactErr with NYET/NAK/ACK\n");+				qtd->error_count = 0;+			} else {+				DWC_DEBUGPL(DBG_HCD, "XactErr without NYET/NAK/ACK\n");+			}+		}++		/*+		 * Must handle xacterr before nak or ack. Could get a xacterr+		 * at the same time as either of these on a BULK/CONTROL OUT+		 * that started with a PING. The xacterr takes precedence.+		 */+		handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);+	} else if (hcint.b.xcs_xact && hcd->core_if->dma_desc_enable) {+		handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);+	} else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) {+		handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd);+	} else if (hcint.b.bblerr) {+		handle_hc_babble_intr(hcd, hc, hc_regs, qtd);+	} else if (hcint.b.frmovrun) {+		handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd);+	} else if (hcint.b.datatglerr) {+		handle_hc_datatglerr_intr(hcd, hc, hc_regs, qtd);+	} else if (!out_nak_enh) {+		if (hcint.b.nyet) {+			/*+			 * Must handle nyet before nak or ack. Could get a nyet at the+			 * same time as either of those on a BULK/CONTROL OUT that+			 * started with a PING. The nyet takes precedence.+			 */+			handle_hc_nyet_intr(hcd, hc, hc_regs, qtd);+		} else if (hcint.b.nak && !hcintmsk.b.nak) {+			/*+			 * If nak is not masked, it's because a non-split IN transfer+			 * is in an error state. In that case, the nak is handled by+			 * the nak interrupt handler, not here. Handle nak here for+			 * BULK/CONTROL OUT transfers, which halt on a NAK to allow+			 * rewinding the buffer pointer.+			 */+			handle_hc_nak_intr(hcd, hc, hc_regs, qtd);+		} else if (hcint.b.ack && !hcintmsk.b.ack) {+			/*+			 * If ack is not masked, it's because a non-split IN transfer+			 * is in an error state. In that case, the ack is handled by+			 * the ack interrupt handler, not here. Handle ack here for+			 * split transfers. Start splits halt on ACK.+			 */+			handle_hc_ack_intr(hcd, hc, hc_regs, qtd);+		} else {+			if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||+			    hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {+				/*+				 * A periodic transfer halted with no other channel+				 * interrupts set. Assume it was halted by the core+				 * because it could not be completed in its scheduled+				 * (micro)frame.+				 */+#ifdef DEBUG+				DWC_PRINTF+				    ("%s: Halt channel %d (assume incomplete periodic transfer)\n",+				     __func__, hc->hc_num);+#endif+				halt_channel(hcd, hc, qtd,+					     DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE);+			} else {+				DWC_ERROR+				    ("%s: Channel %d, DMA Mode -- ChHltd set, but reason "+				     "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n",+				     __func__, hc->hc_num, hcint.d32,+				     DWC_READ_REG32(&hcd->+						    core_if->core_global_regs->+						    gintsts));+				/* Failthrough: use 3-strikes rule */+				qtd->error_count++;+				dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);+				update_urb_state_xfer_intr(hc, hc_regs,+					   qtd->urb, qtd, DWC_OTG_HC_XFER_XACT_ERR);+				halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);+			}++		}+	} else {+		DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n",+			   hcint.d32);+		/* Failthrough: use 3-strikes rule */+		qtd->error_count++;+		dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);+		update_urb_state_xfer_intr(hc, hc_regs,+			   qtd->urb, qtd, DWC_OTG_HC_XFER_XACT_ERR);+		halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);+	}+}++/**+ * Handles a host channel Channel Halted interrupt.+ *+ * In slave mode, this handler is called only when the driver specifically+ * requests a halt. This occurs during handling other host channel interrupts+ * (e.g. nak, xacterr, stall, nyet, etc.).+ *+ * In DMA mode, this is the interrupt that occurs when the core has finished+ * processing a transfer on a channel. Other host channel interrupts (except+ * ahberr) are disabled in DMA mode.+ */+static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd,+				     dwc_hc_t * hc,+				     dwc_otg_hc_regs_t * hc_regs,+				     dwc_otg_qtd_t * qtd,+				     hcint_data_t hcint,+				     hcintmsk_data_t hcintmsk)+{+	DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "+		    "Channel Halted--\n", hc->hc_num);++	if (hcd->core_if->dma_enable) {+		handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd, hcint, hcintmsk);+	} else {+#ifdef DEBUG+		if (!halt_status_ok(hcd, hc, hc_regs, qtd)) {+			return 1;+		}+#endif+		release_channel(hcd, hc, qtd, hc->halt_status);+	}++	return 1;+}++/** Handles interrupt for a specific Host Channel */+int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)+{+	int retval = 0;+	hcint_data_t hcint, hcint_orig;+	hcintmsk_data_t hcintmsk;+	dwc_hc_t *hc;+	dwc_otg_hc_regs_t *hc_regs;+	dwc_otg_qtd_t *qtd;++	DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", num);++	hc = dwc_otg_hcd->hc_ptr_array[num];+	hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num];+	if(hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {+		/* We are responding to a channel disable. Driver+		 * state is cleared - our qtd has gone away.+		 */+		release_channel(dwc_otg_hcd, hc, NULL, hc->halt_status);+		return 1;+	}+	qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);++	hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);+	hcint_orig = hcint;+	hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);+	DWC_DEBUGPL(DBG_HCDV,+		    "  hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",+		    hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32));+	hcint.d32 = hcint.d32 & hcintmsk.d32;++	if(fiq_split_enable)+	{+		// replace with the saved interrupts from the fiq handler+		local_fiq_disable();+		hcint_orig.d32 = hcint_saved[num].d32;+		hcint.d32 = hcint_orig.d32 & hcintmsk_saved[num].d32;+		hcint_saved[num].d32 = 0;+		local_fiq_enable();+	}++	if (!dwc_otg_hcd->core_if->dma_enable) {+		if (hcint.b.chhltd && hcint.d32 != 0x2) {+			hcint.b.chhltd = 0;+		}+	}++	if (hcint.b.xfercomp) {+		retval |=+		    handle_hc_xfercomp_intr(dwc_otg_hcd, hc, hc_regs, qtd);+		/*+		 * If NYET occurred at same time as Xfer Complete, the NYET is+		 * handled by the Xfer Complete interrupt handler. Don't want+		 * to call the NYET interrupt handler in this case.+		 */+		hcint.b.nyet = 0;+	}+	if (hcint.b.chhltd) {+		retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd, hcint_orig, hcintmsk_saved[num]);+	}+	if (hcint.b.ahberr) {+		retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd);+	}+	if (hcint.b.stall) {+		retval |= handle_hc_stall_intr(dwc_otg_hcd, hc, hc_regs, qtd);+	}+	if (hcint.b.nak) {+		retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd);+	}+	if (hcint.b.ack) {+		if(!hcint.b.chhltd)+			retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd);+	}+	if (hcint.b.nyet) {+		retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd);+	}+	if (hcint.b.xacterr) {+		retval |= handle_hc_xacterr_intr(dwc_otg_hcd, hc, hc_regs, qtd);+	}+	if (hcint.b.bblerr) {+		retval |= handle_hc_babble_intr(dwc_otg_hcd, hc, hc_regs, qtd);+	}+	if (hcint.b.frmovrun) {+		retval |=+		    handle_hc_frmovrun_intr(dwc_otg_hcd, hc, hc_regs, qtd);+	}+	if (hcint.b.datatglerr) {+		retval |=+		    handle_hc_datatglerr_intr(dwc_otg_hcd, hc, hc_regs, qtd);+	}++	return retval;+}+#endif /* DWC_DEVICE_ONLY */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,972 @@++/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $+ * $Revision: #20 $+ * $Date: 2011/10/26 $+ * $Change: 1872981 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */+#ifndef DWC_DEVICE_ONLY++/**+ * @file+ *+ * This file contains the implementation of the HCD. In Linux, the HCD+ * implements the hc_driver API.+ */+#include <linux/kernel.h>+#include <linux/module.h>+#include <linux/moduleparam.h>+#include <linux/init.h>+#include <linux/device.h>+#include <linux/errno.h>+#include <linux/list.h>+#include <linux/interrupt.h>+#include <linux/string.h>+#include <linux/dma-mapping.h>+#include <linux/version.h>+#include <asm/io.h>+#include <asm/fiq.h>+#include <linux/usb.h>+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)+#include <../drivers/usb/core/hcd.h>+#else+#include <linux/usb/hcd.h>+#endif++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))+#define USB_URB_EP_LINKING 1+#else+#define USB_URB_EP_LINKING 0+#endif++#include "dwc_otg_hcd_if.h"+#include "dwc_otg_dbg.h"+#include "dwc_otg_driver.h"+#include "dwc_otg_hcd.h"+#include "dwc_otg_mphi_fix.h"++/**+ * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is+ * qualified with its direction (possible 32 endpoints per device).+ */+#define dwc_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \+						     ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4)++static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";++extern bool fiq_fix_enable;++/** @name Linux HC Driver API Functions */+/** @{ */+/* manage i/o requests, device state */+static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)+		       struct usb_host_endpoint *ep,+#endif+		       struct urb *urb, gfp_t mem_flags);++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)+static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb);+#endif+#else /* kernels at or post 2.6.30 */+static int dwc_otg_urb_dequeue(struct usb_hcd *hcd,+                               struct urb *urb, int status);+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) */++static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep);+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)+static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep);+#endif+static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd);+extern int hcd_start(struct usb_hcd *hcd);+extern void hcd_stop(struct usb_hcd *hcd);+static int get_frame_number(struct usb_hcd *hcd);+extern int hub_status_data(struct usb_hcd *hcd, char *buf);+extern int hub_control(struct usb_hcd *hcd,+		       u16 typeReq,+		       u16 wValue, u16 wIndex, char *buf, u16 wLength);++struct wrapper_priv_data {+	dwc_otg_hcd_t *dwc_otg_hcd;+};++/** @} */++static struct hc_driver dwc_otg_hc_driver = {++	.description = dwc_otg_hcd_name,+	.product_desc = "DWC OTG Controller",+	.hcd_priv_size = sizeof(struct wrapper_priv_data),++	.irq = dwc_otg_hcd_irq,++	.flags = HCD_MEMORY | HCD_USB2,++	//.reset =+	.start = hcd_start,+	//.suspend =+	//.resume =+	.stop = hcd_stop,++	.urb_enqueue = dwc_otg_urb_enqueue,+	.urb_dequeue = dwc_otg_urb_dequeue,+	.endpoint_disable = endpoint_disable,+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)+	.endpoint_reset = endpoint_reset,+#endif+	.get_frame_number = get_frame_number,++	.hub_status_data = hub_status_data,+	.hub_control = hub_control,+	//.bus_suspend =+	//.bus_resume =+};++/** Gets the dwc_otg_hcd from a struct usb_hcd */+static inline dwc_otg_hcd_t *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd)+{+	struct wrapper_priv_data *p;+	p = (struct wrapper_priv_data *)(hcd->hcd_priv);+	return p->dwc_otg_hcd;+}++/** Gets the struct usb_hcd that contains a dwc_otg_hcd_t. */+static inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t * dwc_otg_hcd)+{+	return dwc_otg_hcd_get_priv_data(dwc_otg_hcd);+}++/** Gets the usb_host_endpoint associated with an URB. */+inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb)+{+	struct usb_device *dev = urb->dev;+	int ep_num = usb_pipeendpoint(urb->pipe);++	if (usb_pipein(urb->pipe))+		return dev->ep_in[ep_num];+	else+		return dev->ep_out[ep_num];+}++static int _disconnect(dwc_otg_hcd_t * hcd)+{+	struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);++	usb_hcd->self.is_b_host = 0;+	return 0;+}++static int _start(dwc_otg_hcd_t * hcd)+{+	struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);++	usb_hcd->self.is_b_host = dwc_otg_hcd_is_b_host(hcd);+	hcd_start(usb_hcd);++	return 0;+}++static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr,+		     uint32_t * port_addr)+{+   struct urb *urb = (struct urb *)urb_handle;+   struct usb_bus *bus;+#if 1 //GRAYG - temporary+   if (NULL == urb_handle)+      DWC_ERROR("**** %s - NULL URB handle\n", __func__);//GRAYG+   if (NULL == urb->dev)+      DWC_ERROR("**** %s - URB has no device\n", __func__);//GRAYG+   if (NULL == port_addr)+      DWC_ERROR("**** %s - NULL port_address\n", __func__);//GRAYG+#endif+   if (urb->dev->tt) {+        if (NULL == urb->dev->tt->hub) {+                DWC_ERROR("**** %s - (URB's transactor has no TT - giving no hub)\n",+                           __func__); //GRAYG+                //*hub_addr = (u8)usb_pipedevice(urb->pipe); //GRAYG+                *hub_addr = 0; //GRAYG+                // we probably shouldn't have a transaction translator if+                // there's no associated hub?+        } else {+		bus = hcd_to_bus(dwc_otg_hcd_to_hcd(hcd));+		if (urb->dev->tt->hub == bus->root_hub)+			*hub_addr = 0;+		else+			*hub_addr = urb->dev->tt->hub->devnum;+	}+	*port_addr = urb->dev->tt->multi ? urb->dev->ttport : 1;+   } else {+        *hub_addr = 0;+	*port_addr = urb->dev->ttport;+   }+   return 0;+}++static int _speed(dwc_otg_hcd_t * hcd, void *urb_handle)+{+	struct urb *urb = (struct urb *)urb_handle;+	return urb->dev->speed;+}++static int _get_b_hnp_enable(dwc_otg_hcd_t * hcd)+{+	struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);+	return usb_hcd->self.b_hnp_enable;+}++static void allocate_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,+				   struct urb *urb)+{+	hcd_to_bus(hcd)->bandwidth_allocated += bw / urb->interval;+	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {+		hcd_to_bus(hcd)->bandwidth_isoc_reqs++;+	} else {+		hcd_to_bus(hcd)->bandwidth_int_reqs++;+	}+}++static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,+			       struct urb *urb)+{+	hcd_to_bus(hcd)->bandwidth_allocated -= bw / urb->interval;+	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {+		hcd_to_bus(hcd)->bandwidth_isoc_reqs--;+	} else {+		hcd_to_bus(hcd)->bandwidth_int_reqs--;+	}+}++/**+ * Sets the final status of an URB and returns it to the device driver. Any+ * required cleanup of the URB is performed.  The HCD lock should be held on+ * entry.+ */+static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,+		     dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status)+{+	struct urb *urb = (struct urb *)urb_handle;+	urb_tq_entry_t *new_entry;+	int rc = 0;+	if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {+		DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n",+			   __func__, urb, usb_pipedevice(urb->pipe),+			   usb_pipeendpoint(urb->pipe),+			   usb_pipein(urb->pipe) ? "IN" : "OUT", status);+		if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {+			int i;+			for (i = 0; i < urb->number_of_packets; i++) {+				DWC_PRINTF("  ISO Desc %d status: %d\n",+					   i, urb->iso_frame_desc[i].status);+			}+		}+	}+	new_entry = DWC_ALLOC_ATOMIC(sizeof(urb_tq_entry_t));+	urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb);+	/* Convert status value. */+	switch (status) {+	case -DWC_E_PROTOCOL:+		status = -EPROTO;+		break;+	case -DWC_E_IN_PROGRESS:+		status = -EINPROGRESS;+		break;+	case -DWC_E_PIPE:+		status = -EPIPE;+		break;+	case -DWC_E_IO:+		status = -EIO;+		break;+	case -DWC_E_TIMEOUT:+		status = -ETIMEDOUT;+		break;+	case -DWC_E_OVERFLOW:+		status = -EOVERFLOW;+		break;+	case -DWC_E_SHUTDOWN:+		status = -ESHUTDOWN;+		break;+	default:+		if (status) {+			DWC_PRINTF("Uknown urb status %d\n", status);++		}+	}++	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {+		int i;++		urb->error_count = dwc_otg_hcd_urb_get_error_count(dwc_otg_urb);+		for (i = 0; i < urb->number_of_packets; ++i) {+			urb->iso_frame_desc[i].actual_length =+			    dwc_otg_hcd_urb_get_iso_desc_actual_length+			    (dwc_otg_urb, i);+			urb->iso_frame_desc[i].status =+			    dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_urb, i);+		}+	}++	urb->status = status;+	urb->hcpriv = NULL;+	if (!status) {+		if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&+		    (urb->actual_length < urb->transfer_buffer_length)) {+			urb->status = -EREMOTEIO;+		}+	}++	if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) ||+	    (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {+		struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb);+		if (ep) {+			free_bus_bandwidth(dwc_otg_hcd_to_hcd(hcd),+					   dwc_otg_hcd_get_ep_bandwidth(hcd,+									ep->hcpriv),+					   urb);+		}+	}++	DWC_FREE(dwc_otg_urb);+	if (!new_entry) {+		DWC_ERROR("dwc_otg_hcd: complete: cannot allocate URB TQ entry\n");+		urb->status = -EPROTO;+		/* don't schedule the tasklet -+		 * directly return the packet here with error. */+#if USB_URB_EP_LINKING+		usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);+#endif+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)+		usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);+#else+		usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, urb->status);+#endif+	} else {+		new_entry->urb = urb;+#if USB_URB_EP_LINKING+		rc = usb_hcd_check_unlink_urb(dwc_otg_hcd_to_hcd(hcd), urb, urb->status);+		if(0 == rc) {+			usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);+		}+#endif+		if(0 == rc) {+			DWC_TAILQ_INSERT_TAIL(&hcd->completed_urb_list, new_entry,+						urb_tq_entries);+			DWC_TASK_HI_SCHEDULE(hcd->completion_tasklet);+		}+	}+	return 0;+}++static struct dwc_otg_hcd_function_ops hcd_fops = {+	.start = _start,+	.disconnect = _disconnect,+	.hub_info = _hub_info,+	.speed = _speed,+	.complete = _complete,+	.get_b_hnp_enable = _get_b_hnp_enable,+};++static struct fiq_handler fh = {+  .name = "usb_fiq",+};+struct fiq_stack_s {+	int magic1;+	uint8_t stack[2048];+	int magic2;+} fiq_stack;++extern mphi_regs_t c_mphi_regs;+/**+ * Initializes the HCD. This function allocates memory for and initializes the+ * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the+ * USB bus with the core and calls the hc_driver->start() function. It returns+ * a negative error on failure.+ */+int hcd_init(dwc_bus_dev_t *_dev)+{+	struct usb_hcd *hcd = NULL;+	dwc_otg_hcd_t *dwc_otg_hcd = NULL;+	dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);+	int retval = 0;+        u64 dmamask;+	struct pt_regs regs;++	DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT otg_dev=%p\n", otg_dev);++	/* Set device flags indicating whether the HCD supports DMA. */+	if (dwc_otg_is_dma_enable(otg_dev->core_if))+                dmamask = DMA_BIT_MASK(32);+        else+                dmamask = 0;++#if    defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)+        dma_set_mask(&_dev->dev, dmamask);+        dma_set_coherent_mask(&_dev->dev, dmamask);+#elif  defined(PCI_INTERFACE)+        pci_set_dma_mask(_dev, dmamask);+        pci_set_consistent_dma_mask(_dev, dmamask);+#endif++	if (fiq_fix_enable)+	{+		// Set up fiq+		claim_fiq(&fh);+		set_fiq_handler(__FIQ_Branch, 4);+		memset(®s,0,sizeof(regs));+		regs.ARM_r8 = (long)dwc_otg_hcd_handle_fiq;+		regs.ARM_r9 = (long)0;+		regs.ARM_sp = (long)fiq_stack.stack + sizeof(fiq_stack.stack) - 4;+		set_fiq_regs(®s);+		fiq_stack.magic1 = 0xdeadbeef;+		fiq_stack.magic2 = 0xaa995566;+	}++	/*+	 * Allocate memory for the base HCD plus the DWC OTG HCD.+	 * Initialize the base HCD.+	 */+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)+	hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, _dev->dev.bus_id);+#else+	hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, dev_name(&_dev->dev));+	hcd->has_tt = 1;+//      hcd->uses_new_polling = 1;+//      hcd->poll_rh = 0;+#endif+	if (!hcd) {+		retval = -ENOMEM;+		goto error1;+	}++	hcd->regs = otg_dev->os_dep.base;++	if (fiq_fix_enable)+	{+		volatile extern void *dwc_regs_base;++		//Set the mphi periph to  the required registers+		c_mphi_regs.base    = otg_dev->os_dep.mphi_base;+		c_mphi_regs.ctrl    = otg_dev->os_dep.mphi_base + 0x4c;+		c_mphi_regs.outdda  = otg_dev->os_dep.mphi_base + 0x28;+		c_mphi_regs.outddb  = otg_dev->os_dep.mphi_base + 0x2c;+		c_mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;++		dwc_regs_base = otg_dev->os_dep.base;++		//Enable mphi peripheral+		writel((1<<31),c_mphi_regs.ctrl);+#ifdef DEBUG+		if (readl(c_mphi_regs.ctrl) & 0x80000000)+			DWC_DEBUGPL(DBG_USER, "MPHI periph has been enabled\n");+		else+			DWC_DEBUGPL(DBG_USER, "MPHI periph has NOT been enabled\n");+#endif+		// Enable FIQ interrupt from USB peripheral+		enable_fiq(INTERRUPT_VC_USB);+	}+	/* Initialize the DWC OTG HCD. */+	dwc_otg_hcd = dwc_otg_hcd_alloc_hcd();+	if (!dwc_otg_hcd) {+		goto error2;+	}+	((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd =+	    dwc_otg_hcd;+	otg_dev->hcd = dwc_otg_hcd;++	if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) {+		goto error2;+	}++	otg_dev->hcd->otg_dev = otg_dev;+	hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd);+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel)+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) //version field absent later+	hcd->self.otg_version = dwc_otg_get_otg_version(otg_dev->core_if);+#endif+	/* Don't support SG list at this point */+	hcd->self.sg_tablesize = 0;+#endif+	/*+	 * Finish generic HCD initialization and start the HCD. This function+	 * allocates the DMA buffer pool, registers the USB bus, requests the+	 * IRQ line, and calls hcd_start method.+	 */+#ifdef PLATFORM_INTERFACE+        retval = usb_add_hcd(hcd, platform_get_irq(_dev, 0), IRQF_SHARED | IRQF_DISABLED);+#else+        retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED | IRQF_DISABLED);+#endif+	if (retval < 0) {+		goto error2;+	}++	dwc_otg_hcd_set_priv_data(dwc_otg_hcd, hcd);+	return 0;++error2:+	usb_put_hcd(hcd);+error1:+	return retval;+}++/**+ * Removes the HCD.+ * Frees memory and resources associated with the HCD and deregisters the bus.+ */+void hcd_remove(dwc_bus_dev_t *_dev)+{+	dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);+	dwc_otg_hcd_t *dwc_otg_hcd;+	struct usb_hcd *hcd;++	DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD REMOVE otg_dev=%p\n", otg_dev);++	if (!otg_dev) {+		DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);+		return;+	}++	dwc_otg_hcd = otg_dev->hcd;++	if (!dwc_otg_hcd) {+		DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);+		return;+	}++	hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd);++	if (!hcd) {+		DWC_DEBUGPL(DBG_ANY,+			    "%s: dwc_otg_hcd_to_hcd(dwc_otg_hcd) NULL!\n",+			    __func__);+		return;+	}+	usb_remove_hcd(hcd);+	dwc_otg_hcd_set_priv_data(dwc_otg_hcd, NULL);+	dwc_otg_hcd_remove(dwc_otg_hcd);+	usb_put_hcd(hcd);+}++/* =========================================================================+ *  Linux HC Driver Functions+ * ========================================================================= */++/** Initializes the DWC_otg controller and its root hub and prepares it for host+ * mode operation. Activates the root port. Returns 0 on success and a negative+ * error code on failure. */+int hcd_start(struct usb_hcd *hcd)+{+	dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);+	struct usb_bus *bus;++	DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n");+	bus = hcd_to_bus(hcd);++	hcd->state = HC_STATE_RUNNING;+	if (dwc_otg_hcd_start(dwc_otg_hcd, &hcd_fops)) {+		return 0;+	}++	/* Initialize and connect root hub if one is not already attached */+	if (bus->root_hub) {+		DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Has Root Hub\n");+		/* Inform the HUB driver to resume. */+		usb_hcd_resume_root_hub(hcd);+	}++	return 0;+}++/**+ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are+ * stopped.+ */+void hcd_stop(struct usb_hcd *hcd)+{+	dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);++	dwc_otg_hcd_stop(dwc_otg_hcd);+}++/** Returns the current frame number. */+static int get_frame_number(struct usb_hcd *hcd)+{+	dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);++	return dwc_otg_hcd_get_frame_number(dwc_otg_hcd);+}++#ifdef DEBUG+static void dump_urb_info(struct urb *urb, char *fn_name)+{+	DWC_PRINTF("%s, urb %p\n", fn_name, urb);+	DWC_PRINTF("  Device address: %d\n", usb_pipedevice(urb->pipe));+	DWC_PRINTF("  Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe),+		   (usb_pipein(urb->pipe) ? "IN" : "OUT"));+	DWC_PRINTF("  Endpoint type: %s\n", ( {+					     char *pipetype;+					     switch (usb_pipetype(urb->pipe)) {+case PIPE_CONTROL:+pipetype = "CONTROL"; break; case PIPE_BULK:+pipetype = "BULK"; break; case PIPE_INTERRUPT:+pipetype = "INTERRUPT"; break; case PIPE_ISOCHRONOUS:+pipetype = "ISOCHRONOUS"; break; default:+					     pipetype = "UNKNOWN"; break;};+					     pipetype;}+		   )) ;+	DWC_PRINTF("  Speed: %s\n", ( {+				     char *speed; switch (urb->dev->speed) {+case USB_SPEED_HIGH:+speed = "HIGH"; break; case USB_SPEED_FULL:+speed = "FULL"; break; case USB_SPEED_LOW:+speed = "LOW"; break; default:+				     speed = "UNKNOWN"; break;};+				     speed;}+		   )) ;+	DWC_PRINTF("  Max packet size: %d\n",+		   usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)));+	DWC_PRINTF("  Data buffer length: %d\n", urb->transfer_buffer_length);+	DWC_PRINTF("  Transfer buffer: %p, Transfer DMA: %p\n",+		   urb->transfer_buffer, (void *)urb->transfer_dma);+	DWC_PRINTF("  Setup buffer: %p, Setup DMA: %p\n",+		   urb->setup_packet, (void *)urb->setup_dma);+	DWC_PRINTF("  Interval: %d\n", urb->interval);+	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {+		int i;+		for (i = 0; i < urb->number_of_packets; i++) {+			DWC_PRINTF("  ISO Desc %d:\n", i);+			DWC_PRINTF("    offset: %d, length %d\n",+				   urb->iso_frame_desc[i].offset,+				   urb->iso_frame_desc[i].length);+		}+	}+}+#endif++/** Starts processing a USB transfer request specified by a USB Request Block+ * (URB). mem_flags indicates the type of memory allocation to use while+ * processing this URB. */+static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)+		       struct usb_host_endpoint *ep,+#endif+		       struct urb *urb, gfp_t mem_flags)+{+	int retval = 0;+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)+	struct usb_host_endpoint *ep = urb->ep;+#endif+	dwc_irqflags_t irqflags;+        void **ref_ep_hcpriv = &ep->hcpriv;+	dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);+	dwc_otg_hcd_urb_t *dwc_otg_urb;+	int i;+	int alloc_bandwidth = 0;+	uint8_t ep_type = 0;+	uint32_t flags = 0;+	void *buf;++#ifdef DEBUG+	if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {+		dump_urb_info(urb, "dwc_otg_urb_enqueue");+	}+#endif++	if (!urb->transfer_buffer && urb->transfer_buffer_length)+		return -EINVAL;++	if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)+	    || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {+		if (!dwc_otg_hcd_is_bandwidth_allocated+		    (dwc_otg_hcd, ref_ep_hcpriv)) {+			alloc_bandwidth = 1;+		}+	}++	switch (usb_pipetype(urb->pipe)) {+	case PIPE_CONTROL:+		ep_type = USB_ENDPOINT_XFER_CONTROL;+		break;+	case PIPE_ISOCHRONOUS:+		ep_type = USB_ENDPOINT_XFER_ISOC;+		break;+	case PIPE_BULK:+		ep_type = USB_ENDPOINT_XFER_BULK;+		break;+	case PIPE_INTERRUPT:+		ep_type = USB_ENDPOINT_XFER_INT;+		break;+	default:+                DWC_WARN("Wrong EP type - %d\n", usb_pipetype(urb->pipe));+	}++        /* # of packets is often 0 - do we really need to call this then? */+	dwc_otg_urb = dwc_otg_hcd_urb_alloc(dwc_otg_hcd,+					    urb->number_of_packets,+					    mem_flags == GFP_ATOMIC ? 1 : 0);++	if(dwc_otg_urb == NULL)+		return -ENOMEM;++	if (!dwc_otg_urb && urb->number_of_packets)+		return -ENOMEM;++	dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe),+				     usb_pipeendpoint(urb->pipe), ep_type,+				     usb_pipein(urb->pipe),+				     usb_maxpacket(urb->dev, urb->pipe,+						   !(usb_pipein(urb->pipe))));++	buf = urb->transfer_buffer;+	if (hcd->self.uses_dma) {+		/*+		 * Calculate virtual address from physical address,+		 * because some class driver may not fill transfer_buffer.+		 * In Buffer DMA mode virual address is used,+		 * when handling non DWORD aligned buffers.+		 */+		//buf = phys_to_virt(urb->transfer_dma);+                // DMA addresses are bus addresses not physical addresses!+                buf = dma_to_virt(&urb->dev->dev, urb->transfer_dma);+	}++	if (!(urb->transfer_flags & URB_NO_INTERRUPT))+		flags |= URB_GIVEBACK_ASAP;+	if (urb->transfer_flags & URB_ZERO_PACKET)+		flags |= URB_SEND_ZERO_PACKET;++	dwc_otg_hcd_urb_set_params(dwc_otg_urb, urb, buf,+				   urb->transfer_dma,+				   urb->transfer_buffer_length,+				   urb->setup_packet,+				   urb->setup_dma, flags, urb->interval);++	for (i = 0; i < urb->number_of_packets; ++i) {+		dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_urb, i,+						    urb->+						    iso_frame_desc[i].offset,+						    urb->+						    iso_frame_desc[i].length);+	}++	DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);+	urb->hcpriv = dwc_otg_urb;+#if USB_URB_EP_LINKING+	retval = usb_hcd_link_urb_to_ep(hcd, urb);+	if (0 == retval)+#endif+	{+		retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb,+						/*(dwc_otg_qh_t **)*/+						ref_ep_hcpriv, 1);+		if (0 == retval) {+			if (alloc_bandwidth) {+				allocate_bus_bandwidth(hcd,+						dwc_otg_hcd_get_ep_bandwidth(+							dwc_otg_hcd, *ref_ep_hcpriv),+						urb);+			}+		} else {+			DWC_DEBUGPL(DBG_HCD, "DWC OTG dwc_otg_hcd_urb_enqueue failed rc %d\n", retval);+#if USB_URB_EP_LINKING+			usb_hcd_unlink_urb_from_ep(hcd, urb);+#endif+			DWC_FREE(dwc_otg_urb);+			urb->hcpriv = NULL;+			if (retval == -DWC_E_NO_DEVICE)+				retval = -ENODEV;+		}+	}+#if USB_URB_EP_LINKING+	else+	{+		DWC_FREE(dwc_otg_urb);+		urb->hcpriv = NULL;+	}+#endif+	DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);+	return retval;+}++/** Aborts/cancels a USB transfer request. Always returns 0 to indicate+ * success.  */+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)+static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)+#else+static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)+#endif+{+	dwc_irqflags_t flags;+	dwc_otg_hcd_t *dwc_otg_hcd;+        int rc;++	DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n");++	dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);++#ifdef DEBUG+	if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {+		dump_urb_info(urb, "dwc_otg_urb_dequeue");+	}+#endif++	DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);+	rc = usb_hcd_check_unlink_urb(hcd, urb, status);+	if (0 == rc) {+		if(urb->hcpriv != NULL) {+	                dwc_otg_hcd_urb_dequeue(dwc_otg_hcd,+	                                    (dwc_otg_hcd_urb_t *)urb->hcpriv);++		        DWC_FREE(urb->hcpriv);+			urb->hcpriv = NULL;+		}+        }++        if (0 == rc) {+		/* Higher layer software sets URB status. */+#if USB_URB_EP_LINKING+                usb_hcd_unlink_urb_from_ep(hcd, urb);+#endif+		DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);+++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)+                usb_hcd_giveback_urb(hcd, urb);+#else+                usb_hcd_giveback_urb(hcd, urb, status);+#endif+                if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {+                        DWC_PRINTF("Called usb_hcd_giveback_urb() \n");+                        DWC_PRINTF("  1urb->status = %d\n", urb->status);+                }+                DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue OK\n");+        } else {+		DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);+                DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue failed - rc %d\n",+                            rc);+        }++	return rc;+}++/* Frees resources in the DWC_otg controller related to a given endpoint. Also+ * clears state in the HCD related to the endpoint. Any URBs for the endpoint+ * must already be dequeued. */+static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)+{+	dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);++	DWC_DEBUGPL(DBG_HCD,+		    "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, "+		    "endpoint=%d\n", ep->desc.bEndpointAddress,+		    dwc_ep_addr_to_endpoint(ep->desc.bEndpointAddress));+	dwc_otg_hcd_endpoint_disable(dwc_otg_hcd, ep->hcpriv, 250);+	ep->hcpriv = NULL;+}++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)+/* Resets endpoint specific parameter values, in current version used to reset+ * the data toggle(as a WA). This function can be called from usb_clear_halt routine */+static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)+{+	dwc_irqflags_t flags;+	struct usb_device *udev = NULL;+	int epnum = usb_endpoint_num(&ep->desc);+	int is_out = usb_endpoint_dir_out(&ep->desc);+	int is_control = usb_endpoint_xfer_control(&ep->desc);+	dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);+        struct device *dev = DWC_OTG_OS_GETDEV(dwc_otg_hcd->otg_dev->os_dep);++	if (dev)+		udev = to_usb_device(dev);+	else+		return;++	DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD EP RESET: Endpoint Num=0x%02d\n", epnum);++	DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);+	usb_settoggle(udev, epnum, is_out, 0);+	if (is_control)+		usb_settoggle(udev, epnum, !is_out, 0);++	if (ep->hcpriv) {+		dwc_otg_hcd_endpoint_reset(dwc_otg_hcd, ep->hcpriv);+	}+	DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);+}+#endif++/** Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if+ * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid+ * interrupt.+ *+ * This function is called by the USB core when an interrupt occurs */+static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd)+{+	dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);+	int32_t retval = dwc_otg_hcd_handle_intr(dwc_otg_hcd);+	if (retval != 0) {+		S3C2410X_CLEAR_EINTPEND();+	}+	return IRQ_RETVAL(retval);+}++/** Creates Status Change bitmap for the root hub and root port. The bitmap is+ * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1+ * is the status change indicator for the single root port. Returns 1 if either+ * change indicator is 1, otherwise returns 0. */+int hub_status_data(struct usb_hcd *hcd, char *buf)+{+	dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);++	buf[0] = 0;+	buf[0] |= (dwc_otg_hcd_is_status_changed(dwc_otg_hcd, 1)) << 1;++	return (buf[0] != 0);+}++/** Handles hub class-specific requests. */+int hub_control(struct usb_hcd *hcd,+		u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength)+{+	int retval;++	retval = dwc_otg_hcd_hub_control(hcd_to_dwc_otg_hcd(hcd),+					 typeReq, wValue, wIndex, buf, wLength);++	switch (retval) {+	case -DWC_E_INVALID:+		retval = -EINVAL;+		break;+	}++	return retval;+}++#endif /* DWC_DEVICE_ONLY */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,959 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $+ * $Revision: #44 $+ * $Date: 2011/10/26 $+ * $Change: 1873028 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */+#ifndef DWC_DEVICE_ONLY++/**+ * @file+ *+ * This file contains the functions to manage Queue Heads and Queue+ * Transfer Descriptors.+ */++#include "dwc_otg_hcd.h"+#include "dwc_otg_regs.h"+#include "dwc_otg_mphi_fix.h"++extern bool microframe_schedule;++/**+ * Free each QTD in the QH's QTD-list then free the QH.  QH should already be+ * removed from a list.  QTD list should already be empty if called from URB+ * Dequeue.+ *+ * @param hcd HCD instance.+ * @param qh The QH to free.+ */+void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)+{+	dwc_otg_qtd_t *qtd, *qtd_tmp;++	/* Free each QTD in the QTD list */+	DWC_SPINLOCK(hcd->lock);+	DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {+		DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);+		dwc_otg_hcd_qtd_free(qtd);+	}++	if (hcd->core_if->dma_desc_enable) {+		dwc_otg_hcd_qh_free_ddma(hcd, qh);+	} else if (qh->dw_align_buf) {+		uint32_t buf_size;+		if (qh->ep_type == UE_ISOCHRONOUS) {+			buf_size = 4096;+		} else {+			buf_size = hcd->core_if->core_params->max_transfer_size;+		}+		DWC_DMA_FREE(buf_size, qh->dw_align_buf, qh->dw_align_buf_dma);+	}++	DWC_FREE(qh);+	DWC_SPINUNLOCK(hcd->lock);+	return;+}++#define BitStuffTime(bytecount)  ((8 * 7* bytecount) / 6)+#define HS_HOST_DELAY		5	/* nanoseconds */+#define FS_LS_HOST_DELAY	1000	/* nanoseconds */+#define HUB_LS_SETUP		333	/* nanoseconds */+#define NS_TO_US(ns)		((ns + 500) / 1000)+				/* convert & round nanoseconds to microseconds */++static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, int bytecount)+{+	unsigned long retval;++	switch (speed) {+	case USB_SPEED_HIGH:+		if (is_isoc) {+			retval =+			    ((38 * 8 * 2083) ++			     (2083 * (3 + BitStuffTime(bytecount)))) / 1000 ++			    HS_HOST_DELAY;+		} else {+			retval =+			    ((55 * 8 * 2083) ++			     (2083 * (3 + BitStuffTime(bytecount)))) / 1000 ++			    HS_HOST_DELAY;+		}+		break;+	case USB_SPEED_FULL:+		if (is_isoc) {+			retval =+			    (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000;+			if (is_in) {+				retval = 7268 + FS_LS_HOST_DELAY + retval;+			} else {+				retval = 6265 + FS_LS_HOST_DELAY + retval;+			}+		} else {+			retval =+			    (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000;+			retval = 9107 + FS_LS_HOST_DELAY + retval;+		}+		break;+	case USB_SPEED_LOW:+		if (is_in) {+			retval =+			    (67667 * (31 + 10 * BitStuffTime(bytecount))) /+			    1000;+			retval =+			    64060 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY ++			    retval;+		} else {+			retval =+			    (66700 * (31 + 10 * BitStuffTime(bytecount))) /+			    1000;+			retval =+			    64107 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY ++			    retval;+		}+		break;+	default:+		DWC_WARN("Unknown device speed\n");+		retval = -1;+	}++	return NS_TO_US(retval);+}++/**+ * Initializes a QH structure.+ *+ * @param hcd The HCD state structure for the DWC OTG controller.+ * @param qh  The QH to init.+ * @param urb Holds the information about the device/endpoint that we need+ * 	      to initialize the QH.+ */+#define SCHEDULE_SLOP 10+void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb)+{+	char *speed, *type;+	int dev_speed;+	uint32_t hub_addr, hub_port;++	dwc_memset(qh, 0, sizeof(dwc_otg_qh_t));++	/* Initialize QH */+	qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);+	qh->ep_is_in = dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0;++	qh->data_toggle = DWC_OTG_HC_PID_DATA0;+	qh->maxp = dwc_otg_hcd_get_mps(&urb->pipe_info);+	DWC_CIRCLEQ_INIT(&qh->qtd_list);+	DWC_LIST_INIT(&qh->qh_list_entry);+	qh->channel = NULL;++	/* FS/LS Enpoint on HS Hub+	 * NOT virtual root hub */+	dev_speed = hcd->fops->speed(hcd, urb->priv);++	hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &hub_port);+	qh->do_split = 0;+	if (microframe_schedule)+		qh->speed = dev_speed;++	qh->nak_frame = 0xffff;++	if (((dev_speed == USB_SPEED_LOW) ||+	     (dev_speed == USB_SPEED_FULL)) &&+	    (hub_addr != 0 && hub_addr != 1)) {+		DWC_DEBUGPL(DBG_HCD,+			    "QH init: EP %d: TT found at hub addr %d, for port %d\n",+			    dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr,+			    hub_port);+		qh->do_split = 1;+		qh->skip_count = 0;+	}++	if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) {+		/* Compute scheduling parameters once and save them. */+		hprt0_data_t hprt;++		/** @todo Account for split transfers in the bus time. */+		int bytecount =+		    dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp);++		qh->usecs =+		    calc_bus_time((qh->do_split ? USB_SPEED_HIGH : dev_speed),+				  qh->ep_is_in, (qh->ep_type == UE_ISOCHRONOUS),+				  bytecount);+		/* Start in a slightly future (micro)frame. */+		qh->sched_frame = dwc_frame_num_inc(hcd->frame_number,+						    SCHEDULE_SLOP);+		qh->interval = urb->interval;++#if 0+		/* Increase interrupt polling rate for debugging. */+		if (qh->ep_type == UE_INTERRUPT) {+			qh->interval = 8;+		}+#endif+		hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);+		if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) &&+		    ((dev_speed == USB_SPEED_LOW) ||+		     (dev_speed == USB_SPEED_FULL))) {+			qh->interval *= 8;+			qh->sched_frame |= 0x7;+			qh->start_split_frame = qh->sched_frame;+		}++	}++	DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n");+	DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - qh = %p\n", qh);+	DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Device Address = %d\n",+		    dwc_otg_hcd_get_dev_addr(&urb->pipe_info));+	DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Endpoint %d, %s\n",+		    dwc_otg_hcd_get_ep_num(&urb->pipe_info),+		    dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT");+	switch (dev_speed) {+	case USB_SPEED_LOW:+		qh->dev_speed = DWC_OTG_EP_SPEED_LOW;+		speed = "low";+		break;+	case USB_SPEED_FULL:+		qh->dev_speed = DWC_OTG_EP_SPEED_FULL;+		speed = "full";+		break;+	case USB_SPEED_HIGH:+		qh->dev_speed = DWC_OTG_EP_SPEED_HIGH;+		speed = "high";+		break;+	default:+		speed = "?";+		break;+	}+	DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Speed = %s\n", speed);++	switch (qh->ep_type) {+	case UE_ISOCHRONOUS:+		type = "isochronous";+		break;+	case UE_INTERRUPT:+		type = "interrupt";+		break;+	case UE_CONTROL:+		type = "control";+		break;+	case UE_BULK:+		type = "bulk";+		break;+	default:+		type = "?";+		break;+	}++	DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Type = %s\n", type);++#ifdef DEBUG+	if (qh->ep_type == UE_INTERRUPT) {+		DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n",+			    qh->usecs);+		DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n",+			    qh->interval);+	}+#endif++}++/**+ * This function allocates and initializes a QH.+ *+ * @param hcd The HCD state structure for the DWC OTG controller.+ * @param urb Holds the information about the device/endpoint that we need+ * 	      to initialize the QH.+ * @param atomic_alloc Flag to do atomic allocation if needed+ *+ * @return Returns pointer to the newly allocated QH, or NULL on error. */+dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,+				    dwc_otg_hcd_urb_t * urb, int atomic_alloc)+{+	dwc_otg_qh_t *qh;++	/* Allocate memory */+	/** @todo add memflags argument */+	qh = dwc_otg_hcd_qh_alloc(atomic_alloc);+	if (qh == NULL) {+		DWC_ERROR("qh allocation failed");+		return NULL;+	}++	qh_init(hcd, qh, urb);++	if (hcd->core_if->dma_desc_enable+	    && (dwc_otg_hcd_qh_init_ddma(hcd, qh) < 0)) {+		dwc_otg_hcd_qh_free(hcd, qh);+		return NULL;+	}++	return qh;+}++/* microframe_schedule=0 start */++/**+ * Checks that a channel is available for a periodic transfer.+ *+ * @return 0 if successful, negative error code otherise.+ */+static int periodic_channel_available(dwc_otg_hcd_t * hcd)+{+	/*+	 * Currently assuming that there is a dedicated host channnel for each+	 * periodic transaction plus at least one host channel for+	 * non-periodic transactions.+	 */+	int status;+	int num_channels;++	num_channels = hcd->core_if->core_params->host_channels;+	if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels)+	    && (hcd->periodic_channels < num_channels - 1)) {+		status = 0;+	} else {+		DWC_INFO("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n",+			__func__, num_channels, hcd->periodic_channels, hcd->non_periodic_channels);	//NOTICE+		status = -DWC_E_NO_SPACE;+	}++	return status;+}++/**+ * Checks that there is sufficient bandwidth for the specified QH in the+ * periodic schedule. For simplicity, this calculation assumes that all the+ * transfers in the periodic schedule may occur in the same (micro)frame.+ *+ * @param hcd The HCD state structure for the DWC OTG controller.+ * @param qh QH containing periodic bandwidth required.+ *+ * @return 0 if successful, negative error code otherwise.+ */+static int check_periodic_bandwidth(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)+{+	int status;+	int16_t max_claimed_usecs;++	status = 0;++	if ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) || qh->do_split) {+		/*+		 * High speed mode.+		 * Max periodic usecs is 80% x 125 usec = 100 usec.+		 */++		max_claimed_usecs = 100 - qh->usecs;+	} else {+		/*+		 * Full speed mode.+		 * Max periodic usecs is 90% x 1000 usec = 900 usec.+		 */+		max_claimed_usecs = 900 - qh->usecs;+	}++	if (hcd->periodic_usecs > max_claimed_usecs) {+		DWC_INFO("%s: already claimed usecs %d, required usecs %d\n", __func__, hcd->periodic_usecs, qh->usecs);	//NOTICE+		status = -DWC_E_NO_SPACE;+	}++	return status;+}++/* microframe_schedule=0 end */++/**+ * Microframe scheduler+ * track the total use in hcd->frame_usecs+ * keep each qh use in qh->frame_usecs+ * when surrendering the qh then donate the time back+ */+const unsigned short max_uframe_usecs[]={ 100, 100, 100, 100, 100, 100, 30, 0 };++/*+ * called from dwc_otg_hcd.c:dwc_otg_hcd_init+ */+int init_hcd_usecs(dwc_otg_hcd_t *_hcd)+{+	int i;+	for (i=0; i<8; i++) {+		_hcd->frame_usecs[i] = max_uframe_usecs[i];+	}+	return 0;+}++static int find_single_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)+{+	int i;+	unsigned short utime;+	int t_left;+	int ret;+	int done;++	ret = -1;+	utime = _qh->usecs;+	t_left = utime;+	i = 0;+	done = 0;+	while (done == 0) {+		/* At the start _hcd->frame_usecs[i] = max_uframe_usecs[i]; */+		if (utime <= _hcd->frame_usecs[i]) {+			_hcd->frame_usecs[i] -= utime;+			_qh->frame_usecs[i] += utime;+			t_left -= utime;+			ret = i;+			done = 1;+			return ret;+		} else {+			i++;+			if (i == 8) {+				done = 1;+				ret = -1;+			}+		}+	}+	return ret;+ }++/*+ * use this for FS apps that can span multiple uframes+  */+static int find_multi_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)+{+	int i;+	int j;+	unsigned short utime;+	int t_left;+	int ret;+	int done;+	unsigned short xtime;++	ret = -1;+	utime = _qh->usecs;+	t_left = utime;+	i = 0;+	done = 0;+loop:+	while (done == 0) {+		if(_hcd->frame_usecs[i] <= 0) {+			i++;+			if (i == 8) {+				done = 1;+				ret = -1;+			}+			goto loop;+		}++		/*+		 * we need n consecutive slots+		 * so use j as a start slot j plus j+1 must be enough time (for now)+		 */+		xtime= _hcd->frame_usecs[i];+		for (j = i+1 ; j < 8 ; j++ ) {+                       /*+                        * if we add this frame remaining time to xtime we may+                        * be OK, if not we need to test j for a complete frame+                        */+                       if ((xtime+_hcd->frame_usecs[j]) < utime) {+                               if (_hcd->frame_usecs[j] < max_uframe_usecs[j]) {+                                       j = 8;+                                       ret = -1;+                                       continue;+                               }+                       }+                       if (xtime >= utime) {+                               ret = i;+                               j = 8;  /* stop loop with a good value ret */+                               continue;+                       }+                       /* add the frame time to x time */+                       xtime += _hcd->frame_usecs[j];+		       /* we must have a fully available next frame or break */+		       if ((xtime < utime)+				       && (_hcd->frame_usecs[j] == max_uframe_usecs[j])) {+			       ret = -1;+			       j = 8;  /* stop loop with a bad value ret */+			       continue;+		       }+		}+		if (ret >= 0) {+			t_left = utime;+			for (j = i; (t_left>0) && (j < 8); j++ ) {+				t_left -= _hcd->frame_usecs[j];+				if ( t_left <= 0 ) {+					_qh->frame_usecs[j] += _hcd->frame_usecs[j] + t_left;+					_hcd->frame_usecs[j]= -t_left;+					ret = i;+					done = 1;+				} else {+					_qh->frame_usecs[j] += _hcd->frame_usecs[j];+					_hcd->frame_usecs[j] = 0;+				}+			}+		} else {+			i++;+			if (i == 8) {+				done = 1;+				ret = -1;+			}+		}+	}+	return ret;+}++static int find_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)+{+	int ret;+	ret = -1;++	if (_qh->speed == USB_SPEED_HIGH) {+		/* if this is a hs transaction we need a full frame */+		ret = find_single_uframe(_hcd, _qh);+	} else {+		/* if this is a fs transaction we may need a sequence of frames */+		ret = find_multi_uframe(_hcd, _qh);+	}+	return ret;+}++/**+ * Checks that the max transfer size allowed in a host channel is large enough+ * to handle the maximum data transfer in a single (micro)frame for a periodic+ * transfer.+ *+ * @param hcd The HCD state structure for the DWC OTG controller.+ * @param qh QH for a periodic endpoint.+ *+ * @return 0 if successful, negative error code otherwise.+ */+static int check_max_xfer_size(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)+{+	int status;+	uint32_t max_xfer_size;+	uint32_t max_channel_xfer_size;++	status = 0;++	max_xfer_size = dwc_max_packet(qh->maxp) * dwc_hb_mult(qh->maxp);+	max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size;++	if (max_xfer_size > max_channel_xfer_size) {+		DWC_INFO("%s: Periodic xfer length %d > " "max xfer length for channel %d\n",+				__func__, max_xfer_size, max_channel_xfer_size);	//NOTICE+		status = -DWC_E_NO_SPACE;+	}++	return status;+}+++extern int g_next_sched_frame, g_np_count, g_np_sent;++/**+ * Schedules an interrupt or isochronous transfer in the periodic schedule.+ *+ * @param hcd The HCD state structure for the DWC OTG controller.+ * @param qh QH for the periodic transfer. The QH should already contain the+ * scheduling information.+ *+ * @return 0 if successful, negative error code otherwise.+ */+static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)+{+	int status = 0;++	if (microframe_schedule) {+		int frame;+		status = find_uframe(hcd, qh);+		frame = -1;+		if (status == 0) {+			frame = 7;+		} else {+			if (status > 0 )+				frame = status-1;+		}++		/* Set the new frame up */+		if (frame > -1) {+			qh->sched_frame &= ~0x7;+			qh->sched_frame |= (frame & 7);+		}++		if (status != -1)+			status = 0;+	} else {+		status = periodic_channel_available(hcd);+		if (status) {+			DWC_INFO("%s: No host channel available for periodic " "transfer.\n", __func__);	//NOTICE+			return status;+		}++		status = check_periodic_bandwidth(hcd, qh);+	}+	if (status) {+		DWC_INFO("%s: Insufficient periodic bandwidth for "+			    "periodic transfer.\n", __func__);+		return status;+	}+	status = check_max_xfer_size(hcd, qh);+	if (status) {+		DWC_INFO("%s: Channel max transfer size too small "+			    "for periodic transfer.\n", __func__);+		return status;+	}++	if (hcd->core_if->dma_desc_enable) {+		/* Don't rely on SOF and start in ready schedule */+		DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry);+	}+	else {+		if(DWC_LIST_EMPTY(&hcd->periodic_sched_inactive) || dwc_frame_num_le(qh->sched_frame, g_next_sched_frame))+		{+			g_next_sched_frame = qh->sched_frame;++		}+		/* Always start in the inactive schedule. */+		DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);+	}++	if (!microframe_schedule) {+		/* Reserve the periodic channel. */+		hcd->periodic_channels++;+	}++	/* Update claimed usecs per (micro)frame. */+	hcd->periodic_usecs += qh->usecs;++	return status;+}+++/**+ * This function adds a QH to either the non periodic or periodic schedule if+ * it is not already in the schedule. If the QH is already in the schedule, no+ * action is taken.+ *+ * @return 0 if successful, negative error code otherwise.+ */+int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)+{+	int status = 0;+	gintmsk_data_t intr_mask = {.d32 = 0 };++	if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {+		/* QH already in a schedule. */+		return status;+	}++	/* Add the new QH to the appropriate schedule */+	if (dwc_qh_is_non_per(qh)) {+		/* Always start in the inactive schedule. */+		DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive,+				     &qh->qh_list_entry);+		g_np_count++;+	} else {+		status = schedule_periodic(hcd, qh);+		if ( !hcd->periodic_qh_count ) {+			intr_mask.b.sofintr = 1;+			DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,+								intr_mask.d32, intr_mask.d32);+		}+		hcd->periodic_qh_count++;+	}++	return status;+}++/**+ * Removes an interrupt or isochronous transfer from the periodic schedule.+ *+ * @param hcd The HCD state structure for the DWC OTG controller.+ * @param qh QH for the periodic transfer.+ */+static void deschedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)+{+	int i;+	DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);++	/* Update claimed usecs per (micro)frame. */+	hcd->periodic_usecs -= qh->usecs;++	if (!microframe_schedule) {+		/* Release the periodic channel reservation. */+		hcd->periodic_channels--;+	} else {+		for (i = 0; i < 8; i++) {+			hcd->frame_usecs[i] += qh->frame_usecs[i];+			qh->frame_usecs[i] = 0;+		}+	}+}++/**+ * Removes a QH from either the non-periodic or periodic schedule.  Memory is+ * not freed.+ *+ * @param hcd The HCD state structure.+ * @param qh QH to remove from schedule. */+void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)+{+	gintmsk_data_t intr_mask = {.d32 = 0 };++	if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {+		/* QH is not in a schedule. */+		return;+	}++	if (dwc_qh_is_non_per(qh)) {+		if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry) {+			hcd->non_periodic_qh_ptr =+			    hcd->non_periodic_qh_ptr->next;+		}+		DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);++		// If we've removed the last non-periodic entry then there are none left!+		g_np_count = g_np_sent;+	} else {+		deschedule_periodic(hcd, qh);+		hcd->periodic_qh_count--;+		if( !hcd->periodic_qh_count ) {+			intr_mask.b.sofintr = 1;+				DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,+									intr_mask.d32, 0);+		}+	}+}++/**+ * Deactivates a QH. For non-periodic QHs, removes the QH from the active+ * non-periodic schedule. The QH is added to the inactive non-periodic+ * schedule if any QTDs are still attached to the QH.+ *+ * For periodic QHs, the QH is removed from the periodic queued schedule. If+ * there are any QTDs still attached to the QH, the QH is added to either the+ * periodic inactive schedule or the periodic ready schedule and its next+ * scheduled frame is calculated. The QH is placed in the ready schedule if+ * the scheduled frame has been reached already. Otherwise it's placed in the+ * inactive schedule. If there are no QTDs attached to the QH, the QH is+ * completely removed from the periodic schedule.+ */+void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,+			       int sched_next_periodic_split)+{+	if (dwc_qh_is_non_per(qh)) {++		dwc_otg_qh_t *qh_tmp;+		dwc_list_link_t *qh_list;+		DWC_LIST_FOREACH(qh_list, &hcd->non_periodic_sched_inactive)+		{+			qh_tmp = DWC_LIST_ENTRY(qh_list, struct dwc_otg_qh, qh_list_entry);+			if(qh_tmp == qh)+			{+				/*+				 *  FIQ is being disabled because this one nevers gets a np_count increment+				 *  This is still not absolutely correct, but it should fix itself with+				 *  just an unnecessary extra interrupt+				 */+				g_np_sent = g_np_count;+			}+		}+++		dwc_otg_hcd_qh_remove(hcd, qh);+		if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {+			/* Add back to inactive non-periodic schedule. */+			dwc_otg_hcd_qh_add(hcd, qh);+		}+	} else {+		uint16_t frame_number = dwc_otg_hcd_get_frame_number(hcd);++		if (qh->do_split) {+			/* Schedule the next continuing periodic split transfer */+			if (sched_next_periodic_split) {++				qh->sched_frame = frame_number;++				if (dwc_frame_num_le(frame_number,+						     dwc_frame_num_inc+						     (qh->start_split_frame,+						      1))) {+					/*+					 * Allow one frame to elapse after start+					 * split microframe before scheduling+					 * complete split, but DONT if we are+					 * doing the next start split in the+					 * same frame for an ISOC out.+					 */+					if ((qh->ep_type != UE_ISOCHRONOUS) ||+					    (qh->ep_is_in != 0)) {+						qh->sched_frame =+						    dwc_frame_num_inc(qh->sched_frame, 1);+					}+				}+			} else {+				qh->sched_frame =+				    dwc_frame_num_inc(qh->start_split_frame,+						      qh->interval);+				if (dwc_frame_num_le+				    (qh->sched_frame, frame_number)) {+					qh->sched_frame = frame_number;+				}+				qh->sched_frame |= 0x7;+				qh->start_split_frame = qh->sched_frame;+			}+		} else {+			qh->sched_frame =+			    dwc_frame_num_inc(qh->sched_frame, qh->interval);+			if (dwc_frame_num_le(qh->sched_frame, frame_number)) {+				qh->sched_frame = frame_number;+			}+		}++		if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {+			dwc_otg_hcd_qh_remove(hcd, qh);+		} else {+			/*+			 * Remove from periodic_sched_queued and move to+			 * appropriate queue.+			 */+			if ((microframe_schedule && dwc_frame_num_le(qh->sched_frame, frame_number)) ||+			(!microframe_schedule && qh->sched_frame == frame_number)) {+				DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,+						   &qh->qh_list_entry);+			} else {+				if(!dwc_frame_num_le(g_next_sched_frame, qh->sched_frame))+				{+					g_next_sched_frame = qh->sched_frame;+				}++				DWC_LIST_MOVE_HEAD+				    (&hcd->periodic_sched_inactive,+				     &qh->qh_list_entry);+			}+		}+	}+}++/**+ * This function allocates and initializes a QTD.+ *+ * @param urb The URB to create a QTD from.  Each URB-QTD pair will end up+ * 	      pointing to each other so each pair should have a unique correlation.+ * @param atomic_alloc Flag to do atomic alloc if needed+ *+ * @return Returns pointer to the newly allocated QTD, or NULL on error. */+dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, int atomic_alloc)+{+	dwc_otg_qtd_t *qtd;++	qtd = dwc_otg_hcd_qtd_alloc(atomic_alloc);+	if (qtd == NULL) {+		return NULL;+	}++	dwc_otg_hcd_qtd_init(qtd, urb);+	return qtd;+}++/**+ * Initializes a QTD structure.+ *+ * @param qtd The QTD to initialize.+ * @param urb The URB to use for initialization.  */+void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb)+{+	dwc_memset(qtd, 0, sizeof(dwc_otg_qtd_t));+	qtd->urb = urb;+	if (dwc_otg_hcd_get_pipe_type(&urb->pipe_info) == UE_CONTROL) {+		/*+		 * The only time the QTD data toggle is used is on the data+		 * phase of control transfers. This phase always starts with+		 * DATA1.+		 */+		qtd->data_toggle = DWC_OTG_HC_PID_DATA1;+		qtd->control_phase = DWC_OTG_CONTROL_SETUP;+	}++	/* start split */+	qtd->complete_split = 0;+	qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;+	qtd->isoc_split_offset = 0;+	qtd->in_process = 0;++	/* Store the qtd ptr in the urb to reference what QTD. */+	urb->qtd = qtd;+	return;+}++/**+ * This function adds a QTD to the QTD-list of a QH.  It will find the correct+ * QH to place the QTD into.  If it does not find a QH, then it will create a+ * new QH. If the QH to which the QTD is added is not currently scheduled, it+ * is placed into the proper schedule based on its EP type.+ * HCD lock must be held and interrupts must be disabled on entry+ *+ * @param[in] qtd The QTD to add+ * @param[in] hcd The DWC HCD structure+ * @param[out] qh out parameter to return queue head+ * @param atomic_alloc Flag to do atomic alloc if needed+ *+ * @return 0 if successful, negative error code otherwise.+ */+int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd,+			dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh, int atomic_alloc)+{+	int retval = 0;+	dwc_otg_hcd_urb_t *urb = qtd->urb;++	/*+	 * Get the QH which holds the QTD-list to insert to. Create QH if it+	 * doesn't exist.+	 */+	if (*qh == NULL) {+		*qh = dwc_otg_hcd_qh_create(hcd, urb, atomic_alloc);+		if (*qh == NULL) {+			retval = -DWC_E_NO_MEMORY;+			goto done;+		}+	}+	retval = dwc_otg_hcd_qh_add(hcd, *qh);+	if (retval == 0) {+		DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd,+					qtd_list_entry);+		qtd->qh = *qh;+	}+done:++	return retval;+}++#endif /* DWC_DEVICE_ONLY */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,113 @@+#include "dwc_otg_regs.h"+#include "dwc_otg_dbg.h"++void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name)+{+	DWC_DEBUGPL(DBG_USER,   "*** Debugging from within the %s  function: ***\n"+				"curmode:     %1i    Modemismatch: %1i    otgintr:    %1i    sofintr:    %1i\n"+				"rxstsqlvl:   %1i    nptxfempty  : %1i    ginnakeff:  %1i    goutnakeff: %1i\n"+				"ulpickint:   %1i    i2cintr:      %1i    erlysuspend:%1i    usbsuspend: %1i\n"+				"usbreset:    %1i    enumdone:     %1i    isooutdrop: %1i    eopframe:   %1i\n"+				"restoredone: %1i    epmismatch:   %1i    inepint:    %1i    outepintr:  %1i\n"+				"incomplisoin:%1i    incomplisoout:%1i    fetsusp:    %1i    resetdet:   %1i\n"+				"portintr:    %1i    hcintr:       %1i    ptxfempty:  %1i    lpmtranrcvd:%1i\n"+				"conidstschng:%1i    disconnect:   %1i    sessreqintr:%1i    wkupintr:   %1i\n",+				function_name,+				gintsts.b.curmode,+				gintsts.b.modemismatch,+				gintsts.b.otgintr,+				gintsts.b.sofintr,+				gintsts.b.rxstsqlvl,+				gintsts.b.nptxfempty,+				gintsts.b.ginnakeff,+				gintsts.b.goutnakeff,+				gintsts.b.ulpickint,+				gintsts.b.i2cintr,+				gintsts.b.erlysuspend,+				gintsts.b.usbsuspend,+				gintsts.b.usbreset,+				gintsts.b.enumdone,+				gintsts.b.isooutdrop,+				gintsts.b.eopframe,+				gintsts.b.restoredone,+				gintsts.b.epmismatch,+				gintsts.b.inepint,+				gintsts.b.outepintr,+				gintsts.b.incomplisoin,+				gintsts.b.incomplisoout,+				gintsts.b.fetsusp,+				gintsts.b.resetdet,+				gintsts.b.portintr,+				gintsts.b.hcintr,+				gintsts.b.ptxfempty,+				gintsts.b.lpmtranrcvd,+				gintsts.b.conidstschng,+				gintsts.b.disconnect,+				gintsts.b.sessreqintr,+				gintsts.b.wkupintr);+	return;+}++void dwc_debug_core_int_mask(gintmsk_data_t gintmsk, const char* function_name)+{+	DWC_DEBUGPL(DBG_USER,	"Interrupt Mask status (called from %s) :\n"+				"modemismatch: %1i     otgintr:    %1i    sofintr:    %1i    rxstsqlvl:   %1i\n"+				"nptxfempty:   %1i     ginnakeff:  %1i    goutnakeff: %1i    ulpickint:   %1i\n"+				"i2cintr:      %1i     erlysuspend:%1i    usbsuspend: %1i    usbreset:    %1i\n"+				"enumdone:     %1i     isooutdrop: %1i    eopframe:   %1i    restoredone: %1i\n"+				"epmismatch:   %1i     inepintr:   %1i    outepintr:  %1i    incomplisoin:%1i\n"+				"incomplisoout:%1i     fetsusp:    %1i    resetdet:   %1i    portintr:    %1i\n"+				"hcintr:       %1i     ptxfempty:  %1i    lpmtranrcvd:%1i    conidstschng:%1i\n"+				"disconnect:   %1i     sessreqintr:%1i    wkupintr:   %1i\n",+				function_name,+				gintmsk.b.modemismatch,+				gintmsk.b.otgintr,+				gintmsk.b.sofintr,+				gintmsk.b.rxstsqlvl,+				gintmsk.b.nptxfempty,+				gintmsk.b.ginnakeff,+				gintmsk.b.goutnakeff,+				gintmsk.b.ulpickint,+				gintmsk.b.i2cintr,+				gintmsk.b.erlysuspend,+				gintmsk.b.usbsuspend,+				gintmsk.b.usbreset,+				gintmsk.b.enumdone,+				gintmsk.b.isooutdrop,+				gintmsk.b.eopframe,+				gintmsk.b.restoredone,+				gintmsk.b.epmismatch,+				gintmsk.b.inepintr,+				gintmsk.b.outepintr,+				gintmsk.b.incomplisoin,+				gintmsk.b.incomplisoout,+				gintmsk.b.fetsusp,+				gintmsk.b.resetdet,+				gintmsk.b.portintr,+				gintmsk.b.hcintr,+				gintmsk.b.ptxfempty,+				gintmsk.b.lpmtranrcvd,+				gintmsk.b.conidstschng,+				gintmsk.b.disconnect,+				gintmsk.b.sessreqintr,+				gintmsk.b.wkupintr);+	return;+}++void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name)+{+	DWC_DEBUGPL(DBG_USER,	"otg int register (from %s function):\n"+				"sesenddet:%1i    sesreqsucstschung:%2i    hstnegsucstschng:%1i\n"+				"hstnegdet:%1i    adevtoutchng:     %2i    debdone:         %1i\n"+				"mvic:     %1i\n",+				function_name,+				gotgint.b.sesenddet,+				gotgint.b.sesreqsucstschng,+				gotgint.b.hstnegsucstschng,+				gotgint.b.hstnegdet,+				gotgint.b.adevtoutchng,+				gotgint.b.debdone,+				gotgint.b.mvic);++	return;+}diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,48 @@+#ifndef __DWC_OTG_MPHI_FIX_H__+#define __DWC_OTG_MPHI_FIX_H__+#define FIQ_WRITE(_addr_,_data_) (*(volatile uint32_t *) (_addr_) = (_data_))+#define FIQ_READ(_addr_) (*(volatile uint32_t *) (_addr_))++typedef struct {+	volatile void* base;+	volatile void* ctrl;+	volatile void* outdda;+	volatile void* outddb;+	volatile void* intstat;+} mphi_regs_t;++void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name);+void dwc_debug_core_int_mask(gintsts_data_t gintmsk, const char* function_name);+void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name);++extern gintsts_data_t gintsts_saved;++#ifdef DEBUG+#define DWC_DBG_PRINT_CORE_INT(_arg_) dwc_debug_print_core_int_reg(_arg_,__func__)+#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_) dwc_debug_core_int_mask(_arg_,__func__)+#define DWC_DBG_PRINT_OTG_INT(_arg_) dwc_debug_otg_int(_arg_,__func__)++#else+#define DWC_DBG_PRINT_CORE_INT(_arg_)+#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_)+#define DWC_DBG_PRINT_OTG_INT(_arg_)++#endif++typedef enum {+	FIQDBG_SCHED = (1 << 0),+	FIQDBG_INT   = (1 << 1),+	FIQDBG_ERR   = (1 << 2),+	FIQDBG_PORTHUB = (1 << 3),+} FIQDBG_T;++void _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...);+#ifdef FIQ_DEBUG+#define fiq_print _fiq_print+#else+#define fiq_print(x, y, ...)+#endif++extern bool fiq_fix_enable, nak_holdoff_enable, fiq_split_enable;++#endifdiff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,188 @@+#ifndef _DWC_OS_DEP_H_+#define _DWC_OS_DEP_H_++/**+ * @file+ *+ * This file contains OS dependent structures.+ *+ */++#include <linux/kernel.h>+#include <linux/module.h>+#include <linux/moduleparam.h>+#include <linux/init.h>+#include <linux/device.h>+#include <linux/errno.h>+#include <linux/types.h>+#include <linux/slab.h>+#include <linux/list.h>+#include <linux/interrupt.h>+#include <linux/ctype.h>+#include <linux/string.h>+#include <linux/dma-mapping.h>+#include <linux/jiffies.h>+#include <linux/delay.h>+#include <linux/timer.h>+#include <linux/workqueue.h>+#include <linux/stat.h>+#include <linux/pci.h>++#include <linux/version.h>++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)+# include <linux/irq.h>+#endif++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)+# include <linux/usb/ch9.h>+#else+# include <linux/usb_ch9.h>+#endif++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)+# include <linux/usb/gadget.h>+#else+# include <linux/usb_gadget.h>+#endif++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)+# include <asm/irq.h>+#endif++#ifdef PCI_INTERFACE+# include <asm/io.h>+#endif++#ifdef LM_INTERFACE+# include <asm/unaligned.h>+# include <asm/sizes.h>+# include <asm/param.h>+# include <asm/io.h>+# if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))+#  include <asm/arch/hardware.h>+#  include <asm/arch/lm.h>+#  include <asm/arch/irqs.h>+#  include <asm/arch/regs-irq.h>+# else+/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure -+   here we assume that the machine architecture provides definitions+   in its own header+*/+#  include <mach/lm.h>+#  include <mach/hardware.h>+# endif+#endif++#ifdef PLATFORM_INTERFACE+#include <linux/platform_device.h>+#include <asm/mach/map.h>+#endif++/** The OS page size */+#define DWC_OS_PAGE_SIZE	PAGE_SIZE++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)+typedef int gfp_t;+#endif++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)+# define IRQF_SHARED SA_SHIRQ+#endif++typedef struct os_dependent {+	/** Base address returned from ioremap() */+	void *base;++	/** Register offset for Diagnostic API */+	uint32_t reg_offset;++	/** Base address for MPHI peripheral */+	void *mphi_base;++#ifdef LM_INTERFACE+	struct lm_device *lmdev;+#elif  defined(PCI_INTERFACE)+	struct pci_dev *pcidev;++	/** Start address of a PCI region */+	resource_size_t rsrc_start;++	/** Length address of a PCI region */+	resource_size_t rsrc_len;+#elif  defined(PLATFORM_INTERFACE)+	struct platform_device *platformdev;+#endif++} os_dependent_t;++#ifdef __cplusplus+}+#endif++++/* Type for the our device on the chosen bus */+#if   defined(LM_INTERFACE)+typedef struct lm_device       dwc_bus_dev_t;+#elif defined(PCI_INTERFACE)+typedef struct pci_dev         dwc_bus_dev_t;+#elif defined(PLATFORM_INTERFACE)+typedef struct platform_device dwc_bus_dev_t;+#endif++/* Helper macro to retrieve drvdata from the device on the chosen bus */+#if    defined(LM_INTERFACE)+#define DWC_OTG_BUSDRVDATA(_dev) lm_get_drvdata(_dev)+#elif  defined(PCI_INTERFACE)+#define DWC_OTG_BUSDRVDATA(_dev) pci_get_drvdata(_dev)+#elif  defined(PLATFORM_INTERFACE)+#define DWC_OTG_BUSDRVDATA(_dev) platform_get_drvdata(_dev)+#endif++/**+ * Helper macro returning the otg_device structure of a given struct device+ *+ * c.f. static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev)+ */+#ifdef LM_INTERFACE+#define DWC_OTG_GETDRVDEV(_var, _dev) do { \+                struct lm_device *lm_dev = \+                        container_of(_dev, struct lm_device, dev); \+                _var = lm_get_drvdata(lm_dev); \+        } while (0)++#elif defined(PCI_INTERFACE)+#define DWC_OTG_GETDRVDEV(_var, _dev) do { \+                _var = dev_get_drvdata(_dev); \+        } while (0)++#elif defined(PLATFORM_INTERFACE)+#define DWC_OTG_GETDRVDEV(_var, _dev) do { \+                struct platform_device *platform_dev = \+                        container_of(_dev, struct platform_device, dev); \+                _var = platform_get_drvdata(platform_dev); \+        } while (0)+#endif+++/**+ * Helper macro returning the struct dev of the given struct os_dependent+ *+ * c.f. static struct device *dwc_otg_getdev(struct os_dependent *osdep)+ */+#ifdef LM_INTERFACE+#define DWC_OTG_OS_GETDEV(_osdep) \+        ((_osdep).lmdev == NULL? NULL: &(_osdep).lmdev->dev)+#elif defined(PCI_INTERFACE)+#define DWC_OTG_OS_GETDEV(_osdep) \+        ((_osdep).pci_dev == NULL? NULL: &(_osdep).pci_dev->dev)+#elif defined(PLATFORM_INTERFACE)+#define DWC_OTG_OS_GETDEV(_osdep) \+        ((_osdep).platformdev == NULL? NULL: &(_osdep).platformdev->dev)+#endif+++++#endif /* _DWC_OS_DEP_H_ */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_pcd.c--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_pcd.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,2708 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $+ * $Revision: #101 $+ * $Date: 2012/08/10 $+ * $Change: 2047372 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */+#ifndef DWC_HOST_ONLY++/** @file+ * This file implements PCD Core. All code in this file is portable and doesn't+ * use any OS specific functions.+ * PCD Core provides Interface, defined in <code><dwc_otg_pcd_if.h></code>+ * header file, which can be used to implement OS specific PCD interface.+ *+ * An important function of the PCD is managing interrupts generated+ * by the DWC_otg controller. The implementation of the DWC_otg device+ * mode interrupt service routines is in dwc_otg_pcd_intr.c.+ *+ * @todo Add Device Mode test modes (Test J mode, Test K mode, etc).+ * @todo Does it work when the request size is greater than DEPTSIZ+ * transfer size+ *+ */++#include "dwc_otg_pcd.h"++#ifdef DWC_UTE_CFI+#include "dwc_otg_cfi.h"++extern int init_cfi(cfiobject_t * cfiobj);+#endif++/**+ * Choose endpoint from ep arrays using usb_ep structure.+ */+static dwc_otg_pcd_ep_t *get_ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)+{+	int i;+	if (pcd->ep0.priv == handle) {+		return &pcd->ep0;+	}+	for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {+		if (pcd->in_ep[i].priv == handle)+			return &pcd->in_ep[i];+		if (pcd->out_ep[i].priv == handle)+			return &pcd->out_ep[i];+	}++	return NULL;+}++/**+ * This function completes a request.  It call's the request call back.+ */+void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req,+			  int32_t status)+{+	unsigned stopped = ep->stopped;++	DWC_DEBUGPL(DBG_PCDV, "%s(ep %p req %p)\n", __func__, ep, req);+	DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);++	/* don't modify queue heads during completion callback */+	ep->stopped = 1;+	/* spin_unlock/spin_lock now done in fops->complete() */+	ep->pcd->fops->complete(ep->pcd, ep->priv, req->priv, status,+				req->actual);++	if (ep->pcd->request_pending > 0) {+		--ep->pcd->request_pending;+	}++	ep->stopped = stopped;+	DWC_FREE(req);+}++/**+ * This function terminates all the requsts in the EP request queue.+ */+void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep)+{+	dwc_otg_pcd_request_t *req;++	ep->stopped = 1;++	/* called with irqs blocked?? */+	while (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {+		req = DWC_CIRCLEQ_FIRST(&ep->queue);+		dwc_otg_request_done(ep, req, -DWC_E_SHUTDOWN);+	}+}++void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,+		       const struct dwc_otg_pcd_function_ops *fops)+{+	pcd->fops = fops;+}++/**+ * PCD Callback function for initializing the PCD when switching to+ * device mode.+ *+ * @param p void pointer to the <code>dwc_otg_pcd_t</code>+ */+static int32_t dwc_otg_pcd_start_cb(void *p)+{+	dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);++	/*+	 * Initialized the Core for Device mode.+	 */+	if (dwc_otg_is_device_mode(core_if)) {+		dwc_otg_core_dev_init(core_if);+		/* Set core_if's lock pointer to the pcd->lock */+		core_if->lock = pcd->lock;+	}+	return 1;+}++/** CFI-specific buffer allocation function for EP */+#ifdef DWC_UTE_CFI+uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,+			      size_t buflen, int flags)+{+	dwc_otg_pcd_ep_t *ep;+	ep = get_ep_from_handle(pcd, pep);+	if (!ep) {+		DWC_WARN("bad ep\n");+		return -DWC_E_INVALID;+	}++	return pcd->cfi->ops.ep_alloc_buf(pcd->cfi, pcd, ep, addr, buflen,+					  flags);+}+#else+uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,+			      size_t buflen, int flags);+#endif++/**+ * PCD Callback function for notifying the PCD when resuming from+ * suspend.+ *+ * @param p void pointer to the <code>dwc_otg_pcd_t</code>+ */+static int32_t dwc_otg_pcd_resume_cb(void *p)+{+	dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;++	if (pcd->fops->resume) {+		pcd->fops->resume(pcd);+	}++	/* Stop the SRP timeout timer. */+	if ((GET_CORE_IF(pcd)->core_params->phy_type != DWC_PHY_TYPE_PARAM_FS)+	    || (!GET_CORE_IF(pcd)->core_params->i2c_enable)) {+		if (GET_CORE_IF(pcd)->srp_timer_started) {+			GET_CORE_IF(pcd)->srp_timer_started = 0;+			DWC_TIMER_CANCEL(GET_CORE_IF(pcd)->srp_timer);+		}+	}+	return 1;+}++/**+ * PCD Callback function for notifying the PCD device is suspended.+ *+ * @param p void pointer to the <code>dwc_otg_pcd_t</code>+ */+static int32_t dwc_otg_pcd_suspend_cb(void *p)+{+	dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;++	if (pcd->fops->suspend) {+		DWC_SPINUNLOCK(pcd->lock);+		pcd->fops->suspend(pcd);+		DWC_SPINLOCK(pcd->lock);+	}++	return 1;+}++/**+ * PCD Callback function for stopping the PCD when switching to Host+ * mode.+ *+ * @param p void pointer to the <code>dwc_otg_pcd_t</code>+ */+static int32_t dwc_otg_pcd_stop_cb(void *p)+{+	dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;+	extern void dwc_otg_pcd_stop(dwc_otg_pcd_t * _pcd);++	dwc_otg_pcd_stop(pcd);+	return 1;+}++/**+ * PCD Callback structure for handling mode switching.+ */+static dwc_otg_cil_callbacks_t pcd_callbacks = {+	.start = dwc_otg_pcd_start_cb,+	.stop = dwc_otg_pcd_stop_cb,+	.suspend = dwc_otg_pcd_suspend_cb,+	.resume_wakeup = dwc_otg_pcd_resume_cb,+	.p = 0,			/* Set at registration */+};++/**+ * This function allocates a DMA Descriptor chain for the Endpoint+ * buffer to be used for a transfer to/from the specified endpoint.+ */+dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(dwc_dma_t * dma_desc_addr,+						    uint32_t count)+{+	return DWC_DMA_ALLOC_ATOMIC(count * sizeof(dwc_otg_dev_dma_desc_t),+							dma_desc_addr);+}++/**+ * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc.+ */+void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr,+				uint32_t dma_desc_addr, uint32_t count)+{+	DWC_DMA_FREE(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr,+		     dma_desc_addr);+}++#ifdef DWC_EN_ISOC++/**+ * This function initializes a descriptor chain for Isochronous transfer+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param dwc_ep The EP to start the transfer on.+ *+ */+void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if,+					dwc_ep_t * dwc_ep)+{++	dsts_data_t dsts = {.d32 = 0 };+	depctl_data_t depctl = {.d32 = 0 };+	volatile uint32_t *addr;+	int i, j;+	uint32_t len;++	if (dwc_ep->is_in)+		dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl / dwc_ep->bInterval;+	else+		dwc_ep->desc_cnt =+		    dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /+		    dwc_ep->bInterval;++	/** Allocate descriptors for double buffering */+	dwc_ep->iso_desc_addr =+	    dwc_otg_ep_alloc_desc_chain(&dwc_ep->iso_dma_desc_addr,+					dwc_ep->desc_cnt * 2);+	if (dwc_ep->desc_addr) {+		DWC_WARN("%s, can't allocate DMA descriptor chain\n", __func__);+		return;+	}++	dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);++	/** ISO OUT EP */+	if (dwc_ep->is_in == 0) {+		dev_dma_desc_sts_t sts = {.d32 = 0 };+		dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;+		dma_addr_t dma_ad;+		uint32_t data_per_desc;+		dwc_otg_dev_out_ep_regs_t *out_regs =+		    core_if->dev_if->out_ep_regs[dwc_ep->num];+		int offset;++		addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;+		dma_ad = (dma_addr_t) DWC_READ_REG32(&(out_regs->doepdma));++		/** Buffer 0 descriptors setup */+		dma_ad = dwc_ep->dma_addr0;++		sts.b_iso_out.bs = BS_HOST_READY;+		sts.b_iso_out.rxsts = 0;+		sts.b_iso_out.l = 0;+		sts.b_iso_out.sp = 0;+		sts.b_iso_out.ioc = 0;+		sts.b_iso_out.pid = 0;+		sts.b_iso_out.framenum = 0;++		offset = 0;+		for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;+		     i += dwc_ep->pkt_per_frm) {++			for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {+				uint32_t len = (j + 1) * dwc_ep->maxpacket;+				if (len > dwc_ep->data_per_frame)+					data_per_desc =+					    dwc_ep->data_per_frame -+					    j * dwc_ep->maxpacket;+				else+					data_per_desc = dwc_ep->maxpacket;+				len = data_per_desc % 4;+				if (len)+					data_per_desc += 4 - len;++				sts.b_iso_out.rxbytes = data_per_desc;+				dma_desc->buf = dma_ad;+				dma_desc->status.d32 = sts.d32;++				offset += data_per_desc;+				dma_desc++;+				dma_ad += data_per_desc;+			}+		}++		for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {+			uint32_t len = (j + 1) * dwc_ep->maxpacket;+			if (len > dwc_ep->data_per_frame)+				data_per_desc =+				    dwc_ep->data_per_frame -+				    j * dwc_ep->maxpacket;+			else+				data_per_desc = dwc_ep->maxpacket;+			len = data_per_desc % 4;+			if (len)+				data_per_desc += 4 - len;+			sts.b_iso_out.rxbytes = data_per_desc;+			dma_desc->buf = dma_ad;+			dma_desc->status.d32 = sts.d32;++			offset += data_per_desc;+			dma_desc++;+			dma_ad += data_per_desc;+		}++		sts.b_iso_out.ioc = 1;+		len = (j + 1) * dwc_ep->maxpacket;+		if (len > dwc_ep->data_per_frame)+			data_per_desc =+			    dwc_ep->data_per_frame - j * dwc_ep->maxpacket;+		else+			data_per_desc = dwc_ep->maxpacket;+		len = data_per_desc % 4;+		if (len)+			data_per_desc += 4 - len;+		sts.b_iso_out.rxbytes = data_per_desc;++		dma_desc->buf = dma_ad;+		dma_desc->status.d32 = sts.d32;+		dma_desc++;++		/** Buffer 1 descriptors setup */+		sts.b_iso_out.ioc = 0;+		dma_ad = dwc_ep->dma_addr1;++		offset = 0;+		for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;+		     i += dwc_ep->pkt_per_frm) {+			for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {+				uint32_t len = (j + 1) * dwc_ep->maxpacket;+				if (len > dwc_ep->data_per_frame)+					data_per_desc =+					    dwc_ep->data_per_frame -+					    j * dwc_ep->maxpacket;+				else+					data_per_desc = dwc_ep->maxpacket;+				len = data_per_desc % 4;+				if (len)+					data_per_desc += 4 - len;++				data_per_desc =+				    sts.b_iso_out.rxbytes = data_per_desc;+				dma_desc->buf = dma_ad;+				dma_desc->status.d32 = sts.d32;++				offset += data_per_desc;+				dma_desc++;+				dma_ad += data_per_desc;+			}+		}+		for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {+			data_per_desc =+			    ((j + 1) * dwc_ep->maxpacket >+			     dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -+			    j * dwc_ep->maxpacket : dwc_ep->maxpacket;+			data_per_desc +=+			    (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;+			sts.b_iso_out.rxbytes = data_per_desc;+			dma_desc->buf = dma_ad;+			dma_desc->status.d32 = sts.d32;++			offset += data_per_desc;+			dma_desc++;+			dma_ad += data_per_desc;+		}++		sts.b_iso_out.ioc = 1;+		sts.b_iso_out.l = 1;+		data_per_desc =+		    ((j + 1) * dwc_ep->maxpacket >+		     dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -+		    j * dwc_ep->maxpacket : dwc_ep->maxpacket;+		data_per_desc +=+		    (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;+		sts.b_iso_out.rxbytes = data_per_desc;++		dma_desc->buf = dma_ad;+		dma_desc->status.d32 = sts.d32;++		dwc_ep->next_frame = 0;++		/** Write dma_ad into DOEPDMA register */+		DWC_WRITE_REG32(&(out_regs->doepdma),+				(uint32_t) dwc_ep->iso_dma_desc_addr);++	}+	/** ISO IN EP */+	else {+		dev_dma_desc_sts_t sts = {.d32 = 0 };+		dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;+		dma_addr_t dma_ad;+		dwc_otg_dev_in_ep_regs_t *in_regs =+		    core_if->dev_if->in_ep_regs[dwc_ep->num];+		unsigned int frmnumber;+		fifosize_data_t txfifosize, rxfifosize;++		txfifosize.d32 =+		    DWC_READ_REG32(&core_if->dev_if->in_ep_regs[dwc_ep->num]->+				   dtxfsts);+		rxfifosize.d32 =+		    DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);++		addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;++		dma_ad = dwc_ep->dma_addr0;++		dsts.d32 =+		    DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);++		sts.b_iso_in.bs = BS_HOST_READY;+		sts.b_iso_in.txsts = 0;+		sts.b_iso_in.sp =+		    (dwc_ep->data_per_frame % dwc_ep->maxpacket) ? 1 : 0;+		sts.b_iso_in.ioc = 0;+		sts.b_iso_in.pid = dwc_ep->pkt_per_frm;++		frmnumber = dwc_ep->next_frame;++		sts.b_iso_in.framenum = frmnumber;+		sts.b_iso_in.txbytes = dwc_ep->data_per_frame;+		sts.b_iso_in.l = 0;++		/** Buffer 0 descriptors setup */+		for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {+			dma_desc->buf = dma_ad;+			dma_desc->status.d32 = sts.d32;+			dma_desc++;++			dma_ad += dwc_ep->data_per_frame;+			sts.b_iso_in.framenum += dwc_ep->bInterval;+		}++		sts.b_iso_in.ioc = 1;+		dma_desc->buf = dma_ad;+		dma_desc->status.d32 = sts.d32;+		++dma_desc;++		/** Buffer 1 descriptors setup */+		sts.b_iso_in.ioc = 0;+		dma_ad = dwc_ep->dma_addr1;++		for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;+		     i += dwc_ep->pkt_per_frm) {+			dma_desc->buf = dma_ad;+			dma_desc->status.d32 = sts.d32;+			dma_desc++;++			dma_ad += dwc_ep->data_per_frame;+			sts.b_iso_in.framenum += dwc_ep->bInterval;++			sts.b_iso_in.ioc = 0;+		}+		sts.b_iso_in.ioc = 1;+		sts.b_iso_in.l = 1;++		dma_desc->buf = dma_ad;+		dma_desc->status.d32 = sts.d32;++		dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval;++		/** Write dma_ad into diepdma register */+		DWC_WRITE_REG32(&(in_regs->diepdma),+				(uint32_t) dwc_ep->iso_dma_desc_addr);+	}+	/** Enable endpoint, clear nak  */+	depctl.d32 = 0;+	depctl.b.epena = 1;+	depctl.b.usbactep = 1;+	depctl.b.cnak = 1;++	DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);+	depctl.d32 = DWC_READ_REG32(addr);+}++/**+ * This function initializes a descriptor chain for Isochronous transfer+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP to start the transfer on.+ *+ */+void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,+				       dwc_ep_t * ep)+{+	depctl_data_t depctl = {.d32 = 0 };+	volatile uint32_t *addr;++	if (ep->is_in) {+		addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;+	} else {+		addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;+	}++	if (core_if->dma_enable == 0 || core_if->dma_desc_enable != 0) {+		return;+	} else {+		deptsiz_data_t deptsiz = {.d32 = 0 };++		ep->xfer_len =+		    ep->data_per_frame * ep->buf_proc_intrvl / ep->bInterval;+		ep->pkt_cnt =+		    (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;+		ep->xfer_count = 0;+		ep->xfer_buff =+		    (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;+		ep->dma_addr =+		    (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;++		if (ep->is_in) {+			/* Program the transfer size and packet count+			 *      as follows: xfersize = N * maxpacket ++			 *      short_packet pktcnt = N + (short_packet+			 *      exist ? 1 : 0)+			 */+			deptsiz.b.mc = ep->pkt_per_frm;+			deptsiz.b.xfersize = ep->xfer_len;+			deptsiz.b.pktcnt =+			    (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;+			DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->+					dieptsiz, deptsiz.d32);++			/* Write the DMA register */+			DWC_WRITE_REG32(&+					(core_if->dev_if->in_ep_regs[ep->num]->+					 diepdma), (uint32_t) ep->dma_addr);++		} else {+			deptsiz.b.pktcnt =+			    (ep->xfer_len + (ep->maxpacket - 1)) /+			    ep->maxpacket;+			deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;++			DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->+					doeptsiz, deptsiz.d32);++			/* Write the DMA register */+			DWC_WRITE_REG32(&+					(core_if->dev_if->out_ep_regs[ep->num]->+					 doepdma), (uint32_t) ep->dma_addr);++		}+		/** Enable endpoint, clear nak  */+		depctl.d32 = 0;+		depctl.b.epena = 1;+		depctl.b.cnak = 1;++		DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);+	}+}++/**+ * This function does the setup for a data transfer for an EP and+ * starts the transfer. For an IN transfer, the packets will be+ * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,+ * the packets are unloaded from the Rx FIFO in the ISR.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP to start the transfer on.+ */++static void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t * core_if,+					  dwc_ep_t * ep)+{+	if (core_if->dma_enable) {+		if (core_if->dma_desc_enable) {+			if (ep->is_in) {+				ep->desc_cnt = ep->pkt_cnt / ep->pkt_per_frm;+			} else {+				ep->desc_cnt = ep->pkt_cnt;+			}+			dwc_otg_iso_ep_start_ddma_transfer(core_if, ep);+		} else {+			if (core_if->pti_enh_enable) {+				dwc_otg_iso_ep_start_buf_transfer(core_if, ep);+			} else {+				ep->cur_pkt_addr =+				    (ep->proc_buf_num) ? ep->xfer_buff1 : ep->+				    xfer_buff0;+				ep->cur_pkt_dma_addr =+				    (ep->proc_buf_num) ? ep->dma_addr1 : ep->+				    dma_addr0;+				dwc_otg_iso_ep_start_frm_transfer(core_if, ep);+			}+		}+	} else {+		ep->cur_pkt_addr =+		    (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;+		ep->cur_pkt_dma_addr =+		    (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;+		dwc_otg_iso_ep_start_frm_transfer(core_if, ep);+	}+}++/**+ * This function stops transfer for an EP and+ * resets the ep's variables.+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP to start the transfer on.+ */++void dwc_otg_iso_ep_stop_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)+{+	depctl_data_t depctl = {.d32 = 0 };+	volatile uint32_t *addr;++	if (ep->is_in == 1) {+		addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;+	} else {+		addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;+	}++	/* disable the ep */+	depctl.d32 = DWC_READ_REG32(addr);++	depctl.b.epdis = 1;+	depctl.b.snak = 1;++	DWC_WRITE_REG32(addr, depctl.d32);++	if (core_if->dma_desc_enable &&+	    ep->iso_desc_addr && ep->iso_dma_desc_addr) {+		dwc_otg_ep_free_desc_chain(ep->iso_desc_addr,+					   ep->iso_dma_desc_addr,+					   ep->desc_cnt * 2);+	}++	/* reset varibales */+	ep->dma_addr0 = 0;+	ep->dma_addr1 = 0;+	ep->xfer_buff0 = 0;+	ep->xfer_buff1 = 0;+	ep->data_per_frame = 0;+	ep->data_pattern_frame = 0;+	ep->sync_frame = 0;+	ep->buf_proc_intrvl = 0;+	ep->bInterval = 0;+	ep->proc_buf_num = 0;+	ep->pkt_per_frm = 0;+	ep->pkt_per_frm = 0;+	ep->desc_cnt = 0;+	ep->iso_desc_addr = 0;+	ep->iso_dma_desc_addr = 0;+}++int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,+			     uint8_t * buf0, uint8_t * buf1, dwc_dma_t dma0,+			     dwc_dma_t dma1, int sync_frame, int dp_frame,+			     int data_per_frame, int start_frame,+			     int buf_proc_intrvl, void *req_handle,+			     int atomic_alloc)+{+	dwc_otg_pcd_ep_t *ep;+	dwc_irqflags_t flags = 0;+	dwc_ep_t *dwc_ep;+	int32_t frm_data;+	dsts_data_t dsts;+	dwc_otg_core_if_t *core_if;++	ep = get_ep_from_handle(pcd, ep_handle);++	if (!ep || !ep->desc || ep->dwc_ep.num == 0) {+		DWC_WARN("bad ep\n");+		return -DWC_E_INVALID;+	}++	DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);+	core_if = GET_CORE_IF(pcd);+	dwc_ep = &ep->dwc_ep;++	if (ep->iso_req_handle) {+		DWC_WARN("ISO request in progress\n");+	}++	dwc_ep->dma_addr0 = dma0;+	dwc_ep->dma_addr1 = dma1;++	dwc_ep->xfer_buff0 = buf0;+	dwc_ep->xfer_buff1 = buf1;++	dwc_ep->data_per_frame = data_per_frame;++	/** @todo - pattern data support is to be implemented in the future */+	dwc_ep->data_pattern_frame = dp_frame;+	dwc_ep->sync_frame = sync_frame;++	dwc_ep->buf_proc_intrvl = buf_proc_intrvl;++	dwc_ep->bInterval = 1 << (ep->desc->bInterval - 1);++	dwc_ep->proc_buf_num = 0;++	dwc_ep->pkt_per_frm = 0;+	frm_data = ep->dwc_ep.data_per_frame;+	while (frm_data > 0) {+		dwc_ep->pkt_per_frm++;+		frm_data -= ep->dwc_ep.maxpacket;+	}++	dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);++	if (start_frame == -1) {+		dwc_ep->next_frame = dsts.b.soffn + 1;+		if (dwc_ep->bInterval != 1) {+			dwc_ep->next_frame =+			    dwc_ep->next_frame + (dwc_ep->bInterval - 1 -+						  dwc_ep->next_frame %+						  dwc_ep->bInterval);+		}+	} else {+		dwc_ep->next_frame = start_frame;+	}++	if (!core_if->pti_enh_enable) {+		dwc_ep->pkt_cnt =+		    dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /+		    dwc_ep->bInterval;+	} else {+		dwc_ep->pkt_cnt =+		    (dwc_ep->data_per_frame *+		     (dwc_ep->buf_proc_intrvl / dwc_ep->bInterval)+		     - 1 + dwc_ep->maxpacket) / dwc_ep->maxpacket;+	}++	if (core_if->dma_desc_enable) {+		dwc_ep->desc_cnt =+		    dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /+		    dwc_ep->bInterval;+	}++	if (atomic_alloc) {+		dwc_ep->pkt_info =+		    DWC_ALLOC_ATOMIC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);+	} else {+		dwc_ep->pkt_info =+		    DWC_ALLOC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);+	}+	if (!dwc_ep->pkt_info) {+		DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);+		return -DWC_E_NO_MEMORY;+	}+	if (core_if->pti_enh_enable) {+		dwc_memset(dwc_ep->pkt_info, 0,+			   sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);+	}++	dwc_ep->cur_pkt = 0;+	ep->iso_req_handle = req_handle;++	DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);+	dwc_otg_iso_ep_start_transfer(core_if, dwc_ep);+	return 0;+}++int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,+			    void *req_handle)+{+	dwc_irqflags_t flags = 0;+	dwc_otg_pcd_ep_t *ep;+	dwc_ep_t *dwc_ep;++	ep = get_ep_from_handle(pcd, ep_handle);+	if (!ep || !ep->desc || ep->dwc_ep.num == 0) {+		DWC_WARN("bad ep\n");+		return -DWC_E_INVALID;+	}+	dwc_ep = &ep->dwc_ep;++	dwc_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), dwc_ep);++	DWC_FREE(dwc_ep->pkt_info);+	DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);+	if (ep->iso_req_handle != req_handle) {+		DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);+		return -DWC_E_INVALID;+	}++	DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);++	ep->iso_req_handle = 0;+	return 0;+}++/**+ * This function is used for perodical data exchnage between PCD and gadget drivers.+ * for Isochronous EPs+ *+ *	- Every time a sync period completes this function is called to+ *	  perform data exchange between PCD and gadget+ */+void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,+			     void *req_handle)+{+	int i;+	dwc_ep_t *dwc_ep;++	dwc_ep = &ep->dwc_ep;++	DWC_SPINUNLOCK(ep->pcd->lock);+	pcd->fops->isoc_complete(pcd, ep->priv, ep->iso_req_handle,+				 dwc_ep->proc_buf_num ^ 0x1);+	DWC_SPINLOCK(ep->pcd->lock);++	for (i = 0; i < dwc_ep->pkt_cnt; ++i) {+		dwc_ep->pkt_info[i].status = 0;+		dwc_ep->pkt_info[i].offset = 0;+		dwc_ep->pkt_info[i].length = 0;+	}+}++int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, void *ep_handle,+				     void *iso_req_handle)+{+	dwc_otg_pcd_ep_t *ep;+	dwc_ep_t *dwc_ep;++	ep = get_ep_from_handle(pcd, ep_handle);+	if (!ep->desc || ep->dwc_ep.num == 0) {+		DWC_WARN("bad ep\n");+		return -DWC_E_INVALID;+	}+	dwc_ep = &ep->dwc_ep;++	return dwc_ep->pkt_cnt;+}++void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, void *ep_handle,+				       void *iso_req_handle, int packet,+				       int *status, int *actual, int *offset)+{+	dwc_otg_pcd_ep_t *ep;+	dwc_ep_t *dwc_ep;++	ep = get_ep_from_handle(pcd, ep_handle);+	if (!ep)+		DWC_WARN("bad ep\n");++	dwc_ep = &ep->dwc_ep;++	*status = dwc_ep->pkt_info[packet].status;+	*actual = dwc_ep->pkt_info[packet].length;+	*offset = dwc_ep->pkt_info[packet].offset;+}++#endif /* DWC_EN_ISOC */++static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep,+				uint32_t is_in, uint32_t ep_num)+{+	/* Init EP structure */+	pcd_ep->desc = 0;+	pcd_ep->pcd = pcd;+	pcd_ep->stopped = 1;+	pcd_ep->queue_sof = 0;++	/* Init DWC ep structure */+	pcd_ep->dwc_ep.is_in = is_in;+	pcd_ep->dwc_ep.num = ep_num;+	pcd_ep->dwc_ep.active = 0;+	pcd_ep->dwc_ep.tx_fifo_num = 0;+	/* Control until ep is actvated */+	pcd_ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;+	pcd_ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;+	pcd_ep->dwc_ep.dma_addr = 0;+	pcd_ep->dwc_ep.start_xfer_buff = 0;+	pcd_ep->dwc_ep.xfer_buff = 0;+	pcd_ep->dwc_ep.xfer_len = 0;+	pcd_ep->dwc_ep.xfer_count = 0;+	pcd_ep->dwc_ep.sent_zlp = 0;+	pcd_ep->dwc_ep.total_len = 0;+	pcd_ep->dwc_ep.desc_addr = 0;+	pcd_ep->dwc_ep.dma_desc_addr = 0;+	DWC_CIRCLEQ_INIT(&pcd_ep->queue);+}++/**+ * Initialize ep's+ */+static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd)+{+	int i;+	uint32_t hwcfg1;+	dwc_otg_pcd_ep_t *ep;+	int in_ep_cntr, out_ep_cntr;+	uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps;+	uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps;++	/**+	 * Initialize the EP0 structure.+	 */+	ep = &pcd->ep0;+	dwc_otg_pcd_init_ep(pcd, ep, 0, 0);++	in_ep_cntr = 0;+	hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3;+	for (i = 1; in_ep_cntr < num_in_eps; i++) {+		if ((hwcfg1 & 0x1) == 0) {+			dwc_otg_pcd_ep_t *ep = &pcd->in_ep[in_ep_cntr];+			in_ep_cntr++;+			/**+			 * @todo NGS: Add direction to EP, based on contents+			 * of HWCFG1.  Need a copy of HWCFG1 in pcd structure?+			 * sprintf(";r+			 */+			dwc_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i);++			DWC_CIRCLEQ_INIT(&ep->queue);+		}+		hwcfg1 >>= 2;+	}++	out_ep_cntr = 0;+	hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2;+	for (i = 1; out_ep_cntr < num_out_eps; i++) {+		if ((hwcfg1 & 0x1) == 0) {+			dwc_otg_pcd_ep_t *ep = &pcd->out_ep[out_ep_cntr];+			out_ep_cntr++;+			/**+			 * @todo NGS: Add direction to EP, based on contents+			 * of HWCFG1.  Need a copy of HWCFG1 in pcd structure?+			 * sprintf(";r+			 */+			dwc_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i);+			DWC_CIRCLEQ_INIT(&ep->queue);+		}+		hwcfg1 >>= 2;+	}++	pcd->ep0state = EP0_DISCONNECT;+	pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE;+	pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;+}++/**+ * This function is called when the SRP timer expires. The SRP should+ * complete within 6 seconds.+ */+static void srp_timeout(void *ptr)+{+	gotgctl_data_t gotgctl;+	dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;+	volatile uint32_t *addr = &core_if->core_global_regs->gotgctl;++	gotgctl.d32 = DWC_READ_REG32(addr);++	core_if->srp_timer_started = 0;++	if (core_if->adp_enable) {+		if (gotgctl.b.bsesvld == 0) {+			gpwrdn_data_t gpwrdn = {.d32 = 0 };+			DWC_PRINTF("SRP Timeout BSESSVLD = 0\n");+			/* Power off the core */+			if (core_if->power_down == 2) {+				gpwrdn.b.pwrdnswtch = 1;+				DWC_MODIFY_REG32(&core_if->+						 core_global_regs->gpwrdn,+						 gpwrdn.d32, 0);+			}++			gpwrdn.d32 = 0;+			gpwrdn.b.pmuintsel = 1;+			gpwrdn.b.pmuactv = 1;+			DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,+					 gpwrdn.d32);+			dwc_otg_adp_probe_start(core_if);+		} else {+			DWC_PRINTF("SRP Timeout BSESSVLD = 1\n");+			core_if->op_state = B_PERIPHERAL;+			dwc_otg_core_init(core_if);+			dwc_otg_enable_global_interrupts(core_if);+			cil_pcd_start(core_if);+		}+	}++	if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) &&+	    (core_if->core_params->i2c_enable)) {+		DWC_PRINTF("SRP Timeout\n");++		if ((core_if->srp_success) && (gotgctl.b.bsesvld)) {+			if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {+				core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);+			}++			/* Clear Session Request */+			gotgctl.d32 = 0;+			gotgctl.b.sesreq = 1;+			DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl,+					 gotgctl.d32, 0);++			core_if->srp_success = 0;+		} else {+			__DWC_ERROR("Device not connected/responding\n");+			gotgctl.b.sesreq = 0;+			DWC_WRITE_REG32(addr, gotgctl.d32);+		}+	} else if (gotgctl.b.sesreq) {+		DWC_PRINTF("SRP Timeout\n");++		__DWC_ERROR("Device not connected/responding\n");+		gotgctl.b.sesreq = 0;+		DWC_WRITE_REG32(addr, gotgctl.d32);+	} else {+		DWC_PRINTF(" SRP GOTGCTL=%0x\n", gotgctl.d32);+	}+}++/**+ * Tasklet+ *+ */+extern void start_next_request(dwc_otg_pcd_ep_t * ep);++static void start_xfer_tasklet_func(void *data)+{+	dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);++	int i;+	depctl_data_t diepctl;++	DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n");++	diepctl.d32 = DWC_READ_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl);++	if (pcd->ep0.queue_sof) {+		pcd->ep0.queue_sof = 0;+		start_next_request(&pcd->ep0);+		// break;+	}++	for (i = 0; i < core_if->dev_if->num_in_eps; i++) {+		depctl_data_t diepctl;+		diepctl.d32 =+		    DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl);++		if (pcd->in_ep[i].queue_sof) {+			pcd->in_ep[i].queue_sof = 0;+			start_next_request(&pcd->in_ep[i]);+			// break;+		}+	}++	return;+}++/**+ * This function initialized the PCD portion of the driver.+ *+ */+dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if)+{+	dwc_otg_pcd_t *pcd = NULL;+	dwc_otg_dev_if_t *dev_if;+	int i;++	/*+	 * Allocate PCD structure+	 */+	pcd = DWC_ALLOC(sizeof(dwc_otg_pcd_t));++	if (pcd == NULL) {+		return NULL;+	}++	pcd->lock = DWC_SPINLOCK_ALLOC();+        DWC_DEBUGPL(DBG_HCDV, "Init of PCD %p given core_if %p\n",+                    pcd, core_if);//GRAYG+	if (!pcd->lock) {+		DWC_ERROR("Could not allocate lock for pcd");+		DWC_FREE(pcd);+		return NULL;+	}+	/* Set core_if's lock pointer to hcd->lock */+	core_if->lock = pcd->lock;+	pcd->core_if = core_if;++	dev_if = core_if->dev_if;+	dev_if->isoc_ep = NULL;++	if (core_if->hwcfg4.b.ded_fifo_en) {+		DWC_PRINTF("Dedicated Tx FIFOs mode\n");+	} else {+		DWC_PRINTF("Shared Tx FIFO mode\n");+	}++	/*+	 * Initialized the Core for Device mode here if there is nod ADP support.+	 * Otherwise it will be done later in dwc_otg_adp_start routine.+	 */+	if (dwc_otg_is_device_mode(core_if) /*&& !core_if->adp_enable*/) {+		dwc_otg_core_dev_init(core_if);+	}++	/*+	 * Register the PCD Callbacks.+	 */+	dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd);++	/*+	 * Initialize the DMA buffer for SETUP packets+	 */+	if (GET_CORE_IF(pcd)->dma_enable) {+		pcd->setup_pkt =+		    DWC_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5,+				  &pcd->setup_pkt_dma_handle);+		if (pcd->setup_pkt == NULL) {+			DWC_FREE(pcd);+			return NULL;+		}++		pcd->status_buf =+		    DWC_DMA_ALLOC(sizeof(uint16_t),+				  &pcd->status_buf_dma_handle);+		if (pcd->status_buf == NULL) {+			DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5,+				     pcd->setup_pkt, pcd->setup_pkt_dma_handle);+			DWC_FREE(pcd);+			return NULL;+		}++		if (GET_CORE_IF(pcd)->dma_desc_enable) {+			dev_if->setup_desc_addr[0] =+			    dwc_otg_ep_alloc_desc_chain+			    (&dev_if->dma_setup_desc_addr[0], 1);+			dev_if->setup_desc_addr[1] =+			    dwc_otg_ep_alloc_desc_chain+			    (&dev_if->dma_setup_desc_addr[1], 1);+			dev_if->in_desc_addr =+			    dwc_otg_ep_alloc_desc_chain+			    (&dev_if->dma_in_desc_addr, 1);+			dev_if->out_desc_addr =+			    dwc_otg_ep_alloc_desc_chain+			    (&dev_if->dma_out_desc_addr, 1);+			pcd->data_terminated = 0;++			if (dev_if->setup_desc_addr[0] == 0+			    || dev_if->setup_desc_addr[1] == 0+			    || dev_if->in_desc_addr == 0+			    || dev_if->out_desc_addr == 0) {++				if (dev_if->out_desc_addr)+					dwc_otg_ep_free_desc_chain+					    (dev_if->out_desc_addr,+					     dev_if->dma_out_desc_addr, 1);+				if (dev_if->in_desc_addr)+					dwc_otg_ep_free_desc_chain+					    (dev_if->in_desc_addr,+					     dev_if->dma_in_desc_addr, 1);+				if (dev_if->setup_desc_addr[1])+					dwc_otg_ep_free_desc_chain+					    (dev_if->setup_desc_addr[1],+					     dev_if->dma_setup_desc_addr[1], 1);+				if (dev_if->setup_desc_addr[0])+					dwc_otg_ep_free_desc_chain+					    (dev_if->setup_desc_addr[0],+					     dev_if->dma_setup_desc_addr[0], 1);++				DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5,+					     pcd->setup_pkt,+					     pcd->setup_pkt_dma_handle);+				DWC_DMA_FREE(sizeof(*pcd->status_buf),+					     pcd->status_buf,+					     pcd->status_buf_dma_handle);++				DWC_FREE(pcd);++				return NULL;+			}+		}+	} else {+		pcd->setup_pkt = DWC_ALLOC(sizeof(*pcd->setup_pkt) * 5);+		if (pcd->setup_pkt == NULL) {+			DWC_FREE(pcd);+			return NULL;+		}++		pcd->status_buf = DWC_ALLOC(sizeof(uint16_t));+		if (pcd->status_buf == NULL) {+			DWC_FREE(pcd->setup_pkt);+			DWC_FREE(pcd);+			return NULL;+		}+	}++	dwc_otg_pcd_reinit(pcd);++	/* Allocate the cfi object for the PCD */+#ifdef DWC_UTE_CFI+	pcd->cfi = DWC_ALLOC(sizeof(cfiobject_t));+	if (NULL == pcd->cfi)+		goto fail;+	if (init_cfi(pcd->cfi)) {+		CFI_INFO("%s: Failed to init the CFI object\n", __func__);+		goto fail;+	}+#endif++	/* Initialize tasklets */+	pcd->start_xfer_tasklet = DWC_TASK_ALLOC("xfer_tasklet",+						 start_xfer_tasklet_func, pcd);+	pcd->test_mode_tasklet = DWC_TASK_ALLOC("test_mode_tasklet",+						do_test_mode, pcd);++	/* Initialize SRP timer */+	core_if->srp_timer = DWC_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if);++	if (core_if->core_params->dev_out_nak) {+		/**+		* Initialize xfer timeout timer. Implemented for+		* 2.93a feature "Device DDMA OUT NAK Enhancement"+		*/+		for(i = 0; i < MAX_EPS_CHANNELS; i++) {+			pcd->core_if->ep_xfer_timer[i] =+				DWC_TIMER_ALLOC("ep timer", ep_xfer_timeout,+				&pcd->core_if->ep_xfer_info[i]);+		}+	}++	return pcd;+#ifdef DWC_UTE_CFI+fail:+#endif+	if (pcd->setup_pkt)+		DWC_FREE(pcd->setup_pkt);+	if (pcd->status_buf)+		DWC_FREE(pcd->status_buf);+#ifdef DWC_UTE_CFI+	if (pcd->cfi)+		DWC_FREE(pcd->cfi);+#endif+	if (pcd)+		DWC_FREE(pcd);+	return NULL;++}++/**+ * Remove PCD specific data+ */+void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd)+{+	dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;+	int i;+	if (pcd->core_if->core_params->dev_out_nak) {+		for (i = 0; i < MAX_EPS_CHANNELS; i++) {+			DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]);+			pcd->core_if->ep_xfer_info[i].state = 0;+		}+	}++	if (GET_CORE_IF(pcd)->dma_enable) {+		DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt,+			     pcd->setup_pkt_dma_handle);+		DWC_DMA_FREE(sizeof(uint16_t), pcd->status_buf,+			     pcd->status_buf_dma_handle);+		if (GET_CORE_IF(pcd)->dma_desc_enable) {+			dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0],+						   dev_if->dma_setup_desc_addr+						   [0], 1);+			dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1],+						   dev_if->dma_setup_desc_addr+						   [1], 1);+			dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr,+						   dev_if->dma_in_desc_addr, 1);+			dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr,+						   dev_if->dma_out_desc_addr,+						   1);+		}+	} else {+		DWC_FREE(pcd->setup_pkt);+		DWC_FREE(pcd->status_buf);+	}+	DWC_SPINLOCK_FREE(pcd->lock);+	/* Set core_if's lock pointer to NULL */+	pcd->core_if->lock = NULL;++	DWC_TASK_FREE(pcd->start_xfer_tasklet);+	DWC_TASK_FREE(pcd->test_mode_tasklet);+	if (pcd->core_if->core_params->dev_out_nak) {+		for (i = 0; i < MAX_EPS_CHANNELS; i++) {+			if (pcd->core_if->ep_xfer_timer[i]) {+					DWC_TIMER_FREE(pcd->core_if->ep_xfer_timer[i]);+			}+		}+	}++/* Release the CFI object's dynamic memory */+#ifdef DWC_UTE_CFI+	if (pcd->cfi->ops.release) {+		pcd->cfi->ops.release(pcd->cfi);+	}+#endif++	DWC_FREE(pcd);+}++/**+ * Returns whether registered pcd is dual speed or not+ */+uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);++	if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) ||+	    ((core_if->hwcfg2.b.hs_phy_type == 2) &&+	     (core_if->hwcfg2.b.fs_phy_type == 1) &&+	     (core_if->core_params->ulpi_fs_ls))) {+		return 0;+	}++	return 1;+}++/**+ * Returns whether registered pcd is OTG capable or not+ */+uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	gusbcfg_data_t usbcfg = {.d32 = 0 };++	usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);+	if (!usbcfg.b.srpcap || !usbcfg.b.hnpcap) {+		return 0;+	}++	return 1;+}++/**+ * This function assigns periodic Tx FIFO to an periodic EP+ * in shared Tx FIFO mode+ */+static uint32_t assign_tx_fifo(dwc_otg_core_if_t * core_if)+{+	uint32_t TxMsk = 1;+	int i;++	for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++i) {+		if ((TxMsk & core_if->tx_msk) == 0) {+			core_if->tx_msk |= TxMsk;+			return i + 1;+		}+		TxMsk <<= 1;+	}+	return 0;+}++/**+ * This function assigns periodic Tx FIFO to an periodic EP+ * in shared Tx FIFO mode+ */+static uint32_t assign_perio_tx_fifo(dwc_otg_core_if_t * core_if)+{+	uint32_t PerTxMsk = 1;+	int i;+	for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; ++i) {+		if ((PerTxMsk & core_if->p_tx_msk) == 0) {+			core_if->p_tx_msk |= PerTxMsk;+			return i + 1;+		}+		PerTxMsk <<= 1;+	}+	return 0;+}++/**+ * This function releases periodic Tx FIFO+ * in shared Tx FIFO mode+ */+static void release_perio_tx_fifo(dwc_otg_core_if_t * core_if,+				  uint32_t fifo_num)+{+	core_if->p_tx_msk =+	    (core_if->p_tx_msk & (1 << (fifo_num - 1))) ^ core_if->p_tx_msk;+}++/**+ * This function releases periodic Tx FIFO+ * in shared Tx FIFO mode+ */+static void release_tx_fifo(dwc_otg_core_if_t * core_if, uint32_t fifo_num)+{+	core_if->tx_msk =+	    (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk;+}++/**+ * This function is being called from gadget+ * to enable PCD endpoint.+ */+int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,+			  const uint8_t * ep_desc, void *usb_ep)+{+	int num, dir;+	dwc_otg_pcd_ep_t *ep = NULL;+	const usb_endpoint_descriptor_t *desc;+	dwc_irqflags_t flags;+	fifosize_data_t dptxfsiz = {.d32 = 0 };+	gdfifocfg_data_t gdfifocfg = {.d32 = 0 };+	gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 };+	int retval = 0;+	int i, epcount;++	desc = (const usb_endpoint_descriptor_t *)ep_desc;++	if (!desc) {+		pcd->ep0.priv = usb_ep;+		ep = &pcd->ep0;+		retval = -DWC_E_INVALID;+		goto out;+	}++	num = UE_GET_ADDR(desc->bEndpointAddress);+	dir = UE_GET_DIR(desc->bEndpointAddress);++	if (!desc->wMaxPacketSize) {+		DWC_WARN("bad maxpacketsize\n");+		retval = -DWC_E_INVALID;+		goto out;+	}++	if (dir == UE_DIR_IN) {+		epcount = pcd->core_if->dev_if->num_in_eps;+		for (i = 0; i < epcount; i++) {+			if (num == pcd->in_ep[i].dwc_ep.num) {+				ep = &pcd->in_ep[i];+				break;+			}+		}+	} else {+		epcount = pcd->core_if->dev_if->num_out_eps;+		for (i = 0; i < epcount; i++) {+			if (num == pcd->out_ep[i].dwc_ep.num) {+				ep = &pcd->out_ep[i];+				break;+			}+		}+	}++	if (!ep) {+		DWC_WARN("bad address\n");+		retval = -DWC_E_INVALID;+		goto out;+	}++	DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);++	ep->desc = desc;+	ep->priv = usb_ep;++	/*+	 * Activate the EP+	 */+	ep->stopped = 0;++	ep->dwc_ep.is_in = (dir == UE_DIR_IN);+	ep->dwc_ep.maxpacket = UGETW(desc->wMaxPacketSize);++	ep->dwc_ep.type = desc->bmAttributes & UE_XFERTYPE;++	if (ep->dwc_ep.is_in) {+		if (!GET_CORE_IF(pcd)->en_multiple_tx_fifo) {+			ep->dwc_ep.tx_fifo_num = 0;++			if (ep->dwc_ep.type == UE_ISOCHRONOUS) {+				/*+				 * if ISOC EP then assign a Periodic Tx FIFO.+				 */+				ep->dwc_ep.tx_fifo_num =+				    assign_perio_tx_fifo(GET_CORE_IF(pcd));+			}+		} else {+			/*+			 * if Dedicated FIFOs mode is on then assign a Tx FIFO.+			 */+			ep->dwc_ep.tx_fifo_num =+			    assign_tx_fifo(GET_CORE_IF(pcd));+		}++		/* Calculating EP info controller base address */+		if (ep->dwc_ep.tx_fifo_num+		    && GET_CORE_IF(pcd)->en_multiple_tx_fifo) {+			gdfifocfg.d32 =+			    DWC_READ_REG32(&GET_CORE_IF(pcd)->+					   core_global_regs->gdfifocfg);+			gdfifocfgbase.d32 = gdfifocfg.d32 >> 16;+			dptxfsiz.d32 =+			    (DWC_READ_REG32+			     (&GET_CORE_IF(pcd)->core_global_regs->+			      dtxfsiz[ep->dwc_ep.tx_fifo_num - 1]) >> 16);+			gdfifocfg.b.epinfobase =+			    gdfifocfgbase.d32 + dptxfsiz.d32;+			if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) {+				DWC_WRITE_REG32(&GET_CORE_IF(pcd)->+						core_global_regs->gdfifocfg,+						gdfifocfg.d32);+			}+		}+	}+	/* Set initial data PID. */+	if (ep->dwc_ep.type == UE_BULK) {+		ep->dwc_ep.data_pid_start = 0;+	}++	/* Alloc DMA Descriptors */+	if (GET_CORE_IF(pcd)->dma_desc_enable) {+#ifndef DWC_UTE_PER_IO+		if (ep->dwc_ep.type != UE_ISOCHRONOUS) {+#endif+			ep->dwc_ep.desc_addr =+			    dwc_otg_ep_alloc_desc_chain(&ep->+							dwc_ep.dma_desc_addr,+							MAX_DMA_DESC_CNT);+			if (!ep->dwc_ep.desc_addr) {+				DWC_WARN("%s, can't allocate DMA descriptor\n",+					 __func__);+				retval = -DWC_E_SHUTDOWN;+				DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);+				goto out;+			}+#ifndef DWC_UTE_PER_IO+		}+#endif+	}++	DWC_DEBUGPL(DBG_PCD, "Activate %s: type=%d, mps=%d desc=%p\n",+		    (ep->dwc_ep.is_in ? "IN" : "OUT"),+		    ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc);+#ifdef DWC_UTE_PER_IO+	ep->dwc_ep.xiso_bInterval = 1 << (ep->desc->bInterval - 1);+#endif+	if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {+		ep->dwc_ep.bInterval = 1 << (ep->desc->bInterval - 1);+		ep->dwc_ep.frame_num = 0xFFFFFFFF;+	}++	dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);++#ifdef DWC_UTE_CFI+	if (pcd->cfi->ops.ep_enable) {+		pcd->cfi->ops.ep_enable(pcd->cfi, pcd, ep);+	}+#endif++	DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);++out:+	return retval;+}++/**+ * This function is being called from gadget+ * to disable PCD endpoint.+ */+int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle)+{+	dwc_otg_pcd_ep_t *ep;+	dwc_irqflags_t flags;+	dwc_otg_dev_dma_desc_t *desc_addr;+	dwc_dma_t dma_desc_addr;+	gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 };+	gdfifocfg_data_t gdfifocfg = {.d32 = 0 };+	fifosize_data_t dptxfsiz = {.d32 = 0 };++	ep = get_ep_from_handle(pcd, ep_handle);++	if (!ep || !ep->desc) {+		DWC_DEBUGPL(DBG_PCD, "bad ep address\n");+		return -DWC_E_INVALID;+	}++	DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);++	dwc_otg_request_nuke(ep);++	dwc_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->dwc_ep);+	if (pcd->core_if->core_params->dev_out_nak) {+		DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[ep->dwc_ep.num]);+		pcd->core_if->ep_xfer_info[ep->dwc_ep.num].state = 0;+	}+	ep->desc = NULL;+	ep->stopped = 1;++	gdfifocfg.d32 =+	    DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg);+	gdfifocfgbase.d32 = gdfifocfg.d32 >> 16;++	if (ep->dwc_ep.is_in) {+		if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) {+			/* Flush the Tx FIFO */+			dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd),+					      ep->dwc_ep.tx_fifo_num);+		}+		release_perio_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);+		release_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);+		if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) {+			/* Decreasing EPinfo Base Addr */+			dptxfsiz.d32 =+			    (DWC_READ_REG32+			     (&GET_CORE_IF(pcd)->+				core_global_regs->dtxfsiz[ep->dwc_ep.tx_fifo_num-1]) >> 16);+			gdfifocfg.b.epinfobase = gdfifocfgbase.d32 - dptxfsiz.d32;+			if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) {+				DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg,+					gdfifocfg.d32);+			}+		}+	}++	/* Free DMA Descriptors */+	if (GET_CORE_IF(pcd)->dma_desc_enable) {+		if (ep->dwc_ep.type != UE_ISOCHRONOUS) {+			desc_addr = ep->dwc_ep.desc_addr;+			dma_desc_addr = ep->dwc_ep.dma_desc_addr;++			/* Cannot call dma_free_coherent() with IRQs disabled */+			DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);+			dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr,+						   MAX_DMA_DESC_CNT);++			goto out_unlocked;+		}+	}+	DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);++out_unlocked:+	DWC_DEBUGPL(DBG_PCD, "%d %s disabled\n", ep->dwc_ep.num,+		    ep->dwc_ep.is_in ? "IN" : "OUT");+	return 0;++}++/******************************************************************************/+#ifdef DWC_UTE_PER_IO++/**+ * Free the request and its extended parts+ *+ */+void dwc_pcd_xiso_ereq_free(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req)+{+	DWC_FREE(req->ext_req.per_io_frame_descs);+	DWC_FREE(req);+}++/**+ * Start the next request in the endpoint's queue.+ *+ */+int dwc_otg_pcd_xiso_start_next_request(dwc_otg_pcd_t * pcd,+					dwc_otg_pcd_ep_t * ep)+{+	int i;+	dwc_otg_pcd_request_t *req = NULL;+	dwc_ep_t *dwcep = NULL;+	struct dwc_iso_xreq_port *ereq = NULL;+	struct dwc_iso_pkt_desc_port *ddesc_iso;+	uint16_t nat;+	depctl_data_t diepctl;++	dwcep = &ep->dwc_ep;++	if (dwcep->xiso_active_xfers > 0) {+#if 0	//Disable this to decrease s/w overhead that is crucial for Isoc transfers+		DWC_WARN("There are currently active transfers for EP%d \+				(active=%d; queued=%d)", dwcep->num, dwcep->xiso_active_xfers,+				dwcep->xiso_queued_xfers);+#endif+		return 0;+	}++	nat = UGETW(ep->desc->wMaxPacketSize);+	nat = (nat >> 11) & 0x03;++	if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {+		req = DWC_CIRCLEQ_FIRST(&ep->queue);+		ereq = &req->ext_req;+		ep->stopped = 0;++		/* Get the frame number */+		dwcep->xiso_frame_num =+		    dwc_otg_get_frame_number(GET_CORE_IF(pcd));+		DWC_DEBUG("FRM_NUM=%d", dwcep->xiso_frame_num);++		ddesc_iso = ereq->per_io_frame_descs;++		if (dwcep->is_in) {+			/* Setup DMA Descriptor chain for IN Isoc request */+			for (i = 0; i < ereq->pio_pkt_count; i++) {+				//if ((i % (nat + 1)) == 0)+				if ( i > 0 )+					dwcep->xiso_frame_num =+					    (dwcep->xiso_bInterval ++										dwcep->xiso_frame_num) & 0x3FFF;+				dwcep->desc_addr[i].buf =+				    req->dma + ddesc_iso[i].offset;+				dwcep->desc_addr[i].status.b_iso_in.txbytes =+				    ddesc_iso[i].length;+				dwcep->desc_addr[i].status.b_iso_in.framenum =+				    dwcep->xiso_frame_num;+				dwcep->desc_addr[i].status.b_iso_in.bs =+				    BS_HOST_READY;+				dwcep->desc_addr[i].status.b_iso_in.txsts = 0;+				dwcep->desc_addr[i].status.b_iso_in.sp =+				    (ddesc_iso[i].length %+				     dwcep->maxpacket) ? 1 : 0;+				dwcep->desc_addr[i].status.b_iso_in.ioc = 0;+				dwcep->desc_addr[i].status.b_iso_in.pid = nat + 1;+				dwcep->desc_addr[i].status.b_iso_in.l = 0;++				/* Process the last descriptor */+				if (i == ereq->pio_pkt_count - 1) {+					dwcep->desc_addr[i].status.b_iso_in.ioc = 1;+					dwcep->desc_addr[i].status.b_iso_in.l = 1;+				}+			}++			/* Setup and start the transfer for this endpoint */+			dwcep->xiso_active_xfers++;+			DWC_WRITE_REG32(&GET_CORE_IF(pcd)->dev_if->+					in_ep_regs[dwcep->num]->diepdma,+					dwcep->dma_desc_addr);+			diepctl.d32 = 0;+			diepctl.b.epena = 1;+			diepctl.b.cnak = 1;+			DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if->+					 in_ep_regs[dwcep->num]->diepctl, 0,+					 diepctl.d32);+		} else {+			/* Setup DMA Descriptor chain for OUT Isoc request */+			for (i = 0; i < ereq->pio_pkt_count; i++) {+				//if ((i % (nat + 1)) == 0)+				dwcep->xiso_frame_num = (dwcep->xiso_bInterval ++										dwcep->xiso_frame_num) & 0x3FFF;+				dwcep->desc_addr[i].buf =+				    req->dma + ddesc_iso[i].offset;+				dwcep->desc_addr[i].status.b_iso_out.rxbytes =+				    ddesc_iso[i].length;+				dwcep->desc_addr[i].status.b_iso_out.framenum =+				    dwcep->xiso_frame_num;+				dwcep->desc_addr[i].status.b_iso_out.bs =+				    BS_HOST_READY;+				dwcep->desc_addr[i].status.b_iso_out.rxsts = 0;+				dwcep->desc_addr[i].status.b_iso_out.sp =+				    (ddesc_iso[i].length %+				     dwcep->maxpacket) ? 1 : 0;+				dwcep->desc_addr[i].status.b_iso_out.ioc = 0;+				dwcep->desc_addr[i].status.b_iso_out.pid = nat + 1;+				dwcep->desc_addr[i].status.b_iso_out.l = 0;++				/* Process the last descriptor */+				if (i == ereq->pio_pkt_count - 1) {+					dwcep->desc_addr[i].status.b_iso_out.ioc = 1;+					dwcep->desc_addr[i].status.b_iso_out.l = 1;+				}+			}++			/* Setup and start the transfer for this endpoint */+			dwcep->xiso_active_xfers++;+			DWC_WRITE_REG32(&GET_CORE_IF(pcd)->+					dev_if->out_ep_regs[dwcep->num]->+					doepdma, dwcep->dma_desc_addr);+			diepctl.d32 = 0;+			diepctl.b.epena = 1;+			diepctl.b.cnak = 1;+			DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->+					 dev_if->out_ep_regs[dwcep->num]->+					 doepctl, 0, diepctl.d32);+		}++	} else {+		ep->stopped = 1;+	}++	return 0;+}++/**+ *	- Remove the request from the queue+ */+void complete_xiso_ep(dwc_otg_pcd_ep_t * ep)+{+	dwc_otg_pcd_request_t *req = NULL;+	struct dwc_iso_xreq_port *ereq = NULL;+	struct dwc_iso_pkt_desc_port *ddesc_iso = NULL;+	dwc_ep_t *dwcep = NULL;+	int i;++	//DWC_DEBUG();+	dwcep = &ep->dwc_ep;++	/* Get the first pending request from the queue */+	if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {+		req = DWC_CIRCLEQ_FIRST(&ep->queue);+		if (!req) {+			DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);+			return;+		}+		dwcep->xiso_active_xfers--;+		dwcep->xiso_queued_xfers--;+		/* Remove this request from the queue */+		DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);+	} else {+		DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);+		return;+	}++	ep->stopped = 1;+	ereq = &req->ext_req;+	ddesc_iso = ereq->per_io_frame_descs;++	if (dwcep->xiso_active_xfers < 0) {+		DWC_WARN("EP#%d (xiso_active_xfers=%d)", dwcep->num,+			 dwcep->xiso_active_xfers);+	}++	/* Fill the Isoc descs of portable extended req from dma descriptors */+	for (i = 0; i < ereq->pio_pkt_count; i++) {+		if (dwcep->is_in) {	/* IN endpoints */+			ddesc_iso[i].actual_length = ddesc_iso[i].length -+			    dwcep->desc_addr[i].status.b_iso_in.txbytes;+			ddesc_iso[i].status =+			    dwcep->desc_addr[i].status.b_iso_in.txsts;+		} else {	/* OUT endpoints */+			ddesc_iso[i].actual_length = ddesc_iso[i].length -+			    dwcep->desc_addr[i].status.b_iso_out.rxbytes;+			ddesc_iso[i].status =+			    dwcep->desc_addr[i].status.b_iso_out.rxsts;+		}+	}++	DWC_SPINUNLOCK(ep->pcd->lock);++	/* Call the completion function in the non-portable logic */+	ep->pcd->fops->xisoc_complete(ep->pcd, ep->priv, req->priv, 0,+				      &req->ext_req);++	DWC_SPINLOCK(ep->pcd->lock);++	/* Free the request - specific freeing needed for extended request object */+	dwc_pcd_xiso_ereq_free(ep, req);++	/* Start the next request */+	dwc_otg_pcd_xiso_start_next_request(ep->pcd, ep);++	return;+}++/**+ * Create and initialize the Isoc pkt descriptors of the extended request.+ *+ */+static int dwc_otg_pcd_xiso_create_pkt_descs(dwc_otg_pcd_request_t * req,+					     void *ereq_nonport,+					     int atomic_alloc)+{+	struct dwc_iso_xreq_port *ereq = NULL;+	struct dwc_iso_xreq_port *req_mapped = NULL;+	struct dwc_iso_pkt_desc_port *ipds = NULL;	/* To be created in this function */+	uint32_t pkt_count;+	int i;++	ereq = &req->ext_req;+	req_mapped = (struct dwc_iso_xreq_port *)ereq_nonport;+	pkt_count = req_mapped->pio_pkt_count;++	/* Create the isoc descs */+	if (atomic_alloc) {+		ipds = DWC_ALLOC_ATOMIC(sizeof(*ipds) * pkt_count);+	} else {+		ipds = DWC_ALLOC(sizeof(*ipds) * pkt_count);+	}++	if (!ipds) {+		DWC_ERROR("Failed to allocate isoc descriptors");+		return -DWC_E_NO_MEMORY;+	}++	/* Initialize the extended request fields */+	ereq->per_io_frame_descs = ipds;+	ereq->error_count = 0;+	ereq->pio_alloc_pkt_count = pkt_count;+	ereq->pio_pkt_count = pkt_count;+	ereq->tr_sub_flags = req_mapped->tr_sub_flags;++	/* Init the Isoc descriptors */+	for (i = 0; i < pkt_count; i++) {+		ipds[i].length = req_mapped->per_io_frame_descs[i].length;+		ipds[i].offset = req_mapped->per_io_frame_descs[i].offset;+		ipds[i].status = req_mapped->per_io_frame_descs[i].status;	/* 0 */+		ipds[i].actual_length =+		    req_mapped->per_io_frame_descs[i].actual_length;+	}++	return 0;+}++static void prn_ext_request(struct dwc_iso_xreq_port *ereq)+{+	struct dwc_iso_pkt_desc_port *xfd = NULL;+	int i;++	DWC_DEBUG("per_io_frame_descs=%p", ereq->per_io_frame_descs);+	DWC_DEBUG("tr_sub_flags=%d", ereq->tr_sub_flags);+	DWC_DEBUG("error_count=%d", ereq->error_count);+	DWC_DEBUG("pio_alloc_pkt_count=%d", ereq->pio_alloc_pkt_count);+	DWC_DEBUG("pio_pkt_count=%d", ereq->pio_pkt_count);+	DWC_DEBUG("res=%d", ereq->res);++	for (i = 0; i < ereq->pio_pkt_count; i++) {+		xfd = &ereq->per_io_frame_descs[0];+		DWC_DEBUG("FD #%d", i);++		DWC_DEBUG("xfd->actual_length=%d", xfd->actual_length);+		DWC_DEBUG("xfd->length=%d", xfd->length);+		DWC_DEBUG("xfd->offset=%d", xfd->offset);+		DWC_DEBUG("xfd->status=%d", xfd->status);+	}+}++/**+ *+ */+int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,+			      uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,+			      int zero, void *req_handle, int atomic_alloc,+			      void *ereq_nonport)+{+	dwc_otg_pcd_request_t *req = NULL;+	dwc_otg_pcd_ep_t *ep;+	dwc_irqflags_t flags;+	int res;++	ep = get_ep_from_handle(pcd, ep_handle);+	if (!ep) {+		DWC_WARN("bad ep\n");+		return -DWC_E_INVALID;+	}++	/* We support this extension only for DDMA mode */+	if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)+		if (!GET_CORE_IF(pcd)->dma_desc_enable)+			return -DWC_E_INVALID;++	/* Create a dwc_otg_pcd_request_t object */+	if (atomic_alloc) {+		req = DWC_ALLOC_ATOMIC(sizeof(*req));+	} else {+		req = DWC_ALLOC(sizeof(*req));+	}++	if (!req) {+		return -DWC_E_NO_MEMORY;+	}++	/* Create the Isoc descs for this request which shall be the exact match+	 * of the structure sent to us from the non-portable logic */+	res =+	    dwc_otg_pcd_xiso_create_pkt_descs(req, ereq_nonport, atomic_alloc);+	if (res) {+		DWC_WARN("Failed to init the Isoc descriptors");+		DWC_FREE(req);+		return res;+	}++	DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);++	DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);+	req->buf = buf;+	req->dma = dma_buf;+	req->length = buflen;+	req->sent_zlp = zero;+	req->priv = req_handle;++	//DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);+	ep->dwc_ep.dma_addr = dma_buf;+	ep->dwc_ep.start_xfer_buff = buf;+	ep->dwc_ep.xfer_buff = buf;+	ep->dwc_ep.xfer_len = 0;+	ep->dwc_ep.xfer_count = 0;+	ep->dwc_ep.sent_zlp = 0;+	ep->dwc_ep.total_len = buflen;++	/* Add this request to the tail */+	DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);+	ep->dwc_ep.xiso_queued_xfers++;++//DWC_DEBUG("CP_0");+//DWC_DEBUG("req->ext_req.tr_sub_flags=%d", req->ext_req.tr_sub_flags);+//prn_ext_request((struct dwc_iso_xreq_port *) ereq_nonport);+//prn_ext_request(&req->ext_req);++	//DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);++	/* If the req->status == ASAP  then check if there is any active transfer+	 * for this endpoint. If no active transfers, then get the first entry+	 * from the queue and start that transfer+	 */+	if (req->ext_req.tr_sub_flags == DWC_EREQ_TF_ASAP) {+		res = dwc_otg_pcd_xiso_start_next_request(pcd, ep);+		if (res) {+			DWC_WARN("Failed to start the next Isoc transfer");+			DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);+			DWC_FREE(req);+			return res;+		}+	}++	DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);+	return 0;+}++#endif+/* END ifdef DWC_UTE_PER_IO ***************************************************/+int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,+			 uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,+			 int zero, void *req_handle, int atomic_alloc)+{+	dwc_irqflags_t flags;+	dwc_otg_pcd_request_t *req;+	dwc_otg_pcd_ep_t *ep;+	uint32_t max_transfer;++	ep = get_ep_from_handle(pcd, ep_handle);+	if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) {+		DWC_WARN("bad ep\n");+		return -DWC_E_INVALID;+	}++	if (atomic_alloc) {+		req = DWC_ALLOC_ATOMIC(sizeof(*req));+	} else {+		req = DWC_ALLOC(sizeof(*req));+	}++	if (!req) {+		return -DWC_E_NO_MEMORY;+	}+	DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);+	if (!GET_CORE_IF(pcd)->core_params->opt) {+		if (ep->dwc_ep.num != 0) {+			DWC_ERROR("queue req %p, len %d buf %p\n",+				  req_handle, buflen, buf);+		}+	}++	req->buf = buf;+	req->dma = dma_buf;+	req->length = buflen;+	req->sent_zlp = zero;+	req->priv = req_handle;+	req->dw_align_buf = NULL;+	if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable+			&& !GET_CORE_IF(pcd)->dma_desc_enable)+		req->dw_align_buf = DWC_DMA_ALLOC(buflen,+				 &req->dw_align_buf_dma);+	DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);++	/*+	 * After adding request to the queue for IN ISOC wait for In Token Received+	 * when TX FIFO is empty interrupt and for OUT ISOC wait for OUT Token+	 * Received when EP is disabled interrupt to obtain starting microframe+	 * (odd/even) start transfer+	 */+	if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {+		if (req != 0) {+			depctl_data_t depctl = {.d32 =+				    DWC_READ_REG32(&pcd->core_if->dev_if->+						   in_ep_regs[ep->dwc_ep.num]->+						   diepctl) };+			++pcd->request_pending;++			DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);+			if (ep->dwc_ep.is_in) {+				depctl.b.cnak = 1;+				DWC_WRITE_REG32(&pcd->core_if->dev_if->+						in_ep_regs[ep->dwc_ep.num]->+						diepctl, depctl.d32);+			}++			DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);+		}+		return 0;+	}++	/*+	 * For EP0 IN without premature status, zlp is required?+	 */+	if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) {+		DWC_DEBUGPL(DBG_PCDV, "%d-OUT ZLP\n", ep->dwc_ep.num);+		//_req->zero = 1;+	}++	/* Start the transfer */+	if (DWC_CIRCLEQ_EMPTY(&ep->queue) && !ep->stopped) {+		/* EP0 Transfer? */+		if (ep->dwc_ep.num == 0) {+			switch (pcd->ep0state) {+			case EP0_IN_DATA_PHASE:+				DWC_DEBUGPL(DBG_PCD,+					    "%s ep0: EP0_IN_DATA_PHASE\n",+					    __func__);+				break;++			case EP0_OUT_DATA_PHASE:+				DWC_DEBUGPL(DBG_PCD,+					    "%s ep0: EP0_OUT_DATA_PHASE\n",+					    __func__);+				if (pcd->request_config) {+					/* Complete STATUS PHASE */+					ep->dwc_ep.is_in = 1;+					pcd->ep0state = EP0_IN_STATUS_PHASE;+				}+				break;++			case EP0_IN_STATUS_PHASE:+				DWC_DEBUGPL(DBG_PCD,+					    "%s ep0: EP0_IN_STATUS_PHASE\n",+					    __func__);+				break;++			default:+				DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n",+					    pcd->ep0state);+				DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);+				return -DWC_E_SHUTDOWN;+			}++			ep->dwc_ep.dma_addr = dma_buf;+			ep->dwc_ep.start_xfer_buff = buf;+			ep->dwc_ep.xfer_buff = buf;+			ep->dwc_ep.xfer_len = buflen;+			ep->dwc_ep.xfer_count = 0;+			ep->dwc_ep.sent_zlp = 0;+			ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;++			if (zero) {+				if ((ep->dwc_ep.xfer_len %+				     ep->dwc_ep.maxpacket == 0)+				    && (ep->dwc_ep.xfer_len != 0)) {+					ep->dwc_ep.sent_zlp = 1;+				}++			}++			dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),+						   &ep->dwc_ep);+		}		// non-ep0 endpoints+		else {+#ifdef DWC_UTE_CFI+			if (ep->dwc_ep.buff_mode != BM_STANDARD) {+				/* store the request length */+				ep->dwc_ep.cfi_req_len = buflen;+				pcd->cfi->ops.build_descriptors(pcd->cfi, pcd,+								ep, req);+			} else {+#endif+				max_transfer =+				    GET_CORE_IF(ep->pcd)->core_params->+				    max_transfer_size;++				/* Setup and start the Transfer */+				if (req->dw_align_buf){+					if (ep->dwc_ep.is_in)+						dwc_memcpy(req->dw_align_buf,+							   buf, buflen);+					ep->dwc_ep.dma_addr =+					    req->dw_align_buf_dma;+					ep->dwc_ep.start_xfer_buff =+					    req->dw_align_buf;+					ep->dwc_ep.xfer_buff =+					    req->dw_align_buf;+				} else {+					ep->dwc_ep.dma_addr = dma_buf;+					ep->dwc_ep.start_xfer_buff = buf;+                                        ep->dwc_ep.xfer_buff = buf;+				}+				ep->dwc_ep.xfer_len = 0;+				ep->dwc_ep.xfer_count = 0;+				ep->dwc_ep.sent_zlp = 0;+				ep->dwc_ep.total_len = buflen;++				ep->dwc_ep.maxxfer = max_transfer;+				if (GET_CORE_IF(pcd)->dma_desc_enable) {+					uint32_t out_max_xfer =+					    DDMA_MAX_TRANSFER_SIZE -+					    (DDMA_MAX_TRANSFER_SIZE % 4);+					if (ep->dwc_ep.is_in) {+						if (ep->dwc_ep.maxxfer >+						    DDMA_MAX_TRANSFER_SIZE) {+							ep->dwc_ep.maxxfer =+							    DDMA_MAX_TRANSFER_SIZE;+						}+					} else {+						if (ep->dwc_ep.maxxfer >+						    out_max_xfer) {+							ep->dwc_ep.maxxfer =+							    out_max_xfer;+						}+					}+				}+				if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {+					ep->dwc_ep.maxxfer -=+					    (ep->dwc_ep.maxxfer %+					     ep->dwc_ep.maxpacket);+				}++				if (zero) {+					if ((ep->dwc_ep.total_len %+					     ep->dwc_ep.maxpacket == 0)+					    && (ep->dwc_ep.total_len != 0)) {+						ep->dwc_ep.sent_zlp = 1;+					}+				}+#ifdef DWC_UTE_CFI+			}+#endif+			dwc_otg_ep_start_transfer(GET_CORE_IF(pcd),+						  &ep->dwc_ep);+		}+	}++	if (req != 0) {+		++pcd->request_pending;+		DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);+		if (ep->dwc_ep.is_in && ep->stopped+		    && !(GET_CORE_IF(pcd)->dma_enable)) {+			/** @todo NGS Create a function for this. */+			diepmsk_data_t diepmsk = {.d32 = 0 };+			diepmsk.b.intktxfemp = 1;+			if (GET_CORE_IF(pcd)->multiproc_int_enable) {+				DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->+						 dev_if->dev_global_regs->diepeachintmsk+						 [ep->dwc_ep.num], 0,+						 diepmsk.d32);+			} else {+				DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->+						 dev_if->dev_global_regs->+						 diepmsk, 0, diepmsk.d32);+			}++		}+	}+	DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);++	return 0;+}++int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,+			   void *req_handle)+{+	dwc_irqflags_t flags;+	dwc_otg_pcd_request_t *req;+	dwc_otg_pcd_ep_t *ep;++	ep = get_ep_from_handle(pcd, ep_handle);+	if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) {+		DWC_WARN("bad argument\n");+		return -DWC_E_INVALID;+	}++	DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);++	/* make sure it's actually queued on this endpoint */+	DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) {+		if (req->priv == (void *)req_handle) {+			break;+		}+	}++	if (req->priv != (void *)req_handle) {+		DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);+		return -DWC_E_INVALID;+	}++	if (!DWC_CIRCLEQ_EMPTY_ENTRY(req, queue_entry)) {+		dwc_otg_request_done(ep, req, -DWC_E_RESTART);+	} else {+		req = NULL;+	}++	DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);++	return req ? 0 : -DWC_E_SHUTDOWN;++}++/**+ * dwc_otg_pcd_ep_wedge - sets the halt feature and ignores clear requests+ *+ * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)+ * requests. If the gadget driver clears the halt status, it will+ * automatically unwedge the endpoint.+ *+ * Returns zero on success, else negative DWC error code.+ */+int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle)+{+	dwc_otg_pcd_ep_t *ep;+	dwc_irqflags_t flags;+	int retval = 0;++	ep = get_ep_from_handle(pcd, ep_handle);++	if ((!ep->desc && ep != &pcd->ep0) ||+	    (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {+		DWC_WARN("%s, bad ep\n", __func__);+		return -DWC_E_INVALID;+	}++	DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);+	if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {+		DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,+			 ep->dwc_ep.is_in ? "IN" : "OUT");+		retval = -DWC_E_AGAIN;+	} else {+                /* This code needs to be reviewed */+		if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {+			dtxfsts_data_t txstatus;+			fifosize_data_t txfifosize;++			txfifosize.d32 =+			    DWC_READ_REG32(&GET_CORE_IF(pcd)->+					   core_global_regs->dtxfsiz[ep->dwc_ep.+								     tx_fifo_num]);+			txstatus.d32 =+			    DWC_READ_REG32(&GET_CORE_IF(pcd)->+					   dev_if->in_ep_regs[ep->dwc_ep.num]->+					   dtxfsts);++			if (txstatus.b.txfspcavail < txfifosize.b.depth) {+				DWC_WARN("%s() Data In Tx Fifo\n", __func__);+				retval = -DWC_E_AGAIN;+			} else {+				if (ep->dwc_ep.num == 0) {+					pcd->ep0state = EP0_STALL;+				}++				ep->stopped = 1;+				dwc_otg_ep_set_stall(GET_CORE_IF(pcd),+						     &ep->dwc_ep);+			}+		} else {+			if (ep->dwc_ep.num == 0) {+				pcd->ep0state = EP0_STALL;+			}++			ep->stopped = 1;+			dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);+		}+	}++	DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);++	return retval;+}++int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value)+{+	dwc_otg_pcd_ep_t *ep;+	dwc_irqflags_t flags;+	int retval = 0;++	ep = get_ep_from_handle(pcd, ep_handle);++	if (!ep || (!ep->desc && ep != &pcd->ep0) ||+	    (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {+		DWC_WARN("%s, bad ep\n", __func__);+		return -DWC_E_INVALID;+	}++	DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);+	if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {+		DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,+			 ep->dwc_ep.is_in ? "IN" : "OUT");+		retval = -DWC_E_AGAIN;+	} else if (value == 0) {+		dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);+	} else if (value == 1) {+		if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {+			dtxfsts_data_t txstatus;+			fifosize_data_t txfifosize;++			txfifosize.d32 =+			    DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->+					   dtxfsiz[ep->dwc_ep.tx_fifo_num]);+			txstatus.d32 =+			    DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->+					   in_ep_regs[ep->dwc_ep.num]->dtxfsts);++			if (txstatus.b.txfspcavail < txfifosize.b.depth) {+				DWC_WARN("%s() Data In Tx Fifo\n", __func__);+				retval = -DWC_E_AGAIN;+			} else {+				if (ep->dwc_ep.num == 0) {+					pcd->ep0state = EP0_STALL;+				}++				ep->stopped = 1;+				dwc_otg_ep_set_stall(GET_CORE_IF(pcd),+						     &ep->dwc_ep);+			}+		} else {+			if (ep->dwc_ep.num == 0) {+				pcd->ep0state = EP0_STALL;+			}++			ep->stopped = 1;+			dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);+		}+	} else if (value == 2) {+		ep->dwc_ep.stall_clear_flag = 0;+	} else if (value == 3) {+		ep->dwc_ep.stall_clear_flag = 1;+	}++	DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);++	return retval;+}++/**+ * This function initiates remote wakeup of the host from suspend state.+ */+void dwc_otg_pcd_rem_wkup_from_suspend(dwc_otg_pcd_t * pcd, int set)+{+	dctl_data_t dctl = { 0 };+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	dsts_data_t dsts;++	dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);+	if (!dsts.b.suspsts) {+		DWC_WARN("Remote wakeup while is not in suspend state\n");+	}+	/* Check if DEVICE_REMOTE_WAKEUP feature enabled */+	if (pcd->remote_wakeup_enable) {+		if (set) {++			if (core_if->adp_enable) {+				gpwrdn_data_t gpwrdn;++				dwc_otg_adp_probe_stop(core_if);++				/* Mask SRP detected interrupt from Power Down Logic */+				gpwrdn.d32 = 0;+				gpwrdn.b.srp_det_msk = 1;+				DWC_MODIFY_REG32(&core_if->+						 core_global_regs->gpwrdn,+						 gpwrdn.d32, 0);++				/* Disable Power Down Logic */+				gpwrdn.d32 = 0;+				gpwrdn.b.pmuactv = 1;+				DWC_MODIFY_REG32(&core_if->+						 core_global_regs->gpwrdn,+						 gpwrdn.d32, 0);++				/*+				 * Initialize the Core for Device mode.+				 */+				core_if->op_state = B_PERIPHERAL;+				dwc_otg_core_init(core_if);+				dwc_otg_enable_global_interrupts(core_if);+				cil_pcd_start(core_if);++				dwc_otg_initiate_srp(core_if);+			}++			dctl.b.rmtwkupsig = 1;+			DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->+					 dctl, 0, dctl.d32);+			DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");++			dwc_mdelay(2);+			DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->+					 dctl, dctl.d32, 0);+			DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n");+		}+	} else {+		DWC_DEBUGPL(DBG_PCD, "Remote Wakeup is disabled\n");+	}+}++#ifdef CONFIG_USB_DWC_OTG_LPM+/**+ * This function initiates remote wakeup of the host from L1 sleep state.+ */+void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set)+{+	glpmcfg_data_t lpmcfg;+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);++	lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);++	/* Check if we are in L1 state */+	if (!lpmcfg.b.prt_sleep_sts) {+		DWC_DEBUGPL(DBG_PCD, "Device is not in sleep state\n");+		return;+	}++	/* Check if host allows remote wakeup */+	if (!lpmcfg.b.rem_wkup_en) {+		DWC_DEBUGPL(DBG_PCD, "Host does not allow remote wakeup\n");+		return;+	}++	/* Check if Resume OK */+	if (!lpmcfg.b.sleep_state_resumeok) {+		DWC_DEBUGPL(DBG_PCD, "Sleep state resume is not OK\n");+		return;+	}++	lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);+	lpmcfg.b.en_utmi_sleep = 0;+	lpmcfg.b.hird_thres &= (~(1 << 4));+	DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);++	if (set) {+		dctl_data_t dctl = {.d32 = 0 };+		dctl.b.rmtwkupsig = 1;+		/* Set RmtWkUpSig bit to start remote wakup signaling.+		 * Hardware will automatically clear this bit.+		 */+		DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl,+				 0, dctl.d32);+		DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");+	}++}+#endif++/**+ * Performs remote wakeup.+ */+void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	dwc_irqflags_t flags;+	if (dwc_otg_is_device_mode(core_if)) {+		DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);+#ifdef CONFIG_USB_DWC_OTG_LPM+		if (core_if->lx_state == DWC_OTG_L1) {+			dwc_otg_pcd_rem_wkup_from_sleep(pcd, set);+		} else {+#endif+			dwc_otg_pcd_rem_wkup_from_suspend(pcd, set);+#ifdef CONFIG_USB_DWC_OTG_LPM+		}+#endif+		DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);+	}+	return;+}++void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	dctl_data_t dctl = { 0 };++	if (dwc_otg_is_device_mode(core_if)) {+		dctl.b.sftdiscon = 1;+		DWC_PRINTF("Soft disconnect for %d useconds\n",no_of_usecs);+		DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);+		dwc_udelay(no_of_usecs);+		DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32,0);++	} else{+		DWC_PRINTF("NOT SUPPORTED IN HOST MODE\n");+	}+	return;++}++int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd)+{+	dsts_data_t dsts;+	gotgctl_data_t gotgctl;++	/*+	 * This function starts the Protocol if no session is in progress. If+	 * a session is already in progress, but the device is suspended,+	 * remote wakeup signaling is started.+	 */++	/* Check if valid session */+	gotgctl.d32 =+	    DWC_READ_REG32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl));+	if (gotgctl.b.bsesvld) {+		/* Check if suspend state */+		dsts.d32 =+		    DWC_READ_REG32(&+				   (GET_CORE_IF(pcd)->dev_if->+				    dev_global_regs->dsts));+		if (dsts.b.suspsts) {+			dwc_otg_pcd_remote_wakeup(pcd, 1);+		}+	} else {+		dwc_otg_pcd_initiate_srp(pcd);+	}++	return 0;++}++/**+ * Start the SRP timer to detect when the SRP does not complete within+ * 6 seconds.+ *+ * @param pcd the pcd structure.+ */+void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd)+{+	dwc_irqflags_t flags;+	DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);+	dwc_otg_initiate_srp(GET_CORE_IF(pcd));+	DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);+}++int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd)+{+	return dwc_otg_get_frame_number(GET_CORE_IF(pcd));+}++int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd)+{+	return GET_CORE_IF(pcd)->core_params->lpm_enable;+}++uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd)+{+	return pcd->b_hnp_enable;+}++uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd)+{+	return pcd->a_hnp_support;+}++uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd)+{+	return pcd->a_alt_hnp_support;+}++int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd)+{+	return pcd->remote_wakeup_enable;+}++#endif /* DWC_HOST_ONLY */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_pcd.h--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_pcd.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,266 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $+ * $Revision: #48 $+ * $Date: 2012/08/10 $+ * $Change: 2047372 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */+#ifndef DWC_HOST_ONLY+#if !defined(__DWC_PCD_H__)+#define __DWC_PCD_H__++#include "dwc_otg_os_dep.h"+#include "usb.h"+#include "dwc_otg_cil.h"+#include "dwc_otg_pcd_if.h"+struct cfiobject;++/**+ * @file+ *+ * This file contains the structures, constants, and interfaces for+ * the Perpherial Contoller Driver (PCD).+ *+ * The Peripheral Controller Driver (PCD) for Linux will implement the+ * Gadget API, so that the existing Gadget drivers can be used. For+ * the Mass Storage Function driver the File-backed USB Storage Gadget+ * (FBS) driver will be used.  The FBS driver supports the+ * Control-Bulk (CB), Control-Bulk-Interrupt (CBI), and Bulk-Only+ * transports.+ *+ */++/** Invalid DMA Address */+#define DWC_DMA_ADDR_INVALID	(~(dwc_dma_t)0)++/** Max Transfer size for any EP */+#define DDMA_MAX_TRANSFER_SIZE 65535++/**+ * Get the pointer to the core_if from the pcd pointer.+ */+#define GET_CORE_IF( _pcd ) (_pcd->core_if)++/**+ * States of EP0.+ */+typedef enum ep0_state {+	EP0_DISCONNECT,		/* no host */+	EP0_IDLE,+	EP0_IN_DATA_PHASE,+	EP0_OUT_DATA_PHASE,+	EP0_IN_STATUS_PHASE,+	EP0_OUT_STATUS_PHASE,+	EP0_STALL,+} ep0state_e;++/** Fordward declaration.*/+struct dwc_otg_pcd;++/** DWC_otg iso request structure.+ *+ */+typedef struct usb_iso_request dwc_otg_pcd_iso_request_t;++#ifdef DWC_UTE_PER_IO++/**+ * This shall be the exact analogy of the same type structure defined in the+ * usb_gadget.h. Each descriptor contains+ */+struct dwc_iso_pkt_desc_port {+	uint32_t offset;+	uint32_t length;	/* expected length */+	uint32_t actual_length;+	uint32_t status;+};++struct dwc_iso_xreq_port {+	/** transfer/submission flag */+	uint32_t tr_sub_flags;+	/** Start the request ASAP */+#define DWC_EREQ_TF_ASAP		0x00000002+	/** Just enqueue the request w/o initiating a transfer */+#define DWC_EREQ_TF_ENQUEUE		0x00000004++	/**+	* count of ISO packets attached to this request - shall+	* not exceed the pio_alloc_pkt_count+	*/+	uint32_t pio_pkt_count;+	/** count of ISO packets allocated for this request */+	uint32_t pio_alloc_pkt_count;+	/** number of ISO packet errors */+	uint32_t error_count;+	/** reserved for future extension */+	uint32_t res;+	/** Will be allocated and freed in the UTE gadget and based on the CFC value */+	struct dwc_iso_pkt_desc_port *per_io_frame_descs;+};+#endif+/** DWC_otg request structure.+ * This structure is a list of requests.+ */+typedef struct dwc_otg_pcd_request {+	void *priv;+	void *buf;+	dwc_dma_t dma;+	uint32_t length;+	uint32_t actual;+	unsigned sent_zlp:1;+    /**+     * Used instead of original buffer if+     * it(physical address) is not dword-aligned.+     **/+     uint8_t *dw_align_buf;+     dwc_dma_t dw_align_buf_dma;++	 DWC_CIRCLEQ_ENTRY(dwc_otg_pcd_request) queue_entry;+#ifdef DWC_UTE_PER_IO+	struct dwc_iso_xreq_port ext_req;+	//void *priv_ereq_nport; /*  */+#endif+} dwc_otg_pcd_request_t;++DWC_CIRCLEQ_HEAD(req_list, dwc_otg_pcd_request);++/**	  PCD EP structure.+ * This structure describes an EP, there is an array of EPs in the PCD+ * structure.+ */+typedef struct dwc_otg_pcd_ep {+	/** USB EP Descriptor */+	const usb_endpoint_descriptor_t *desc;++	/** queue of dwc_otg_pcd_requests. */+	struct req_list queue;+	unsigned stopped:1;+	unsigned disabling:1;+	unsigned dma:1;+	unsigned queue_sof:1;++#ifdef DWC_EN_ISOC+	/** ISOC req handle passed */+	void *iso_req_handle;+#endif				//_EN_ISOC_++	/** DWC_otg ep data. */+	dwc_ep_t dwc_ep;++	/** Pointer to PCD */+	struct dwc_otg_pcd *pcd;++	void *priv;+} dwc_otg_pcd_ep_t;++/** DWC_otg PCD Structure.+ * This structure encapsulates the data for the dwc_otg PCD.+ */+struct dwc_otg_pcd {+	const struct dwc_otg_pcd_function_ops *fops;+	/** The DWC otg device pointer */+	struct dwc_otg_device *otg_dev;+	/** Core Interface */+	dwc_otg_core_if_t *core_if;+	/** State of EP0 */+	ep0state_e ep0state;+	/** EP0 Request is pending */+	unsigned ep0_pending:1;+	/** Indicates when SET CONFIGURATION Request is in process */+	unsigned request_config:1;+	/** The state of the Remote Wakeup Enable. */+	unsigned remote_wakeup_enable:1;+	/** The state of the B-Device HNP Enable. */+	unsigned b_hnp_enable:1;+	/** The state of A-Device HNP Support. */+	unsigned a_hnp_support:1;+	/** The state of the A-Device Alt HNP support. */+	unsigned a_alt_hnp_support:1;+	/** Count of pending Requests */+	unsigned request_pending;++	/** SETUP packet for EP0+	 * This structure is allocated as a DMA buffer on PCD initialization+	 * with enough space for up to 3 setup packets.+	 */+	union {+		usb_device_request_t req;+		uint32_t d32[2];+	} *setup_pkt;++	dwc_dma_t setup_pkt_dma_handle;++	/* Additional buffer and flag for CTRL_WR premature case */+	uint8_t *backup_buf;+	unsigned data_terminated;++	/** 2-byte dma buffer used to return status from GET_STATUS */+	uint16_t *status_buf;+	dwc_dma_t status_buf_dma_handle;++	/** EP0 */+	dwc_otg_pcd_ep_t ep0;++	/** Array of IN EPs. */+	dwc_otg_pcd_ep_t in_ep[MAX_EPS_CHANNELS - 1];+	/** Array of OUT EPs. */+	dwc_otg_pcd_ep_t out_ep[MAX_EPS_CHANNELS - 1];+	/** number of valid EPs in the above array. */+//        unsigned      num_eps : 4;+	dwc_spinlock_t *lock;++	/** Tasklet to defer starting of TEST mode transmissions until+	 *	Status Phase has been completed.+	 */+	dwc_tasklet_t *test_mode_tasklet;++	/** Tasklet to delay starting of xfer in DMA mode */+	dwc_tasklet_t *start_xfer_tasklet;++	/** The test mode to enter when the tasklet is executed. */+	unsigned test_mode;+	/** The cfi_api structure that implements most of the CFI API+	 * and OTG specific core configuration functionality+	 */+#ifdef DWC_UTE_CFI+	struct cfiobject *cfi;+#endif++};++//FIXME this functions should be static, and this prototypes should be removed+extern void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep);+extern void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep,+				 dwc_otg_pcd_request_t * req, int32_t status);++void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,+			     void *req_handle);++extern void do_test_mode(void *data);+#endif+#endif /* DWC_HOST_ONLY */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,360 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $+ * $Revision: #11 $+ * $Date: 2011/10/26 $+ * $Change: 1873028 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */+#ifndef DWC_HOST_ONLY++#if !defined(__DWC_PCD_IF_H__)+#define __DWC_PCD_IF_H__++//#include "dwc_os.h"+#include "dwc_otg_core_if.h"++/** @file+ * This file defines DWC_OTG PCD Core API.+ */++struct dwc_otg_pcd;+typedef struct dwc_otg_pcd dwc_otg_pcd_t;++/** Maxpacket size for EP0 */+#define MAX_EP0_SIZE	64+/** Maxpacket size for any EP */+#define MAX_PACKET_SIZE 1024++/** @name Function Driver Callbacks */+/** @{ */++/** This function will be called whenever a previously queued request has+ * completed.  The status value will be set to -DWC_E_SHUTDOWN to indicated a+ * failed or aborted transfer, or -DWC_E_RESTART to indicate the device was reset,+ * or -DWC_E_TIMEOUT to indicate it timed out, or -DWC_E_INVALID to indicate invalid+ * parameters. */+typedef int (*dwc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,+				    void *req_handle, int32_t status,+				    uint32_t actual);+/**+ * This function will be called whenever a previousle queued ISOC request has+ * completed. Count of ISOC packets could be read using dwc_otg_pcd_get_iso_packet_count+ * function.+ * The status of each ISOC packet could be read using dwc_otg_pcd_get_iso_packet_*+ * functions.+ */+typedef int (*dwc_isoc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,+					 void *req_handle, int proc_buf_num);+/** This function should handle any SETUP request that cannot be handled by the+ * PCD Core.  This includes most GET_DESCRIPTORs, SET_CONFIGS, Any+ * class-specific requests, etc.  The function must non-blocking.+ *+ * Returns 0 on success.+ * Returns -DWC_E_NOT_SUPPORTED if the request is not supported.+ * Returns -DWC_E_INVALID if the setup request had invalid parameters or bytes.+ * Returns -DWC_E_SHUTDOWN on any other error. */+typedef int (*dwc_setup_cb_t) (dwc_otg_pcd_t * pcd, uint8_t * bytes);+/** This is called whenever the device has been disconnected.  The function+ * driver should take appropriate action to clean up all pending requests in the+ * PCD Core, remove all endpoints (except ep0), and initialize back to reset+ * state. */+typedef int (*dwc_disconnect_cb_t) (dwc_otg_pcd_t * pcd);+/** This function is called when device has been connected. */+typedef int (*dwc_connect_cb_t) (dwc_otg_pcd_t * pcd, int speed);+/** This function is called when device has been suspended */+typedef int (*dwc_suspend_cb_t) (dwc_otg_pcd_t * pcd);+/** This function is called when device has received LPM tokens, i.e.+ * device has been sent to sleep state. */+typedef int (*dwc_sleep_cb_t) (dwc_otg_pcd_t * pcd);+/** This function is called when device has been resumed+ * from suspend(L2) or L1 sleep state. */+typedef int (*dwc_resume_cb_t) (dwc_otg_pcd_t * pcd);+/** This function is called whenever hnp params has been changed.+ * User can call get_b_hnp_enable, get_a_hnp_support, get_a_alt_hnp_support functions+ * to get hnp parameters. */+typedef int (*dwc_hnp_params_changed_cb_t) (dwc_otg_pcd_t * pcd);+/** This function is called whenever USB RESET is detected. */+typedef int (*dwc_reset_cb_t) (dwc_otg_pcd_t * pcd);++typedef int (*cfi_setup_cb_t) (dwc_otg_pcd_t * pcd, void *ctrl_req_bytes);++/**+ *+ * @param ep_handle	Void pointer to the usb_ep structure+ * @param ereq_port Pointer to the extended request structure created in the+ *					portable part.+ */+typedef int (*xiso_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,+				     void *req_handle, int32_t status,+				     void *ereq_port);+/** Function Driver Ops Data Structure */+struct dwc_otg_pcd_function_ops {+	dwc_connect_cb_t connect;+	dwc_disconnect_cb_t disconnect;+	dwc_setup_cb_t setup;+	dwc_completion_cb_t complete;+	dwc_isoc_completion_cb_t isoc_complete;+	dwc_suspend_cb_t suspend;+	dwc_sleep_cb_t sleep;+	dwc_resume_cb_t resume;+	dwc_reset_cb_t reset;+	dwc_hnp_params_changed_cb_t hnp_changed;+	cfi_setup_cb_t cfi_setup;+#ifdef DWC_UTE_PER_IO+	xiso_completion_cb_t xisoc_complete;+#endif+};+/** @} */++/** @name Function Driver Functions */+/** @{ */++/** Call this function to get pointer on dwc_otg_pcd_t,+ * this pointer will be used for all PCD API functions.+ *+ * @param core_if The DWC_OTG Core+ */+extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if);++/** Frees PCD allocated by dwc_otg_pcd_init+ *+ * @param pcd The PCD+ */+extern void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd);++/** Call this to bind the function driver to the PCD Core.+ *+ * @param pcd Pointer on dwc_otg_pcd_t returned by dwc_otg_pcd_init function.+ * @param fops The Function Driver Ops data structure containing pointers to all callbacks.+ */+extern void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,+			      const struct dwc_otg_pcd_function_ops *fops);++/** Enables an endpoint for use.  This function enables an endpoint in+ * the PCD.  The endpoint is described by the ep_desc which has the+ * same format as a USB ep descriptor.  The ep_handle parameter is used to refer+ * to the endpoint from other API functions and in callbacks.  Normally this+ * should be called after a SET_CONFIGURATION/SET_INTERFACE to configure the+ * core for that interface.+ *+ * Returns -DWC_E_INVALID if invalid parameters were passed.+ * Returns -DWC_E_SHUTDOWN if any other error ocurred.+ * Returns 0 on success.+ *+ * @param pcd The PCD+ * @param ep_desc Endpoint descriptor+ * @param usb_ep Handle on endpoint, that will be used to identify endpoint.+ */+extern int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,+				 const uint8_t * ep_desc, void *usb_ep);++/** Disable the endpoint referenced by ep_handle.+ *+ * Returns -DWC_E_INVALID if invalid parameters were passed.+ * Returns -DWC_E_SHUTDOWN if any other error occurred.+ * Returns 0 on success. */+extern int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle);++/** Queue a data transfer request on the endpoint referenced by ep_handle.+ * After the transfer is completes, the complete callback will be called with+ * the request status.+ *+ * @param pcd The PCD+ * @param ep_handle The handle of the endpoint+ * @param buf The buffer for the data+ * @param dma_buf The DMA buffer for the data+ * @param buflen The length of the data transfer+ * @param zero Specifies whether to send zero length last packet.+ * @param req_handle Set this handle to any value to use to reference this+ * request in the ep_dequeue function or from the complete callback+ * @param atomic_alloc If driver need to perform atomic allocations+ * for internal data structures.+ *+ * Returns -DWC_E_INVALID if invalid parameters were passed.+ * Returns -DWC_E_SHUTDOWN if any other error ocurred.+ * Returns 0 on success. */+extern int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,+				uint8_t * buf, dwc_dma_t dma_buf,+				uint32_t buflen, int zero, void *req_handle,+				int atomic_alloc);+#ifdef DWC_UTE_PER_IO+/**+ *+ * @param ereq_nonport	Pointer to the extended request part of the+ *						usb_request structure defined in usb_gadget.h file.+ */+extern int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,+				     uint8_t * buf, dwc_dma_t dma_buf,+				     uint32_t buflen, int zero,+				     void *req_handle, int atomic_alloc,+				     void *ereq_nonport);++#endif++/** De-queue the specified data transfer that has not yet completed.+ *+ * Returns -DWC_E_INVALID if invalid parameters were passed.+ * Returns -DWC_E_SHUTDOWN if any other error ocurred.+ * Returns 0 on success. */+extern int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,+				  void *req_handle);++/** Halt (STALL) an endpoint or clear it.+ *+ * Returns -DWC_E_INVALID if invalid parameters were passed.+ * Returns -DWC_E_SHUTDOWN if any other error ocurred.+ * Returns -DWC_E_AGAIN if the STALL cannot be sent and must be tried again later+ * Returns 0 on success. */+extern int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value);++/** This function */+extern int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle);++/** This function should be called on every hardware interrupt */+extern int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd);++/** This function returns current frame number */+extern int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd);++/**+ * Start isochronous transfers on the endpoint referenced by ep_handle.+ * For isochronous transfers duble buffering is used.+ * After processing each of buffers comlete callback will be called with+ * status for each transaction.+ *+ * @param pcd The PCD+ * @param ep_handle The handle of the endpoint+ * @param buf0 The virtual address of first data buffer+ * @param buf1 The virtual address of second data buffer+ * @param dma0 The DMA address of first data buffer+ * @param dma1 The DMA address of second data buffer+ * @param sync_frame Data pattern frame number+ * @param dp_frame Data size for pattern frame+ * @param data_per_frame Data size for regular frame+ * @param start_frame Frame number to start transfers, if -1 then start transfers ASAP.+ * @param buf_proc_intrvl Interval of ISOC Buffer processing+ * @param req_handle Handle of ISOC request+ * @param atomic_alloc Specefies whether to perform atomic allocation for+ * 			internal data structures.+ *+ * Returns -DWC_E_NO_MEMORY if there is no enough memory.+ * Returns -DWC_E_INVALID if incorrect arguments are passed to the function.+ * Returns -DW_E_SHUTDOWN for any other error.+ * Returns 0 on success+ */+extern int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,+				    uint8_t * buf0, uint8_t * buf1,+				    dwc_dma_t dma0, dwc_dma_t dma1,+				    int sync_frame, int dp_frame,+				    int data_per_frame, int start_frame,+				    int buf_proc_intrvl, void *req_handle,+				    int atomic_alloc);++/** Stop ISOC transfers on endpoint referenced by ep_handle.+ *+ * @param pcd The PCD+ * @param ep_handle The handle of the endpoint+ * @param req_handle Handle of ISOC request+ *+ * Returns -DWC_E_INVALID if incorrect arguments are passed to the function+ * Returns 0 on success+ */+int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,+			    void *req_handle);++/** Get ISOC packet status.+ *+ * @param pcd The PCD+ * @param ep_handle The handle of the endpoint+ * @param iso_req_handle Isochronoush request handle+ * @param packet Number of packet+ * @param status Out parameter for returning status+ * @param actual Out parameter for returning actual length+ * @param offset Out parameter for returning offset+ *+ */+extern void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd,+					      void *ep_handle,+					      void *iso_req_handle, int packet,+					      int *status, int *actual,+					      int *offset);++/** Get ISOC packet count.+ *+ * @param pcd The PCD+ * @param ep_handle The handle of the endpoint+ * @param iso_req_handle+ */+extern int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd,+					    void *ep_handle,+					    void *iso_req_handle);++/** This function starts the SRP Protocol if no session is in progress. If+ * a session is already in progress, but the device is suspended,+ * remote wakeup signaling is started.+ */+extern int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd);++/** This function returns 1 if LPM support is enabled, and 0 otherwise. */+extern int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd);++/** This function returns 1 if remote wakeup is allowed and 0, otherwise. */+extern int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd);++/** Initiate SRP */+extern void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd);++/** Starts remote wakeup signaling. */+extern void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set);++/** Starts micorsecond soft disconnect. */+extern void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs);+/** This function returns whether device is dualspeed.*/+extern uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd);++/** This function returns whether device is otg. */+extern uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd);++/** These functions allow to get hnp parameters */+extern uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd);+extern uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd);+extern uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd);++/** CFI specific Interface functions */+/** Allocate a cfi buffer */+extern uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep,+				     dwc_dma_t * addr, size_t buflen,+				     int flags);++/******************************************************************************/++/** @} */++#endif				/* __DWC_PCD_IF_H__ */++#endif				/* DWC_HOST_ONLY */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,5147 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $+ * $Revision: #116 $+ * $Date: 2012/08/10 $+ * $Change: 2047372 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */+#ifndef DWC_HOST_ONLY++#include "dwc_otg_pcd.h"++#ifdef DWC_UTE_CFI+#include "dwc_otg_cfi.h"+#endif++#ifdef DWC_UTE_PER_IO+extern void complete_xiso_ep(dwc_otg_pcd_ep_t * ep);+#endif+//#define PRINT_CFI_DMA_DESCS++#define DEBUG_EP0++/**+ * This function updates OTG.+ */+static void dwc_otg_pcd_update_otg(dwc_otg_pcd_t * pcd, const unsigned reset)+{++	if (reset) {+		pcd->b_hnp_enable = 0;+		pcd->a_hnp_support = 0;+		pcd->a_alt_hnp_support = 0;+	}++	if (pcd->fops->hnp_changed) {+		pcd->fops->hnp_changed(pcd);+	}+}++/** @file+ * This file contains the implementation of the PCD Interrupt handlers.+ *+ * The PCD handles the device interrupts.  Many conditions can cause a+ * device interrupt. When an interrupt occurs, the device interrupt+ * service routine determines the cause of the interrupt and+ * dispatches handling to the appropriate function. These interrupt+ * handling functions are described below.+ * All interrupt registers are processed from LSB to MSB.+ */++/**+ * This function prints the ep0 state for debug purposes.+ */+static inline void print_ep0_state(dwc_otg_pcd_t * pcd)+{+#ifdef DEBUG+	char str[40];++	switch (pcd->ep0state) {+	case EP0_DISCONNECT:+		dwc_strcpy(str, "EP0_DISCONNECT");+		break;+	case EP0_IDLE:+		dwc_strcpy(str, "EP0_IDLE");+		break;+	case EP0_IN_DATA_PHASE:+		dwc_strcpy(str, "EP0_IN_DATA_PHASE");+		break;+	case EP0_OUT_DATA_PHASE:+		dwc_strcpy(str, "EP0_OUT_DATA_PHASE");+		break;+	case EP0_IN_STATUS_PHASE:+		dwc_strcpy(str, "EP0_IN_STATUS_PHASE");+		break;+	case EP0_OUT_STATUS_PHASE:+		dwc_strcpy(str, "EP0_OUT_STATUS_PHASE");+		break;+	case EP0_STALL:+		dwc_strcpy(str, "EP0_STALL");+		break;+	default:+		dwc_strcpy(str, "EP0_INVALID");+	}++	DWC_DEBUGPL(DBG_ANY, "%s(%d)\n", str, pcd->ep0state);+#endif+}++/**+ * This function calculate the size of the payload in the memory+ * for out endpoints and prints size for debug purposes(used in+ * 2.93a DevOutNak feature).+ */+static inline void print_memory_payload(dwc_otg_pcd_t * pcd,  dwc_ep_t * ep)+{+#ifdef DEBUG+	deptsiz_data_t deptsiz_init = {.d32 = 0 };+	deptsiz_data_t deptsiz_updt = {.d32 = 0 };+	int pack_num;+	unsigned payload;++	deptsiz_init.d32 = pcd->core_if->start_doeptsiz_val[ep->num];+	deptsiz_updt.d32 =+		DWC_READ_REG32(&pcd->core_if->dev_if->+						out_ep_regs[ep->num]->doeptsiz);+	/* Payload will be */+	payload = deptsiz_init.b.xfersize - deptsiz_updt.b.xfersize;+	/* Packet count is decremented every time a packet+	 * is written to the RxFIFO not in to the external memory+	 * So, if payload == 0, then it means no packet was sent to ext memory*/+	pack_num = (!payload) ? 0 : (deptsiz_init.b.pktcnt - deptsiz_updt.b.pktcnt);+	DWC_DEBUGPL(DBG_PCDV,+		"Payload for EP%d-%s\n",+		ep->num, (ep->is_in ? "IN" : "OUT"));+	DWC_DEBUGPL(DBG_PCDV,+		"Number of transfered bytes = 0x%08x\n", payload);+	DWC_DEBUGPL(DBG_PCDV,+		"Number of transfered packets = %d\n", pack_num);+#endif+}+++#ifdef DWC_UTE_CFI+static inline void print_desc(struct dwc_otg_dma_desc *ddesc,+			      const uint8_t * epname, int descnum)+{+	CFI_INFO+	    ("%s DMA_DESC(%d) buf=0x%08x bytes=0x%04x; sp=0x%x; l=0x%x; sts=0x%02x; bs=0x%02x\n",+	     epname, descnum, ddesc->buf, ddesc->status.b.bytes,+	     ddesc->status.b.sp, ddesc->status.b.l, ddesc->status.b.sts,+	     ddesc->status.b.bs);+}+#endif++/**+ * This function returns pointer to in ep struct with number ep_num+ */+static inline dwc_otg_pcd_ep_t *get_in_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)+{+	int i;+	int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;+	if (ep_num == 0) {+		return &pcd->ep0;+	} else {+		for (i = 0; i < num_in_eps; ++i) {+			if (pcd->in_ep[i].dwc_ep.num == ep_num)+				return &pcd->in_ep[i];+		}+		return 0;+	}+}++/**+ * This function returns pointer to out ep struct with number ep_num+ */+static inline dwc_otg_pcd_ep_t *get_out_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)+{+	int i;+	int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;+	if (ep_num == 0) {+		return &pcd->ep0;+	} else {+		for (i = 0; i < num_out_eps; ++i) {+			if (pcd->out_ep[i].dwc_ep.num == ep_num)+				return &pcd->out_ep[i];+		}+		return 0;+	}+}++/**+ * This functions gets a pointer to an EP from the wIndex address+ * value of the control request.+ */+dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex)+{+	dwc_otg_pcd_ep_t *ep;+	uint32_t ep_num = UE_GET_ADDR(wIndex);++	if (ep_num == 0) {+		ep = &pcd->ep0;+	} else if (UE_GET_DIR(wIndex) == UE_DIR_IN) {	/* in ep */+		ep = &pcd->in_ep[ep_num - 1];+	} else {+		ep = &pcd->out_ep[ep_num - 1];+	}++	return ep;+}++/**+ * This function checks the EP request queue, if the queue is not+ * empty the next request is started.+ */+void start_next_request(dwc_otg_pcd_ep_t * ep)+{+	dwc_otg_pcd_request_t *req = 0;+	uint32_t max_transfer =+	    GET_CORE_IF(ep->pcd)->core_params->max_transfer_size;++#ifdef DWC_UTE_CFI+	struct dwc_otg_pcd *pcd;+	pcd = ep->pcd;+#endif++	if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {+		req = DWC_CIRCLEQ_FIRST(&ep->queue);++#ifdef DWC_UTE_CFI+		if (ep->dwc_ep.buff_mode != BM_STANDARD) {+			ep->dwc_ep.cfi_req_len = req->length;+			pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ep, req);+		} else {+#endif+			/* Setup and start the Transfer */+			if (req->dw_align_buf) {+				ep->dwc_ep.dma_addr = req->dw_align_buf_dma;+				ep->dwc_ep.start_xfer_buff = req->dw_align_buf;+				ep->dwc_ep.xfer_buff = req->dw_align_buf;+			} else {+				ep->dwc_ep.dma_addr = req->dma;+				ep->dwc_ep.start_xfer_buff = req->buf;+				ep->dwc_ep.xfer_buff = req->buf;+			}+			ep->dwc_ep.sent_zlp = 0;+			ep->dwc_ep.total_len = req->length;+			ep->dwc_ep.xfer_len = 0;+			ep->dwc_ep.xfer_count = 0;++			ep->dwc_ep.maxxfer = max_transfer;+			if (GET_CORE_IF(ep->pcd)->dma_desc_enable) {+				uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE+				    - (DDMA_MAX_TRANSFER_SIZE % 4);+				if (ep->dwc_ep.is_in) {+					if (ep->dwc_ep.maxxfer >+					    DDMA_MAX_TRANSFER_SIZE) {+						ep->dwc_ep.maxxfer =+						    DDMA_MAX_TRANSFER_SIZE;+					}+				} else {+					if (ep->dwc_ep.maxxfer > out_max_xfer) {+						ep->dwc_ep.maxxfer =+						    out_max_xfer;+					}+				}+			}+			if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {+				ep->dwc_ep.maxxfer -=+				    (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket);+			}+			if (req->sent_zlp) {+				if ((ep->dwc_ep.total_len %+				     ep->dwc_ep.maxpacket == 0)+				    && (ep->dwc_ep.total_len != 0)) {+					ep->dwc_ep.sent_zlp = 1;+				}++			}+#ifdef DWC_UTE_CFI+		}+#endif+		dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep);+	} else if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {+		DWC_PRINTF("There are no more ISOC requests \n");+		ep->dwc_ep.frame_num = 0xFFFFFFFF;+	}+}++/**+ * This function handles the SOF Interrupts. At this time the SOF+ * Interrupt is disabled.+ */+int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t * pcd)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);++	gintsts_data_t gintsts;++	DWC_DEBUGPL(DBG_PCD, "SOF\n");++	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.sofintr = 1;+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);++	return 1;+}++/**+ * This function handles the Rx Status Queue Level Interrupt, which+ * indicates that there is a least one packet in the Rx FIFO.  The+ * packets are moved from the FIFO to memory, where they will be+ * processed when the Endpoint Interrupt Register indicates Transfer+ * Complete or SETUP Phase Done.+ *+ * Repeat the following until the Rx Status Queue is empty:+ *	 -# Read the Receive Status Pop Register (GRXSTSP) to get Packet+ *		info+ *	 -# If Receive FIFO is empty then skip to step Clear the interrupt+ *		and exit+ *	 -# If SETUP Packet call dwc_otg_read_setup_packet to copy the+ *		SETUP data to the buffer+ *	 -# If OUT Data Packet call dwc_otg_read_packet to copy the data+ *		to the destination buffer+ */+int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;+	gintmsk_data_t gintmask = {.d32 = 0 };+	device_grxsts_data_t status;+	dwc_otg_pcd_ep_t *ep;+	gintsts_data_t gintsts;+#ifdef DEBUG+	static char *dpid_str[] = { "D0", "D2", "D1", "MDATA" };+#endif++	//DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd);+	/* Disable the Rx Status Queue Level interrupt */+	gintmask.b.rxstsqlvl = 1;+	DWC_MODIFY_REG32(&global_regs->gintmsk, gintmask.d32, 0);++	/* Get the Status from the top of the FIFO */+	status.d32 = DWC_READ_REG32(&global_regs->grxstsp);++	DWC_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s "+		    "pktsts:%x Frame:%d(0x%0x)\n",+		    status.b.epnum, status.b.bcnt,+		    dpid_str[status.b.dpid],+		    status.b.pktsts, status.b.fn, status.b.fn);+	/* Get pointer to EP structure */+	ep = get_out_ep(pcd, status.b.epnum);++	switch (status.b.pktsts) {+	case DWC_DSTS_GOUT_NAK:+		DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n");+		break;+	case DWC_STS_DATA_UPDT:+		DWC_DEBUGPL(DBG_PCDV, "OUT Data Packet\n");+		if (status.b.bcnt && ep->dwc_ep.xfer_buff) {+			/** @todo NGS Check for buffer overflow? */+			dwc_otg_read_packet(core_if,+					    ep->dwc_ep.xfer_buff,+					    status.b.bcnt);+			ep->dwc_ep.xfer_count += status.b.bcnt;+			ep->dwc_ep.xfer_buff += status.b.bcnt;+		}+		break;+	case DWC_STS_XFER_COMP:+		DWC_DEBUGPL(DBG_PCDV, "OUT Complete\n");+		break;+	case DWC_DSTS_SETUP_COMP:+#ifdef DEBUG_EP0+		DWC_DEBUGPL(DBG_PCDV, "Setup Complete\n");+#endif+		break;+	case DWC_DSTS_SETUP_UPDT:+		dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32);+#ifdef DEBUG_EP0+		DWC_DEBUGPL(DBG_PCD,+			    "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n",+			    pcd->setup_pkt->req.bmRequestType,+			    pcd->setup_pkt->req.bRequest,+			    UGETW(pcd->setup_pkt->req.wValue),+			    UGETW(pcd->setup_pkt->req.wIndex),+			    UGETW(pcd->setup_pkt->req.wLength));+#endif+		ep->dwc_ep.xfer_count += status.b.bcnt;+		break;+	default:+		DWC_DEBUGPL(DBG_PCDV, "Invalid Packet Status (0x%0x)\n",+			    status.b.pktsts);+		break;+	}++	/* Enable the Rx Status Queue Level interrupt */+	DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmask.d32);+	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.rxstsqlvl = 1;+	DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);++	//DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__);+	return 1;+}++/**+ * This function examines the Device IN Token Learning Queue to+ * determine the EP number of the last IN token received.  This+ * implementation is for the Mass Storage device where there are only+ * 2 IN EPs (Control-IN and BULK-IN).+ *+ * The EP numbers for the first six IN Tokens are in DTKNQR1 and there+ * are 8 EP Numbers in each of the other possible DTKNQ Registers.+ *+ * @param core_if Programming view of DWC_otg controller.+ *+ */+static inline int get_ep_of_last_in_token(dwc_otg_core_if_t * core_if)+{+	dwc_otg_device_global_regs_t *dev_global_regs =+	    core_if->dev_if->dev_global_regs;+	const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;+	/* Number of Token Queue Registers */+	const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;+	dtknq1_data_t dtknqr1;+	uint32_t in_tkn_epnums[4];+	int ndx = 0;+	int i = 0;+	volatile uint32_t *addr = &dev_global_regs->dtknqr1;+	int epnum = 0;++	//DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);++	/* Read the DTKNQ Registers */+	for (i = 0; i < DTKNQ_REG_CNT; i++) {+		in_tkn_epnums[i] = DWC_READ_REG32(addr);+		DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,+			    in_tkn_epnums[i]);+		if (addr == &dev_global_regs->dvbusdis) {+			addr = &dev_global_regs->dtknqr3_dthrctl;+		} else {+			++addr;+		}++	}++	/* Copy the DTKNQR1 data to the bit field. */+	dtknqr1.d32 = in_tkn_epnums[0];+	/* Get the EP numbers */+	in_tkn_epnums[0] = dtknqr1.b.epnums0_5;+	ndx = dtknqr1.b.intknwptr - 1;++	//DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx);+	if (ndx == -1) {+		/** @todo Find a simpler way to calculate the max+		 * queue position.*/+		int cnt = TOKEN_Q_DEPTH;+		if (TOKEN_Q_DEPTH <= 6) {+			cnt = TOKEN_Q_DEPTH - 1;+		} else if (TOKEN_Q_DEPTH <= 14) {+			cnt = TOKEN_Q_DEPTH - 7;+		} else if (TOKEN_Q_DEPTH <= 22) {+			cnt = TOKEN_Q_DEPTH - 15;+		} else {+			cnt = TOKEN_Q_DEPTH - 23;+		}+		epnum = (in_tkn_epnums[DTKNQ_REG_CNT - 1] >> (cnt * 4)) & 0xF;+	} else {+		if (ndx <= 5) {+			epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF;+		} else if (ndx <= 13) {+			ndx -= 6;+			epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF;+		} else if (ndx <= 21) {+			ndx -= 14;+			epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF;+		} else if (ndx <= 29) {+			ndx -= 22;+			epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF;+		}+	}+	//DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum);+	return epnum;+}++/**+ * This interrupt occurs when the non-periodic Tx FIFO is half-empty.+ * The active request is checked for the next packet to be loaded into+ * the non-periodic Tx FIFO.+ */+int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t * pcd)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;+	dwc_otg_dev_in_ep_regs_t *ep_regs;+	gnptxsts_data_t txstatus = {.d32 = 0 };+	gintsts_data_t gintsts;++	int epnum = 0;+	dwc_otg_pcd_ep_t *ep = 0;+	uint32_t len = 0;+	int dwords;++	/* Get the epnum from the IN Token Learning Queue. */+	epnum = get_ep_of_last_in_token(core_if);+	ep = get_in_ep(pcd, epnum);++	DWC_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %d \n", epnum);++	ep_regs = core_if->dev_if->in_ep_regs[epnum];++	len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;+	if (len > ep->dwc_ep.maxpacket) {+		len = ep->dwc_ep.maxpacket;+	}+	dwords = (len + 3) / 4;++	/* While there is space in the queue and space in the FIFO and+	 * More data to tranfer, Write packets to the Tx FIFO */+	txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts);+	DWC_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n", txstatus.d32);++	while (txstatus.b.nptxqspcavail > 0 &&+	       txstatus.b.nptxfspcavail > dwords &&+	       ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) {+		/* Write the FIFO */+		dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);+		len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;++		if (len > ep->dwc_ep.maxpacket) {+			len = ep->dwc_ep.maxpacket;+		}++		dwords = (len + 3) / 4;+		txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts);+		DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", txstatus.d32);+	}++	DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n",+		    DWC_READ_REG32(&global_regs->gnptxsts));++	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.nptxfempty = 1;+	DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);++	return 1;+}++/**+ * This function is called when dedicated Tx FIFO Empty interrupt occurs.+ * The active request is checked for the next packet to be loaded into+ * apropriate Tx FIFO.+ */+static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	dwc_otg_dev_if_t *dev_if = core_if->dev_if;+	dwc_otg_dev_in_ep_regs_t *ep_regs;+	dtxfsts_data_t txstatus = {.d32 = 0 };+	dwc_otg_pcd_ep_t *ep = 0;+	uint32_t len = 0;+	int dwords;++	ep = get_in_ep(pcd, epnum);++	DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);++	ep_regs = core_if->dev_if->in_ep_regs[epnum];++	len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;++	if (len > ep->dwc_ep.maxpacket) {+		len = ep->dwc_ep.maxpacket;+	}++	dwords = (len + 3) / 4;++	/* While there is space in the queue and space in the FIFO and+	 * More data to tranfer, Write packets to the Tx FIFO */+	txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);+	DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);++	while (txstatus.b.txfspcavail > dwords &&+	       ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len &&+	       ep->dwc_ep.xfer_len != 0) {+		/* Write the FIFO */+		dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);++		len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;+		if (len > ep->dwc_ep.maxpacket) {+			len = ep->dwc_ep.maxpacket;+		}++		dwords = (len + 3) / 4;+		txstatus.d32 =+		    DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);+		DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,+			    txstatus.d32);+	}++	DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,+		    DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts));++	return 1;+}++/**+ * This function is called when the Device is disconnected. It stops+ * any active requests and informs the Gadget driver of the+ * disconnect.+ */+void dwc_otg_pcd_stop(dwc_otg_pcd_t * pcd)+{+	int i, num_in_eps, num_out_eps;+	dwc_otg_pcd_ep_t *ep;++	gintmsk_data_t intr_mask = {.d32 = 0 };++	DWC_SPINLOCK(pcd->lock);++	num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;+	num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;++	DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__);+	/* don't disconnect drivers more than once */+	if (pcd->ep0state == EP0_DISCONNECT) {+		DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__);+		DWC_SPINUNLOCK(pcd->lock);+		return;+	}+	pcd->ep0state = EP0_DISCONNECT;++	/* Reset the OTG state. */+	dwc_otg_pcd_update_otg(pcd, 1);++	/* Disable the NP Tx Fifo Empty Interrupt. */+	intr_mask.b.nptxfempty = 1;+	DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,+			 intr_mask.d32, 0);++	/* Flush the FIFOs */+	/**@todo NGS Flush Periodic FIFOs */+	dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), 0x10);+	dwc_otg_flush_rx_fifo(GET_CORE_IF(pcd));++	/* prevent new request submissions, kill any outstanding requests  */+	ep = &pcd->ep0;+	dwc_otg_request_nuke(ep);+	/* prevent new request submissions, kill any outstanding requests  */+	for (i = 0; i < num_in_eps; i++) {+		dwc_otg_pcd_ep_t *ep = &pcd->in_ep[i];+		dwc_otg_request_nuke(ep);+	}+	/* prevent new request submissions, kill any outstanding requests  */+	for (i = 0; i < num_out_eps; i++) {+		dwc_otg_pcd_ep_t *ep = &pcd->out_ep[i];+		dwc_otg_request_nuke(ep);+	}++	/* report disconnect; the driver is already quiesced */+	if (pcd->fops->disconnect) {+		DWC_SPINUNLOCK(pcd->lock);+		pcd->fops->disconnect(pcd);+		DWC_SPINLOCK(pcd->lock);+	}+	DWC_SPINUNLOCK(pcd->lock);+}++/**+ * This interrupt indicates that ...+ */+int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t * pcd)+{+	gintmsk_data_t intr_mask = {.d32 = 0 };+	gintsts_data_t gintsts;++	DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "i2cintr");+	intr_mask.b.i2cintr = 1;+	DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,+			 intr_mask.d32, 0);++	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.i2cintr = 1;+	DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,+			gintsts.d32);+	return 1;+}++/**+ * This interrupt indicates that ...+ */+int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t * pcd)+{+	gintsts_data_t gintsts;+#if defined(VERBOSE)+	DWC_PRINTF("Early Suspend Detected\n");+#endif++	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.erlysuspend = 1;+	DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,+			gintsts.d32);+	return 1;+}++/**+ * This function configures EPO to receive SETUP packets.+ *+ * @todo NGS: Update the comments from the HW FS.+ *+ *	-# Program the following fields in the endpoint specific registers+ *	for Control OUT EP 0, in order to receive a setup packet+ *	- DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back+ *	  setup packets)+ *	- DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back+ *	  to back setup packets)+ *		- In DMA mode, DOEPDMA0 Register with a memory address to+ *		  store any setup packets received+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param pcd	  Programming view of the PCD.+ */+static inline void ep0_out_start(dwc_otg_core_if_t * core_if,+				 dwc_otg_pcd_t * pcd)+{+	dwc_otg_dev_if_t *dev_if = core_if->dev_if;+	deptsiz0_data_t doeptsize0 = {.d32 = 0 };+	dwc_otg_dev_dma_desc_t *dma_desc;+	depctl_data_t doepctl = {.d32 = 0 };++#ifdef VERBOSE+	DWC_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__,+		    DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));+#endif+	if (core_if->snpsid >= OTG_CORE_REV_3_00a) {+		doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl);+		if (doepctl.b.epena) {+			return;+		}+	}++	doeptsize0.b.supcnt = 3;+	doeptsize0.b.pktcnt = 1;+	doeptsize0.b.xfersize = 8 * 3;++	if (core_if->dma_enable) {+		if (!core_if->dma_desc_enable) {+			/** put here as for Hermes mode deptisz register should not be written */+			DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,+					doeptsize0.d32);++			/** @todo dma needs to handle multiple setup packets (up to 3) */+			DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma,+					pcd->setup_pkt_dma_handle);+		} else {+			dev_if->setup_desc_index =+			    (dev_if->setup_desc_index + 1) & 1;+			dma_desc =+			    dev_if->setup_desc_addr[dev_if->setup_desc_index];++			/** DMA Descriptor Setup */+			dma_desc->status.b.bs = BS_HOST_BUSY;+			if (core_if->snpsid >= OTG_CORE_REV_3_00a) {+				dma_desc->status.b.sr = 0;+				dma_desc->status.b.mtrf = 0;+			}+			dma_desc->status.b.l = 1;+			dma_desc->status.b.ioc = 1;+			dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket;+			dma_desc->buf = pcd->setup_pkt_dma_handle;+			dma_desc->status.b.sts = 0;+			dma_desc->status.b.bs = BS_HOST_READY;++			/** DOEPDMA0 Register write */+			DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma,+					dev_if->dma_setup_desc_addr+					[dev_if->setup_desc_index]);+		}++	} else {+		/** put here as for Hermes mode deptisz register should not be written */+		DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,+				doeptsize0.d32);+	}++	/** DOEPCTL0 Register write cnak will be set after setup interrupt */+	doepctl.d32 = 0;+	doepctl.b.epena = 1;+	if (core_if->snpsid <= OTG_CORE_REV_2_94a) {+	doepctl.b.cnak = 1;+	DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);+	} else {+		DWC_MODIFY_REG32(&dev_if->out_ep_regs[0]->doepctl, 0, doepctl.d32);+	}++#ifdef VERBOSE+	DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",+		    DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));+	DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",+		    DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl));+#endif+}++/**+ * This interrupt occurs when a USB Reset is detected. When the USB+ * Reset Interrupt occurs the device state is set to DEFAULT and the+ * EP0 state is set to IDLE.+ *	-#	Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1)+ *	-#	Unmask the following interrupt bits+ *		- DAINTMSK.INEP0 = 1 (Control 0 IN endpoint)+ *	- DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint)+ *	- DOEPMSK.SETUP = 1+ *	- DOEPMSK.XferCompl = 1+ *	- DIEPMSK.XferCompl = 1+ *	- DIEPMSK.TimeOut = 1+ *	-# Program the following fields in the endpoint specific registers+ *	for Control OUT EP 0, in order to receive a setup packet+ *	- DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back+ *	  setup packets)+ *	- DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back+ *	  to back setup packets)+ *		- In DMA mode, DOEPDMA0 Register with a memory address to+ *		  store any setup packets received+ * At this point, all the required initialization, except for enabling+ * the control 0 OUT endpoint is done, for receiving SETUP packets.+ */+int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	dwc_otg_dev_if_t *dev_if = core_if->dev_if;+	depctl_data_t doepctl = {.d32 = 0 };+	depctl_data_t diepctl = {.d32 = 0 };+	daint_data_t daintmsk = {.d32 = 0 };+	doepmsk_data_t doepmsk = {.d32 = 0 };+	diepmsk_data_t diepmsk = {.d32 = 0 };+	dcfg_data_t dcfg = {.d32 = 0 };+	grstctl_t resetctl = {.d32 = 0 };+	dctl_data_t dctl = {.d32 = 0 };+	int i = 0;+	gintsts_data_t gintsts;+	pcgcctl_data_t power = {.d32 = 0 };++	power.d32 = DWC_READ_REG32(core_if->pcgcctl);+	if (power.b.stoppclk) {+		power.d32 = 0;+		power.b.stoppclk = 1;+		DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);++		power.b.pwrclmp = 1;+		DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);++		power.b.rstpdwnmodule = 1;+		DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);+	}++	core_if->lx_state = DWC_OTG_L0;++	DWC_PRINTF("USB RESET\n");+#ifdef DWC_EN_ISOC+	for (i = 1; i < 16; ++i) {+		dwc_otg_pcd_ep_t *ep;+		dwc_ep_t *dwc_ep;+		ep = get_in_ep(pcd, i);+		if (ep != 0) {+			dwc_ep = &ep->dwc_ep;+			dwc_ep->next_frame = 0xffffffff;+		}+	}+#endif /* DWC_EN_ISOC */++	/* reset the HNP settings */+	dwc_otg_pcd_update_otg(pcd, 1);++	/* Clear the Remote Wakeup Signalling */+	dctl.b.rmtwkupsig = 1;+	DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);++	/* Set NAK for all OUT EPs */+	doepctl.b.snak = 1;+	for (i = 0; i <= dev_if->num_out_eps; i++) {+		DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);+	}++	/* Flush the NP Tx FIFO */+	dwc_otg_flush_tx_fifo(core_if, 0x10);+	/* Flush the Learning Queue */+	resetctl.b.intknqflsh = 1;+	DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);++	if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) {+		core_if->start_predict = 0;+		for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) {+			core_if->nextep_seq[i] = 0xff;	// 0xff - EP not active+		}+		core_if->nextep_seq[0] = 0;+		core_if->first_in_nextep_seq = 0;+		diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);+		diepctl.b.nextep = 0;+		DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);++		/* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */+		dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);+		dcfg.b.epmscnt = 2;+		DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);++		DWC_DEBUGPL(DBG_PCDV,+			    "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",+			__func__, core_if->first_in_nextep_seq);+		for (i=0; i <= core_if->dev_if->num_in_eps; i++) {+			DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]);+		}+	}++	if (core_if->multiproc_int_enable) {+		daintmsk.b.inep0 = 1;+		daintmsk.b.outep0 = 1;+		DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk,+				daintmsk.d32);++		doepmsk.b.setup = 1;+		doepmsk.b.xfercompl = 1;+		doepmsk.b.ahberr = 1;+		doepmsk.b.epdisabled = 1;++		if ((core_if->dma_desc_enable) ||+		    (core_if->dma_enable+		     && core_if->snpsid >= OTG_CORE_REV_3_00a)) {+			doepmsk.b.stsphsercvd = 1;+		}+		if (core_if->dma_desc_enable)+			doepmsk.b.bna = 1;+/*+		doepmsk.b.babble = 1;+		doepmsk.b.nyet = 1;++		if (core_if->dma_enable) {+			doepmsk.b.nak = 1;+		}+*/+		DWC_WRITE_REG32(&dev_if->dev_global_regs->doepeachintmsk[0],+				doepmsk.d32);++		diepmsk.b.xfercompl = 1;+		diepmsk.b.timeout = 1;+		diepmsk.b.epdisabled = 1;+		diepmsk.b.ahberr = 1;+		diepmsk.b.intknepmis = 1;+		if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)+			diepmsk.b.intknepmis = 0;++/*		if (core_if->dma_desc_enable) {+			diepmsk.b.bna = 1;+		}+*/+/*+		if (core_if->dma_enable) {+			diepmsk.b.nak = 1;+		}+*/+		DWC_WRITE_REG32(&dev_if->dev_global_regs->diepeachintmsk[0],+				diepmsk.d32);+	} else {+		daintmsk.b.inep0 = 1;+		daintmsk.b.outep0 = 1;+		DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk,+				daintmsk.d32);++		doepmsk.b.setup = 1;+		doepmsk.b.xfercompl = 1;+		doepmsk.b.ahberr = 1;+		doepmsk.b.epdisabled = 1;++		if ((core_if->dma_desc_enable) ||+		    (core_if->dma_enable+		     && core_if->snpsid >= OTG_CORE_REV_3_00a)) {+			doepmsk.b.stsphsercvd = 1;+		}+		if (core_if->dma_desc_enable)+			doepmsk.b.bna = 1;+		DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32);++		diepmsk.b.xfercompl = 1;+		diepmsk.b.timeout = 1;+		diepmsk.b.epdisabled = 1;+		diepmsk.b.ahberr = 1;+		if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)+			diepmsk.b.intknepmis = 0;+/*+		if (core_if->dma_desc_enable) {+			diepmsk.b.bna = 1;+		}+*/++		DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32);+	}++	/* Reset Device Address */+	dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);+	dcfg.b.devaddr = 0;+	DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);++	/* setup EP0 to receive SETUP packets */+	if (core_if->snpsid <= OTG_CORE_REV_2_94a)+		ep0_out_start(core_if, pcd);++	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.usbreset = 1;+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);++	return 1;+}++/**+ * Get the device speed from the device status register and convert it+ * to USB speed constant.+ *+ * @param core_if Programming view of DWC_otg controller.+ */+static int get_device_speed(dwc_otg_core_if_t * core_if)+{+	dsts_data_t dsts;+	int speed = 0;+	dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);++	switch (dsts.b.enumspd) {+	case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:+		speed = USB_SPEED_HIGH;+		break;+	case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:+	case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:+		speed = USB_SPEED_FULL;+		break;++	case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:+		speed = USB_SPEED_LOW;+		break;+	}++	return speed;+}++/**+ * Read the device status register and set the device speed in the+ * data structure.+ * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate.+ */+int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd)+{+	dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;+	gintsts_data_t gintsts;+	gusbcfg_data_t gusbcfg;+	dwc_otg_core_global_regs_t *global_regs =+	    GET_CORE_IF(pcd)->core_global_regs;+	uint8_t utmi16b, utmi8b;+	int speed;+	DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n");++	if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) {+		utmi16b = 6;	//vahrama old value was 6;+		utmi8b = 9;+	} else {+		utmi16b = 4;+		utmi8b = 8;+	}+	dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep);+	if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) {+		ep0_out_start(GET_CORE_IF(pcd), pcd);+	}++#ifdef DEBUG_EP0+	print_ep0_state(pcd);+#endif++	if (pcd->ep0state == EP0_DISCONNECT) {+		pcd->ep0state = EP0_IDLE;+	} else if (pcd->ep0state == EP0_STALL) {+		pcd->ep0state = EP0_IDLE;+	}++	pcd->ep0state = EP0_IDLE;++	ep0->stopped = 0;++	speed = get_device_speed(GET_CORE_IF(pcd));+	pcd->fops->connect(pcd, speed);++	/* Set USB turnaround time based on device speed and PHY interface. */+	gusbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);+	if (speed == USB_SPEED_HIGH) {+		if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==+		    DWC_HWCFG2_HS_PHY_TYPE_ULPI) {+			/* ULPI interface */+			gusbcfg.b.usbtrdtim = 9;+		}+		if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==+		    DWC_HWCFG2_HS_PHY_TYPE_UTMI) {+			/* UTMI+ interface */+			if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 0) {+				gusbcfg.b.usbtrdtim = utmi8b;+			} else if (GET_CORE_IF(pcd)->hwcfg4.+				   b.utmi_phy_data_width == 1) {+				gusbcfg.b.usbtrdtim = utmi16b;+			} else if (GET_CORE_IF(pcd)->+				   core_params->phy_utmi_width == 8) {+				gusbcfg.b.usbtrdtim = utmi8b;+			} else {+				gusbcfg.b.usbtrdtim = utmi16b;+			}+		}+		if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==+		    DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) {+			/* UTMI+  OR  ULPI interface */+			if (gusbcfg.b.ulpi_utmi_sel == 1) {+				/* ULPI interface */+				gusbcfg.b.usbtrdtim = 9;+			} else {+				/* UTMI+ interface */+				if (GET_CORE_IF(pcd)->+				    core_params->phy_utmi_width == 16) {+					gusbcfg.b.usbtrdtim = utmi16b;+				} else {+					gusbcfg.b.usbtrdtim = utmi8b;+				}+			}+		}+	} else {+		/* Full or low speed */+		gusbcfg.b.usbtrdtim = 9;+	}+	DWC_WRITE_REG32(&global_regs->gusbcfg, gusbcfg.d32);++	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.enumdone = 1;+	DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,+			gintsts.d32);+	return 1;+}++/**+ * This interrupt indicates that the ISO OUT Packet was dropped due to+ * Rx FIFO full or Rx Status Queue Full.  If this interrupt occurs+ * read all the data from the Rx FIFO.+ */+int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t * pcd)+{+	gintmsk_data_t intr_mask = {.d32 = 0 };+	gintsts_data_t gintsts;++	DWC_WARN("INTERRUPT Handler not implemented for %s\n",+		 "ISOC Out Dropped");++	intr_mask.b.isooutdrop = 1;+	DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,+			 intr_mask.d32, 0);++	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.isooutdrop = 1;+	DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,+			gintsts.d32);++	return 1;+}++/**+ * This interrupt indicates the end of the portion of the micro-frame+ * for periodic transactions.  If there is a periodic transaction for+ * the next frame, load the packets into the EP periodic Tx FIFO.+ */+int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t * pcd)+{+	gintmsk_data_t intr_mask = {.d32 = 0 };+	gintsts_data_t gintsts;+	DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "EOP");++	intr_mask.b.eopframe = 1;+	DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,+			 intr_mask.d32, 0);++	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.eopframe = 1;+	DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,+			gintsts.d32);++	return 1;+}++/**+ * This interrupt indicates that EP of the packet on the top of the+ * non-periodic Tx FIFO does not match EP of the IN Token received.+ *+ * The "Device IN Token Queue" Registers are read to determine the+ * order the IN Tokens have been received. The non-periodic Tx FIFO+ * is flushed, so it can be reloaded in the order seen in the IN Token+ * Queue.+ */+int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_pcd_t * pcd)+{+	gintsts_data_t gintsts;+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	dctl_data_t dctl;+	gintmsk_data_t intr_mask = {.d32 = 0 };++	if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) {+		core_if->start_predict = 1;++		DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);++		gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);+		if (!gintsts.b.ginnakeff) {+			/* Disable EP Mismatch interrupt */+			intr_mask.d32 = 0;+			intr_mask.b.epmismatch = 1;+			DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32, 0);+			/* Enable the Global IN NAK Effective Interrupt */+			intr_mask.d32 = 0;+			intr_mask.b.ginnakeff = 1;+			DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);+			/* Set the global non-periodic IN NAK handshake */+			dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);+			dctl.b.sgnpinnak = 1;+			DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);+		} else {+			DWC_PRINTF("gintsts.b.ginnakeff = 1! dctl.b.sgnpinnak not set\n");+		}+		/* Disabling of all EP's will be done in dwc_otg_pcd_handle_in_nak_effective()+		 * handler after Global IN NAK Effective interrupt will be asserted */+	}+	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.epmismatch = 1;+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);++	return 1;+}++/**+ * This interrupt is valid only in DMA mode. This interrupt indicates that the+ * core has stopped fetching data for IN endpoints due to the unavailability of+ * TxFIFO space or Request Queue space. This interrupt is used by the+ * application for an endpoint mismatch algorithm.+ *+ * @param pcd The PCD+ */+int32_t dwc_otg_pcd_handle_ep_fetsusp_intr(dwc_otg_pcd_t * pcd)+{+	gintsts_data_t gintsts;+	gintmsk_data_t gintmsk_data;+	dctl_data_t dctl;+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);++	/* Clear the global non-periodic IN NAK handshake */+	dctl.d32 = 0;+	dctl.b.cgnpinnak = 1;+	DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);++	/* Mask GINTSTS.FETSUSP interrupt */+	gintmsk_data.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);+	gintmsk_data.b.fetsusp = 0;+	DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_data.d32);++	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.fetsusp = 1;+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);++	return 1;+}+/**+ * This funcion stalls EP0.+ */+static inline void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val)+{+	dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;+	usb_device_request_t *ctrl = &pcd->setup_pkt->req;+	DWC_WARN("req %02x.%02x protocol STALL; err %d\n",+		 ctrl->bmRequestType, ctrl->bRequest, err_val);++	ep0->dwc_ep.is_in = 1;+	dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep);+	pcd->ep0.stopped = 1;+	pcd->ep0state = EP0_IDLE;+	ep0_out_start(GET_CORE_IF(pcd), pcd);+}++/**+ * This functions delegates the setup command to the gadget driver.+ */+static inline void do_gadget_setup(dwc_otg_pcd_t * pcd,+				   usb_device_request_t * ctrl)+{+	int ret = 0;+	DWC_SPINUNLOCK(pcd->lock);+	ret = pcd->fops->setup(pcd, (uint8_t *) ctrl);+	DWC_SPINLOCK(pcd->lock);+	if (ret < 0) {+		ep0_do_stall(pcd, ret);+	}++	/** @todo This is a g_file_storage gadget driver specific+	 * workaround: a DELAYED_STATUS result from the fsg_setup+	 * routine will result in the gadget queueing a EP0 IN status+	 * phase for a two-stage control transfer. Exactly the same as+	 * a SET_CONFIGURATION/SET_INTERFACE except that this is a class+	 * specific request.  Need a generic way to know when the gadget+	 * driver will queue the status phase. Can we assume when we+	 * call the gadget driver setup() function that it will always+	 * queue and require the following flag? Need to look into+	 * this.+	 */++	if (ret == 256 + 999) {+		pcd->request_config = 1;+	}+}++#ifdef DWC_UTE_CFI+/**+ * This functions delegates the CFI setup commands to the gadget driver.+ * This function will return a negative value to indicate a failure.+ */+static inline int cfi_gadget_setup(dwc_otg_pcd_t * pcd,+				   struct cfi_usb_ctrlrequest *ctrl_req)+{+	int ret = 0;++	if (pcd->fops && pcd->fops->cfi_setup) {+		DWC_SPINUNLOCK(pcd->lock);+		ret = pcd->fops->cfi_setup(pcd, ctrl_req);+		DWC_SPINLOCK(pcd->lock);+		if (ret < 0) {+			ep0_do_stall(pcd, ret);+			return ret;+		}+	}++	return ret;+}+#endif++/**+ * This function starts the Zero-Length Packet for the IN status phase+ * of a 2 stage control transfer.+ */+static inline void do_setup_in_status_phase(dwc_otg_pcd_t * pcd)+{+	dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;+	if (pcd->ep0state == EP0_STALL) {+		return;+	}++	pcd->ep0state = EP0_IN_STATUS_PHASE;++	/* Prepare for more SETUP Packets */+	DWC_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n");+	if ((GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a)+	    && (pcd->core_if->dma_desc_enable)+	    && (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)) {+		DWC_DEBUGPL(DBG_PCDV,+			    "Data terminated wait next packet in out_desc_addr\n");+		pcd->backup_buf = phys_to_virt(ep0->dwc_ep.dma_addr);+		pcd->data_terminated = 1;+	}+	ep0->dwc_ep.xfer_len = 0;+	ep0->dwc_ep.xfer_count = 0;+	ep0->dwc_ep.is_in = 1;+	ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;+	dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);++	/* Prepare for more SETUP Packets */+	//ep0_out_start(GET_CORE_IF(pcd), pcd);+}++/**+ * This function starts the Zero-Length Packet for the OUT status phase+ * of a 2 stage control transfer.+ */+static inline void do_setup_out_status_phase(dwc_otg_pcd_t * pcd)+{+	dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;+	if (pcd->ep0state == EP0_STALL) {+		DWC_DEBUGPL(DBG_PCD, "EP0 STALLED\n");+		return;+	}+	pcd->ep0state = EP0_OUT_STATUS_PHASE;++	DWC_DEBUGPL(DBG_PCD, "EP0 OUT ZLP\n");+	ep0->dwc_ep.xfer_len = 0;+	ep0->dwc_ep.xfer_count = 0;+	ep0->dwc_ep.is_in = 0;+	ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;+	dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);++	/* Prepare for more SETUP Packets */+	if (GET_CORE_IF(pcd)->dma_enable == 0) {+		ep0_out_start(GET_CORE_IF(pcd), pcd);+	}+}++/**+ * Clear the EP halt (STALL) and if pending requests start the+ * transfer.+ */+static inline void pcd_clear_halt(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)+{+	if (ep->dwc_ep.stall_clear_flag == 0)+		dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);++	/* Reactive the EP */+	dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);+	if (ep->stopped) {+		ep->stopped = 0;+		/* If there is a request in the EP queue start it */++		/** @todo FIXME: this causes an EP mismatch in DMA mode.+		 * epmismatch not yet implemented. */++		/*+		 * Above fixme is solved by implmenting a tasklet to call the+		 * start_next_request(), outside of interrupt context at some+		 * time after the current time, after a clear-halt setup packet.+		 * Still need to implement ep mismatch in the future if a gadget+		 * ever uses more than one endpoint at once+		 */+		ep->queue_sof = 1;+		DWC_TASK_SCHEDULE(pcd->start_xfer_tasklet);+	}+	/* Start Control Status Phase */+	do_setup_in_status_phase(pcd);+}++/**+ * This function is called when the SET_FEATURE TEST_MODE Setup packet+ * is sent from the host.  The Device Control register is written with+ * the Test Mode bits set to the specified Test Mode.  This is done as+ * a tasklet so that the "Status" phase of the control transfer+ * completes before transmitting the TEST packets.+ *+ * @todo This has not been tested since the tasklet struct was put+ * into the PCD struct!+ *+ */+void do_test_mode(void *data)+{+	dctl_data_t dctl;+	dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	int test_mode = pcd->test_mode;++//        DWC_WARN("%s() has not been tested since being rewritten!\n", __func__);++	dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);+	switch (test_mode) {+	case 1:		// TEST_J+		dctl.b.tstctl = 1;+		break;++	case 2:		// TEST_K+		dctl.b.tstctl = 2;+		break;++	case 3:		// TEST_SE0_NAK+		dctl.b.tstctl = 3;+		break;++	case 4:		// TEST_PACKET+		dctl.b.tstctl = 4;+		break;++	case 5:		// TEST_FORCE_ENABLE+		dctl.b.tstctl = 5;+		break;+	}+	DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);+}++/**+ * This function process the GET_STATUS Setup Commands.+ */+static inline void do_get_status(dwc_otg_pcd_t * pcd)+{+	usb_device_request_t ctrl = pcd->setup_pkt->req;+	dwc_otg_pcd_ep_t *ep;+	dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;+	uint16_t *status = pcd->status_buf;+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);++#ifdef DEBUG_EP0+	DWC_DEBUGPL(DBG_PCD,+		    "GET_STATUS %02x.%02x v%04x i%04x l%04x\n",+		    ctrl.bmRequestType, ctrl.bRequest,+		    UGETW(ctrl.wValue), UGETW(ctrl.wIndex),+		    UGETW(ctrl.wLength));+#endif++	switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {+	case UT_DEVICE:+		if(UGETW(ctrl.wIndex) == 0xF000) { /* OTG Status selector */+			DWC_PRINTF("wIndex - %d\n", UGETW(ctrl.wIndex));+			DWC_PRINTF("OTG VERSION - %d\n", core_if->otg_ver);+			DWC_PRINTF("OTG CAP - %d, %d\n",+				   core_if->core_params->otg_cap,+						DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);+			if (core_if->otg_ver == 1+			    && core_if->core_params->otg_cap ==+			    DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {+				uint8_t *otgsts = (uint8_t*)pcd->status_buf;+				*otgsts = (core_if->otg_sts & 0x1);+				pcd->ep0_pending = 1;+				ep0->dwc_ep.start_xfer_buff =+				    (uint8_t *) otgsts;+				ep0->dwc_ep.xfer_buff = (uint8_t *) otgsts;+				ep0->dwc_ep.dma_addr =+				    pcd->status_buf_dma_handle;+				ep0->dwc_ep.xfer_len = 1;+				ep0->dwc_ep.xfer_count = 0;+				ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;+				dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),+							   &ep0->dwc_ep);+				return;+			} else {+				ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);+				return;+			}+			break;+		} else {+			*status = 0x1;	/* Self powered */+			*status |= pcd->remote_wakeup_enable << 1;+			break;+		}+	case UT_INTERFACE:+		*status = 0;+		break;++	case UT_ENDPOINT:+		ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));+		if (ep == 0 || UGETW(ctrl.wLength) > 2) {+			ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);+			return;+		}+		/** @todo check for EP stall */+		*status = ep->stopped;+		break;+	}+	pcd->ep0_pending = 1;+	ep0->dwc_ep.start_xfer_buff = (uint8_t *) status;+	ep0->dwc_ep.xfer_buff = (uint8_t *) status;+	ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle;+	ep0->dwc_ep.xfer_len = 2;+	ep0->dwc_ep.xfer_count = 0;+	ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;+	dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);+}++/**+ * This function process the SET_FEATURE Setup Commands.+ */+static inline void do_set_feature(dwc_otg_pcd_t * pcd)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;+	usb_device_request_t ctrl = pcd->setup_pkt->req;+	dwc_otg_pcd_ep_t *ep = 0;+	int32_t otg_cap_param = core_if->core_params->otg_cap;+	gotgctl_data_t gotgctl = {.d32 = 0 };++	DWC_DEBUGPL(DBG_PCD, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n",+		    ctrl.bmRequestType, ctrl.bRequest,+		    UGETW(ctrl.wValue), UGETW(ctrl.wIndex),+		    UGETW(ctrl.wLength));+	DWC_DEBUGPL(DBG_PCD, "otg_cap=%d\n", otg_cap_param);++	switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {+	case UT_DEVICE:+		switch (UGETW(ctrl.wValue)) {+		case UF_DEVICE_REMOTE_WAKEUP:+			pcd->remote_wakeup_enable = 1;+			break;++		case UF_TEST_MODE:+			/* Setup the Test Mode tasklet to do the Test+			 * Packet generation after the SETUP Status+			 * phase has completed. */++			/** @todo This has not been tested since the+			 * tasklet struct was put into the PCD+			 * struct! */+			pcd->test_mode = UGETW(ctrl.wIndex) >> 8;+			DWC_TASK_SCHEDULE(pcd->test_mode_tasklet);+			break;++		case UF_DEVICE_B_HNP_ENABLE:+			DWC_DEBUGPL(DBG_PCDV,+				    "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n");++			/* dev may initiate HNP */+			if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {+				pcd->b_hnp_enable = 1;+				dwc_otg_pcd_update_otg(pcd, 0);+				DWC_DEBUGPL(DBG_PCD, "Request B HNP\n");+				/**@todo Is the gotgctl.devhnpen cleared+				 * by a USB Reset? */+				gotgctl.b.devhnpen = 1;+				gotgctl.b.hnpreq = 1;+				DWC_WRITE_REG32(&global_regs->gotgctl,+						gotgctl.d32);+			} else {+				ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);+				return;+			}+			break;++		case UF_DEVICE_A_HNP_SUPPORT:+			/* RH port supports HNP */+			DWC_DEBUGPL(DBG_PCDV,+				    "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n");+			if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {+				pcd->a_hnp_support = 1;+				dwc_otg_pcd_update_otg(pcd, 0);+			} else {+				ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);+				return;+			}+			break;++		case UF_DEVICE_A_ALT_HNP_SUPPORT:+			/* other RH port does */+			DWC_DEBUGPL(DBG_PCDV,+				    "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n");+			if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {+				pcd->a_alt_hnp_support = 1;+				dwc_otg_pcd_update_otg(pcd, 0);+			} else {+				ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);+				return;+			}+			break;++		default:+			ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);+			return;++		}+		do_setup_in_status_phase(pcd);+		break;++	case UT_INTERFACE:+		do_gadget_setup(pcd, &ctrl);+		break;++	case UT_ENDPOINT:+		if (UGETW(ctrl.wValue) == UF_ENDPOINT_HALT) {+			ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));+			if (ep == 0) {+				ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);+				return;+			}+			ep->stopped = 1;+			dwc_otg_ep_set_stall(core_if, &ep->dwc_ep);+		}+		do_setup_in_status_phase(pcd);+		break;+	}+}++/**+ * This function process the CLEAR_FEATURE Setup Commands.+ */+static inline void do_clear_feature(dwc_otg_pcd_t * pcd)+{+	usb_device_request_t ctrl = pcd->setup_pkt->req;+	dwc_otg_pcd_ep_t *ep = 0;++	DWC_DEBUGPL(DBG_PCD,+		    "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n",+		    ctrl.bmRequestType, ctrl.bRequest,+		    UGETW(ctrl.wValue), UGETW(ctrl.wIndex),+		    UGETW(ctrl.wLength));++	switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {+	case UT_DEVICE:+		switch (UGETW(ctrl.wValue)) {+		case UF_DEVICE_REMOTE_WAKEUP:+			pcd->remote_wakeup_enable = 0;+			break;++		case UF_TEST_MODE:+			/** @todo Add CLEAR_FEATURE for TEST modes. */+			break;++		default:+			ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);+			return;+		}+		do_setup_in_status_phase(pcd);+		break;++	case UT_ENDPOINT:+		ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));+		if (ep == 0) {+			ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);+			return;+		}++		pcd_clear_halt(pcd, ep);++		break;+	}+}++/**+ * This function process the SET_ADDRESS Setup Commands.+ */+static inline void do_set_address(dwc_otg_pcd_t * pcd)+{+	dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;+	usb_device_request_t ctrl = pcd->setup_pkt->req;++	if (ctrl.bmRequestType == UT_DEVICE) {+		dcfg_data_t dcfg = {.d32 = 0 };++#ifdef DEBUG_EP0+//                      DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue);+#endif+		dcfg.b.devaddr = UGETW(ctrl.wValue);+		DWC_MODIFY_REG32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32);+		do_setup_in_status_phase(pcd);+	}+}++/**+ *	This function processes SETUP commands. In Linux, the USB Command+ *	processing is done in two places - the first being the PCD and the+ *	second in the Gadget Driver (for example, the File-Backed Storage+ *	Gadget Driver).+ *+ * <table>+ * <tr><td>Command	</td><td>Driver </td><td>Description</td></tr>+ *+ * <tr><td>GET_STATUS </td><td>PCD </td><td>Command is processed as+ * defined in chapter 9 of the USB 2.0 Specification chapter 9+ * </td></tr>+ *+ * <tr><td>CLEAR_FEATURE </td><td>PCD </td><td>The Device and Endpoint+ * requests are the ENDPOINT_HALT feature is procesed, all others the+ * interface requests are ignored.</td></tr>+ *+ * <tr><td>SET_FEATURE </td><td>PCD </td><td>The Device and Endpoint+ * requests are processed by the PCD.  Interface requests are passed+ * to the Gadget Driver.</td></tr>+ *+ * <tr><td>SET_ADDRESS </td><td>PCD </td><td>Program the DCFG reg,+ * with device address received </td></tr>+ *+ * <tr><td>GET_DESCRIPTOR </td><td>Gadget Driver </td><td>Return the+ * requested descriptor</td></tr>+ *+ * <tr><td>SET_DESCRIPTOR </td><td>Gadget Driver </td><td>Optional -+ * not implemented by any of the existing Gadget Drivers.</td></tr>+ *+ * <tr><td>SET_CONFIGURATION </td><td>Gadget Driver </td><td>Disable+ * all EPs and enable EPs for new configuration.</td></tr>+ *+ * <tr><td>GET_CONFIGURATION </td><td>Gadget Driver </td><td>Return+ * the current configuration</td></tr>+ *+ * <tr><td>SET_INTERFACE </td><td>Gadget Driver </td><td>Disable all+ * EPs and enable EPs for new configuration.</td></tr>+ *+ * <tr><td>GET_INTERFACE </td><td>Gadget Driver </td><td>Return the+ * current interface.</td></tr>+ *+ * <tr><td>SYNC_FRAME </td><td>PCD </td><td>Display debug+ * message.</td></tr>+ * </table>+ *+ * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are+ * processed by pcd_setup. Calling the Function Driver's setup function from+ * pcd_setup processes the gadget SETUP commands.+ */+static inline void pcd_setup(dwc_otg_pcd_t * pcd)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	dwc_otg_dev_if_t *dev_if = core_if->dev_if;+	usb_device_request_t ctrl = pcd->setup_pkt->req;+	dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;++	deptsiz0_data_t doeptsize0 = {.d32 = 0 };++#ifdef DWC_UTE_CFI+	int retval = 0;+	struct cfi_usb_ctrlrequest cfi_req;+#endif++	doeptsize0.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doeptsiz);++	/** In BDMA more then 1 setup packet is not supported till 3.00a */+	if (core_if->dma_enable && core_if->dma_desc_enable == 0+	    && (doeptsize0.b.supcnt < 2)+	    && (core_if->snpsid < OTG_CORE_REV_2_94a)) {+		DWC_ERROR+		    ("\n\n-----------	 CANNOT handle > 1 setup packet in DMA mode\n\n");+	}+	if ((core_if->snpsid >= OTG_CORE_REV_3_00a)+	    && (core_if->dma_enable == 1) && (core_if->dma_desc_enable == 0)) {+		ctrl =+		    (pcd->setup_pkt ++		     (3 - doeptsize0.b.supcnt - 1 ++		      ep0->dwc_ep.stp_rollover))->req;+	}+#ifdef DEBUG_EP0+	DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n",+		    ctrl.bmRequestType, ctrl.bRequest,+		    UGETW(ctrl.wValue), UGETW(ctrl.wIndex),+		    UGETW(ctrl.wLength));+#endif++	/* Clean up the request queue */+	dwc_otg_request_nuke(ep0);+	ep0->stopped = 0;++	if (ctrl.bmRequestType & UE_DIR_IN) {+		ep0->dwc_ep.is_in = 1;+		pcd->ep0state = EP0_IN_DATA_PHASE;+	} else {+		ep0->dwc_ep.is_in = 0;+		pcd->ep0state = EP0_OUT_DATA_PHASE;+	}++	if (UGETW(ctrl.wLength) == 0) {+		ep0->dwc_ep.is_in = 1;+		pcd->ep0state = EP0_IN_STATUS_PHASE;+	}++	if (UT_GET_TYPE(ctrl.bmRequestType) != UT_STANDARD) {++#ifdef DWC_UTE_CFI+		DWC_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t));++		//printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n",+				ctrl.bRequestType, ctrl.bRequest);+		if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) {+			if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) {+				retval = cfi_setup(pcd, &cfi_req);+				if (retval < 0) {+					ep0_do_stall(pcd, retval);+					pcd->ep0_pending = 0;+					return;+				}++				/* if need gadget setup then call it and check the retval */+				if (pcd->cfi->need_gadget_att) {+					retval =+					    cfi_gadget_setup(pcd,+							     &pcd->+							     cfi->ctrl_req);+					if (retval < 0) {+						pcd->ep0_pending = 0;+						return;+					}+				}++				if (pcd->cfi->need_status_in_complete) {+					do_setup_in_status_phase(pcd);+				}+				return;+			}+		}+#endif++		/* handle non-standard (class/vendor) requests in the gadget driver */+		do_gadget_setup(pcd, &ctrl);+		return;+	}++	/** @todo NGS: Handle bad setup packet? */++///////////////////////////////////////////+//// --- Standard Request handling --- ////++	switch (ctrl.bRequest) {+	case UR_GET_STATUS:+		do_get_status(pcd);+		break;++	case UR_CLEAR_FEATURE:+		do_clear_feature(pcd);+		break;++	case UR_SET_FEATURE:+		do_set_feature(pcd);+		break;++	case UR_SET_ADDRESS:+		do_set_address(pcd);+		break;++	case UR_SET_INTERFACE:+	case UR_SET_CONFIG:+//              _pcd->request_config = 1;       /* Configuration changed */+		do_gadget_setup(pcd, &ctrl);+		break;++	case UR_SYNCH_FRAME:+		do_gadget_setup(pcd, &ctrl);+		break;++	default:+		/* Call the Gadget Driver's setup functions */+		do_gadget_setup(pcd, &ctrl);+		break;+	}+}++/**+ * This function completes the ep0 control transfer.+ */+static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);+	dwc_otg_dev_if_t *dev_if = core_if->dev_if;+	dwc_otg_dev_in_ep_regs_t *in_ep_regs =+	    dev_if->in_ep_regs[ep->dwc_ep.num];+#ifdef DEBUG_EP0+	dwc_otg_dev_out_ep_regs_t *out_ep_regs =+	    dev_if->out_ep_regs[ep->dwc_ep.num];+#endif+	deptsiz0_data_t deptsiz;+	dev_dma_desc_sts_t desc_sts;+	dwc_otg_pcd_request_t *req;+	int is_last = 0;+	dwc_otg_pcd_t *pcd = ep->pcd;++#ifdef DWC_UTE_CFI+	struct cfi_usb_ctrlrequest *ctrlreq;+	int retval = -DWC_E_NOT_SUPPORTED;+#endif++        desc_sts.b.bytes = 0;++	if (pcd->ep0_pending && DWC_CIRCLEQ_EMPTY(&ep->queue)) {+		if (ep->dwc_ep.is_in) {+#ifdef DEBUG_EP0+			DWC_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n");+#endif+			do_setup_out_status_phase(pcd);+		} else {+#ifdef DEBUG_EP0+			DWC_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n");+#endif++#ifdef DWC_UTE_CFI+			ctrlreq = &pcd->cfi->ctrl_req;++			if (UT_GET_TYPE(ctrlreq->bRequestType) == UT_VENDOR) {+				if (ctrlreq->bRequest > 0xB0+				    && ctrlreq->bRequest < 0xBF) {++					/* Return if the PCD failed to handle the request */+					if ((retval =+					     pcd->cfi->ops.+					     ctrl_write_complete(pcd->cfi,+								 pcd)) < 0) {+						CFI_INFO+						    ("ERROR setting a new value in the PCD(%d)\n",+						     retval);+						ep0_do_stall(pcd, retval);+						pcd->ep0_pending = 0;+						return 0;+					}++					/* If the gadget needs to be notified on the request */+					if (pcd->cfi->need_gadget_att == 1) {+						//retval = do_gadget_setup(pcd, &pcd->cfi->ctrl_req);+						retval =+						    cfi_gadget_setup(pcd,+								     &pcd->cfi->+								     ctrl_req);++						/* Return from the function if the gadget failed to process+						 * the request properly - this should never happen !!!+						 */+						if (retval < 0) {+							CFI_INFO+							    ("ERROR setting a new value in the gadget(%d)\n",+							     retval);+							pcd->ep0_pending = 0;+							return 0;+						}+					}++					CFI_INFO("%s: RETVAL=%d\n", __func__,+						 retval);+					/* If we hit here then the PCD and the gadget has properly+					 * handled the request - so send the ZLP IN to the host.+					 */+					/* @todo: MAS - decide whether we need to start the setup+					 * stage based on the need_setup value of the cfi object+					 */+					do_setup_in_status_phase(pcd);+					pcd->ep0_pending = 0;+					return 1;+				}+			}+#endif++			do_setup_in_status_phase(pcd);+		}+		pcd->ep0_pending = 0;+		return 1;+	}++	if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {+		return 0;+	}+	req = DWC_CIRCLEQ_FIRST(&ep->queue);++	if (pcd->ep0state == EP0_OUT_STATUS_PHASE+	    || pcd->ep0state == EP0_IN_STATUS_PHASE) {+		is_last = 1;+	} else if (ep->dwc_ep.is_in) {+		deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);+		if (core_if->dma_desc_enable != 0)+			desc_sts = dev_if->in_desc_addr->status;+#ifdef DEBUG_EP0+		DWC_DEBUGPL(DBG_PCDV, "%d len=%d  xfersize=%d pktcnt=%d\n",+			    ep->dwc_ep.num, ep->dwc_ep.xfer_len,+			    deptsiz.b.xfersize, deptsiz.b.pktcnt);+#endif++		if (((core_if->dma_desc_enable == 0)+		     && (deptsiz.b.xfersize == 0))+		    || ((core_if->dma_desc_enable != 0)+			&& (desc_sts.b.bytes == 0))) {+			req->actual = ep->dwc_ep.xfer_count;+			/* Is a Zero Len Packet needed? */+			if (req->sent_zlp) {+#ifdef DEBUG_EP0+				DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n");+#endif+				req->sent_zlp = 0;+			}+			do_setup_out_status_phase(pcd);+		}+	} else {+		/* ep0-OUT */+#ifdef DEBUG_EP0+		deptsiz.d32 = DWC_READ_REG32(&out_ep_regs->doeptsiz);+		DWC_DEBUGPL(DBG_PCDV, "%d len=%d xsize=%d pktcnt=%d\n",+			    ep->dwc_ep.num, ep->dwc_ep.xfer_len,+			    deptsiz.b.xfersize, deptsiz.b.pktcnt);+#endif+		req->actual = ep->dwc_ep.xfer_count;++		/* Is a Zero Len Packet needed? */+		if (req->sent_zlp) {+#ifdef DEBUG_EP0+			DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n");+#endif+			req->sent_zlp = 0;+		}+		/* For older cores do setup in status phase in Slave/BDMA modes,+		 * starting from 3.00 do that only in slave, and for DMA modes+		 * just re-enable ep 0 OUT here*/+		if (core_if->dma_enable == 0+		    || (core_if->dma_desc_enable == 0+			&& core_if->snpsid <= OTG_CORE_REV_2_94a)) {+			do_setup_in_status_phase(pcd);+		} else if (core_if->snpsid >= OTG_CORE_REV_3_00a) {+			DWC_DEBUGPL(DBG_PCDV,+				    "Enable out ep before in status phase\n");+			ep0_out_start(core_if, pcd);+		}+	}++	/* Complete the request */+	if (is_last) {+		dwc_otg_request_done(ep, req, 0);+		ep->dwc_ep.start_xfer_buff = 0;+		ep->dwc_ep.xfer_buff = 0;+		ep->dwc_ep.xfer_len = 0;+		return 1;+	}+	return 0;+}++#ifdef DWC_UTE_CFI+/**+ * This function calculates traverses all the CFI DMA descriptors and+ * and accumulates the bytes that are left to be transfered.+ *+ * @return The total bytes left to transfered, or a negative value as failure+ */+static inline int cfi_calc_desc_residue(dwc_otg_pcd_ep_t * ep)+{+	int32_t ret = 0;+	int i;+	struct dwc_otg_dma_desc *ddesc = NULL;+	struct cfi_ep *cfiep;++	/* See if the pcd_ep has its respective cfi_ep mapped */+	cfiep = get_cfi_ep_by_pcd_ep(ep->pcd->cfi, ep);+	if (!cfiep) {+		CFI_INFO("%s: Failed to find ep\n", __func__);+		return -1;+	}++	ddesc = ep->dwc_ep.descs;++	for (i = 0; (i < cfiep->desc_count) && (i < MAX_DMA_DESCS_PER_EP); i++) {++#if defined(PRINT_CFI_DMA_DESCS)+		print_desc(ddesc, ep->ep.name, i);+#endif+		ret += ddesc->status.b.bytes;+		ddesc++;+	}++	if (ret)+		CFI_INFO("!!!!!!!!!! WARNING (%s) - residue=%d\n", __func__,+			 ret);++	return ret;+}+#endif++/**+ * This function completes the request for the EP. If there are+ * additional requests for the EP in the queue they will be started.+ */+static void complete_ep(dwc_otg_pcd_ep_t * ep)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);+	dwc_otg_dev_if_t *dev_if = core_if->dev_if;+	dwc_otg_dev_in_ep_regs_t *in_ep_regs =+	    dev_if->in_ep_regs[ep->dwc_ep.num];+	deptsiz_data_t deptsiz;+	dev_dma_desc_sts_t desc_sts;+	dwc_otg_pcd_request_t *req = 0;+	dwc_otg_dev_dma_desc_t *dma_desc;+	uint32_t byte_count = 0;+	int is_last = 0;+	int i;++	DWC_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->dwc_ep.num,+		    (ep->dwc_ep.is_in ? "IN" : "OUT"));++	/* Get any pending requests */+	if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {+		req = DWC_CIRCLEQ_FIRST(&ep->queue);+		if (!req) {+			DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);+			return;+		}+	} else {+		DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);+		return;+	}++	DWC_DEBUGPL(DBG_PCD, "Requests %d\n", ep->pcd->request_pending);++	if (ep->dwc_ep.is_in) {+		deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);++		if (core_if->dma_enable) {+			if (core_if->dma_desc_enable == 0) {+				if (deptsiz.b.xfersize == 0+				    && deptsiz.b.pktcnt == 0) {+					byte_count =+					    ep->dwc_ep.xfer_len -+					    ep->dwc_ep.xfer_count;++					ep->dwc_ep.xfer_buff += byte_count;+					ep->dwc_ep.dma_addr += byte_count;+					ep->dwc_ep.xfer_count += byte_count;++					DWC_DEBUGPL(DBG_PCDV,+						    "%d-%s len=%d  xfersize=%d pktcnt=%d\n",+						    ep->dwc_ep.num,+						    (ep->dwc_ep.+						     is_in ? "IN" : "OUT"),+						    ep->dwc_ep.xfer_len,+						    deptsiz.b.xfersize,+						    deptsiz.b.pktcnt);++					if (ep->dwc_ep.xfer_len <+					    ep->dwc_ep.total_len) {+						dwc_otg_ep_start_transfer+						    (core_if, &ep->dwc_ep);+					} else if (ep->dwc_ep.sent_zlp) {+						/*+						 * This fragment of code should initiate 0+						 * length transfer in case if it is queued+						 * a transfer with size divisible to EPs max+						 * packet size and with usb_request zero field+						 * is set, which means that after data is transfered,+						 * it is also should be transfered+						 * a 0 length packet at the end. For Slave and+						 * Buffer DMA modes in this case SW has+						 * to initiate 2 transfers one with transfer size,+						 * and the second with 0 size. For Descriptor+						 * DMA mode SW is able to initiate a transfer,+						 * which will handle all the packets including+						 * the last  0 length.+						 */+						ep->dwc_ep.sent_zlp = 0;+						dwc_otg_ep_start_zl_transfer+						    (core_if, &ep->dwc_ep);+					} else {+						is_last = 1;+					}+				} else {+					if (ep->dwc_ep.type ==+					    DWC_OTG_EP_TYPE_ISOC) {+						req->actual = 0;+						dwc_otg_request_done(ep, req, 0);++						ep->dwc_ep.start_xfer_buff = 0;+						ep->dwc_ep.xfer_buff = 0;+						ep->dwc_ep.xfer_len = 0;++						/* If there is a request in the queue start it. */+						start_next_request(ep);+					} else+						DWC_WARN+						("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n",+						ep->dwc_ep.num,+						(ep->dwc_ep.is_in ? "IN" : "OUT"),+						deptsiz.b.xfersize,+						deptsiz.b.pktcnt);+				}+			} else {+				dma_desc = ep->dwc_ep.desc_addr;+				byte_count = 0;+				ep->dwc_ep.sent_zlp = 0;++#ifdef DWC_UTE_CFI+				CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,+					 ep->dwc_ep.buff_mode);+				if (ep->dwc_ep.buff_mode != BM_STANDARD) {+					int residue;++					residue = cfi_calc_desc_residue(ep);+					if (residue < 0)+						return;++					byte_count = residue;+				} else {+#endif+					for (i = 0; i < ep->dwc_ep.desc_cnt;+					     ++i) {+					desc_sts = dma_desc->status;+					byte_count += desc_sts.b.bytes;+					dma_desc++;+				}+#ifdef DWC_UTE_CFI+				}+#endif+				if (byte_count == 0) {+					ep->dwc_ep.xfer_count =+					    ep->dwc_ep.total_len;+					is_last = 1;+				} else {+					DWC_WARN("Incomplete transfer\n");+				}+			}+		} else {+			if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0) {+				DWC_DEBUGPL(DBG_PCDV,+					    "%d-%s len=%d  xfersize=%d pktcnt=%d\n",+					    ep->dwc_ep.num,+					    ep->dwc_ep.is_in ? "IN" : "OUT",+					    ep->dwc_ep.xfer_len,+					    deptsiz.b.xfersize,+					    deptsiz.b.pktcnt);++				/*      Check if the whole transfer was completed,+				 *      if no, setup transfer for next portion of data+				 */+				if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {+					dwc_otg_ep_start_transfer(core_if,+								  &ep->dwc_ep);+				} else if (ep->dwc_ep.sent_zlp) {+					/*+					 * This fragment of code should initiate 0+					 * length trasfer in case if it is queued+					 * a trasfer with size divisible to EPs max+					 * packet size and with usb_request zero field+					 * is set, which means that after data is transfered,+					 * it is also should be transfered+					 * a 0 length packet at the end. For Slave and+					 * Buffer DMA modes in this case SW has+					 * to initiate 2 transfers one with transfer size,+					 * and the second with 0 size. For Desriptor+					 * DMA mode SW is able to initiate a transfer,+					 * which will handle all the packets including+					 * the last  0 legth.+					 */+					ep->dwc_ep.sent_zlp = 0;+					dwc_otg_ep_start_zl_transfer(core_if,+								     &ep->dwc_ep);+				} else {+					is_last = 1;+				}+			} else {+				DWC_WARN+				    ("Incomplete transfer (%d-%s [siz=%d pkt=%d])\n",+				     ep->dwc_ep.num,+				     (ep->dwc_ep.is_in ? "IN" : "OUT"),+				     deptsiz.b.xfersize, deptsiz.b.pktcnt);+			}+		}+	} else {+		dwc_otg_dev_out_ep_regs_t *out_ep_regs =+		    dev_if->out_ep_regs[ep->dwc_ep.num];+		desc_sts.d32 = 0;+		if (core_if->dma_enable) {+			if (core_if->dma_desc_enable) {+				dma_desc = ep->dwc_ep.desc_addr;+				byte_count = 0;+				ep->dwc_ep.sent_zlp = 0;++#ifdef DWC_UTE_CFI+				CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,+					 ep->dwc_ep.buff_mode);+				if (ep->dwc_ep.buff_mode != BM_STANDARD) {+					int residue;+					residue = cfi_calc_desc_residue(ep);+					if (residue < 0)+						return;+					byte_count = residue;+				} else {+#endif++					for (i = 0; i < ep->dwc_ep.desc_cnt;+					     ++i) {+						desc_sts = dma_desc->status;+						byte_count += desc_sts.b.bytes;+						dma_desc++;+					}++#ifdef DWC_UTE_CFI+				}+#endif+				/* Checking for interrupt Out transfers with not+				 * dword aligned mps sizes+				 */+				if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_INTR &&+							(ep->dwc_ep.maxpacket%4)) {+					ep->dwc_ep.xfer_count =+					    ep->dwc_ep.total_len - byte_count;+					if ((ep->dwc_ep.xfer_len %+					     ep->dwc_ep.maxpacket)+					    && (ep->dwc_ep.xfer_len /+						ep->dwc_ep.maxpacket <+						MAX_DMA_DESC_CNT))+						ep->dwc_ep.xfer_len -=+						    (ep->dwc_ep.desc_cnt -+						     1) * ep->dwc_ep.maxpacket ++						    ep->dwc_ep.xfer_len %+						    ep->dwc_ep.maxpacket;+					else+						ep->dwc_ep.xfer_len -=+						    ep->dwc_ep.desc_cnt *+						    ep->dwc_ep.maxpacket;+					if (ep->dwc_ep.xfer_len > 0) {+						dwc_otg_ep_start_transfer+						    (core_if, &ep->dwc_ep);+					} else {+						is_last = 1;+					}+				} else {+					ep->dwc_ep.xfer_count =+					    ep->dwc_ep.total_len - byte_count ++					    ((4 -+					      (ep->dwc_ep.+					       total_len & 0x3)) & 0x3);+					is_last = 1;+				}+			} else {+				deptsiz.d32 = 0;+				deptsiz.d32 =+				    DWC_READ_REG32(&out_ep_regs->doeptsiz);++				byte_count = (ep->dwc_ep.xfer_len -+					      ep->dwc_ep.xfer_count -+					      deptsiz.b.xfersize);+				ep->dwc_ep.xfer_buff += byte_count;+				ep->dwc_ep.dma_addr += byte_count;+				ep->dwc_ep.xfer_count += byte_count;++				/*      Check if the whole transfer was completed,+				 *      if no, setup transfer for next portion of data+				 */+				if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {+					dwc_otg_ep_start_transfer(core_if,+								  &ep->dwc_ep);+				} else if (ep->dwc_ep.sent_zlp) {+					/*+					 * This fragment of code should initiate 0+					 * length trasfer in case if it is queued+					 * a trasfer with size divisible to EPs max+					 * packet size and with usb_request zero field+					 * is set, which means that after data is transfered,+					 * it is also should be transfered+					 * a 0 length packet at the end. For Slave and+					 * Buffer DMA modes in this case SW has+					 * to initiate 2 transfers one with transfer size,+					 * and the second with 0 size. For Desriptor+					 * DMA mode SW is able to initiate a transfer,+					 * which will handle all the packets including+					 * the last  0 legth.+					 */+					ep->dwc_ep.sent_zlp = 0;+					dwc_otg_ep_start_zl_transfer(core_if,+								     &ep->dwc_ep);+				} else {+					is_last = 1;+				}+			}+		} else {+			/*      Check if the whole transfer was completed,+			 *      if no, setup transfer for next portion of data+			 */+			if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {+				dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);+			} else if (ep->dwc_ep.sent_zlp) {+				/*+				 * This fragment of code should initiate 0+				 * length transfer in case if it is queued+				 * a transfer with size divisible to EPs max+				 * packet size and with usb_request zero field+				 * is set, which means that after data is transfered,+				 * it is also should be transfered+				 * a 0 length packet at the end. For Slave and+				 * Buffer DMA modes in this case SW has+				 * to initiate 2 transfers one with transfer size,+				 * and the second with 0 size. For Descriptor+				 * DMA mode SW is able to initiate a transfer,+				 * which will handle all the packets including+				 * the last  0 length.+				 */+				ep->dwc_ep.sent_zlp = 0;+				dwc_otg_ep_start_zl_transfer(core_if,+							     &ep->dwc_ep);+			} else {+				is_last = 1;+			}+		}++		DWC_DEBUGPL(DBG_PCDV,+			    "addr %p,	 %d-%s len=%d cnt=%d xsize=%d pktcnt=%d\n",+			    &out_ep_regs->doeptsiz, ep->dwc_ep.num,+			    ep->dwc_ep.is_in ? "IN" : "OUT",+			    ep->dwc_ep.xfer_len, ep->dwc_ep.xfer_count,+			    deptsiz.b.xfersize, deptsiz.b.pktcnt);+	}++	/* Complete the request */+	if (is_last) {+#ifdef DWC_UTE_CFI+		if (ep->dwc_ep.buff_mode != BM_STANDARD) {+			req->actual = ep->dwc_ep.cfi_req_len - byte_count;+		} else {+#endif+			req->actual = ep->dwc_ep.xfer_count;+#ifdef DWC_UTE_CFI+		}+#endif+		if (req->dw_align_buf) {+			if (!ep->dwc_ep.is_in) {+				dwc_memcpy(req->buf, req->dw_align_buf, req->length);+			}+			DWC_DMA_FREE(req->length, req->dw_align_buf,+				     req->dw_align_buf_dma);+		}++		dwc_otg_request_done(ep, req, 0);++		ep->dwc_ep.start_xfer_buff = 0;+		ep->dwc_ep.xfer_buff = 0;+		ep->dwc_ep.xfer_len = 0;++		/* If there is a request in the queue start it. */+		start_next_request(ep);+	}+}++#ifdef DWC_EN_ISOC++/**+ * This function BNA interrupt for Isochronous EPs+ *+ */+static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t * ep)+{+	dwc_ep_t *dwc_ep = &ep->dwc_ep;+	volatile uint32_t *addr;+	depctl_data_t depctl = {.d32 = 0 };+	dwc_otg_pcd_t *pcd = ep->pcd;+	dwc_otg_dev_dma_desc_t *dma_desc;+	int i;++	dma_desc =+	    dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * (dwc_ep->proc_buf_num);++	if (dwc_ep->is_in) {+		dev_dma_desc_sts_t sts = {.d32 = 0 };+		for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {+			sts.d32 = dma_desc->status.d32;+			sts.b_iso_in.bs = BS_HOST_READY;+			dma_desc->status.d32 = sts.d32;+		}+	} else {+		dev_dma_desc_sts_t sts = {.d32 = 0 };+		for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {+			sts.d32 = dma_desc->status.d32;+			sts.b_iso_out.bs = BS_HOST_READY;+			dma_desc->status.d32 = sts.d32;+		}+	}++	if (dwc_ep->is_in == 0) {+		addr =+		    &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->+							   num]->doepctl;+	} else {+		addr =+		    &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;+	}+	depctl.b.epena = 1;+	DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);+}++/**+ * This function sets latest iso packet information(non-PTI mode)+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP to start the transfer on.+ *+ */+void set_current_pkt_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)+{+	deptsiz_data_t deptsiz = {.d32 = 0 };+	dma_addr_t dma_addr;+	uint32_t offset;++	if (ep->proc_buf_num)+		dma_addr = ep->dma_addr1;+	else+		dma_addr = ep->dma_addr0;++	if (ep->is_in) {+		deptsiz.d32 =+		    DWC_READ_REG32(&core_if->dev_if->+				   in_ep_regs[ep->num]->dieptsiz);+		offset = ep->data_per_frame;+	} else {+		deptsiz.d32 =+		    DWC_READ_REG32(&core_if->dev_if->+				   out_ep_regs[ep->num]->doeptsiz);+		offset =+		    ep->data_per_frame ++		    (0x4 & (0x4 - (ep->data_per_frame & 0x3)));+	}++	if (!deptsiz.b.xfersize) {+		ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;+		ep->pkt_info[ep->cur_pkt].offset =+		    ep->cur_pkt_dma_addr - dma_addr;+		ep->pkt_info[ep->cur_pkt].status = 0;+	} else {+		ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;+		ep->pkt_info[ep->cur_pkt].offset =+		    ep->cur_pkt_dma_addr - dma_addr;+		ep->pkt_info[ep->cur_pkt].status = -DWC_E_NO_DATA;+	}+	ep->cur_pkt_addr += offset;+	ep->cur_pkt_dma_addr += offset;+	ep->cur_pkt++;+}++/**+ * This function sets latest iso packet information(DDMA mode)+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param dwc_ep The EP to start the transfer on.+ *+ */+static void set_ddma_iso_pkts_info(dwc_otg_core_if_t * core_if,+				   dwc_ep_t * dwc_ep)+{+	dwc_otg_dev_dma_desc_t *dma_desc;+	dev_dma_desc_sts_t sts = {.d32 = 0 };+	iso_pkt_info_t *iso_packet;+	uint32_t data_per_desc;+	uint32_t offset;+	int i, j;++	iso_packet = dwc_ep->pkt_info;++	/** Reinit closed DMA Descriptors*/+	/** ISO OUT EP */+	if (dwc_ep->is_in == 0) {+		dma_desc =+		    dwc_ep->iso_desc_addr ++		    dwc_ep->desc_cnt * dwc_ep->proc_buf_num;+		offset = 0;++		for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;+		     i += dwc_ep->pkt_per_frm) {+			for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {+				data_per_desc =+				    ((j + 1) * dwc_ep->maxpacket >+				     dwc_ep->+				     data_per_frame) ? dwc_ep->data_per_frame -+				    j * dwc_ep->maxpacket : dwc_ep->maxpacket;+				data_per_desc +=+				    (data_per_desc % 4) ? (4 -+							   data_per_desc %+							   4) : 0;++				sts.d32 = dma_desc->status.d32;++				/* Write status in iso_packet_decsriptor  */+				iso_packet->status =+				    sts.b_iso_out.rxsts ++				    (sts.b_iso_out.bs ^ BS_DMA_DONE);+				if (iso_packet->status) {+					iso_packet->status = -DWC_E_NO_DATA;+				}++				/* Received data length */+				if (!sts.b_iso_out.rxbytes) {+					iso_packet->length =+					    data_per_desc -+					    sts.b_iso_out.rxbytes;+				} else {+					iso_packet->length =+					    data_per_desc -+					    sts.b_iso_out.rxbytes + (4 -+								     dwc_ep->data_per_frame+								     % 4);+				}++				iso_packet->offset = offset;++				offset += data_per_desc;+				dma_desc++;+				iso_packet++;+			}+		}++		for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {+			data_per_desc =+			    ((j + 1) * dwc_ep->maxpacket >+			     dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -+			    j * dwc_ep->maxpacket : dwc_ep->maxpacket;+			data_per_desc +=+			    (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;++			sts.d32 = dma_desc->status.d32;++			/* Write status in iso_packet_decsriptor  */+			iso_packet->status =+			    sts.b_iso_out.rxsts ++			    (sts.b_iso_out.bs ^ BS_DMA_DONE);+			if (iso_packet->status) {+				iso_packet->status = -DWC_E_NO_DATA;+			}++			/* Received data length */+			iso_packet->length =+			    dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;++			iso_packet->offset = offset;++			offset += data_per_desc;+			iso_packet++;+			dma_desc++;+		}++		sts.d32 = dma_desc->status.d32;++		/* Write status in iso_packet_decsriptor  */+		iso_packet->status =+		    sts.b_iso_out.rxsts + (sts.b_iso_out.bs ^ BS_DMA_DONE);+		if (iso_packet->status) {+			iso_packet->status = -DWC_E_NO_DATA;+		}+		/* Received data length */+		if (!sts.b_iso_out.rxbytes) {+			iso_packet->length =+			    dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;+		} else {+			iso_packet->length =+			    dwc_ep->data_per_frame - sts.b_iso_out.rxbytes ++			    (4 - dwc_ep->data_per_frame % 4);+		}++		iso_packet->offset = offset;+	} else {+/** ISO IN EP */++		dma_desc =+		    dwc_ep->iso_desc_addr ++		    dwc_ep->desc_cnt * dwc_ep->proc_buf_num;++		for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {+			sts.d32 = dma_desc->status.d32;++			/* Write status in iso packet descriptor */+			iso_packet->status =+			    sts.b_iso_in.txsts ++			    (sts.b_iso_in.bs ^ BS_DMA_DONE);+			if (iso_packet->status != 0) {+				iso_packet->status = -DWC_E_NO_DATA;++			}+			/* Bytes has been transfered */+			iso_packet->length =+			    dwc_ep->data_per_frame - sts.b_iso_in.txbytes;++			dma_desc++;+			iso_packet++;+		}++		sts.d32 = dma_desc->status.d32;+		while (sts.b_iso_in.bs == BS_DMA_BUSY) {+			sts.d32 = dma_desc->status.d32;+		}++		/* Write status in iso packet descriptor ??? do be done with ERROR codes */+		iso_packet->status =+		    sts.b_iso_in.txsts + (sts.b_iso_in.bs ^ BS_DMA_DONE);+		if (iso_packet->status != 0) {+			iso_packet->status = -DWC_E_NO_DATA;+		}++		/* Bytes has been transfered */+		iso_packet->length =+		    dwc_ep->data_per_frame - sts.b_iso_in.txbytes;+	}+}++/**+ * This function reinitialize DMA Descriptors for Isochronous transfer+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param dwc_ep The EP to start the transfer on.+ *+ */+static void reinit_ddma_iso_xfer(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)+{+	int i, j;+	dwc_otg_dev_dma_desc_t *dma_desc;+	dma_addr_t dma_ad;+	volatile uint32_t *addr;+	dev_dma_desc_sts_t sts = {.d32 = 0 };+	uint32_t data_per_desc;++	if (dwc_ep->is_in == 0) {+		addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;+	} else {+		addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;+	}++	if (dwc_ep->proc_buf_num == 0) {+		/** Buffer 0 descriptors setup */+		dma_ad = dwc_ep->dma_addr0;+	} else {+		/** Buffer 1 descriptors setup */+		dma_ad = dwc_ep->dma_addr1;+	}++	/** Reinit closed DMA Descriptors*/+	/** ISO OUT EP */+	if (dwc_ep->is_in == 0) {+		dma_desc =+		    dwc_ep->iso_desc_addr ++		    dwc_ep->desc_cnt * dwc_ep->proc_buf_num;++		sts.b_iso_out.bs = BS_HOST_READY;+		sts.b_iso_out.rxsts = 0;+		sts.b_iso_out.l = 0;+		sts.b_iso_out.sp = 0;+		sts.b_iso_out.ioc = 0;+		sts.b_iso_out.pid = 0;+		sts.b_iso_out.framenum = 0;++		for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;+		     i += dwc_ep->pkt_per_frm) {+			for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {+				data_per_desc =+				    ((j + 1) * dwc_ep->maxpacket >+				     dwc_ep->+				     data_per_frame) ? dwc_ep->data_per_frame -+				    j * dwc_ep->maxpacket : dwc_ep->maxpacket;+				data_per_desc +=+				    (data_per_desc % 4) ? (4 -+							   data_per_desc %+							   4) : 0;+				sts.b_iso_out.rxbytes = data_per_desc;+				dma_desc->buf = dma_ad;+				dma_desc->status.d32 = sts.d32;++				dma_ad += data_per_desc;+				dma_desc++;+			}+		}++		for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {++			data_per_desc =+			    ((j + 1) * dwc_ep->maxpacket >+			     dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -+			    j * dwc_ep->maxpacket : dwc_ep->maxpacket;+			data_per_desc +=+			    (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;+			sts.b_iso_out.rxbytes = data_per_desc;++			dma_desc->buf = dma_ad;+			dma_desc->status.d32 = sts.d32;++			dma_desc++;+			dma_ad += data_per_desc;+		}++		sts.b_iso_out.ioc = 1;+		sts.b_iso_out.l = dwc_ep->proc_buf_num;++		data_per_desc =+		    ((j + 1) * dwc_ep->maxpacket >+		     dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -+		    j * dwc_ep->maxpacket : dwc_ep->maxpacket;+		data_per_desc +=+		    (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;+		sts.b_iso_out.rxbytes = data_per_desc;++		dma_desc->buf = dma_ad;+		dma_desc->status.d32 = sts.d32;+	} else {+/** ISO IN EP */++		dma_desc =+		    dwc_ep->iso_desc_addr ++		    dwc_ep->desc_cnt * dwc_ep->proc_buf_num;++		sts.b_iso_in.bs = BS_HOST_READY;+		sts.b_iso_in.txsts = 0;+		sts.b_iso_in.sp = 0;+		sts.b_iso_in.ioc = 0;+		sts.b_iso_in.pid = dwc_ep->pkt_per_frm;+		sts.b_iso_in.framenum = dwc_ep->next_frame;+		sts.b_iso_in.txbytes = dwc_ep->data_per_frame;+		sts.b_iso_in.l = 0;++		for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {+			dma_desc->buf = dma_ad;+			dma_desc->status.d32 = sts.d32;++			sts.b_iso_in.framenum += dwc_ep->bInterval;+			dma_ad += dwc_ep->data_per_frame;+			dma_desc++;+		}++		sts.b_iso_in.ioc = 1;+		sts.b_iso_in.l = dwc_ep->proc_buf_num;++		dma_desc->buf = dma_ad;+		dma_desc->status.d32 = sts.d32;++		dwc_ep->next_frame =+		    sts.b_iso_in.framenum + dwc_ep->bInterval * 1;+	}+	dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;+}++/**+ * This function is to handle Iso EP transfer complete interrupt+ * in case Iso out packet was dropped+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param dwc_ep The EP for wihich transfer complete was asserted+ *+ */+static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t * core_if,+					   dwc_ep_t * dwc_ep)+{+	uint32_t dma_addr;+	uint32_t drp_pkt;+	uint32_t drp_pkt_cnt;+	deptsiz_data_t deptsiz = {.d32 = 0 };+	depctl_data_t depctl = {.d32 = 0 };+	int i;++	deptsiz.d32 =+	    DWC_READ_REG32(&core_if->dev_if->+			   out_ep_regs[dwc_ep->num]->doeptsiz);++	drp_pkt = dwc_ep->pkt_cnt - deptsiz.b.pktcnt;+	drp_pkt_cnt = dwc_ep->pkt_per_frm - (drp_pkt % dwc_ep->pkt_per_frm);++	/* Setting dropped packets status */+	for (i = 0; i < drp_pkt_cnt; ++i) {+		dwc_ep->pkt_info[drp_pkt].status = -DWC_E_NO_DATA;+		drp_pkt++;+		deptsiz.b.pktcnt--;+	}++	if (deptsiz.b.pktcnt > 0) {+		deptsiz.b.xfersize =+		    dwc_ep->xfer_len - (dwc_ep->pkt_cnt -+					deptsiz.b.pktcnt) * dwc_ep->maxpacket;+	} else {+		deptsiz.b.xfersize = 0;+		deptsiz.b.pktcnt = 0;+	}++	DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz,+			deptsiz.d32);++	if (deptsiz.b.pktcnt > 0) {+		if (dwc_ep->proc_buf_num) {+			dma_addr =+			    dwc_ep->dma_addr1 + dwc_ep->xfer_len -+			    deptsiz.b.xfersize;+		} else {+			dma_addr =+			    dwc_ep->dma_addr0 + dwc_ep->xfer_len -+			    deptsiz.b.xfersize;;+		}++		DWC_WRITE_REG32(&core_if->dev_if->+				out_ep_regs[dwc_ep->num]->doepdma, dma_addr);++		/** Re-enable endpoint, clear nak  */+		depctl.d32 = 0;+		depctl.b.epena = 1;+		depctl.b.cnak = 1;++		DWC_MODIFY_REG32(&core_if->dev_if->+				 out_ep_regs[dwc_ep->num]->doepctl, depctl.d32,+				 depctl.d32);+		return 0;+	} else {+		return 1;+	}+}++/**+ * This function sets iso packets information(PTI mode)+ *+ * @param core_if Programming view of DWC_otg controller.+ * @param ep The EP to start the transfer on.+ *+ */+static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)+{+	int i, j;+	dma_addr_t dma_ad;+	iso_pkt_info_t *packet_info = ep->pkt_info;+	uint32_t offset;+	uint32_t frame_data;+	deptsiz_data_t deptsiz;++	if (ep->proc_buf_num == 0) {+		/** Buffer 0 descriptors setup */+		dma_ad = ep->dma_addr0;+	} else {+		/** Buffer 1 descriptors setup */+		dma_ad = ep->dma_addr1;+	}++	if (ep->is_in) {+		deptsiz.d32 =+		    DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->+				   dieptsiz);+	} else {+		deptsiz.d32 =+		    DWC_READ_REG32(&core_if->dev_if->out_ep_regs[ep->num]->+				   doeptsiz);+	}++	if (!deptsiz.b.xfersize) {+		offset = 0;+		for (i = 0; i < ep->pkt_cnt; i += ep->pkt_per_frm) {+			frame_data = ep->data_per_frame;+			for (j = 0; j < ep->pkt_per_frm; ++j) {++				/* Packet status - is not set as initially+				 * it is set to 0 and if packet was sent+				 successfully, status field will remain 0*/++				/* Bytes has been transfered */+				packet_info->length =+				    (ep->maxpacket <+				     frame_data) ? ep->maxpacket : frame_data;++				/* Received packet offset */+				packet_info->offset = offset;+				offset += packet_info->length;+				frame_data -= packet_info->length;++				packet_info++;+			}+		}+		return 1;+	} else {+		/* This is a workaround for in case of Transfer Complete with+		 * PktDrpSts interrupts merging - in this case Transfer complete+		 * interrupt for Isoc Out Endpoint is asserted without PktDrpSts+		 * set and with DOEPTSIZ register non zero. Investigations showed,+		 * that this happens when Out packet is dropped, but because of+		 * interrupts merging during first interrupt handling PktDrpSts+		 * bit is cleared and for next merged interrupts it is not reset.+		 * In this case SW hadles the interrupt as if PktDrpSts bit is set.+		 */+		if (ep->is_in) {+			return 1;+		} else {+			return handle_iso_out_pkt_dropped(core_if, ep);+		}+	}+}++/**+ * This function is to handle Iso EP transfer complete interrupt+ *+ * @param pcd The PCD+ * @param ep The EP for which transfer complete was asserted+ *+ */+static void complete_iso_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);+	dwc_ep_t *dwc_ep = &ep->dwc_ep;+	uint8_t is_last = 0;++	if (ep->dwc_ep.next_frame == 0xffffffff) {+		DWC_WARN("Next frame is not set!\n");+		return;+	}++	if (core_if->dma_enable) {+		if (core_if->dma_desc_enable) {+			set_ddma_iso_pkts_info(core_if, dwc_ep);+			reinit_ddma_iso_xfer(core_if, dwc_ep);+			is_last = 1;+		} else {+			if (core_if->pti_enh_enable) {+				if (set_iso_pkts_info(core_if, dwc_ep)) {+					dwc_ep->proc_buf_num =+					    (dwc_ep->proc_buf_num ^ 1) & 0x1;+					dwc_otg_iso_ep_start_buf_transfer+					    (core_if, dwc_ep);+					is_last = 1;+				}+			} else {+				set_current_pkt_info(core_if, dwc_ep);+				if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {+					is_last = 1;+					dwc_ep->cur_pkt = 0;+					dwc_ep->proc_buf_num =+					    (dwc_ep->proc_buf_num ^ 1) & 0x1;+					if (dwc_ep->proc_buf_num) {+						dwc_ep->cur_pkt_addr =+						    dwc_ep->xfer_buff1;+						dwc_ep->cur_pkt_dma_addr =+						    dwc_ep->dma_addr1;+					} else {+						dwc_ep->cur_pkt_addr =+						    dwc_ep->xfer_buff0;+						dwc_ep->cur_pkt_dma_addr =+						    dwc_ep->dma_addr0;+					}++				}+				dwc_otg_iso_ep_start_frm_transfer(core_if,+								  dwc_ep);+			}+		}+	} else {+		set_current_pkt_info(core_if, dwc_ep);+		if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {+			is_last = 1;+			dwc_ep->cur_pkt = 0;+			dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;+			if (dwc_ep->proc_buf_num) {+				dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1;+				dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1;+			} else {+				dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0;+				dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0;+			}++		}+		dwc_otg_iso_ep_start_frm_transfer(core_if, dwc_ep);+	}+	if (is_last)+		dwc_otg_iso_buffer_done(pcd, ep, ep->iso_req_handle);+}+#endif /* DWC_EN_ISOC */++/**+ * This function handle BNA interrupt for Non Isochronous EPs+ *+ */+static void dwc_otg_pcd_handle_noniso_bna(dwc_otg_pcd_ep_t * ep)+{+	dwc_ep_t *dwc_ep = &ep->dwc_ep;+	volatile uint32_t *addr;+	depctl_data_t depctl = {.d32 = 0 };+	dwc_otg_pcd_t *pcd = ep->pcd;+	dwc_otg_dev_dma_desc_t *dma_desc;+	dev_dma_desc_sts_t sts = {.d32 = 0 };+	dwc_otg_core_if_t *core_if = ep->pcd->core_if;+	int i, start;++	if (!dwc_ep->desc_cnt)+		DWC_WARN("Ep%d %s Descriptor count = %d \n", dwc_ep->num,+			 (dwc_ep->is_in ? "IN" : "OUT"), dwc_ep->desc_cnt);++	if (core_if->core_params->cont_on_bna && !dwc_ep->is_in+							&& dwc_ep->type != DWC_OTG_EP_TYPE_CONTROL) {+		uint32_t doepdma;+		dwc_otg_dev_out_ep_regs_t *out_regs =+			core_if->dev_if->out_ep_regs[dwc_ep->num];+		doepdma = DWC_READ_REG32(&(out_regs->doepdma));+		start = (doepdma - dwc_ep->dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t);+		dma_desc = &(dwc_ep->desc_addr[start]);+	} else {+		start = 0;+		dma_desc = dwc_ep->desc_addr;+	}+++	for (i = start; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {+		sts.d32 = dma_desc->status.d32;+		sts.b.bs = BS_HOST_READY;+		dma_desc->status.d32 = sts.d32;+	}++	if (dwc_ep->is_in == 0) {+		addr =+		    &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]->+		    doepctl;+	} else {+		addr =+		    &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;+	}+	depctl.b.epena = 1;+	depctl.b.cnak = 1;+	DWC_MODIFY_REG32(addr, 0, depctl.d32);+}++/**+ * This function handles EP0 Control transfers.+ *+ * The state of the control transfers are tracked in+ * <code>ep0state</code>.+ */+static void handle_ep0(dwc_otg_pcd_t * pcd)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;+	dev_dma_desc_sts_t desc_sts;+	deptsiz0_data_t deptsiz;+	uint32_t byte_count;++#ifdef DEBUG_EP0+	DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);+	print_ep0_state(pcd);+#endif++//      DWC_PRINTF("HANDLE EP0\n");++	switch (pcd->ep0state) {+	case EP0_DISCONNECT:+		break;++	case EP0_IDLE:+		pcd->request_config = 0;++		pcd_setup(pcd);+		break;++	case EP0_IN_DATA_PHASE:+#ifdef DEBUG_EP0+		DWC_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n",+			    ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),+			    ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);+#endif++		if (core_if->dma_enable != 0) {+			/*+			 * For EP0 we can only program 1 packet at a time so we+			 * need to do the make calculations after each complete.+			 * Call write_packet to make the calculations, as in+			 * slave mode, and use those values to determine if we+			 * can complete.+			 */+			if (core_if->dma_desc_enable == 0) {+				deptsiz.d32 =+				    DWC_READ_REG32(&core_if->+						   dev_if->in_ep_regs[0]->+						   dieptsiz);+				byte_count =+				    ep0->dwc_ep.xfer_len - deptsiz.b.xfersize;+			} else {+				desc_sts =+				    core_if->dev_if->in_desc_addr->status;+				byte_count =+				    ep0->dwc_ep.xfer_len - desc_sts.b.bytes;+			}+			ep0->dwc_ep.xfer_count += byte_count;+			ep0->dwc_ep.xfer_buff += byte_count;+			ep0->dwc_ep.dma_addr += byte_count;+		}+		if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {+			dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),+						      &ep0->dwc_ep);+			DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");+		} else if (ep0->dwc_ep.sent_zlp) {+			dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),+						      &ep0->dwc_ep);+			ep0->dwc_ep.sent_zlp = 0;+			DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n");+		} else {+			ep0_complete_request(ep0);+			DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");+		}+		break;+	case EP0_OUT_DATA_PHASE:+#ifdef DEBUG_EP0+		DWC_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n",+			    ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),+			    ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);+#endif+		if (core_if->dma_enable != 0) {+			if (core_if->dma_desc_enable == 0) {+				deptsiz.d32 =+				    DWC_READ_REG32(&core_if->+						   dev_if->out_ep_regs[0]->+						   doeptsiz);+				byte_count =+				    ep0->dwc_ep.maxpacket - deptsiz.b.xfersize;+			} else {+				desc_sts =+				    core_if->dev_if->out_desc_addr->status;+				byte_count =+				    ep0->dwc_ep.maxpacket - desc_sts.b.bytes;+			}+			ep0->dwc_ep.xfer_count += byte_count;+			ep0->dwc_ep.xfer_buff += byte_count;+			ep0->dwc_ep.dma_addr += byte_count;+		}+		if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {+			dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),+						      &ep0->dwc_ep);+			DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");+		} else if (ep0->dwc_ep.sent_zlp) {+			dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),+						      &ep0->dwc_ep);+			ep0->dwc_ep.sent_zlp = 0;+			DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n");+		} else {+			ep0_complete_request(ep0);+			DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");+		}+		break;++	case EP0_IN_STATUS_PHASE:+	case EP0_OUT_STATUS_PHASE:+		DWC_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n");+		ep0_complete_request(ep0);+		pcd->ep0state = EP0_IDLE;+		ep0->stopped = 1;+		ep0->dwc_ep.is_in = 0;	/* OUT for next SETUP */++		/* Prepare for more SETUP Packets */+		if (core_if->dma_enable) {+			ep0_out_start(core_if, pcd);+		}+		break;++	case EP0_STALL:+		DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n");+		break;+	}+#ifdef DEBUG_EP0+	print_ep0_state(pcd);+#endif+}++/**+ * Restart transfer+ */+static void restart_transfer(dwc_otg_pcd_t * pcd, const uint32_t epnum)+{+	dwc_otg_core_if_t *core_if;+	dwc_otg_dev_if_t *dev_if;+	deptsiz_data_t dieptsiz = {.d32 = 0 };+	dwc_otg_pcd_ep_t *ep;++	ep = get_in_ep(pcd, epnum);++#ifdef DWC_EN_ISOC+	if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {+		return;+	}+#endif /* DWC_EN_ISOC  */++	core_if = GET_CORE_IF(pcd);+	dev_if = core_if->dev_if;++	dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz);++	DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x xfer_len=%0x"+		    " stopped=%d\n", ep->dwc_ep.xfer_buff,+		    ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, ep->stopped);+	/*+	 * If xfersize is 0 and pktcnt in not 0, resend the last packet.+	 */+	if (dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 &&+	    ep->dwc_ep.start_xfer_buff != 0) {+		if (ep->dwc_ep.total_len <= ep->dwc_ep.maxpacket) {+			ep->dwc_ep.xfer_count = 0;+			ep->dwc_ep.xfer_buff = ep->dwc_ep.start_xfer_buff;+			ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;+		} else {+			ep->dwc_ep.xfer_count -= ep->dwc_ep.maxpacket;+			/* convert packet size to dwords. */+			ep->dwc_ep.xfer_buff -= ep->dwc_ep.maxpacket;+			ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;+		}+		ep->stopped = 0;+		DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x "+			    "xfer_len=%0x stopped=%d\n",+			    ep->dwc_ep.xfer_buff,+			    ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len,+			    ep->stopped);+		if (epnum == 0) {+			dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep);+		} else {+			dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);+		}+	}+}++/*+ * This function create new nextep sequnce based on Learn Queue.+ *+ * @param core_if Programming view of DWC_otg controller+ */+void predict_nextep_seq( dwc_otg_core_if_t * core_if)+{+	dwc_otg_device_global_regs_t *dev_global_regs =+	    core_if->dev_if->dev_global_regs;+	const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;+	/* Number of Token Queue Registers */+	const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;+	dtknq1_data_t dtknqr1;+	uint32_t in_tkn_epnums[4];+	uint8_t seqnum[MAX_EPS_CHANNELS];+	uint8_t intkn_seq[TOKEN_Q_DEPTH];+	grstctl_t resetctl = {.d32 = 0 };+	uint8_t temp;+	int ndx = 0;+	int start = 0;+	int end = 0;+	int sort_done = 0;+	int i = 0;+	volatile uint32_t *addr = &dev_global_regs->dtknqr1;+++	DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);++	/* Read the DTKNQ Registers */+	for (i = 0; i < DTKNQ_REG_CNT; i++) {+		in_tkn_epnums[i] = DWC_READ_REG32(addr);+		DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,+			    in_tkn_epnums[i]);+		if (addr == &dev_global_regs->dvbusdis) {+			addr = &dev_global_regs->dtknqr3_dthrctl;+		} else {+			++addr;+		}++	}++	/* Copy the DTKNQR1 data to the bit field. */+	dtknqr1.d32 = in_tkn_epnums[0];+	if (dtknqr1.b.wrap_bit) {+		ndx = dtknqr1.b.intknwptr;+		end = ndx -1;+		if (end < 0)+			end = TOKEN_Q_DEPTH -1;+	} else {+		ndx = 0;+		end = dtknqr1.b.intknwptr -1;+		if (end < 0)+			end = 0;+	}+	start = ndx;++	/* Fill seqnum[] by initial values: EP number + 31 */+	for (i=0; i <= core_if->dev_if->num_in_eps; i++) {+		seqnum[i] = i +31;+	}++	/* Fill intkn_seq[] from in_tkn_epnums[0] */+	for (i=0; i < 6; i++)+		intkn_seq[i] = (in_tkn_epnums[0] >> ((7-i) * 4)) & 0xf;++	if (TOKEN_Q_DEPTH > 6) {+		/* Fill intkn_seq[] from in_tkn_epnums[1] */+		for (i=6; i < 14; i++)+			intkn_seq[i] =+			    (in_tkn_epnums[1] >> ((7 - (i - 6)) * 4)) & 0xf;+	}++	if (TOKEN_Q_DEPTH > 14) {+		/* Fill intkn_seq[] from in_tkn_epnums[1] */+		for (i=14; i < 22; i++)+			intkn_seq[i] =+			    (in_tkn_epnums[2] >> ((7 - (i - 14)) * 4)) & 0xf;+	}++	if (TOKEN_Q_DEPTH > 22) {+		/* Fill intkn_seq[] from in_tkn_epnums[1] */+		for (i=22; i < 30; i++)+			intkn_seq[i] =+			    (in_tkn_epnums[3] >> ((7 - (i - 22)) * 4)) & 0xf;+	}++	DWC_DEBUGPL(DBG_PCDV, "%s start=%d end=%d intkn_seq[]:\n", __func__,+		    start, end);+	for (i=0; i<TOKEN_Q_DEPTH; i++)+		DWC_DEBUGPL(DBG_PCDV,"%d\n", intkn_seq[i]);++	/* Update seqnum based on intkn_seq[] */+	i = 0;+	do {+		seqnum[intkn_seq[ndx]] = i;+		ndx++;+		i++;+		if (ndx == TOKEN_Q_DEPTH)+			ndx = 0;+	} while ( i < TOKEN_Q_DEPTH );++	/* Mark non active EP's in seqnum[] by 0xff */+	for (i=0; i<=core_if->dev_if->num_in_eps; i++) {+		if (core_if->nextep_seq[i] == 0xff )+			seqnum[i] = 0xff;+	}++	/* Sort seqnum[] */+	sort_done = 0;+	while (!sort_done) {+		sort_done = 1;+		for (i=0; i<core_if->dev_if->num_in_eps; i++) {+			if (seqnum[i] > seqnum[i+1]) {+				temp = seqnum[i];+				seqnum[i] = seqnum[i+1];+				seqnum[i+1] = temp;+				sort_done = 0;+			}+		}+	}++	ndx = start + seqnum[0];+	if (ndx >= TOKEN_Q_DEPTH)+		ndx = ndx % TOKEN_Q_DEPTH;+	core_if->first_in_nextep_seq = intkn_seq[ndx];++	/* Update seqnum[] by EP numbers  */+	for (i=0; i<=core_if->dev_if->num_in_eps; i++) {+		ndx = start + i;+		if (seqnum[i] < 31) {+			ndx = start + seqnum[i];+			if (ndx >= TOKEN_Q_DEPTH)+				ndx = ndx % TOKEN_Q_DEPTH;+			seqnum[i] = intkn_seq[ndx];+		} else {+			if (seqnum[i] < 0xff) {+				seqnum[i] = seqnum[i] - 31;+			} else {+				break;+			}+		}+	}++	/* Update nextep_seq[] based on seqnum[] */+	for (i=0; i<core_if->dev_if->num_in_eps; i++) {+		if (seqnum[i] != 0xff) {+			if (seqnum[i+1] != 0xff) {+				core_if->nextep_seq[seqnum[i]] = seqnum[i+1];+			} else {+				core_if->nextep_seq[seqnum[i]] = core_if->first_in_nextep_seq;+				break;+			}+		} else {+			break;+		}+	}++	DWC_DEBUGPL(DBG_PCDV, "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",+		__func__, core_if->first_in_nextep_seq);+	for (i=0; i <= core_if->dev_if->num_in_eps; i++) {+		DWC_DEBUGPL(DBG_PCDV,"%2d\n", core_if->nextep_seq[i]);+	}++	/* Flush the Learning Queue */+	resetctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->grstctl);+	resetctl.b.intknqflsh = 1;+	DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);+++}++/**+ * handle the IN EP disable interrupt.+ */+static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t * pcd,+					     const uint32_t epnum)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	dwc_otg_dev_if_t *dev_if = core_if->dev_if;+	deptsiz_data_t dieptsiz = {.d32 = 0 };+	dctl_data_t dctl = {.d32 = 0 };+	dwc_otg_pcd_ep_t *ep;+	dwc_ep_t *dwc_ep;+	gintmsk_data_t gintmsk_data;+	depctl_data_t depctl;+	uint32_t diepdma;+	uint32_t remain_to_transfer = 0;+	uint8_t i;+	uint32_t xfer_size;++	ep = get_in_ep(pcd, epnum);+	dwc_ep = &ep->dwc_ep;++	if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {+		dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);+		complete_ep(ep);+		return;+	}++	DWC_DEBUGPL(DBG_PCD, "diepctl%d=%0x\n", epnum,+		    DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl));+	dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz);+	depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);++	DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",+		    dieptsiz.b.pktcnt, dieptsiz.b.xfersize);++	if ((core_if->start_predict == 0) || (depctl.b.eptype & 1)) {+		if (ep->stopped) {+			if (core_if->en_multiple_tx_fifo)+				/* Flush the Tx FIFO */+				dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);+			/* Clear the Global IN NP NAK */+			dctl.d32 = 0;+			dctl.b.cgnpinnak = 1;+			DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);+			/* Restart the transaction */+			if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {+				restart_transfer(pcd, epnum);+			}+		} else {+			/* Restart the transaction */+			if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {+				restart_transfer(pcd, epnum);+			}+			DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n");+		}+		return;+	}++	if (core_if->start_predict > 2) {	// NP IN EP+		core_if->start_predict--;+		return;+	}++	core_if->start_predict--;++	if (core_if->start_predict == 1) {	// All NP IN Ep's disabled now++		predict_nextep_seq(core_if);++		/* Update all active IN EP's NextEP field based of nextep_seq[] */+		for ( i = 0; i <= core_if->dev_if->num_in_eps; i++) {+			depctl.d32 =+			    DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);+			if (core_if->nextep_seq[i] != 0xff) {	// Active NP IN EP+				depctl.b.nextep = core_if->nextep_seq[i];+				DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);+			}+		}+		/* Flush Shared NP TxFIFO */+		dwc_otg_flush_tx_fifo(core_if, 0);+		/* Rewind buffers */+		if (!core_if->dma_desc_enable) {+			i = core_if->first_in_nextep_seq;+			do {+				ep = get_in_ep(pcd, i);+				dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);+				xfer_size = ep->dwc_ep.total_len - ep->dwc_ep.xfer_count;+				if (xfer_size > ep->dwc_ep.maxxfer)+					xfer_size = ep->dwc_ep.maxxfer;+				depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);+				if (dieptsiz.b.pktcnt != 0) {+					if (xfer_size == 0) {+						remain_to_transfer = 0;+					} else {+						if ((xfer_size % ep->dwc_ep.maxpacket) == 0) {+							remain_to_transfer =+								dieptsiz.b.pktcnt * ep->dwc_ep.maxpacket;+						} else {+							remain_to_transfer = ((dieptsiz.b.pktcnt -1) * ep->dwc_ep.maxpacket)+								+ (xfer_size % ep->dwc_ep.maxpacket);+						}+					}+					diepdma = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepdma);+					dieptsiz.b.xfersize = remain_to_transfer;+					DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, dieptsiz.d32);+					diepdma = ep->dwc_ep.dma_addr + (xfer_size - remain_to_transfer);+					DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, diepdma);+				}+				i = core_if->nextep_seq[i];+			} while (i != core_if->first_in_nextep_seq);+		} else { // dma_desc_enable+				DWC_PRINTF("%s Learning Queue not supported in DDMA\n", __func__);+		}++		/* Restart transfers in predicted sequences */+		i = core_if->first_in_nextep_seq;+		do {+			dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);+			depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);+			if (dieptsiz.b.pktcnt != 0) {+				depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);+				depctl.b.epena = 1;+				depctl.b.cnak = 1;+				DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);+			}+			i = core_if->nextep_seq[i];+		} while (i != core_if->first_in_nextep_seq);++		/* Clear the global non-periodic IN NAK handshake */+		dctl.d32 = 0;+		dctl.b.cgnpinnak = 1;+		DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);++		/* Unmask EP Mismatch interrupt */+		gintmsk_data.d32 = 0;+		gintmsk_data.b.epmismatch = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk_data.d32);++		core_if->start_predict = 0;++	}+}++/**+ * Handler for the IN EP timeout handshake interrupt.+ */+static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd,+					     const uint32_t epnum)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	dwc_otg_dev_if_t *dev_if = core_if->dev_if;++#ifdef DEBUG+	deptsiz_data_t dieptsiz = {.d32 = 0 };+	uint32_t num = 0;+#endif+	dctl_data_t dctl = {.d32 = 0 };+	dwc_otg_pcd_ep_t *ep;++	gintmsk_data_t intr_mask = {.d32 = 0 };++	ep = get_in_ep(pcd, epnum);++	/* Disable the NP Tx Fifo Empty Interrrupt */+	if (!core_if->dma_enable) {+		intr_mask.b.nptxfempty = 1;+		DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,+				 intr_mask.d32, 0);+	}+	/** @todo NGS Check EP type.+	 * Implement for Periodic EPs */+	/*+	 * Non-periodic EP+	 */+	/* Enable the Global IN NAK Effective Interrupt */+	intr_mask.b.ginnakeff = 1;+	DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);++	/* Set Global IN NAK */+	dctl.b.sgnpinnak = 1;+	DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);++	ep->stopped = 1;++#ifdef DEBUG+	dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[num]->dieptsiz);+	DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",+		    dieptsiz.b.pktcnt, dieptsiz.b.xfersize);+#endif++#ifdef DISABLE_PERIODIC_EP+	/*+	 * Set the NAK bit for this EP to+	 * start the disable process.+	 */+	diepctl.d32 = 0;+	diepctl.b.snak = 1;+	DWC_MODIFY_REG32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32,+			 diepctl.d32);+	ep->disabling = 1;+	ep->stopped = 1;+#endif+}++/**+ * Handler for the IN EP NAK interrupt.+ */+static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t * pcd,+					    const uint32_t epnum)+{+	/** @todo implement ISR */+	dwc_otg_core_if_t *core_if;+	diepmsk_data_t intr_mask = {.d32 = 0 };++	DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "IN EP NAK");+	core_if = GET_CORE_IF(pcd);+	intr_mask.b.nak = 1;++	if (core_if->multiproc_int_enable) {+		DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->+				 diepeachintmsk[epnum], intr_mask.d32, 0);+	} else {+		DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->diepmsk,+				 intr_mask.d32, 0);+	}++	return 1;+}++/**+ * Handler for the OUT EP Babble interrupt.+ */+static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t * pcd,+						const uint32_t epnum)+{+	/** @todo implement ISR */+	dwc_otg_core_if_t *core_if;+	doepmsk_data_t intr_mask = {.d32 = 0 };++	DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",+		   "OUT EP Babble");+	core_if = GET_CORE_IF(pcd);+	intr_mask.b.babble = 1;++	if (core_if->multiproc_int_enable) {+		DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->+				 doepeachintmsk[epnum], intr_mask.d32, 0);+	} else {+		DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,+				 intr_mask.d32, 0);+	}++	return 1;+}++/**+ * Handler for the OUT EP NAK interrupt.+ */+static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd,+					     const uint32_t epnum)+{+	/** @todo implement ISR */+	dwc_otg_core_if_t *core_if;+	doepmsk_data_t intr_mask = {.d32 = 0 };++	DWC_DEBUGPL(DBG_ANY, "INTERRUPT Handler not implemented for %s\n", "OUT EP NAK");+	core_if = GET_CORE_IF(pcd);+	intr_mask.b.nak = 1;++	if (core_if->multiproc_int_enable) {+		DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->+				 doepeachintmsk[epnum], intr_mask.d32, 0);+	} else {+		DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,+				 intr_mask.d32, 0);+	}++	return 1;+}++/**+ * Handler for the OUT EP NYET interrupt.+ */+static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd,+					      const uint32_t epnum)+{+	/** @todo implement ISR */+	dwc_otg_core_if_t *core_if;+	doepmsk_data_t intr_mask = {.d32 = 0 };++	DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NYET");+	core_if = GET_CORE_IF(pcd);+	intr_mask.b.nyet = 1;++	if (core_if->multiproc_int_enable) {+		DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->+				 doepeachintmsk[epnum], intr_mask.d32, 0);+	} else {+		DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,+				 intr_mask.d32, 0);+	}++	return 1;+}++/**+ * This interrupt indicates that an IN EP has a pending Interrupt.+ * The sequence for handling the IN EP interrupt is shown below:+ * -#	Read the Device All Endpoint Interrupt register+ * -#	Repeat the following for each IN EP interrupt bit set (from+ *		LSB to MSB).+ * -#	Read the Device Endpoint Interrupt (DIEPINTn) register+ * -#	If "Transfer Complete" call the request complete function+ * -#	If "Endpoint Disabled" complete the EP disable procedure.+ * -#	If "AHB Error Interrupt" log error+ * -#	If "Time-out Handshake" log error+ * -#	If "IN Token Received when TxFIFO Empty" write packet to Tx+ *		FIFO.+ * -#	If "IN Token EP Mismatch" (disable, this is handled by EP+ *		Mismatch Interrupt)+ */+static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd)+{+#define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \+do { \+		diepint_data_t diepint = {.d32=0}; \+		diepint.b.__intr = 1; \+		DWC_WRITE_REG32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \+		diepint.d32); \+} while (0)++	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	dwc_otg_dev_if_t *dev_if = core_if->dev_if;+	diepint_data_t diepint = {.d32 = 0 };+	depctl_data_t depctl = {.d32 = 0 };+	uint32_t ep_intr;+	uint32_t epnum = 0;+	dwc_otg_pcd_ep_t *ep;+	dwc_ep_t *dwc_ep;+	gintmsk_data_t intr_mask = {.d32 = 0 };++	DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, pcd);++	/* Read in the device interrupt bits */+	ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if);++	/* Service the Device IN interrupts for each endpoint */+	while (ep_intr) {+		if (ep_intr & 0x1) {+			uint32_t empty_msk;+			/* Get EP pointer */+			ep = get_in_ep(pcd, epnum);+			dwc_ep = &ep->dwc_ep;++			depctl.d32 =+			    DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);+			empty_msk =+			    DWC_READ_REG32(&dev_if->+					   dev_global_regs->dtknqr4_fifoemptymsk);++			DWC_DEBUGPL(DBG_PCDV,+				    "IN EP INTERRUPT - %d\nepmty_msk - %8x  diepctl - %8x\n",+				    epnum, empty_msk, depctl.d32);++			DWC_DEBUGPL(DBG_PCD,+				    "EP%d-%s: type=%d, mps=%d\n",+				    dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),+				    dwc_ep->type, dwc_ep->maxpacket);++			diepint.d32 =+			    dwc_otg_read_dev_in_ep_intr(core_if, dwc_ep);++			DWC_DEBUGPL(DBG_PCDV,+				    "EP %d Interrupt Register - 0x%x\n", epnum,+				    diepint.d32);+			/* Transfer complete */+			if (diepint.b.xfercompl) {+				/* Disable the NP Tx FIFO Empty+				 * Interrupt */+				if (core_if->en_multiple_tx_fifo == 0) {+					intr_mask.b.nptxfempty = 1;+					DWC_MODIFY_REG32+					    (&core_if->core_global_regs->gintmsk,+					     intr_mask.d32, 0);+				} else {+					/* Disable the Tx FIFO Empty Interrupt for this EP */+					uint32_t fifoemptymsk =+					    0x1 << dwc_ep->num;+					DWC_MODIFY_REG32(&core_if->+							 dev_if->dev_global_regs->dtknqr4_fifoemptymsk,+							 fifoemptymsk, 0);+				}+				/* Clear the bit in DIEPINTn for this interrupt */+				CLEAR_IN_EP_INTR(core_if, epnum, xfercompl);++				/* Complete the transfer */+				if (epnum == 0) {+					handle_ep0(pcd);+				}+#ifdef DWC_EN_ISOC+				else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {+					if (!ep->stopped)+						complete_iso_ep(pcd, ep);+				}+#endif /* DWC_EN_ISOC */+#ifdef DWC_UTE_PER_IO+				else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {+					if (!ep->stopped)+						complete_xiso_ep(ep);+				}+#endif /* DWC_UTE_PER_IO */+				else {+					if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC &&+							dwc_ep->bInterval > 1) {+						dwc_ep->frame_num += dwc_ep->bInterval;+						if (dwc_ep->frame_num > 0x3FFF)+						{+							dwc_ep->frm_overrun = 1;+							dwc_ep->frame_num &= 0x3FFF;+						} else+							dwc_ep->frm_overrun = 0;+					}+					complete_ep(ep);+					if(diepint.b.nak)+						CLEAR_IN_EP_INTR(core_if, epnum, nak);+				}+			}+			/* Endpoint disable      */+			if (diepint.b.epdisabled) {+				DWC_DEBUGPL(DBG_ANY, "EP%d IN disabled\n",+					    epnum);+				handle_in_ep_disable_intr(pcd, epnum);++				/* Clear the bit in DIEPINTn for this interrupt */+				CLEAR_IN_EP_INTR(core_if, epnum, epdisabled);+			}+			/* AHB Error */+			if (diepint.b.ahberr) {+				DWC_ERROR("EP%d IN AHB Error\n", epnum);+				/* Clear the bit in DIEPINTn for this interrupt */+				CLEAR_IN_EP_INTR(core_if, epnum, ahberr);+			}+			/* TimeOUT Handshake (non-ISOC IN EPs) */+			if (diepint.b.timeout) {+				DWC_ERROR("EP%d IN Time-out\n", epnum);+				handle_in_ep_timeout_intr(pcd, epnum);++				CLEAR_IN_EP_INTR(core_if, epnum, timeout);+			}+			/** IN Token received with TxF Empty */+			if (diepint.b.intktxfemp) {+				DWC_DEBUGPL(DBG_ANY,+					    "EP%d IN TKN TxFifo Empty\n",+					    epnum);+				if (!ep->stopped && epnum != 0) {++					diepmsk_data_t diepmsk = {.d32 = 0 };+					diepmsk.b.intktxfemp = 1;++					if (core_if->multiproc_int_enable) {+						DWC_MODIFY_REG32+						    (&dev_if->dev_global_regs->diepeachintmsk+						     [epnum], diepmsk.d32, 0);+					} else {+						DWC_MODIFY_REG32+						    (&dev_if->dev_global_regs->diepmsk,+						     diepmsk.d32, 0);+					}+				} else if (core_if->dma_desc_enable+					   && epnum == 0+					   && pcd->ep0state ==+					   EP0_OUT_STATUS_PHASE) {+					// EP0 IN set STALL+					depctl.d32 =+					    DWC_READ_REG32(&dev_if->in_ep_regs+							   [epnum]->diepctl);++					/* set the disable and stall bits */+					if (depctl.b.epena) {+						depctl.b.epdis = 1;+					}+					depctl.b.stall = 1;+					DWC_WRITE_REG32(&dev_if->in_ep_regs+							[epnum]->diepctl,+							depctl.d32);+				}+				CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp);+			}+			/** IN Token Received with EP mismatch */+			if (diepint.b.intknepmis) {+				DWC_DEBUGPL(DBG_ANY,+					    "EP%d IN TKN EP Mismatch\n", epnum);+				CLEAR_IN_EP_INTR(core_if, epnum, intknepmis);+			}+			/** IN Endpoint NAK Effective */+			if (diepint.b.inepnakeff) {+				DWC_DEBUGPL(DBG_ANY,+					    "EP%d IN EP NAK Effective\n",+					    epnum);+				/* Periodic EP */+				if (ep->disabling) {+					depctl.d32 = 0;+					depctl.b.snak = 1;+					depctl.b.epdis = 1;+					DWC_MODIFY_REG32(&dev_if->in_ep_regs+							 [epnum]->diepctl,+							 depctl.d32,+							 depctl.d32);+				}+				CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff);++			}++			/** IN EP Tx FIFO Empty Intr */+			if (diepint.b.emptyintr) {+				DWC_DEBUGPL(DBG_ANY,+					    "EP%d Tx FIFO Empty Intr \n",+					    epnum);+				write_empty_tx_fifo(pcd, epnum);++				CLEAR_IN_EP_INTR(core_if, epnum, emptyintr);++			}++			/** IN EP BNA Intr */+			if (diepint.b.bna) {+				CLEAR_IN_EP_INTR(core_if, epnum, bna);+				if (core_if->dma_desc_enable) {+#ifdef DWC_EN_ISOC+					if (dwc_ep->type ==+					    DWC_OTG_EP_TYPE_ISOC) {+						/*+						 * This checking is performed to prevent first "false" BNA+						 * handling occuring right after reconnect+						 */+						if (dwc_ep->next_frame !=+						    0xffffffff)+							dwc_otg_pcd_handle_iso_bna(ep);+					} else+#endif				/* DWC_EN_ISOC */+					{+						dwc_otg_pcd_handle_noniso_bna(ep);+					}+				}+			}+			/* NAK Interrutp */+			if (diepint.b.nak) {+				DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n",+					    epnum);+				if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {+					depctl_data_t depctl;+					if (ep->dwc_ep.frame_num == 0xFFFFFFFF) {+						ep->dwc_ep.frame_num = core_if->frame_num;+						if (ep->dwc_ep.bInterval > 1) {+							depctl.d32 = 0;+							depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);+							if (ep->dwc_ep.frame_num & 0x1) {+								depctl.b.setd1pid = 1;+								depctl.b.setd0pid = 0;+							} else {+								depctl.b.setd0pid = 1;+								depctl.b.setd1pid = 0;+							}+							DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32);+						}+						start_next_request(ep);+					}+					ep->dwc_ep.frame_num += ep->dwc_ep.bInterval;+					if (dwc_ep->frame_num > 0x3FFF)	{+						dwc_ep->frm_overrun = 1;+						dwc_ep->frame_num &= 0x3FFF;+					} else+						dwc_ep->frm_overrun = 0;+				}++				CLEAR_IN_EP_INTR(core_if, epnum, nak);+			}+		}+		epnum++;+		ep_intr >>= 1;+	}++	return 1;+#undef CLEAR_IN_EP_INTR+}++/**+ * This interrupt indicates that an OUT EP has a pending Interrupt.+ * The sequence for handling the OUT EP interrupt is shown below:+ * -#	Read the Device All Endpoint Interrupt register+ * -#	Repeat the following for each OUT EP interrupt bit set (from+ *		LSB to MSB).+ * -#	Read the Device Endpoint Interrupt (DOEPINTn) register+ * -#	If "Transfer Complete" call the request complete function+ * -#	If "Endpoint Disabled" complete the EP disable procedure.+ * -#	If "AHB Error Interrupt" log error+ * -#	If "Setup Phase Done" process Setup Packet (See Standard USB+ *		Command Processing)+ */+static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd)+{+#define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \+do { \+		doepint_data_t doepint = {.d32=0}; \+		doepint.b.__intr = 1; \+		DWC_WRITE_REG32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \+		doepint.d32); \+} while (0)++	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	uint32_t ep_intr;+	doepint_data_t doepint = {.d32 = 0 };+	uint32_t epnum = 0;+	dwc_otg_pcd_ep_t *ep;+	dwc_ep_t *dwc_ep;+	dctl_data_t dctl = {.d32 = 0 };+	gintmsk_data_t gintmsk = {.d32 = 0 };+++	DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);++	/* Read in the device interrupt bits */+	ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if);++	while (ep_intr) {+		if (ep_intr & 0x1) {+			/* Get EP pointer */+			ep = get_out_ep(pcd, epnum);+			dwc_ep = &ep->dwc_ep;++#ifdef VERBOSE+			DWC_DEBUGPL(DBG_PCDV,+				    "EP%d-%s: type=%d, mps=%d\n",+				    dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),+				    dwc_ep->type, dwc_ep->maxpacket);+#endif+			doepint.d32 =+			    dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep);+			/* Moved this interrupt upper due to core deffect of asserting+			 * OUT EP 0 xfercompl along with stsphsrcvd in BDMA */+			if (doepint.b.stsphsercvd) {+				deptsiz0_data_t deptsiz;+				CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd);+				deptsiz.d32 =+				    DWC_READ_REG32(&core_if->dev_if->+						   out_ep_regs[0]->doeptsiz);+				if (core_if->snpsid >= OTG_CORE_REV_3_00a+				    && core_if->dma_enable+				    && core_if->dma_desc_enable == 0+				    && doepint.b.xfercompl+				    && deptsiz.b.xfersize == 24) {+					CLEAR_OUT_EP_INTR(core_if, epnum,+							  xfercompl);+					doepint.b.xfercompl = 0;+					ep0_out_start(core_if, pcd);+				}+				if ((core_if->dma_desc_enable) ||+				    (core_if->dma_enable+				     && core_if->snpsid >=+				     OTG_CORE_REV_3_00a)) {+					do_setup_in_status_phase(pcd);+				}+			}+			/* Transfer complete */+			if (doepint.b.xfercompl) {++				if (epnum == 0) {+					/* Clear the bit in DOEPINTn for this interrupt */+					CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);+					if (core_if->snpsid >= OTG_CORE_REV_3_00a) {+						DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n",+							DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepint),+							doepint.d32);+						DWC_DEBUGPL(DBG_PCDV, "DOEPCTL=%x \n",+							DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepctl));++						if (core_if->snpsid >= OTG_CORE_REV_3_00a+							&& core_if->dma_enable == 0) {+							doepint_data_t doepint;+							doepint.d32 = DWC_READ_REG32(&core_if->dev_if->+														out_ep_regs[0]->doepint);+							if (pcd->ep0state == EP0_IDLE && doepint.b.sr) {+								CLEAR_OUT_EP_INTR(core_if, epnum, sr);+								goto exit_xfercompl;+							}+						}+						/* In case of DDMA  look at SR bit to go to the Data Stage */+						if (core_if->dma_desc_enable) {+							dev_dma_desc_sts_t status = {.d32 = 0};+							if (pcd->ep0state == EP0_IDLE) {+								status.d32 = core_if->dev_if->setup_desc_addr[core_if->+											dev_if->setup_desc_index]->status.d32;+								if(pcd->data_terminated) {+									 pcd->data_terminated = 0;+									 status.d32 = core_if->dev_if->out_desc_addr->status.d32;+									 dwc_memcpy(&pcd->setup_pkt->req, pcd->backup_buf, 8);+								}+								if (status.b.sr) {+									if (doepint.b.setup) {+										DWC_DEBUGPL(DBG_PCDV, "DMA DESC EP0_IDLE SR=1 setup=1\n");+										/* Already started data stage, clear setup */+										CLEAR_OUT_EP_INTR(core_if, epnum, setup);+										doepint.b.setup = 0;+										handle_ep0(pcd);+										/* Prepare for more setup packets */+										if (pcd->ep0state == EP0_IN_STATUS_PHASE ||+											pcd->ep0state == EP0_IN_DATA_PHASE) {+											ep0_out_start(core_if, pcd);+										}++										goto exit_xfercompl;+									} else {+										/* Prepare for more setup packets */+										DWC_DEBUGPL(DBG_PCDV,+											"EP0_IDLE SR=1 setup=0 new setup comes\n");+										ep0_out_start(core_if, pcd);+									}+								}+							} else {+								dwc_otg_pcd_request_t *req;+								dev_dma_desc_sts_t status = {.d32 = 0};+								diepint_data_t diepint0;+								diepint0.d32 = DWC_READ_REG32(&core_if->dev_if->+															in_ep_regs[0]->diepint);++								if (pcd->ep0state == EP0_STALL || pcd->ep0state == EP0_DISCONNECT) {+									DWC_ERROR("EP0 is stalled/disconnected\n");+								}++								/* Clear IN xfercompl if set */+								if (diepint0.b.xfercompl && (pcd->ep0state == EP0_IN_STATUS_PHASE+									|| pcd->ep0state == EP0_IN_DATA_PHASE)) {+									DWC_WRITE_REG32(&core_if->dev_if->+										in_ep_regs[0]->diepint, diepint0.d32);+								}++								status.d32 = core_if->dev_if->setup_desc_addr[core_if->+									dev_if->setup_desc_index]->status.d32;++								if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len+									&& (pcd->ep0state == EP0_OUT_DATA_PHASE))+									status.d32 = core_if->dev_if->out_desc_addr->status.d32;+								if (pcd->ep0state == EP0_OUT_STATUS_PHASE)+									status.d32 = core_if->dev_if->+									out_desc_addr->status.d32;++								if (status.b.sr) {+									if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {+										DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n");+									} else {+										DWC_DEBUGPL(DBG_PCDV, "complete req!!\n");+										req = DWC_CIRCLEQ_FIRST(&ep->queue);+										if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len &&+											pcd->ep0state == EP0_OUT_DATA_PHASE) {+												/* Read arrived setup packet from req->buf */+												dwc_memcpy(&pcd->setup_pkt->req,+													req->buf + ep->dwc_ep.xfer_count, 8);+										}+										req->actual = ep->dwc_ep.xfer_count;+										dwc_otg_request_done(ep, req, -ECONNRESET);+										ep->dwc_ep.start_xfer_buff = 0;+										ep->dwc_ep.xfer_buff = 0;+										ep->dwc_ep.xfer_len = 0;+									}+									pcd->ep0state = EP0_IDLE;+									if (doepint.b.setup) {+										DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n");+										/* Data stage started, clear setup */+										CLEAR_OUT_EP_INTR(core_if, epnum, setup);+										doepint.b.setup = 0;+										handle_ep0(pcd);+										/* Prepare for setup packets if ep0in was enabled*/+										if (pcd->ep0state == EP0_IN_STATUS_PHASE) {+											ep0_out_start(core_if, pcd);+										}++										goto exit_xfercompl;+									} else {+										/* Prepare for more setup packets */+										DWC_DEBUGPL(DBG_PCDV,+											"EP0_IDLE SR=1 setup=0 new setup comes 2\n");+										ep0_out_start(core_if, pcd);+									}+								}+							}+						}+						if (core_if->snpsid >= OTG_CORE_REV_2_94a && core_if->dma_enable+							&& core_if->dma_desc_enable == 0) {+							doepint_data_t doepint_temp = {.d32 = 0};+							deptsiz0_data_t doeptsize0 = {.d32 = 0 };+							doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if->+															out_ep_regs[ep->dwc_ep.num]->doepint);+							doeptsize0.d32 = DWC_READ_REG32(&core_if->dev_if->+															out_ep_regs[ep->dwc_ep.num]->doeptsiz);+							if (pcd->ep0state == EP0_IDLE) {+								if (doepint_temp.b.sr) {+									CLEAR_OUT_EP_INTR(core_if, epnum, sr);+								}+									doepint.d32 = DWC_READ_REG32(&core_if->dev_if->+																	out_ep_regs[0]->doepint);+									if (doeptsize0.b.supcnt == 3) {+										DWC_DEBUGPL(DBG_ANY, "Rolling over!!!!!!!\n");+										ep->dwc_ep.stp_rollover = 1;+									}+									if (doepint.b.setup) {+retry:+										/* Already started data stage, clear setup */+										CLEAR_OUT_EP_INTR(core_if, epnum, setup);+										doepint.b.setup = 0;+										handle_ep0(pcd);+										ep->dwc_ep.stp_rollover = 0;+										/* Prepare for more setup packets */+										if (pcd->ep0state == EP0_IN_STATUS_PHASE ||+											pcd->ep0state == EP0_IN_DATA_PHASE) {+											ep0_out_start(core_if, pcd);+										}+										goto exit_xfercompl;+									} else {+										/* Prepare for more setup packets */+										DWC_DEBUGPL(DBG_ANY,+											"EP0_IDLE SR=1 setup=0 new setup comes\n");+										doepint.d32 = DWC_READ_REG32(&core_if->dev_if->+																	out_ep_regs[0]->doepint);+										if(doepint.b.setup)+											goto retry;+										ep0_out_start(core_if, pcd);+									}+							} else {+								dwc_otg_pcd_request_t *req;+								diepint_data_t diepint0 = {.d32 = 0};+								doepint_data_t doepint_temp = {.d32 = 0};+								depctl_data_t diepctl0;+								diepint0.d32 = DWC_READ_REG32(&core_if->dev_if->+																in_ep_regs[0]->diepint);+								diepctl0.d32 = DWC_READ_REG32(&core_if->dev_if->+																in_ep_regs[0]->diepctl);++								if (pcd->ep0state == EP0_IN_DATA_PHASE+									|| pcd->ep0state == EP0_IN_STATUS_PHASE) {+									if (diepint0.b.xfercompl) {+										DWC_WRITE_REG32(&core_if->dev_if->+											in_ep_regs[0]->diepint, diepint0.d32);+									}+									if (diepctl0.b.epena) {+										diepint_data_t diepint = {.d32 = 0};+										diepctl0.b.snak = 1;+										DWC_WRITE_REG32(&core_if->dev_if->+														in_ep_regs[0]->diepctl, diepctl0.d32);+										do {+											dwc_udelay(10);+											diepint.d32 = DWC_READ_REG32(&core_if->dev_if->+												in_ep_regs[0]->diepint);+										} while (!diepint.b.inepnakeff);+										diepint.b.inepnakeff = 1;+										DWC_WRITE_REG32(&core_if->dev_if->+											in_ep_regs[0]->diepint, diepint.d32);+										diepctl0.d32 = 0;+										diepctl0.b.epdis = 1;+										DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl,+														diepctl0.d32);+										do {+											dwc_udelay(10);+											diepint.d32 = DWC_READ_REG32(&core_if->dev_if->+												in_ep_regs[0]->diepint);+										} while (!diepint.b.epdisabled);+										diepint.b.epdisabled = 1;+										DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepint,+															diepint.d32);+									}+								}+								doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if->+																out_ep_regs[ep->dwc_ep.num]->doepint);+								if (doepint_temp.b.sr) {+									CLEAR_OUT_EP_INTR(core_if, epnum, sr);+									if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {+										DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n");+									} else {+										DWC_DEBUGPL(DBG_PCDV, "complete req!!\n");+										req = DWC_CIRCLEQ_FIRST(&ep->queue);+										if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len &&+											pcd->ep0state == EP0_OUT_DATA_PHASE) {+												/* Read arrived setup packet from req->buf */+												dwc_memcpy(&pcd->setup_pkt->req,+													req->buf + ep->dwc_ep.xfer_count, 8);+										}+										req->actual = ep->dwc_ep.xfer_count;+										dwc_otg_request_done(ep, req, -ECONNRESET);+										ep->dwc_ep.start_xfer_buff = 0;+										ep->dwc_ep.xfer_buff = 0;+										ep->dwc_ep.xfer_len = 0;+									}+									pcd->ep0state = EP0_IDLE;+									if (doepint.b.setup) {+										DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n");+										/* Data stage started, clear setup */+										CLEAR_OUT_EP_INTR(core_if, epnum, setup);+										doepint.b.setup = 0;+										handle_ep0(pcd);+										/* Prepare for setup packets if ep0in was enabled*/+										if (pcd->ep0state == EP0_IN_STATUS_PHASE) {+											ep0_out_start(core_if, pcd);+										}+										goto exit_xfercompl;+									} else {+										/* Prepare for more setup packets */+										DWC_DEBUGPL(DBG_PCDV,+											"EP0_IDLE SR=1 setup=0 new setup comes 2\n");+										ep0_out_start(core_if, pcd);+									}+								}+							}+						}+						if (core_if->dma_enable == 0 || pcd->ep0state != EP0_IDLE)+							handle_ep0(pcd);+exit_xfercompl:+						DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n",+							dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep), doepint.d32);+					} else {+					if (core_if->dma_desc_enable == 0+					    || pcd->ep0state != EP0_IDLE)+						handle_ep0(pcd);+					}+#ifdef DWC_EN_ISOC+				} else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {+					if (doepint.b.pktdrpsts == 0) {+						/* Clear the bit in DOEPINTn for this interrupt */+						CLEAR_OUT_EP_INTR(core_if,+								  epnum,+								  xfercompl);+						complete_iso_ep(pcd, ep);+					} else {++						doepint_data_t doepint = {.d32 = 0 };+						doepint.b.xfercompl = 1;+						doepint.b.pktdrpsts = 1;+						DWC_WRITE_REG32+						    (&core_if->dev_if->out_ep_regs+						     [epnum]->doepint,+						     doepint.d32);+						if (handle_iso_out_pkt_dropped+						    (core_if, dwc_ep)) {+							complete_iso_ep(pcd,+									ep);+						}+					}+#endif /* DWC_EN_ISOC */+#ifdef DWC_UTE_PER_IO+				} else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {+					CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);+					if (!ep->stopped)+						complete_xiso_ep(ep);+#endif /* DWC_UTE_PER_IO */+				} else {+					/* Clear the bit in DOEPINTn for this interrupt */+					CLEAR_OUT_EP_INTR(core_if, epnum,+							  xfercompl);++					if (core_if->core_params->dev_out_nak) {+						DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[epnum]);+						pcd->core_if->ep_xfer_info[epnum].state = 0;+#ifdef DEBUG+						print_memory_payload(pcd, dwc_ep);+#endif+					}+					complete_ep(ep);+				}++			}++			/* Endpoint disable      */+			if (doepint.b.epdisabled) {++				/* Clear the bit in DOEPINTn for this interrupt */+				CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled);+				if (core_if->core_params->dev_out_nak) {+#ifdef DEBUG+					print_memory_payload(pcd, dwc_ep);+#endif+					/* In case of timeout condition */+					if (core_if->ep_xfer_info[epnum].state == 2) {+						dctl.d32 = DWC_READ_REG32(&core_if->dev_if->+										dev_global_regs->dctl);+						dctl.b.cgoutnak = 1;+						DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,+																dctl.d32);+						/* Unmask goutnakeff interrupt which was masked+						 * during handle nak out interrupt */+						gintmsk.b.goutnakeff = 1;+						DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,+																0, gintmsk.d32);++						complete_ep(ep);+					}+				}+				if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)+				{+					dctl_data_t dctl;+					gintmsk_data_t intr_mask = {.d32 = 0};+					dwc_otg_pcd_request_t *req = 0;++					dctl.d32 = DWC_READ_REG32(&core_if->dev_if->+						dev_global_regs->dctl);+					dctl.b.cgoutnak = 1;+					DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,+						dctl.d32);++					intr_mask.d32 = 0;+					intr_mask.b.incomplisoout = 1;++					/* Get any pending requests */+					if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {+						req = DWC_CIRCLEQ_FIRST(&ep->queue);+						if (!req) {+							DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);+						} else {+							dwc_otg_request_done(ep, req, 0);+							start_next_request(ep);+						}+					} else {+						DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);+					}+				}+			}+			/* AHB Error */+			if (doepint.b.ahberr) {+				DWC_ERROR("EP%d OUT AHB Error\n", epnum);+				DWC_ERROR("EP%d DEPDMA=0x%08x \n",+					  epnum, core_if->dev_if->out_ep_regs[epnum]->doepdma);+				CLEAR_OUT_EP_INTR(core_if, epnum, ahberr);+			}+			/* Setup Phase Done (contorl EPs) */+			if (doepint.b.setup) {+#ifdef DEBUG_EP0+				DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n", epnum);+#endif+				CLEAR_OUT_EP_INTR(core_if, epnum, setup);++				handle_ep0(pcd);+			}++			/** OUT EP BNA Intr */+			if (doepint.b.bna) {+				CLEAR_OUT_EP_INTR(core_if, epnum, bna);+				if (core_if->dma_desc_enable) {+#ifdef DWC_EN_ISOC+					if (dwc_ep->type ==+					    DWC_OTG_EP_TYPE_ISOC) {+						/*+						 * This checking is performed to prevent first "false" BNA+						 * handling occuring right after reconnect+						 */+						if (dwc_ep->next_frame !=+						    0xffffffff)+							dwc_otg_pcd_handle_iso_bna(ep);+					} else+#endif				/* DWC_EN_ISOC */+					{+						dwc_otg_pcd_handle_noniso_bna(ep);+					}+				}+			}+			/* Babble Interrupt */+			if (doepint.b.babble) {+				DWC_DEBUGPL(DBG_ANY, "EP%d OUT Babble\n",+					    epnum);+				handle_out_ep_babble_intr(pcd, epnum);++				CLEAR_OUT_EP_INTR(core_if, epnum, babble);+			}+			if (doepint.b.outtknepdis) {+				DWC_DEBUGPL(DBG_ANY, "EP%d OUT Token received when EP is \+					disabled\n",epnum);+				if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {+					doepmsk_data_t doepmsk = {.d32 = 0};+					ep->dwc_ep.frame_num = core_if->frame_num;+					if (ep->dwc_ep.bInterval > 1) {+						depctl_data_t depctl;+						depctl.d32 = DWC_READ_REG32(&core_if->dev_if->+													out_ep_regs[epnum]->doepctl);+						if (ep->dwc_ep.frame_num & 0x1) {+							depctl.b.setd1pid = 1;+							depctl.b.setd0pid = 0;+						} else {+							depctl.b.setd0pid = 1;+							depctl.b.setd1pid = 0;+						}+						DWC_WRITE_REG32(&core_if->dev_if->+										out_ep_regs[epnum]->doepctl, depctl.d32);+					}+					start_next_request(ep);+					doepmsk.b.outtknepdis = 1;+					DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,+								 doepmsk.d32, 0);+				}+				CLEAR_OUT_EP_INTR(core_if, epnum, outtknepdis);+			}++			/* NAK Interrutp */+			if (doepint.b.nak) {+				DWC_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum);+				handle_out_ep_nak_intr(pcd, epnum);++				CLEAR_OUT_EP_INTR(core_if, epnum, nak);+			}+			/* NYET Interrutp */+			if (doepint.b.nyet) {+				DWC_DEBUGPL(DBG_ANY, "EP%d OUT NYET\n", epnum);+				handle_out_ep_nyet_intr(pcd, epnum);++				CLEAR_OUT_EP_INTR(core_if, epnum, nyet);+			}+		}++		epnum++;+		ep_intr >>= 1;+	}++	return 1;++#undef CLEAR_OUT_EP_INTR+}+static int drop_transfer(uint32_t trgt_fr, uint32_t curr_fr, uint8_t frm_overrun)+{+	int retval = 0;+	if(!frm_overrun && curr_fr >= trgt_fr)+		retval = 1;+	else if (frm_overrun+		 && (curr_fr >= trgt_fr && ((curr_fr - trgt_fr) < 0x3FFF / 2)))+		retval = 1;+	return retval;+}+/**+ * Incomplete ISO IN Transfer Interrupt.+ * This interrupt indicates one of the following conditions occurred+ * while transmitting an ISOC transaction.+ * - Corrupted IN Token for ISOC EP.+ * - Packet not complete in FIFO.+ * The follow actions will be taken:+ *	-#	Determine the EP+ *	-#	Set incomplete flag in dwc_ep structure+ *	-#	Disable EP; when "Endpoint Disabled" interrupt is received+ *		Flush FIFO+ */+int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd)+{+	gintsts_data_t gintsts;++#ifdef DWC_EN_ISOC+	dwc_otg_dev_if_t *dev_if;+	deptsiz_data_t deptsiz = {.d32 = 0 };+	depctl_data_t depctl = {.d32 = 0 };+	dsts_data_t dsts = {.d32 = 0 };+	dwc_ep_t *dwc_ep;+	int i;++	dev_if = GET_CORE_IF(pcd)->dev_if;++	for (i = 1; i <= dev_if->num_in_eps; ++i) {+		dwc_ep = &pcd->in_ep[i].dwc_ep;+		if (dwc_ep->active && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {+			deptsiz.d32 =+			    DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);+			depctl.d32 =+			    DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);++			if (depctl.b.epdis && deptsiz.d32) {+				set_current_pkt_info(GET_CORE_IF(pcd), dwc_ep);+				if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {+					dwc_ep->cur_pkt = 0;+					dwc_ep->proc_buf_num =+					    (dwc_ep->proc_buf_num ^ 1) & 0x1;++					if (dwc_ep->proc_buf_num) {+						dwc_ep->cur_pkt_addr =+						    dwc_ep->xfer_buff1;+						dwc_ep->cur_pkt_dma_addr =+						    dwc_ep->dma_addr1;+					} else {+						dwc_ep->cur_pkt_addr =+						    dwc_ep->xfer_buff0;+						dwc_ep->cur_pkt_dma_addr =+						    dwc_ep->dma_addr0;+					}++				}++				dsts.d32 =+				    DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->+						   dev_global_regs->dsts);+				dwc_ep->next_frame = dsts.b.soffn;++				dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF+								  (pcd),+								  dwc_ep);+			}+		}+	}++#else+	depctl_data_t depctl = {.d32 = 0 };+	dwc_ep_t *dwc_ep;+	dwc_otg_dev_if_t *dev_if;+	int i;+	dev_if = GET_CORE_IF(pcd)->dev_if;++	DWC_DEBUGPL(DBG_PCD,"Incomplete ISO IN \n");++	for (i = 1; i <= dev_if->num_in_eps; ++i) {+		dwc_ep = &pcd->in_ep[i-1].dwc_ep;+		depctl.d32 =+			DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);+		if (depctl.b.epena && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {+			if (drop_transfer(dwc_ep->frame_num, GET_CORE_IF(pcd)->frame_num,+							dwc_ep->frm_overrun))+			{+				depctl.d32 =+					DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);+				depctl.b.snak = 1;+				depctl.b.epdis = 1;+				DWC_MODIFY_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32, depctl.d32);+			}+		}+	}++	/*intr_mask.b.incomplisoin = 1;+	DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,+			 intr_mask.d32, 0);	 */+#endif				//DWC_EN_ISOC++	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.incomplisoin = 1;+	DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,+			gintsts.d32);++	return 1;+}++/**+ * Incomplete ISO OUT Transfer Interrupt.+ *+ * This interrupt indicates that the core has dropped an ISO OUT+ * packet. The following conditions can be the cause:+ * - FIFO Full, the entire packet would not fit in the FIFO.+ * - CRC Error+ * - Corrupted Token+ * The follow actions will be taken:+ *	-#	Determine the EP+ *	-#	Set incomplete flag in dwc_ep structure+ *	-#	Read any data from the FIFO+ *	-#	Disable EP. When "Endpoint Disabled" interrupt is received+ *		re-enable EP.+ */+int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd)+{++	gintsts_data_t gintsts;++#ifdef DWC_EN_ISOC+	dwc_otg_dev_if_t *dev_if;+	deptsiz_data_t deptsiz = {.d32 = 0 };+	depctl_data_t depctl = {.d32 = 0 };+	dsts_data_t dsts = {.d32 = 0 };+	dwc_ep_t *dwc_ep;+	int i;++	dev_if = GET_CORE_IF(pcd)->dev_if;++	for (i = 1; i <= dev_if->num_out_eps; ++i) {+		dwc_ep = &pcd->in_ep[i].dwc_ep;+		if (pcd->out_ep[i].dwc_ep.active &&+		    pcd->out_ep[i].dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {+			deptsiz.d32 =+			    DWC_READ_REG32(&dev_if->out_ep_regs[i]->doeptsiz);+			depctl.d32 =+			    DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);++			if (depctl.b.epdis && deptsiz.d32) {+				set_current_pkt_info(GET_CORE_IF(pcd),+						     &pcd->out_ep[i].dwc_ep);+				if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {+					dwc_ep->cur_pkt = 0;+					dwc_ep->proc_buf_num =+					    (dwc_ep->proc_buf_num ^ 1) & 0x1;++					if (dwc_ep->proc_buf_num) {+						dwc_ep->cur_pkt_addr =+						    dwc_ep->xfer_buff1;+						dwc_ep->cur_pkt_dma_addr =+						    dwc_ep->dma_addr1;+					} else {+						dwc_ep->cur_pkt_addr =+						    dwc_ep->xfer_buff0;+						dwc_ep->cur_pkt_dma_addr =+						    dwc_ep->dma_addr0;+					}++				}++				dsts.d32 =+				    DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->+						   dev_global_regs->dsts);+				dwc_ep->next_frame = dsts.b.soffn;++				dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF+								  (pcd),+								  dwc_ep);+			}+		}+	}+#else+	/** @todo implement ISR */+	gintmsk_data_t intr_mask = {.d32 = 0 };+	dwc_otg_core_if_t *core_if;+	deptsiz_data_t deptsiz = {.d32 = 0 };+	depctl_data_t depctl = {.d32 = 0 };+	dctl_data_t dctl = {.d32 = 0 };+	dwc_ep_t *dwc_ep = NULL;+	int i;+	core_if = GET_CORE_IF(pcd);++	for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {+		dwc_ep = &pcd->out_ep[i].dwc_ep;+		depctl.d32 =+			DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);+		if (depctl.b.epena && depctl.b.dpid == (core_if->frame_num & 0x1)) {+			core_if->dev_if->isoc_ep = dwc_ep;+			deptsiz.d32 =+					DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz);+				break;+		}+	}+	dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);+	gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);+	intr_mask.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);++	if (!intr_mask.b.goutnakeff) {+		/* Unmask it */+		intr_mask.b.goutnakeff = 1;+		DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32);+	}+	if (!gintsts.b.goutnakeff) {+		dctl.b.sgoutnak = 1;+	}+	DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);++	depctl.d32 = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);+	if (depctl.b.epena) {+		depctl.b.epdis = 1;+		depctl.b.snak = 1;+	}+	DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl, depctl.d32);++	intr_mask.d32 = 0;+	intr_mask.b.incomplisoout = 1;++#endif /* DWC_EN_ISOC */++	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.incomplisoout = 1;+	DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,+			gintsts.d32);++	return 1;+}++/**+ * This function handles the Global IN NAK Effective interrupt.+ *+ */+int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t * pcd)+{+	dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;+	depctl_data_t diepctl = {.d32 = 0 };+	gintmsk_data_t intr_mask = {.d32 = 0 };+	gintsts_data_t gintsts;+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+	int i;++	DWC_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n");++	/* Disable all active IN EPs */+	for (i = 0; i <= dev_if->num_in_eps; i++) {+		diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);+		if (!(diepctl.b.eptype & 1) && diepctl.b.epena) {+			if (core_if->start_predict > 0)+				core_if->start_predict++;+			diepctl.b.epdis = 1;+			diepctl.b.snak = 1;+			DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, diepctl.d32);+		}+	}+++	/* Disable the Global IN NAK Effective Interrupt */+	intr_mask.b.ginnakeff = 1;+	DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,+			 intr_mask.d32, 0);++	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.ginnakeff = 1;+	DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,+			gintsts.d32);++	return 1;+}++/**+ * OUT NAK Effective.+ *+ */+int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd)+{+	dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;+	gintmsk_data_t intr_mask = {.d32 = 0 };+	gintsts_data_t gintsts;+	depctl_data_t doepctl;+	int i;++	/* Disable the Global OUT NAK Effective Interrupt */+	intr_mask.b.goutnakeff = 1;+	DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,+		intr_mask.d32, 0);++	/* If DEV OUT NAK enabled*/+	if (pcd->core_if->core_params->dev_out_nak) {+		/* Run over all out endpoints to determine the ep number on+		 * which the timeout has happened+		 */+		for (i = 0; i <= dev_if->num_out_eps; i++) {+			if ( pcd->core_if->ep_xfer_info[i].state == 2 )+				break;+		}+		if (i > dev_if->num_out_eps) {+			dctl_data_t dctl;+			dctl.d32 =+			    DWC_READ_REG32(&dev_if->dev_global_regs->dctl);+			dctl.b.cgoutnak = 1;+			DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl,+				dctl.d32);+			goto out;+		}++		/* Disable the endpoint */+		doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);+		if (doepctl.b.epena) {+			doepctl.b.epdis = 1;+			doepctl.b.snak = 1;+		}+		DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);+		return 1;+	}+	/* We come here from Incomplete ISO OUT handler */+	if (dev_if->isoc_ep) {+		dwc_ep_t *dwc_ep = (dwc_ep_t *)dev_if->isoc_ep;+		uint32_t epnum = dwc_ep->num;+		doepint_data_t doepint;+		doepint.d32 =+		    DWC_READ_REG32(&dev_if->out_ep_regs[dwc_ep->num]->doepint);+		dev_if->isoc_ep = NULL;+		doepctl.d32 =+		    DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl);+		DWC_PRINTF("Before disable DOEPCTL = %08x\n", doepctl.d32);+		if (doepctl.b.epena) {+			doepctl.b.epdis = 1;+			doepctl.b.snak = 1;+		}+		DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepctl,+				doepctl.d32);+		return 1;+	} else+		DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",+			   "Global OUT NAK Effective\n");++out:+	/* Clear interrupt */+	gintsts.d32 = 0;+	gintsts.b.goutnakeff = 1;+	DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,+			gintsts.d32);++	return 1;+}++/**+ * PCD interrupt handler.+ *+ * The PCD handles the device interrupts.  Many conditions can cause a+ * device interrupt. When an interrupt occurs, the device interrupt+ * service routine determines the cause of the interrupt and+ * dispatches handling to the appropriate function. These interrupt+ * handling functions are described below.+ *+ * All interrupt registers are processed from LSB to MSB.+ *+ */+int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd)+{+	dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);+#ifdef VERBOSE+	dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;+#endif+	gintsts_data_t gintr_status;+	int32_t retval = 0;++	/* Exit from ISR if core is hibernated */+	if (core_if->hibernation_suspend == 1) {+		return retval;+	}+#ifdef VERBOSE+	DWC_DEBUGPL(DBG_ANY, "%s() gintsts=%08x	 gintmsk=%08x\n",+		    __func__,+		    DWC_READ_REG32(&global_regs->gintsts),+		    DWC_READ_REG32(&global_regs->gintmsk));+#endif++	if (dwc_otg_is_device_mode(core_if)) {+		DWC_SPINLOCK(pcd->lock);+#ifdef VERBOSE+		DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x  gintmsk=%08x\n",+			    __func__,+			    DWC_READ_REG32(&global_regs->gintsts),+			    DWC_READ_REG32(&global_regs->gintmsk));+#endif++		gintr_status.d32 = dwc_otg_read_core_intr(core_if);++		DWC_DEBUGPL(DBG_PCDV, "%s: gintsts&gintmsk=%08x\n",+			    __func__, gintr_status.d32);++		if (gintr_status.b.sofintr) {+			retval |= dwc_otg_pcd_handle_sof_intr(pcd);+		}+		if (gintr_status.b.rxstsqlvl) {+			retval |=+			    dwc_otg_pcd_handle_rx_status_q_level_intr(pcd);+		}+		if (gintr_status.b.nptxfempty) {+			retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd);+		}+		if (gintr_status.b.goutnakeff) {+			retval |= dwc_otg_pcd_handle_out_nak_effective(pcd);+		}+		if (gintr_status.b.i2cintr) {+			retval |= dwc_otg_pcd_handle_i2c_intr(pcd);+		}+		if (gintr_status.b.erlysuspend) {+			retval |= dwc_otg_pcd_handle_early_suspend_intr(pcd);+		}+		if (gintr_status.b.usbreset) {+			retval |= dwc_otg_pcd_handle_usb_reset_intr(pcd);+		}+		if (gintr_status.b.enumdone) {+			retval |= dwc_otg_pcd_handle_enum_done_intr(pcd);+		}+		if (gintr_status.b.isooutdrop) {+			retval |=+			    dwc_otg_pcd_handle_isoc_out_packet_dropped_intr+			    (pcd);+		}+		if (gintr_status.b.eopframe) {+			retval |=+			    dwc_otg_pcd_handle_end_periodic_frame_intr(pcd);+		}+		if (gintr_status.b.inepint) {+			if (!core_if->multiproc_int_enable) {+				retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);+			}+		}+		if (gintr_status.b.outepintr) {+			if (!core_if->multiproc_int_enable) {+				retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);+			}+		}+		if (gintr_status.b.epmismatch) {+			retval |= dwc_otg_pcd_handle_ep_mismatch_intr(pcd);+		}+		if (gintr_status.b.fetsusp) {+			retval |= dwc_otg_pcd_handle_ep_fetsusp_intr(pcd);+		}+		if (gintr_status.b.ginnakeff) {+			retval |= dwc_otg_pcd_handle_in_nak_effective(pcd);+		}+		if (gintr_status.b.incomplisoin) {+			retval |=+			    dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd);+		}+		if (gintr_status.b.incomplisoout) {+			retval |=+			    dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd);+		}++		/* In MPI mode Device Endpoints interrupts are asserted+		 * without setting outepintr and inepint bits set, so these+		 * Interrupt handlers are called without checking these bit-fields+		 */+		if (core_if->multiproc_int_enable) {+			retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);+			retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);+		}+#ifdef VERBOSE+		DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__,+			    DWC_READ_REG32(&global_regs->gintsts));+#endif+		DWC_SPINUNLOCK(pcd->lock);+	}+	return retval;+}++#endif /* DWC_HOST_ONLY */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,1358 @@+ /* ==========================================================================+  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $+  * $Revision: #21 $+  * $Date: 2012/08/10 $+  * $Change: 2047372 $+  *+  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+  * otherwise expressly agreed to in writing between Synopsys and you.+  *+  * The Software IS NOT an item of Licensed Software or Licensed Product under+  * any End User Software License Agreement or Agreement for Licensed Product+  * with Synopsys or any supplement thereto. You are permitted to use and+  * redistribute this Software in source and binary forms, with or without+  * modification, provided that redistributions of source code must retain this+  * notice. You may not view, use, disclose, copy or distribute this file or+  * any information contained herein except pursuant to this license grant from+  * Synopsys. If you do not agree with this notice, including the disclaimer+  * below, then you are not authorized to use the Software.+  *+  * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+  * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+  * DAMAGE.+  * ========================================================================== */+#ifndef DWC_HOST_ONLY++/** @file+ * This file implements the Peripheral Controller Driver.+ *+ * The Peripheral Controller Driver (PCD) is responsible for+ * translating requests from the Function Driver into the appropriate+ * actions on the DWC_otg controller. It isolates the Function Driver+ * from the specifics of the controller by providing an API to the+ * Function Driver.+ *+ * The Peripheral Controller Driver for Linux will implement the+ * Gadget API, so that the existing Gadget drivers can be used.+ * (Gadget Driver is the Linux terminology for a Function Driver.)+ *+ * The Linux Gadget API is defined in the header file+ * <code><linux/usb_gadget.h></code>.  The USB EP operations API is+ * defined in the structure <code>usb_ep_ops</code> and the USB+ * Controller API is defined in the structure+ * <code>usb_gadget_ops</code>.+ *+ */++#include "dwc_otg_os_dep.h"+#include "dwc_otg_pcd_if.h"+#include "dwc_otg_pcd.h"+#include "dwc_otg_driver.h"+#include "dwc_otg_dbg.h"++static struct gadget_wrapper {+	dwc_otg_pcd_t *pcd;++	struct usb_gadget gadget;+	struct usb_gadget_driver *driver;++	struct usb_ep ep0;+	struct usb_ep in_ep[16];+	struct usb_ep out_ep[16];++} *gadget_wrapper;++/* Display the contents of the buffer */+extern void dump_msg(const u8 * buf, unsigned int length);+/**+ * Get the dwc_otg_pcd_ep_t* from usb_ep* pointer - NULL in case+ * if the endpoint is not found+ */+static struct dwc_otg_pcd_ep *ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)+{+	int i;+	if (pcd->ep0.priv == handle) {+		return &pcd->ep0;+	}++	for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {+		if (pcd->in_ep[i].priv == handle)+			return &pcd->in_ep[i];+		if (pcd->out_ep[i].priv == handle)+			return &pcd->out_ep[i];+	}++	return NULL;+}++/* USB Endpoint Operations */+/*+ * The following sections briefly describe the behavior of the Gadget+ * API endpoint operations implemented in the DWC_otg driver+ * software. Detailed descriptions of the generic behavior of each of+ * these functions can be found in the Linux header file+ * include/linux/usb_gadget.h.+ *+ * The Gadget API provides wrapper functions for each of the function+ * pointers defined in usb_ep_ops. The Gadget Driver calls the wrapper+ * function, which then calls the underlying PCD function. The+ * following sections are named according to the wrapper+ * functions. Within each section, the corresponding DWC_otg PCD+ * function name is specified.+ *+ */++/**+ * This function is called by the Gadget Driver for each EP to be+ * configured for the current configuration (SET_CONFIGURATION).+ *+ * This function initializes the dwc_otg_ep_t data structure, and then+ * calls dwc_otg_ep_activate.+ */+static int ep_enable(struct usb_ep *usb_ep,+		     const struct usb_endpoint_descriptor *ep_desc)+{+	int retval;++	DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc);++	if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) {+		DWC_WARN("%s, bad ep or descriptor\n", __func__);+		return -EINVAL;+	}+	if (usb_ep == &gadget_wrapper->ep0) {+		DWC_WARN("%s, bad ep(0)\n", __func__);+		return -EINVAL;+	}++	/* Check FIFO size? */+	if (!ep_desc->wMaxPacketSize) {+		DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name);+		return -ERANGE;+	}++	if (!gadget_wrapper->driver ||+	    gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {+		DWC_WARN("%s, bogus device state\n", __func__);+		return -ESHUTDOWN;+	}++	/* Delete after check - MAS */+#if 0+	nat = (uint32_t) ep_desc->wMaxPacketSize;+	printk(KERN_ALERT "%s: nat (before) =%d\n", __func__, nat);+	nat = (nat >> 11) & 0x03;+	printk(KERN_ALERT "%s: nat (after) =%d\n", __func__, nat);+#endif+	retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd,+				       (const uint8_t *)ep_desc,+				       (void *)usb_ep);+	if (retval) {+		DWC_WARN("dwc_otg_pcd_ep_enable failed\n");+		return -EINVAL;+	}++	usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize);++	return 0;+}++/**+ * This function is called when an EP is disabled due to disconnect or+ * change in configuration. Any pending requests will terminate with a+ * status of -ESHUTDOWN.+ *+ * This function modifies the dwc_otg_ep_t data structure for this EP,+ * and then calls dwc_otg_ep_deactivate.+ */+static int ep_disable(struct usb_ep *usb_ep)+{+	int retval;++	DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, usb_ep);+	if (!usb_ep) {+		DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__,+			    usb_ep ? usb_ep->name : NULL);+		return -EINVAL;+	}++	retval = dwc_otg_pcd_ep_disable(gadget_wrapper->pcd, usb_ep);+	if (retval) {+		retval = -EINVAL;+	}++	return retval;+}++/**+ * This function allocates a request object to use with the specified+ * endpoint.+ *+ * @param ep The endpoint to be used with with the request+ * @param gfp_flags the GFP_* flags to use.+ */+static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *ep,+						     gfp_t gfp_flags)+{+	struct usb_request *usb_req;++	DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d)\n", __func__, ep, gfp_flags);+	if (0 == ep) {+		DWC_WARN("%s() %s\n", __func__, "Invalid EP!\n");+		return 0;+	}+	usb_req = kmalloc(sizeof(*usb_req), gfp_flags);+	if (0 == usb_req) {+		DWC_WARN("%s() %s\n", __func__, "request allocation failed!\n");+		return 0;+	}+	memset(usb_req, 0, sizeof(*usb_req));+	usb_req->dma = DWC_DMA_ADDR_INVALID;++	return usb_req;+}++/**+ * This function frees a request object.+ *+ * @param ep The endpoint associated with the request+ * @param req The request being freed+ */+static void dwc_otg_pcd_free_request(struct usb_ep *ep, struct usb_request *req)+{+	DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, ep, req);++	if (0 == ep || 0 == req) {+		DWC_WARN("%s() %s\n", __func__,+			 "Invalid ep or req argument!\n");+		return;+	}++	kfree(req);+}++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)+/**+ * This function allocates an I/O buffer to be used for a transfer+ * to/from the specified endpoint.+ *+ * @param usb_ep The endpoint to be used with with the request+ * @param bytes The desired number of bytes for the buffer+ * @param dma Pointer to the buffer's DMA address; must be valid+ * @param gfp_flags the GFP_* flags to use.+ * @return address of a new buffer or null is buffer could not be allocated.+ */+static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes,+				      dma_addr_t * dma, gfp_t gfp_flags)+{+	void *buf;+	dwc_otg_pcd_t *pcd = 0;++	pcd = gadget_wrapper->pcd;++	DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d,%p,%0x)\n", __func__, usb_ep, bytes,+		    dma, gfp_flags);++	/* Check dword alignment */+	if ((bytes & 0x3UL) != 0) {+		DWC_WARN("%s() Buffer size is not a multiple of"+			 "DWORD size (%d)", __func__, bytes);+	}++	buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags);++	/* Check dword alignment */+	if (((int)buf & 0x3UL) != 0) {+		DWC_WARN("%s() Buffer is not DWORD aligned (%p)",+			 __func__, buf);+	}++	return buf;+}++/**+ * This function frees an I/O buffer that was allocated by alloc_buffer.+ *+ * @param usb_ep the endpoint associated with the buffer+ * @param buf address of the buffer+ * @param dma The buffer's DMA address+ * @param bytes The number of bytes of the buffer+ */+static void dwc_otg_pcd_free_buffer(struct usb_ep *usb_ep, void *buf,+				    dma_addr_t dma, unsigned bytes)+{+	dwc_otg_pcd_t *pcd = 0;++	pcd = gadget_wrapper->pcd;++	DWC_DEBUGPL(DBG_PCDV, "%s(%p,%0x,%d)\n", __func__, buf, dma, bytes);++	dma_free_coherent(NULL, bytes, buf, dma);+}+#endif++/**+ * This function is used to submit an I/O Request to an EP.+ *+ *	- When the request completes the request's completion callback+ *	  is called to return the request to the driver.+ *	- An EP, except control EPs, may have multiple requests+ *	  pending.+ *	- Once submitted the request cannot be examined or modified.+ *	- Each request is turned into one or more packets.+ *	- A BULK EP can queue any amount of data; the transfer is+ *	  packetized.+ *	- Zero length Packets are specified with the request 'zero'+ *	  flag.+ */+static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req,+		    gfp_t gfp_flags)+{+	dwc_otg_pcd_t *pcd;+	struct dwc_otg_pcd_ep *ep = NULL;+	int retval = 0, is_isoc_ep = 0;+	dma_addr_t dma_addr = DWC_DMA_ADDR_INVALID;++	DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n",+		    __func__, usb_ep, usb_req, gfp_flags);++	if (!usb_req || !usb_req->complete || !usb_req->buf) {+		DWC_WARN("bad params\n");+		return -EINVAL;+	}++	if (!usb_ep) {+		DWC_WARN("bad ep\n");+		return -EINVAL;+	}++	pcd = gadget_wrapper->pcd;+	if (!gadget_wrapper->driver ||+	    gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {+		DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",+			    gadget_wrapper->gadget.speed);+		DWC_WARN("bogus device state\n");+		return -ESHUTDOWN;+	}++	DWC_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n",+		    usb_ep->name, usb_req, usb_req->length, usb_req->buf);++	usb_req->status = -EINPROGRESS;+	usb_req->actual = 0;++	ep = ep_from_handle(pcd, usb_ep);+	if (ep == NULL)+		is_isoc_ep = 0;+	else+		is_isoc_ep = (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ? 1 : 0;+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)+	dma_addr = usb_req->dma;+#else+	if (GET_CORE_IF(pcd)->dma_enable) {+                dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev;+                struct device *dev = NULL;++                if (otg_dev != NULL)+                        dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep);++		if (usb_req->length != 0 &&+                    usb_req->dma == DWC_DMA_ADDR_INVALID) {+                        dma_addr = dma_map_single(dev, usb_req->buf,+                                                  usb_req->length,+                                                  ep->dwc_ep.is_in ?+                                                        DMA_TO_DEVICE:+                                                        DMA_FROM_DEVICE);+		}+	}+#endif++#ifdef DWC_UTE_PER_IO+	if (is_isoc_ep == 1) {+		retval = dwc_otg_pcd_xiso_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,+			usb_req->length, usb_req->zero, usb_req,+			gfp_flags == GFP_ATOMIC ? 1 : 0, &usb_req->ext_req);+		if (retval)+			return -EINVAL;++		return 0;+	}+#endif+	retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,+				      usb_req->length, usb_req->zero, usb_req,+				      gfp_flags == GFP_ATOMIC ? 1 : 0);+	if (retval) {+		return -EINVAL;+	}++	return 0;+}++/**+ * This function cancels an I/O request from an EP.+ */+static int ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req)+{+	DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, usb_req);++	if (!usb_ep || !usb_req) {+		DWC_WARN("bad argument\n");+		return -EINVAL;+	}+	if (!gadget_wrapper->driver ||+	    gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {+		DWC_WARN("bogus device state\n");+		return -ESHUTDOWN;+	}+	if (dwc_otg_pcd_ep_dequeue(gadget_wrapper->pcd, usb_ep, usb_req)) {+		return -EINVAL;+	}++	return 0;+}++/**+ * usb_ep_set_halt stalls an endpoint.+ *+ * usb_ep_clear_halt clears an endpoint halt and resets its data+ * toggle.+ *+ * Both of these functions are implemented with the same underlying+ * function. The behavior depends on the value argument.+ *+ * @param[in] usb_ep the Endpoint to halt or clear halt.+ * @param[in] value+ *	- 0 means clear_halt.+ *	- 1 means set_halt,+ *	- 2 means clear stall lock flag.+ *	- 3 means set  stall lock flag.+ */+static int ep_halt(struct usb_ep *usb_ep, int value)+{+	int retval = 0;++	DWC_DEBUGPL(DBG_PCD, "HALT %s %d\n", usb_ep->name, value);++	if (!usb_ep) {+		DWC_WARN("bad ep\n");+		return -EINVAL;+	}++	retval = dwc_otg_pcd_ep_halt(gadget_wrapper->pcd, usb_ep, value);+	if (retval == -DWC_E_AGAIN) {+		return -EAGAIN;+	} else if (retval) {+		retval = -EINVAL;+	}++	return retval;+}++//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))+#if 0+/**+ * ep_wedge: sets the halt feature and ignores clear requests+ *+ * @usb_ep: the endpoint being wedged+ *+ * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)+ * requests. If the gadget driver clears the halt status, it will+ * automatically unwedge the endpoint.+ *+ * Returns zero on success, else negative errno. *+ * Check usb_ep_set_wedge() at "usb_gadget.h" for details+ */+static int ep_wedge(struct usb_ep *usb_ep)+{+	int retval = 0;++	DWC_DEBUGPL(DBG_PCD, "WEDGE %s\n", usb_ep->name);++	if (!usb_ep) {+		DWC_WARN("bad ep\n");+		return -EINVAL;+	}++	retval = dwc_otg_pcd_ep_wedge(gadget_wrapper->pcd, usb_ep);+	if (retval == -DWC_E_AGAIN) {+		retval = -EAGAIN;+	} else if (retval) {+		retval = -EINVAL;+	}++	return retval;+}+#endif++#ifdef DWC_EN_ISOC+/**+ * This function is used to submit an ISOC Transfer Request to an EP.+ *+ *	- Every time a sync period completes the request's completion callback+ *	  is called to provide data to the gadget driver.+ *	- Once submitted the request cannot be modified.+ *	- Each request is turned into periodic data packets untill ISO+ *	  Transfer is stopped..+ */+static int iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req,+			gfp_t gfp_flags)+{+	int retval = 0;++	if (!req || !req->process_buffer || !req->buf0 || !req->buf1) {+		DWC_WARN("bad params\n");+		return -EINVAL;+	}++	if (!usb_ep) {+		DWC_PRINTF("bad params\n");+		return -EINVAL;+	}++	req->status = -EINPROGRESS;++	retval =+	    dwc_otg_pcd_iso_ep_start(gadget_wrapper->pcd, usb_ep, req->buf0,+				     req->buf1, req->dma0, req->dma1,+				     req->sync_frame, req->data_pattern_frame,+				     req->data_per_frame,+				     req->+				     flags & USB_REQ_ISO_ASAP ? -1 :+				     req->start_frame, req->buf_proc_intrvl,+				     req, gfp_flags == GFP_ATOMIC ? 1 : 0);++	if (retval) {+		return -EINVAL;+	}++	return retval;+}++/**+ * This function stops ISO EP Periodic Data Transfer.+ */+static int iso_ep_stop(struct usb_ep *usb_ep, struct usb_iso_request *req)+{+	int retval = 0;+	if (!usb_ep) {+		DWC_WARN("bad ep\n");+	}++	if (!gadget_wrapper->driver ||+	    gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {+		DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",+			    gadget_wrapper->gadget.speed);+		DWC_WARN("bogus device state\n");+	}++	dwc_otg_pcd_iso_ep_stop(gadget_wrapper->pcd, usb_ep, req);+	if (retval) {+		retval = -EINVAL;+	}++	return retval;+}++static struct usb_iso_request *alloc_iso_request(struct usb_ep *ep,+						 int packets, gfp_t gfp_flags)+{+	struct usb_iso_request *pReq = NULL;+	uint32_t req_size;++	req_size = sizeof(struct usb_iso_request);+	req_size +=+	    (2 * packets * (sizeof(struct usb_gadget_iso_packet_descriptor)));++	pReq = kmalloc(req_size, gfp_flags);+	if (!pReq) {+		DWC_WARN("Can't allocate Iso Request\n");+		return 0;+	}+	pReq->iso_packet_desc0 = (void *)(pReq + 1);++	pReq->iso_packet_desc1 = pReq->iso_packet_desc0 + packets;++	return pReq;+}++static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req)+{+	kfree(req);+}++static struct usb_isoc_ep_ops dwc_otg_pcd_ep_ops = {+	.ep_ops = {+		   .enable = ep_enable,+		   .disable = ep_disable,++		   .alloc_request = dwc_otg_pcd_alloc_request,+		   .free_request = dwc_otg_pcd_free_request,++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)+		   .alloc_buffer = dwc_otg_pcd_alloc_buffer,+		   .free_buffer = dwc_otg_pcd_free_buffer,+#endif++		   .queue = ep_queue,+		   .dequeue = ep_dequeue,++		   .set_halt = ep_halt,+		   .fifo_status = 0,+		   .fifo_flush = 0,+		   },+	.iso_ep_start = iso_ep_start,+	.iso_ep_stop = iso_ep_stop,+	.alloc_iso_request = alloc_iso_request,+	.free_iso_request = free_iso_request,+};++#else++	int (*enable) (struct usb_ep *ep,+		const struct usb_endpoint_descriptor *desc);+	int (*disable) (struct usb_ep *ep);++	struct usb_request *(*alloc_request) (struct usb_ep *ep,+		gfp_t gfp_flags);+	void (*free_request) (struct usb_ep *ep, struct usb_request *req);++	int (*queue) (struct usb_ep *ep, struct usb_request *req,+		gfp_t gfp_flags);+	int (*dequeue) (struct usb_ep *ep, struct usb_request *req);++	int (*set_halt) (struct usb_ep *ep, int value);+	int (*set_wedge) (struct usb_ep *ep);++	int (*fifo_status) (struct usb_ep *ep);+	void (*fifo_flush) (struct usb_ep *ep);+static struct usb_ep_ops dwc_otg_pcd_ep_ops = {+	.enable = ep_enable,+	.disable = ep_disable,++	.alloc_request = dwc_otg_pcd_alloc_request,+	.free_request = dwc_otg_pcd_free_request,++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)+	.alloc_buffer = dwc_otg_pcd_alloc_buffer,+	.free_buffer = dwc_otg_pcd_free_buffer,+#else+	/* .set_wedge = ep_wedge, */+        .set_wedge = NULL, /* uses set_halt instead */+#endif++	.queue = ep_queue,+	.dequeue = ep_dequeue,++	.set_halt = ep_halt,+	.fifo_status = 0,+	.fifo_flush = 0,++};++#endif /* _EN_ISOC_ */+/*	Gadget Operations */+/**+ * The following gadget operations will be implemented in the DWC_otg+ * PCD. Functions in the API that are not described below are not+ * implemented.+ *+ * The Gadget API provides wrapper functions for each of the function+ * pointers defined in usb_gadget_ops. The Gadget Driver calls the+ * wrapper function, which then calls the underlying PCD function. The+ * following sections are named according to the wrapper functions+ * (except for ioctl, which doesn't have a wrapper function). Within+ * each section, the corresponding DWC_otg PCD function name is+ * specified.+ *+ */++/**+ *Gets the USB Frame number of the last SOF.+ */+static int get_frame_number(struct usb_gadget *gadget)+{+	struct gadget_wrapper *d;++	DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);++	if (gadget == 0) {+		return -ENODEV;+	}++	d = container_of(gadget, struct gadget_wrapper, gadget);+	return dwc_otg_pcd_get_frame_number(d->pcd);+}++#ifdef CONFIG_USB_DWC_OTG_LPM+static int test_lpm_enabled(struct usb_gadget *gadget)+{+	struct gadget_wrapper *d;++	d = container_of(gadget, struct gadget_wrapper, gadget);++	return dwc_otg_pcd_is_lpm_enabled(d->pcd);+}+#endif++/**+ * Initiates Session Request Protocol (SRP) to wakeup the host if no+ * session is in progress. If a session is already in progress, but+ * the device is suspended, remote wakeup signaling is started.+ *+ */+static int wakeup(struct usb_gadget *gadget)+{+	struct gadget_wrapper *d;++	DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);++	if (gadget == 0) {+		return -ENODEV;+	} else {+		d = container_of(gadget, struct gadget_wrapper, gadget);+	}+	dwc_otg_pcd_wakeup(d->pcd);+	return 0;+}++static const struct usb_gadget_ops dwc_otg_pcd_ops = {+	.get_frame = get_frame_number,+	.wakeup = wakeup,+#ifdef CONFIG_USB_DWC_OTG_LPM+	.lpm_support = test_lpm_enabled,+#endif+	// current versions must always be self-powered+};++static int _setup(dwc_otg_pcd_t * pcd, uint8_t * bytes)+{+	int retval = -DWC_E_NOT_SUPPORTED;+	if (gadget_wrapper->driver && gadget_wrapper->driver->setup) {+		retval = gadget_wrapper->driver->setup(&gadget_wrapper->gadget,+						       (struct usb_ctrlrequest+							*)bytes);+	}++	if (retval == -ENOTSUPP) {+		retval = -DWC_E_NOT_SUPPORTED;+	} else if (retval < 0) {+		retval = -DWC_E_INVALID;+	}++	return retval;+}++#ifdef DWC_EN_ISOC+static int _isoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,+			  void *req_handle, int proc_buf_num)+{+	int i, packet_count;+	struct usb_gadget_iso_packet_descriptor *iso_packet = 0;+	struct usb_iso_request *iso_req = req_handle;++	if (proc_buf_num) {+		iso_packet = iso_req->iso_packet_desc1;+	} else {+		iso_packet = iso_req->iso_packet_desc0;+	}+	packet_count =+	    dwc_otg_pcd_get_iso_packet_count(pcd, ep_handle, req_handle);+	for (i = 0; i < packet_count; ++i) {+		int status;+		int actual;+		int offset;+		dwc_otg_pcd_get_iso_packet_params(pcd, ep_handle, req_handle,+						  i, &status, &actual, &offset);+		switch (status) {+		case -DWC_E_NO_DATA:+			status = -ENODATA;+			break;+		default:+			if (status) {+				DWC_PRINTF("unknown status in isoc packet\n");+			}++		}+		iso_packet[i].status = status;+		iso_packet[i].offset = offset;+		iso_packet[i].actual_length = actual;+	}++	iso_req->status = 0;+	iso_req->process_buffer(ep_handle, iso_req);++	return 0;+}+#endif /* DWC_EN_ISOC */++#ifdef DWC_UTE_PER_IO+/**+ * Copy the contents of the extended request to the Linux usb_request's+ * extended part and call the gadget's completion.+ *+ * @param pcd			Pointer to the pcd structure+ * @param ep_handle		Void pointer to the usb_ep structure+ * @param req_handle	Void pointer to the usb_request structure+ * @param status		Request status returned from the portable logic+ * @param ereq_port		Void pointer to the extended request structure+ *						created in the the portable part that contains the+ *						results of the processed iso packets.+ */+static int _xisoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,+			   void *req_handle, int32_t status, void *ereq_port)+{+	struct dwc_ute_iso_req_ext *ereqorg = NULL;+	struct dwc_iso_xreq_port *ereqport = NULL;+	struct dwc_ute_iso_packet_descriptor *desc_org = NULL;+	int i;+	struct usb_request *req;+	//struct dwc_ute_iso_packet_descriptor *+	//int status = 0;++	req = (struct usb_request *)req_handle;+	ereqorg = &req->ext_req;+	ereqport = (struct dwc_iso_xreq_port *)ereq_port;+	desc_org = ereqorg->per_io_frame_descs;++	if (req && req->complete) {+		/* Copy the request data from the portable logic to our request */+		for (i = 0; i < ereqport->pio_pkt_count; i++) {+			desc_org[i].actual_length =+			    ereqport->per_io_frame_descs[i].actual_length;+			desc_org[i].status =+			    ereqport->per_io_frame_descs[i].status;+		}++		switch (status) {+		case -DWC_E_SHUTDOWN:+			req->status = -ESHUTDOWN;+			break;+		case -DWC_E_RESTART:+			req->status = -ECONNRESET;+			break;+		case -DWC_E_INVALID:+			req->status = -EINVAL;+			break;+		case -DWC_E_TIMEOUT:+			req->status = -ETIMEDOUT;+			break;+		default:+			req->status = status;+		}++		/* And call the gadget's completion */+		req->complete(ep_handle, req);+	}++	return 0;+}+#endif /* DWC_UTE_PER_IO */++static int _complete(dwc_otg_pcd_t * pcd, void *ep_handle,+		     void *req_handle, int32_t status, uint32_t actual)+{+	struct usb_request *req = (struct usb_request *)req_handle;+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)+	struct dwc_otg_pcd_ep *ep = NULL;+#endif++	if (req && req->complete) {+		switch (status) {+		case -DWC_E_SHUTDOWN:+			req->status = -ESHUTDOWN;+			break;+		case -DWC_E_RESTART:+			req->status = -ECONNRESET;+			break;+		case -DWC_E_INVALID:+			req->status = -EINVAL;+			break;+		case -DWC_E_TIMEOUT:+			req->status = -ETIMEDOUT;+			break;+		default:+			req->status = status;++		}++		req->actual = actual;+		DWC_SPINUNLOCK(pcd->lock);+		req->complete(ep_handle, req);+		DWC_SPINLOCK(pcd->lock);+	}+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)+	ep = ep_from_handle(pcd, ep_handle);+	if (GET_CORE_IF(pcd)->dma_enable) {+                if (req->length != 0) {+                        dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev;+                        struct device *dev = NULL;++                        if (otg_dev != NULL)+                                  dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep);++			dma_unmap_single(dev, req->dma, req->length,+                                         ep->dwc_ep.is_in ?+                                                DMA_TO_DEVICE: DMA_FROM_DEVICE);+                }+	}+#endif++	return 0;+}++static int _connect(dwc_otg_pcd_t * pcd, int speed)+{+	gadget_wrapper->gadget.speed = speed;+	return 0;+}++static int _disconnect(dwc_otg_pcd_t * pcd)+{+	if (gadget_wrapper->driver && gadget_wrapper->driver->disconnect) {+		gadget_wrapper->driver->disconnect(&gadget_wrapper->gadget);+	}+	return 0;+}++static int _resume(dwc_otg_pcd_t * pcd)+{+	if (gadget_wrapper->driver && gadget_wrapper->driver->resume) {+		gadget_wrapper->driver->resume(&gadget_wrapper->gadget);+	}++	return 0;+}++static int _suspend(dwc_otg_pcd_t * pcd)+{+	if (gadget_wrapper->driver && gadget_wrapper->driver->suspend) {+		gadget_wrapper->driver->suspend(&gadget_wrapper->gadget);+	}+	return 0;+}++/**+ * This function updates the otg values in the gadget structure.+ */+static int _hnp_changed(dwc_otg_pcd_t * pcd)+{++	if (!gadget_wrapper->gadget.is_otg)+		return 0;++	gadget_wrapper->gadget.b_hnp_enable = get_b_hnp_enable(pcd);+	gadget_wrapper->gadget.a_hnp_support = get_a_hnp_support(pcd);+	gadget_wrapper->gadget.a_alt_hnp_support = get_a_alt_hnp_support(pcd);+	return 0;+}++static int _reset(dwc_otg_pcd_t * pcd)+{+	return 0;+}++#ifdef DWC_UTE_CFI+static int _cfi_setup(dwc_otg_pcd_t * pcd, void *cfi_req)+{+	int retval = -DWC_E_INVALID;+	if (gadget_wrapper->driver->cfi_feature_setup) {+		retval =+		    gadget_wrapper->driver->+		    cfi_feature_setup(&gadget_wrapper->gadget,+				      (struct cfi_usb_ctrlrequest *)cfi_req);+	}++	return retval;+}+#endif++static const struct dwc_otg_pcd_function_ops fops = {+	.complete = _complete,+#ifdef DWC_EN_ISOC+	.isoc_complete = _isoc_complete,+#endif+	.setup = _setup,+	.disconnect = _disconnect,+	.connect = _connect,+	.resume = _resume,+	.suspend = _suspend,+	.hnp_changed = _hnp_changed,+	.reset = _reset,+#ifdef DWC_UTE_CFI+	.cfi_setup = _cfi_setup,+#endif+#ifdef DWC_UTE_PER_IO+	.xisoc_complete = _xisoc_complete,+#endif+};++/**+ * This function is the top level PCD interrupt handler.+ */+static irqreturn_t dwc_otg_pcd_irq(int irq, void *dev)+{+	dwc_otg_pcd_t *pcd = dev;+	int32_t retval = IRQ_NONE;++	retval = dwc_otg_pcd_handle_intr(pcd);+	if (retval != 0) {+		S3C2410X_CLEAR_EINTPEND();+	}+	return IRQ_RETVAL(retval);+}++/**+ * This function initialized the usb_ep structures to there default+ * state.+ *+ * @param d Pointer on gadget_wrapper.+ */+void gadget_add_eps(struct gadget_wrapper *d)+{+	static const char *names[] = {++		"ep0",+		"ep1in",+		"ep2in",+		"ep3in",+		"ep4in",+		"ep5in",+		"ep6in",+		"ep7in",+		"ep8in",+		"ep9in",+		"ep10in",+		"ep11in",+		"ep12in",+		"ep13in",+		"ep14in",+		"ep15in",+		"ep1out",+		"ep2out",+		"ep3out",+		"ep4out",+		"ep5out",+		"ep6out",+		"ep7out",+		"ep8out",+		"ep9out",+		"ep10out",+		"ep11out",+		"ep12out",+		"ep13out",+		"ep14out",+		"ep15out"+	};++	int i;+	struct usb_ep *ep;+	int8_t dev_endpoints;++	DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__);++	INIT_LIST_HEAD(&d->gadget.ep_list);+	d->gadget.ep0 = &d->ep0;+	d->gadget.speed = USB_SPEED_UNKNOWN;++	INIT_LIST_HEAD(&d->gadget.ep0->ep_list);++	/**+	 * Initialize the EP0 structure.+	 */+	ep = &d->ep0;++	/* Init the usb_ep structure. */+	ep->name = names[0];+	ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;++	/**+	 * @todo NGS: What should the max packet size be set to+	 * here?  Before EP type is set?+	 */+	ep->maxpacket = MAX_PACKET_SIZE;+	dwc_otg_pcd_ep_enable(d->pcd, NULL, ep);++	list_add_tail(&ep->ep_list, &d->gadget.ep_list);++	/**+	 * Initialize the EP structures.+	 */+	dev_endpoints = d->pcd->core_if->dev_if->num_in_eps;++	for (i = 0; i < dev_endpoints; i++) {+		ep = &d->in_ep[i];++		/* Init the usb_ep structure. */+		ep->name = names[d->pcd->in_ep[i].dwc_ep.num];+		ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;++		/**+		 * @todo NGS: What should the max packet size be set to+		 * here?  Before EP type is set?+		 */+		ep->maxpacket = MAX_PACKET_SIZE;+		list_add_tail(&ep->ep_list, &d->gadget.ep_list);+	}++	dev_endpoints = d->pcd->core_if->dev_if->num_out_eps;++	for (i = 0; i < dev_endpoints; i++) {+		ep = &d->out_ep[i];++		/* Init the usb_ep structure. */+		ep->name = names[15 + d->pcd->out_ep[i].dwc_ep.num];+		ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;++		/**+		 * @todo NGS: What should the max packet size be set to+		 * here?  Before EP type is set?+		 */+		ep->maxpacket = MAX_PACKET_SIZE;++		list_add_tail(&ep->ep_list, &d->gadget.ep_list);+	}++	/* remove ep0 from the list.  There is a ep0 pointer. */+	list_del_init(&d->ep0.ep_list);++	d->ep0.maxpacket = MAX_EP0_SIZE;+}++/**+ * This function releases the Gadget device.+ * required by device_unregister().+ *+ * @todo Should this do something?	Should it free the PCD?+ */+static void dwc_otg_pcd_gadget_release(struct device *dev)+{+	DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev);+}++static struct gadget_wrapper *alloc_wrapper(dwc_bus_dev_t *_dev)+{+	static char pcd_name[] = "dwc_otg_pcd";+	dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);+	struct gadget_wrapper *d;+	int retval;++	d = DWC_ALLOC(sizeof(*d));+	if (d == NULL) {+		return NULL;+	}++	memset(d, 0, sizeof(*d));++	d->gadget.name = pcd_name;+	d->pcd = otg_dev->pcd;++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)+	strcpy(d->gadget.dev.bus_id, "gadget");+#else+	dev_set_name(&d->gadget.dev, "%s", "gadget");+#endif++	d->gadget.dev.parent = &_dev->dev;+	d->gadget.dev.release = dwc_otg_pcd_gadget_release;+	d->gadget.ops = &dwc_otg_pcd_ops;+	d->gadget.max_speed = dwc_otg_pcd_is_dualspeed(otg_dev->pcd) ? USB_SPEED_HIGH:USB_SPEED_FULL;+	d->gadget.is_otg = dwc_otg_pcd_is_otg(otg_dev->pcd);++	d->driver = 0;+	/* Register the gadget device */+	retval = device_register(&d->gadget.dev);+	if (retval != 0) {+		DWC_ERROR("device_register failed\n");+		DWC_FREE(d);+		return NULL;+	}++	return d;+}++static void free_wrapper(struct gadget_wrapper *d)+{+	if (d->driver) {+		/* should have been done already by driver model core */+		DWC_WARN("driver '%s' is still registered\n",+			 d->driver->driver.name);+		usb_gadget_unregister_driver(d->driver);+	}++	device_unregister(&d->gadget.dev);+	DWC_FREE(d);+}++/**+ * This function initialized the PCD portion of the driver.+ *+ */+int pcd_init(dwc_bus_dev_t *_dev)+{+	dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);+	int retval = 0;++	DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev=%p\n", __func__, _dev, otg_dev);++	otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if);++	if (!otg_dev->pcd) {+		DWC_ERROR("dwc_otg_pcd_init failed\n");+		return -ENOMEM;+	}++	otg_dev->pcd->otg_dev = otg_dev;+	gadget_wrapper = alloc_wrapper(_dev);++	/*+	 * Initialize EP structures+	 */+	gadget_add_eps(gadget_wrapper);+	/*+	 * Setup interupt handler+	 */+#ifdef PLATFORM_INTERFACE+	DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",+                    platform_get_irq(_dev, 0));+	retval = request_irq(platform_get_irq(_dev, 0), dwc_otg_pcd_irq,+			     IRQF_SHARED, gadget_wrapper->gadget.name,+			     otg_dev->pcd);+	if (retval != 0) {+		DWC_ERROR("request of irq%d failed\n",+                          platform_get_irq(_dev, 0));+		free_wrapper(gadget_wrapper);+		return -EBUSY;+	}+#else+	DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",+                    _dev->irq);+	retval = request_irq(_dev->irq, dwc_otg_pcd_irq,+			     IRQF_SHARED | IRQF_DISABLED,+			     gadget_wrapper->gadget.name, otg_dev->pcd);+	if (retval != 0) {+		DWC_ERROR("request of irq%d failed\n", _dev->irq);+		free_wrapper(gadget_wrapper);+		return -EBUSY;+	}+#endif++	dwc_otg_pcd_start(gadget_wrapper->pcd, &fops);++	return retval;+}++/**+ * Cleanup the PCD.+ */+void pcd_remove(dwc_bus_dev_t *_dev)+{+	dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);+	dwc_otg_pcd_t *pcd = otg_dev->pcd;++	DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev);++	/*+	 * Free the IRQ+	 */+#ifdef PLATFORM_INTERFACE+	free_irq(platform_get_irq(_dev, 0), pcd);+#else+	free_irq(_dev->irq, pcd);+#endif+	dwc_otg_pcd_remove(otg_dev->pcd);+	free_wrapper(gadget_wrapper);+	otg_dev->pcd = 0;+}++/**+ * This function registers a gadget driver with the PCD.+ *+ * When a driver is successfully registered, it will receive control+ * requests including set_configuration(), which enables non-control+ * requests.  then usb traffic follows until a disconnect is reported.+ * then a host may connect again, or the driver might get unbound.+ *+ * @param driver The driver being registered+ * @param bind The bind function of gadget driver+ */++int usb_gadget_probe_driver(struct usb_gadget_driver *driver)+{+	int retval;++	DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n",+		    driver->driver.name);++	if (!driver || driver->max_speed == USB_SPEED_UNKNOWN ||+	    !driver->bind ||+	    !driver->unbind || !driver->disconnect || !driver->setup) {+		DWC_DEBUGPL(DBG_PCDV, "EINVAL\n");+		return -EINVAL;+	}+	if (gadget_wrapper == 0) {+		DWC_DEBUGPL(DBG_PCDV, "ENODEV\n");+		return -ENODEV;+	}+	if (gadget_wrapper->driver != 0) {+		DWC_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", gadget_wrapper->driver);+		return -EBUSY;+	}++	/* hook up the driver */+	gadget_wrapper->driver = driver;+	gadget_wrapper->gadget.dev.driver = &driver->driver;++	DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name);+	retval = driver->bind(&gadget_wrapper->gadget, gadget_wrapper->driver);+	if (retval) {+		DWC_ERROR("bind to driver %s --> error %d\n",+			  driver->driver.name, retval);+		gadget_wrapper->driver = 0;+		gadget_wrapper->gadget.dev.driver = 0;+		return retval;+	}+	DWC_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n",+		    driver->driver.name);+	return 0;+}+EXPORT_SYMBOL(usb_gadget_probe_driver);++/**+ * This function unregisters a gadget driver+ *+ * @param driver The driver being unregistered+ */+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)+{+	//DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _driver);++	if (gadget_wrapper == 0) {+		DWC_DEBUGPL(DBG_ANY, "%s Return(%d): s_pcd==0\n", __func__,+			    -ENODEV);+		return -ENODEV;+	}+	if (driver == 0 || driver != gadget_wrapper->driver) {+		DWC_DEBUGPL(DBG_ANY, "%s Return(%d): driver?\n", __func__,+			    -EINVAL);+		return -EINVAL;+	}++	driver->unbind(&gadget_wrapper->gadget);+	gadget_wrapper->driver = 0;++	DWC_DEBUGPL(DBG_ANY, "unregistered driver '%s'\n", driver->driver.name);+	return 0;+}++EXPORT_SYMBOL(usb_gadget_unregister_driver);++#endif /* DWC_HOST_ONLY */diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_regs.h--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/dwc_otg_regs.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/dwc_otg_regs.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,2550 @@+/* ==========================================================================+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $+ * $Revision: #98 $+ * $Date: 2012/08/10 $+ * $Change: 2047372 $+ *+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless+ * otherwise expressly agreed to in writing between Synopsys and you.+ *+ * The Software IS NOT an item of Licensed Software or Licensed Product under+ * any End User Software License Agreement or Agreement for Licensed Product+ * with Synopsys or any supplement thereto. You are permitted to use and+ * redistribute this Software in source and binary forms, with or without+ * modification, provided that redistributions of source code must retain this+ * notice. You may not view, use, disclose, copy or distribute this file or+ * any information contained herein except pursuant to this license grant from+ * Synopsys. If you do not agree with this notice, including the disclaimer+ * below, then you are not authorized to use the Software.+ *+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+ * DAMAGE.+ * ========================================================================== */++#ifndef __DWC_OTG_REGS_H__+#define __DWC_OTG_REGS_H__++#include "dwc_otg_core_if.h"++/**+ * @file+ *+ * This file contains the data structures for accessing the DWC_otg core registers.+ *+ * The application interfaces with the HS OTG core by reading from and+ * writing to the Control and Status Register (CSR) space through the+ * AHB Slave interface. These registers are 32 bits wide, and the+ * addresses are 32-bit-block aligned.+ * CSRs are classified as follows:+ * - Core Global Registers+ * - Device Mode Registers+ * - Device Global Registers+ * - Device Endpoint Specific Registers+ * - Host Mode Registers+ * - Host Global Registers+ * - Host Port CSRs+ * - Host Channel Specific Registers+ *+ * Only the Core Global registers can be accessed in both Device and+ * Host modes. When the HS OTG core is operating in one mode, either+ * Device or Host, the application must not access registers from the+ * other mode. When the core switches from one mode to another, the+ * registers in the new mode of operation must be reprogrammed as they+ * would be after a power-on reset.+ */++/****************************************************************************/+/** DWC_otg Core registers .+ * The dwc_otg_core_global_regs structure defines the size+ * and relative field offsets for the Core Global registers.+ */+typedef struct dwc_otg_core_global_regs {+	/** OTG Control and Status Register.  <i>Offset: 000h</i> */+	volatile uint32_t gotgctl;+	/** OTG Interrupt Register.	 <i>Offset: 004h</i> */+	volatile uint32_t gotgint;+	/**Core AHB Configuration Register.	 <i>Offset: 008h</i> */+	volatile uint32_t gahbcfg;++#define DWC_GLBINTRMASK		0x0001+#define DWC_DMAENABLE		0x0020+#define DWC_NPTXEMPTYLVL_EMPTY	0x0080+#define DWC_NPTXEMPTYLVL_HALFEMPTY	0x0000+#define DWC_PTXEMPTYLVL_EMPTY	0x0100+#define DWC_PTXEMPTYLVL_HALFEMPTY	0x0000++	/**Core USB Configuration Register.	 <i>Offset: 00Ch</i> */+	volatile uint32_t gusbcfg;+	/**Core Reset Register.	 <i>Offset: 010h</i> */+	volatile uint32_t grstctl;+	/**Core Interrupt Register.	 <i>Offset: 014h</i> */+	volatile uint32_t gintsts;+	/**Core Interrupt Mask Register.  <i>Offset: 018h</i> */+	volatile uint32_t gintmsk;+	/**Receive Status Queue Read Register (Read Only).	<i>Offset: 01Ch</i> */+	volatile uint32_t grxstsr;+	/**Receive Status Queue Read & POP Register (Read Only).  <i>Offset: 020h</i>*/+	volatile uint32_t grxstsp;+	/**Receive FIFO Size Register.	<i>Offset: 024h</i> */+	volatile uint32_t grxfsiz;+	/**Non Periodic Transmit FIFO Size Register.  <i>Offset: 028h</i> */+	volatile uint32_t gnptxfsiz;+	/**Non Periodic Transmit FIFO/Queue Status Register (Read+	 * Only). <i>Offset: 02Ch</i> */+	volatile uint32_t gnptxsts;+	/**I2C Access Register.	 <i>Offset: 030h</i> */+	volatile uint32_t gi2cctl;+	/**PHY Vendor Control Register.	 <i>Offset: 034h</i> */+	volatile uint32_t gpvndctl;+	/**General Purpose Input/Output Register.  <i>Offset: 038h</i> */+	volatile uint32_t ggpio;+	/**User ID Register.  <i>Offset: 03Ch</i> */+	volatile uint32_t guid;+	/**Synopsys ID Register (Read Only).  <i>Offset: 040h</i> */+	volatile uint32_t gsnpsid;+	/**User HW Config1 Register (Read Only).  <i>Offset: 044h</i> */+	volatile uint32_t ghwcfg1;+	/**User HW Config2 Register (Read Only).  <i>Offset: 048h</i> */+	volatile uint32_t ghwcfg2;+#define DWC_SLAVE_ONLY_ARCH 0+#define DWC_EXT_DMA_ARCH 1+#define DWC_INT_DMA_ARCH 2++#define DWC_MODE_HNP_SRP_CAPABLE	0+#define DWC_MODE_SRP_ONLY_CAPABLE	1+#define DWC_MODE_NO_HNP_SRP_CAPABLE		2+#define DWC_MODE_SRP_CAPABLE_DEVICE		3+#define DWC_MODE_NO_SRP_CAPABLE_DEVICE	4+#define DWC_MODE_SRP_CAPABLE_HOST	5+#define DWC_MODE_NO_SRP_CAPABLE_HOST	6++	/**User HW Config3 Register (Read Only).  <i>Offset: 04Ch</i> */+	volatile uint32_t ghwcfg3;+	/**User HW Config4 Register (Read Only).  <i>Offset: 050h</i>*/+	volatile uint32_t ghwcfg4;+	/** Core LPM Configuration register <i>Offset: 054h</i>*/+	volatile uint32_t glpmcfg;+	/** Global PowerDn Register <i>Offset: 058h</i> */+	volatile uint32_t gpwrdn;+	/** Global DFIFO SW Config Register  <i>Offset: 05Ch</i> */+	volatile uint32_t gdfifocfg;+	/** ADP Control Register  <i>Offset: 060h</i> */+	volatile uint32_t adpctl;+	/** Reserved  <i>Offset: 064h-0FFh</i> */+	volatile uint32_t reserved39[39];+	/** Host Periodic Transmit FIFO Size Register. <i>Offset: 100h</i> */+	volatile uint32_t hptxfsiz;+	/** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled,+		otherwise Device Transmit FIFO#n Register.+	 * <i>Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15).</i> */+	volatile uint32_t dtxfsiz[15];+} dwc_otg_core_global_regs_t;++/**+ * This union represents the bit fields of the Core OTG Control+ * and Status Register (GOTGCTL).  Set the bits using the bit+ * fields then write the <i>d32</i> value to the register.+ */+typedef union gotgctl_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned sesreqscs:1;+		unsigned sesreq:1;+		unsigned vbvalidoven:1;+		unsigned vbvalidovval:1;+		unsigned avalidoven:1;+		unsigned avalidovval:1;+		unsigned bvalidoven:1;+		unsigned bvalidovval:1;+		unsigned hstnegscs:1;+		unsigned hnpreq:1;+		unsigned hstsethnpen:1;+		unsigned devhnpen:1;+		unsigned reserved12_15:4;+		unsigned conidsts:1;+		unsigned dbnctime:1;+		unsigned asesvld:1;+		unsigned bsesvld:1;+		unsigned otgver:1;+		unsigned reserved1:1;+		unsigned multvalidbc:5;+		unsigned chirpen:1;+		unsigned reserved28_31:4;+	} b;+} gotgctl_data_t;++/**+ * This union represents the bit fields of the Core OTG Interrupt Register+ * (GOTGINT).  Set/clear the bits using the bit fields then write the <i>d32</i>+ * value to the register.+ */+typedef union gotgint_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		/** Current Mode */+		unsigned reserved0_1:2;++		/** Session End Detected */+		unsigned sesenddet:1;++		unsigned reserved3_7:5;++		/** Session Request Success Status Change */+		unsigned sesreqsucstschng:1;+		/** Host Negotiation Success Status Change */+		unsigned hstnegsucstschng:1;++		unsigned reserved10_16:7;++		/** Host Negotiation Detected */+		unsigned hstnegdet:1;+		/** A-Device Timeout Change */+		unsigned adevtoutchng:1;+		/** Debounce Done */+		unsigned debdone:1;+		/** Multi-Valued input changed */+		unsigned mvic:1;++		unsigned reserved31_21:11;++	} b;+} gotgint_data_t;++/**+ * This union represents the bit fields of the Core AHB Configuration+ * Register (GAHBCFG). Set/clear the bits using the bit fields then+ * write the <i>d32</i> value to the register.+ */+typedef union gahbcfg_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned glblintrmsk:1;+#define DWC_GAHBCFG_GLBINT_ENABLE		1++		unsigned hburstlen:4;+#define DWC_GAHBCFG_INT_DMA_BURST_SINGLE	0+#define DWC_GAHBCFG_INT_DMA_BURST_INCR		1+#define DWC_GAHBCFG_INT_DMA_BURST_INCR4		3+#define DWC_GAHBCFG_INT_DMA_BURST_INCR8		5+#define DWC_GAHBCFG_INT_DMA_BURST_INCR16	7++		unsigned dmaenable:1;+#define DWC_GAHBCFG_DMAENABLE			1+		unsigned reserved:1;+		unsigned nptxfemplvl_txfemplvl:1;+		unsigned ptxfemplvl:1;+#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY		1+#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY	0+		unsigned reserved9_20:12;+		unsigned remmemsupp:1;+		unsigned notialldmawrit:1;+		unsigned ahbsingle:1;+		unsigned reserved24_31:8;+	} b;+} gahbcfg_data_t;++/**+ * This union represents the bit fields of the Core USB Configuration+ * Register (GUSBCFG). Set the bits using the bit fields then write+ * the <i>d32</i> value to the register.+ */+typedef union gusbcfg_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned toutcal:3;+		unsigned phyif:1;+		unsigned ulpi_utmi_sel:1;+		unsigned fsintf:1;+		unsigned physel:1;+		unsigned ddrsel:1;+		unsigned srpcap:1;+		unsigned hnpcap:1;+		unsigned usbtrdtim:4;+		unsigned reserved1:1;+		unsigned phylpwrclksel:1;+		unsigned otgutmifssel:1;+		unsigned ulpi_fsls:1;+		unsigned ulpi_auto_res:1;+		unsigned ulpi_clk_sus_m:1;+		unsigned ulpi_ext_vbus_drv:1;+		unsigned ulpi_int_vbus_indicator:1;+		unsigned term_sel_dl_pulse:1;+		unsigned indicator_complement:1;+		unsigned indicator_pass_through:1;+		unsigned ulpi_int_prot_dis:1;+		unsigned ic_usb_cap:1;+		unsigned ic_traffic_pull_remove:1;+		unsigned tx_end_delay:1;+		unsigned force_host_mode:1;+		unsigned force_dev_mode:1;+		unsigned reserved31:1;+	} b;+} gusbcfg_data_t;++/**+ * This union represents the bit fields of the Core Reset Register+ * (GRSTCTL).  Set/clear the bits using the bit fields then write the+ * <i>d32</i> value to the register.+ */+typedef union grstctl_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		/** Core Soft Reset (CSftRst) (Device and Host)+		 *+		 * The application can flush the control logic in the+		 * entire core using this bit. This bit resets the+		 * pipelines in the AHB Clock domain as well as the+		 * PHY Clock domain.+		 *+		 * The state machines are reset to an IDLE state, the+		 * control bits in the CSRs are cleared, all the+		 * transmit FIFOs and the receive FIFO are flushed.+		 *+		 * The status mask bits that control the generation of+		 * the interrupt, are cleared, to clear the+		 * interrupt. The interrupt status bits are not+		 * cleared, so the application can get the status of+		 * any events that occurred in the core after it has+		 * set this bit.+		 *+		 * Any transactions on the AHB are terminated as soon+		 * as possible following the protocol. Any+		 * transactions on the USB are terminated immediately.+		 *+		 * The configuration settings in the CSRs are+		 * unchanged, so the software doesn't have to+		 * reprogram these registers (Device+		 * Configuration/Host Configuration/Core System+		 * Configuration/Core PHY Configuration).+		 *+		 * The application can write to this bit, any time it+		 * wants to reset the core. This is a self clearing+		 * bit and the core clears this bit after all the+		 * necessary logic is reset in the core, which may+		 * take several clocks, depending on the current state+		 * of the core.+		 */+		unsigned csftrst:1;+		/** Hclk Soft Reset+		 *+		 * The application uses this bit to reset the control logic in+		 * the AHB clock domain. Only AHB clock domain pipelines are+		 * reset.+		 */+		unsigned hsftrst:1;+		/** Host Frame Counter Reset (Host Only)<br>+		 *+		 * The application can reset the (micro)frame number+		 * counter inside the core, using this bit. When the+		 * (micro)frame counter is reset, the subsequent SOF+		 * sent out by the core, will have a (micro)frame+		 * number of 0.+		 */+		unsigned hstfrm:1;+		/** In Token Sequence Learning Queue Flush+		 * (INTknQFlsh) (Device Only)+		 */+		unsigned intknqflsh:1;+		/** RxFIFO Flush (RxFFlsh) (Device and Host)+		 *+		 * The application can flush the entire Receive FIFO+		 * using this bit. The application must first+		 * ensure that the core is not in the middle of a+		 * transaction. The application should write into+		 * this bit, only after making sure that neither the+		 * DMA engine is reading from the RxFIFO nor the MAC+		 * is writing the data in to the FIFO. The+		 * application should wait until the bit is cleared+		 * before performing any other operations. This bit+		 * will takes 8 clocks (slowest of PHY or AHB clock)+		 * to clear.+		 */+		unsigned rxfflsh:1;+		/** TxFIFO Flush (TxFFlsh) (Device and Host).+		 *+		 * This bit is used to selectively flush a single or+		 * all transmit FIFOs. The application must first+		 * ensure that the core is not in the middle of a+		 * transaction. The application should write into+		 * this bit, only after making sure that neither the+		 * DMA engine is writing into the TxFIFO nor the MAC+		 * is reading the data out of the FIFO. The+		 * application should wait until the core clears this+		 * bit, before performing any operations. This bit+		 * will takes 8 clocks (slowest of PHY or AHB clock)+		 * to clear.+		 */+		unsigned txfflsh:1;++		/** TxFIFO Number (TxFNum) (Device and Host).+		 *+		 * This is the FIFO number which needs to be flushed,+		 * using the TxFIFO Flush bit. This field should not+		 * be changed until the TxFIFO Flush bit is cleared by+		 * the core.+		 *	 - 0x0 : Non Periodic TxFIFO Flush+		 *	 - 0x1 : Periodic TxFIFO #1 Flush in device mode+		 *	   or Periodic TxFIFO in host mode+		 *	 - 0x2 : Periodic TxFIFO #2 Flush in device mode.+		 *	 - ...+		 *	 - 0xF : Periodic TxFIFO #15 Flush in device mode+		 *	 - 0x10: Flush all the Transmit NonPeriodic and+		 *	   Transmit Periodic FIFOs in the core+		 */+		unsigned txfnum:5;+		/** Reserved */+		unsigned reserved11_29:19;+		/** DMA Request Signal.	 Indicated DMA request is in+		 * probress. Used for debug purpose. */+		unsigned dmareq:1;+		/** AHB Master Idle.  Indicates the AHB Master State+		 * Machine is in IDLE condition. */+		unsigned ahbidle:1;+	} b;+} grstctl_t;++/**+ * This union represents the bit fields of the Core Interrupt Mask+ * Register (GINTMSK). Set/clear the bits using the bit fields then+ * write the <i>d32</i> value to the register.+ */+typedef union gintmsk_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned reserved0:1;+		unsigned modemismatch:1;+		unsigned otgintr:1;+		unsigned sofintr:1;+		unsigned rxstsqlvl:1;+		unsigned nptxfempty:1;+		unsigned ginnakeff:1;+		unsigned goutnakeff:1;+		unsigned ulpickint:1;+		unsigned i2cintr:1;+		unsigned erlysuspend:1;+		unsigned usbsuspend:1;+		unsigned usbreset:1;+		unsigned enumdone:1;+		unsigned isooutdrop:1;+		unsigned eopframe:1;+		unsigned restoredone:1;+		unsigned epmismatch:1;+		unsigned inepintr:1;+		unsigned outepintr:1;+		unsigned incomplisoin:1;+		unsigned incomplisoout:1;+		unsigned fetsusp:1;+		unsigned resetdet:1;+		unsigned portintr:1;+		unsigned hcintr:1;+		unsigned ptxfempty:1;+		unsigned lpmtranrcvd:1;+		unsigned conidstschng:1;+		unsigned disconnect:1;+		unsigned sessreqintr:1;+		unsigned wkupintr:1;+	} b;+} gintmsk_data_t;+/**+ * This union represents the bit fields of the Core Interrupt Register+ * (GINTSTS).  Set/clear the bits using the bit fields then write the+ * <i>d32</i> value to the register.+ */+typedef union gintsts_data {+	/** raw register data */+	uint32_t d32;+#define DWC_SOF_INTR_MASK 0x0008+	/** register bits */+	struct {+#define DWC_HOST_MODE 1+		unsigned curmode:1;+		unsigned modemismatch:1;+		unsigned otgintr:1;+		unsigned sofintr:1;+		unsigned rxstsqlvl:1;+		unsigned nptxfempty:1;+		unsigned ginnakeff:1;+		unsigned goutnakeff:1;+		unsigned ulpickint:1;+		unsigned i2cintr:1;+		unsigned erlysuspend:1;+		unsigned usbsuspend:1;+		unsigned usbreset:1;+		unsigned enumdone:1;+		unsigned isooutdrop:1;+		unsigned eopframe:1;+		unsigned restoredone:1;+		unsigned epmismatch:1;+		unsigned inepint:1;+		unsigned outepintr:1;+		unsigned incomplisoin:1;+		unsigned incomplisoout:1;+		unsigned fetsusp:1;+		unsigned resetdet:1;+		unsigned portintr:1;+		unsigned hcintr:1;+		unsigned ptxfempty:1;+		unsigned lpmtranrcvd:1;+		unsigned conidstschng:1;+		unsigned disconnect:1;+		unsigned sessreqintr:1;+		unsigned wkupintr:1;+	} b;+} gintsts_data_t;++/**+ * This union represents the bit fields in the Device Receive Status Read and+ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>+ * element then read out the bits using the <i>b</i>it elements.+ */+typedef union device_grxsts_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned epnum:4;+		unsigned bcnt:11;+		unsigned dpid:2;++#define DWC_STS_DATA_UPDT		0x2	// OUT Data Packet+#define DWC_STS_XFER_COMP		0x3	// OUT Data Transfer Complete++#define DWC_DSTS_GOUT_NAK		0x1	// Global OUT NAK+#define DWC_DSTS_SETUP_COMP		0x4	// Setup Phase Complete+#define DWC_DSTS_SETUP_UPDT 0x6	// SETUP Packet+		unsigned pktsts:4;+		unsigned fn:4;+		unsigned reserved25_31:7;+	} b;+} device_grxsts_data_t;++/**+ * This union represents the bit fields in the Host Receive Status Read and+ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>+ * element then read out the bits using the <i>b</i>it elements.+ */+typedef union host_grxsts_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned chnum:4;+		unsigned bcnt:11;+		unsigned dpid:2;++		unsigned pktsts:4;+#define DWC_GRXSTS_PKTSTS_IN			  0x2+#define DWC_GRXSTS_PKTSTS_IN_XFER_COMP	  0x3+#define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5+#define DWC_GRXSTS_PKTSTS_CH_HALTED		  0x7++		unsigned reserved21_31:11;+	} b;+} host_grxsts_data_t;++/**+ * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ,+ * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the <i>d32</i> element+ * then read out the bits using the <i>b</i>it elements.+ */+typedef union fifosize_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned startaddr:16;+		unsigned depth:16;+	} b;+} fifosize_data_t;++/**+ * This union represents the bit fields in the Non-Periodic Transmit+ * FIFO/Queue Status Register (GNPTXSTS). Read the register into the+ * <i>d32</i> element then read out the bits using the <i>b</i>it+ * elements.+ */+typedef union gnptxsts_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned nptxfspcavail:16;+		unsigned nptxqspcavail:8;+		/** Top of the Non-Periodic Transmit Request Queue+		 *	- bit 24 - Terminate (Last entry for the selected+		 *	  channel/EP)+		 *	- bits 26:25 - Token Type+		 *	  - 2'b00 - IN/OUT+		 *	  - 2'b01 - Zero Length OUT+		 *	  - 2'b10 - PING/Complete Split+		 *	  - 2'b11 - Channel Halt+		 *	- bits 30:27 - Channel/EP Number+		 */+		unsigned nptxqtop_terminate:1;+		unsigned nptxqtop_token:2;+		unsigned nptxqtop_chnep:4;+		unsigned reserved:1;+	} b;+} gnptxsts_data_t;++/**+ * This union represents the bit fields in the Transmit+ * FIFO Status Register (DTXFSTS). Read the register into the+ * <i>d32</i> element then read out the bits using the <i>b</i>it+ * elements.+ */+typedef union dtxfsts_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned txfspcavail:16;+		unsigned reserved:16;+	} b;+} dtxfsts_data_t;++/**+ * This union represents the bit fields in the I2C Control Register+ * (I2CCTL). Read the register into the <i>d32</i> element then read out the+ * bits using the <i>b</i>it elements.+ */+typedef union gi2cctl_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned rwdata:8;+		unsigned regaddr:8;+		unsigned addr:7;+		unsigned i2cen:1;+		unsigned ack:1;+		unsigned i2csuspctl:1;+		unsigned i2cdevaddr:2;+		unsigned i2cdatse0:1;+		unsigned reserved:1;+		unsigned rw:1;+		unsigned bsydne:1;+	} b;+} gi2cctl_data_t;++/**+ * This union represents the bit fields in the PHY Vendor Control Register+ * (GPVNDCTL). Read the register into the <i>d32</i> element then read out the+ * bits using the <i>b</i>it elements.+ */+typedef union gpvndctl_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned regdata:8;+		unsigned vctrl:8;+		unsigned regaddr16_21:6;+		unsigned regwr:1;+		unsigned reserved23_24:2;+		unsigned newregreq:1;+		unsigned vstsbsy:1;+		unsigned vstsdone:1;+		unsigned reserved28_30:3;+		unsigned disulpidrvr:1;+	} b;+} gpvndctl_data_t;++/**+ * This union represents the bit fields in the General Purpose+ * Input/Output Register (GGPIO).+ * Read the register into the <i>d32</i> element then read out the+ * bits using the <i>b</i>it elements.+ */+typedef union ggpio_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned gpi:16;+		unsigned gpo:16;+	} b;+} ggpio_data_t;++/**+ * This union represents the bit fields in the User ID Register+ * (GUID). Read the register into the <i>d32</i> element then read out the+ * bits using the <i>b</i>it elements.+ */+typedef union guid_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned rwdata:32;+	} b;+} guid_data_t;++/**+ * This union represents the bit fields in the Synopsys ID Register+ * (GSNPSID). Read the register into the <i>d32</i> element then read out the+ * bits using the <i>b</i>it elements.+ */+typedef union gsnpsid_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned rwdata:32;+	} b;+} gsnpsid_data_t;++/**+ * This union represents the bit fields in the User HW Config1+ * Register.  Read the register into the <i>d32</i> element then read+ * out the bits using the <i>b</i>it elements.+ */+typedef union hwcfg1_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned ep_dir0:2;+		unsigned ep_dir1:2;+		unsigned ep_dir2:2;+		unsigned ep_dir3:2;+		unsigned ep_dir4:2;+		unsigned ep_dir5:2;+		unsigned ep_dir6:2;+		unsigned ep_dir7:2;+		unsigned ep_dir8:2;+		unsigned ep_dir9:2;+		unsigned ep_dir10:2;+		unsigned ep_dir11:2;+		unsigned ep_dir12:2;+		unsigned ep_dir13:2;+		unsigned ep_dir14:2;+		unsigned ep_dir15:2;+	} b;+} hwcfg1_data_t;++/**+ * This union represents the bit fields in the User HW Config2+ * Register.  Read the register into the <i>d32</i> element then read+ * out the bits using the <i>b</i>it elements.+ */+typedef union hwcfg2_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		/* GHWCFG2 */+		unsigned op_mode:3;+#define DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0+#define DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1+#define DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2+#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3+#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4+#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5+#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6++		unsigned architecture:2;+		unsigned point2point:1;+		unsigned hs_phy_type:2;+#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0+#define DWC_HWCFG2_HS_PHY_TYPE_UTMI 1+#define DWC_HWCFG2_HS_PHY_TYPE_ULPI 2+#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3++		unsigned fs_phy_type:2;+		unsigned num_dev_ep:4;+		unsigned num_host_chan:4;+		unsigned perio_ep_supported:1;+		unsigned dynamic_fifo:1;+		unsigned multi_proc_int:1;+		unsigned reserved21:1;+		unsigned nonperio_tx_q_depth:2;+		unsigned host_perio_tx_q_depth:2;+		unsigned dev_token_q_depth:5;+		unsigned otg_enable_ic_usb:1;+	} b;+} hwcfg2_data_t;++/**+ * This union represents the bit fields in the User HW Config3+ * Register.  Read the register into the <i>d32</i> element then read+ * out the bits using the <i>b</i>it elements.+ */+typedef union hwcfg3_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		/* GHWCFG3 */+		unsigned xfer_size_cntr_width:4;+		unsigned packet_size_cntr_width:3;+		unsigned otg_func:1;+		unsigned i2c:1;+		unsigned vendor_ctrl_if:1;+		unsigned optional_features:1;+		unsigned synch_reset_type:1;+		unsigned adp_supp:1;+		unsigned otg_enable_hsic:1;+		unsigned bc_support:1;+		unsigned otg_lpm_en:1;+		unsigned dfifo_depth:16;+	} b;+} hwcfg3_data_t;++/**+ * This union represents the bit fields in the User HW Config4+ * Register.  Read the register into the <i>d32</i> element then read+ * out the bits using the <i>b</i>it elements.+ */+typedef union hwcfg4_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned num_dev_perio_in_ep:4;+		unsigned power_optimiz:1;+		unsigned min_ahb_freq:1;+		unsigned hiber:1;+		unsigned xhiber:1;+		unsigned reserved:6;+		unsigned utmi_phy_data_width:2;+		unsigned num_dev_mode_ctrl_ep:4;+		unsigned iddig_filt_en:1;+		unsigned vbus_valid_filt_en:1;+		unsigned a_valid_filt_en:1;+		unsigned b_valid_filt_en:1;+		unsigned session_end_filt_en:1;+		unsigned ded_fifo_en:1;+		unsigned num_in_eps:4;+		unsigned desc_dma:1;+		unsigned desc_dma_dyn:1;+	} b;+} hwcfg4_data_t;++/**+ * This union represents the bit fields of the Core LPM Configuration+ * Register (GLPMCFG). Set the bits using bit fields then write+ * the <i>d32</i> value to the register.+ */+typedef union glpmctl_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		/** LPM-Capable (LPMCap) (Device and Host)+		 * The application uses this bit to control+		 * the DWC_otg core LPM capabilities.+		 */+		unsigned lpm_cap_en:1;+		/** LPM response programmed by application (AppL1Res) (Device)+		 * Handshake response to LPM token pre-programmed+		 * by device application software.+		 */+		unsigned appl_resp:1;+		/** Host Initiated Resume Duration (HIRD) (Device and Host)+		 * In Host mode this field indicates the value of HIRD+		 * to be sent in an LPM transaction.+		 * In Device mode this field is updated with the+		 * Received LPM Token HIRD bmAttribute+		 * when an ACK/NYET/STALL response is sent+		 * to an LPM transaction.+		 */+		unsigned hird:4;+		/** RemoteWakeEnable (bRemoteWake) (Device and Host)+		 * In Host mode this bit indicates the value of remote+		 * wake up to be sent in wIndex field of LPM transaction.+		 * In Device mode this field is updated with the+		 * Received LPM Token bRemoteWake bmAttribute+		 * when an ACK/NYET/STALL response is sent+		 * to an LPM transaction.+		 */+		unsigned rem_wkup_en:1;+		/** Enable utmi_sleep_n (EnblSlpM) (Device and Host)+		 * The application uses this bit to control+		 * the utmi_sleep_n assertion to the PHY when in L1 state.+		 */+		unsigned en_utmi_sleep:1;+		/** HIRD Threshold (HIRD_Thres) (Device and Host)+		 */+		unsigned hird_thres:5;+		/** LPM Response (CoreL1Res) (Device and Host)+		 * In Host mode this bit contains handsake response to+		 * LPM transaction.+		 * In Device mode the response of the core to+		 * LPM transaction received is reflected in these two bits.+			- 0x0 : ERROR (No handshake response)+			- 0x1 : STALL+			- 0x2 : NYET+			- 0x3 : ACK+		 */+		unsigned lpm_resp:2;+		/** Port Sleep Status (SlpSts) (Device and Host)+		 * This bit is set as long as a Sleep condition+		 * is present on the USB bus.+		 */+		unsigned prt_sleep_sts:1;+		/** Sleep State Resume OK (L1ResumeOK) (Device and Host)+		 * Indicates that the application or host+		 * can start resume from Sleep state.+		 */+		unsigned sleep_state_resumeok:1;+		/** LPM channel Index (LPM_Chnl_Indx) (Host)+		 * The channel number on which the LPM transaction+		 * has to be applied while sending+		 * an LPM transaction to the local device.+		 */+		unsigned lpm_chan_index:4;+		/** LPM Retry Count (LPM_Retry_Cnt) (Host)+		 * Number host retries that would be performed+		 * if the device response was not valid response.+		 */+		unsigned retry_count:3;+		/** Send LPM Transaction (SndLPM) (Host)+		 * When set by application software,+		 * an LPM transaction containing two tokens+		 * is sent.+		 */+		unsigned send_lpm:1;+		/** LPM Retry status (LPM_RetryCnt_Sts) (Host)+		 * Number of LPM Host Retries still remaining+		 * to be transmitted for the current LPM sequence+		 */+		unsigned retry_count_sts:3;+		unsigned reserved28_29:2;+		/** In host mode once this bit is set, the host+		 * configures to drive the HSIC Idle state on the bus.+		 * It then waits for the  device to initiate the Connect sequence.+		 * In device mode once this bit is set, the device waits for+		 * the HSIC Idle line state on the bus. Upon receving the Idle+		 * line state, it initiates the HSIC Connect sequence.+		 */+		unsigned hsic_connect:1;+		/** This bit overrides and functionally inverts+		 * the if_select_hsic input port signal.+		 */+		unsigned inv_sel_hsic:1;+	} b;+} glpmcfg_data_t;++/**+ * This union represents the bit fields of the Core ADP Timer, Control and+ * Status Register (ADPTIMCTLSTS). Set the bits using bit fields then write+ * the <i>d32</i> value to the register.+ */+typedef union adpctl_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		/** Probe Discharge (PRB_DSCHG)+		 *  These bits set the times for TADP_DSCHG.+		 *  These bits are defined as follows:+		 *  2'b00 - 4 msec+		 *  2'b01 - 8 msec+		 *  2'b10 - 16 msec+		 *  2'b11 - 32 msec+		 */+		unsigned prb_dschg:2;+		/** Probe Delta (PRB_DELTA)+		 *  These bits set the resolution for RTIM   value.+		 *  The bits are defined in units of 32 kHz clock cycles as follows:+		 *  2'b00  -  1 cycles+		 *  2'b01  -  2 cycles+		 *  2'b10 -  3 cycles+		 *  2'b11 - 4 cycles+		 *  For example if this value is chosen to 2'b01, it means that RTIM+		 *  increments for every 3(three) 32Khz clock cycles.+		 */+		unsigned prb_delta:2;+		/** Probe Period (PRB_PER)+		 *  These bits sets the TADP_PRD as shown in Figure 4 as follows:+		 *  2'b00  -  0.625 to 0.925 sec (typical 0.775 sec)+		 *  2'b01  -  1.25 to 1.85 sec (typical 1.55 sec)+		 *  2'b10  -  1.9 to 2.6 sec (typical 2.275 sec)+		 *  2'b11  -  Reserved+		 */+		unsigned prb_per:2;+		/** These bits capture the latest time it took for VBUS to ramp from+		 *  VADP_SINK to VADP_PRB.+		 *  0x000  -  1 cycles+		 *  0x001  -  2 cycles+		 *  0x002  -  3 cycles+		 *  etc+		 *  0x7FF  -  2048 cycles+		 *  A time of 1024 cycles at 32 kHz corresponds to a time of 32 msec.+		*/+		unsigned rtim:11;+		/** Enable Probe (EnaPrb)+		 *  When programmed to 1'b1, the core performs a probe operation.+		 *  This bit is valid only if OTG_Ver = 1'b1.+		 */+		unsigned enaprb:1;+		/** Enable Sense (EnaSns)+		 *  When programmed to 1'b1, the core performs a Sense operation.+		 *  This bit is valid only if OTG_Ver = 1'b1.+		 */+		unsigned enasns:1;+		/** ADP Reset (ADPRes)+		 *  When set, ADP controller is reset.+		 *  This bit is valid only if OTG_Ver = 1'b1.+		 */+		unsigned adpres:1;+		/** ADP Enable (ADPEn)+		 *  When set, the core performs either ADP probing or sensing+		 *  based on EnaPrb or EnaSns.+		 *  This bit is valid only if OTG_Ver = 1'b1.+		 */+		unsigned adpen:1;+		/** ADP Probe Interrupt (ADP_PRB_INT)+		 *  When this bit is set, it means that the VBUS+		 *  voltage is greater than VADP_PRB or VADP_PRB is reached.+		 *  This bit is valid only if OTG_Ver = 1'b1.+		 */+		unsigned adp_prb_int:1;+		/**+		 *  ADP Sense Interrupt (ADP_SNS_INT)+		 *  When this bit is set, it means that the VBUS voltage is greater than+		 *  VADP_SNS value or VADP_SNS is reached.+		 *  This bit is valid only if OTG_Ver = 1'b1.+		 */+		unsigned adp_sns_int:1;+		/** ADP Tomeout Interrupt (ADP_TMOUT_INT)+		 *  This bit is relevant only for an ADP probe.+		 *  When this bit is set, it means that the ramp time has+		 *  completed ie ADPCTL.RTIM has reached its terminal value+		 *  of 0x7FF.  This is a debug feature that allows software+		 *  to read the ramp time after each cycle.+		 *  This bit is valid only if OTG_Ver = 1'b1.+		 */+		unsigned adp_tmout_int:1;+		/** ADP Probe Interrupt Mask (ADP_PRB_INT_MSK)+		 *  When this bit is set, it unmasks the interrupt due to ADP_PRB_INT.+		 *  This bit is valid only if OTG_Ver = 1'b1.+		 */+		unsigned adp_prb_int_msk:1;+		/** ADP Sense Interrupt Mask (ADP_SNS_INT_MSK)+		 *  When this bit is set, it unmasks the interrupt due to ADP_SNS_INT.+		 *  This bit is valid only if OTG_Ver = 1'b1.+		 */+		unsigned adp_sns_int_msk:1;+		/** ADP Timoeout Interrupt Mask (ADP_TMOUT_MSK)+		 *  When this bit is set, it unmasks the interrupt due to ADP_TMOUT_INT.+		 *  This bit is valid only if OTG_Ver = 1'b1.+		 */+		unsigned adp_tmout_int_msk:1;+		/** Access Request+		 * 2'b00 - Read/Write Valid (updated by the core)+		 * 2'b01 - Read+		 * 2'b00 - Write+		 * 2'b00 - Reserved+		 */+		unsigned ar:2;+		 /** Reserved */+		unsigned reserved29_31:3;+	} b;+} adpctl_data_t;++////////////////////////////////////////////+// Device Registers+/**+ * Device Global Registers. <i>Offsets 800h-BFFh</i>+ *+ * The following structures define the size and relative field offsets+ * for the Device Mode Registers.+ *+ * <i>These registers are visible only in Device mode and must not be+ * accessed in Host mode, as the results are unknown.</i>+ */+typedef struct dwc_otg_dev_global_regs {+	/** Device Configuration Register. <i>Offset 800h</i> */+	volatile uint32_t dcfg;+	/** Device Control Register. <i>Offset: 804h</i> */+	volatile uint32_t dctl;+	/** Device Status Register (Read Only). <i>Offset: 808h</i> */+	volatile uint32_t dsts;+	/** Reserved. <i>Offset: 80Ch</i> */+	uint32_t unused;+	/** Device IN Endpoint Common Interrupt Mask+	 * Register. <i>Offset: 810h</i> */+	volatile uint32_t diepmsk;+	/** Device OUT Endpoint Common Interrupt Mask+	 * Register. <i>Offset: 814h</i> */+	volatile uint32_t doepmsk;+	/** Device All Endpoints Interrupt Register.  <i>Offset: 818h</i> */+	volatile uint32_t daint;+	/** Device All Endpoints Interrupt Mask Register.  <i>Offset:+	 * 81Ch</i> */+	volatile uint32_t daintmsk;+	/** Device IN Token Queue Read Register-1 (Read Only).+	 * <i>Offset: 820h</i> */+	volatile uint32_t dtknqr1;+	/** Device IN Token Queue Read Register-2 (Read Only).+	 * <i>Offset: 824h</i> */+	volatile uint32_t dtknqr2;+	/** Device VBUS	 discharge Register.  <i>Offset: 828h</i> */+	volatile uint32_t dvbusdis;+	/** Device VBUS Pulse Register.	 <i>Offset: 82Ch</i> */+	volatile uint32_t dvbuspulse;+	/** Device IN Token Queue Read Register-3 (Read Only). /+	 *	Device Thresholding control register (Read/Write)+	 * <i>Offset: 830h</i> */+	volatile uint32_t dtknqr3_dthrctl;+	/** Device IN Token Queue Read Register-4 (Read Only). /+	 *	Device IN EPs empty Inr. Mask Register (Read/Write)+	 * <i>Offset: 834h</i> */+	volatile uint32_t dtknqr4_fifoemptymsk;+	/** Device Each Endpoint Interrupt Register (Read Only). /+	 * <i>Offset: 838h</i> */+	volatile uint32_t deachint;+	/** Device Each Endpoint Interrupt mask Register (Read/Write). /+	 * <i>Offset: 83Ch</i> */+	volatile uint32_t deachintmsk;+	/** Device Each In Endpoint Interrupt mask Register (Read/Write). /+	 * <i>Offset: 840h</i> */+	volatile uint32_t diepeachintmsk[MAX_EPS_CHANNELS];+	/** Device Each Out Endpoint Interrupt mask Register (Read/Write). /+	 * <i>Offset: 880h</i> */+	volatile uint32_t doepeachintmsk[MAX_EPS_CHANNELS];+} dwc_otg_device_global_regs_t;++/**+ * This union represents the bit fields in the Device Configuration+ * Register.  Read the register into the <i>d32</i> member then+ * set/clear the bits using the <i>b</i>it elements.  Write the+ * <i>d32</i> member to the dcfg register.+ */+typedef union dcfg_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		/** Device Speed */+		unsigned devspd:2;+		/** Non Zero Length Status OUT Handshake */+		unsigned nzstsouthshk:1;+#define DWC_DCFG_SEND_STALL 1++		unsigned ena32khzs:1;+		/** Device Addresses */+		unsigned devaddr:7;+		/** Periodic Frame Interval */+		unsigned perfrint:2;+#define DWC_DCFG_FRAME_INTERVAL_80 0+#define DWC_DCFG_FRAME_INTERVAL_85 1+#define DWC_DCFG_FRAME_INTERVAL_90 2+#define DWC_DCFG_FRAME_INTERVAL_95 3++		/** Enable Device OUT NAK for bulk in DDMA mode */+		unsigned endevoutnak:1;++		unsigned reserved14_17:4;+		/** In Endpoint Mis-match count */+		unsigned epmscnt:5;+		/** Enable Descriptor DMA in Device mode */+		unsigned descdma:1;+		unsigned perschintvl:2;+		unsigned resvalid:6;+	} b;+} dcfg_data_t;++/**+ * This union represents the bit fields in the Device Control+ * Register.  Read the register into the <i>d32</i> member then+ * set/clear the bits using the <i>b</i>it elements.+ */+typedef union dctl_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		/** Remote Wakeup */+		unsigned rmtwkupsig:1;+		/** Soft Disconnect */+		unsigned sftdiscon:1;+		/** Global Non-Periodic IN NAK Status */+		unsigned gnpinnaksts:1;+		/** Global OUT NAK Status */+		unsigned goutnaksts:1;+		/** Test Control */+		unsigned tstctl:3;+		/** Set Global Non-Periodic IN NAK */+		unsigned sgnpinnak:1;+		/** Clear Global Non-Periodic IN NAK */+		unsigned cgnpinnak:1;+		/** Set Global OUT NAK */+		unsigned sgoutnak:1;+		/** Clear Global OUT NAK */+		unsigned cgoutnak:1;+		/** Power-On Programming Done */+		unsigned pwronprgdone:1;+		/** Reserved */+		unsigned reserved:1;+		/** Global Multi Count */+		unsigned gmc:2;+		/** Ignore Frame Number for ISOC EPs */+		unsigned ifrmnum:1;+		/** NAK on Babble */+		unsigned nakonbble:1;+		/** Enable Continue on BNA */+		unsigned encontonbna:1;++		unsigned reserved18_31:14;+	} b;+} dctl_data_t;++/**+ * This union represents the bit fields in the Device Status+ * Register.  Read the register into the <i>d32</i> member then+ * set/clear the bits using the <i>b</i>it elements.+ */+typedef union dsts_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		/** Suspend Status */+		unsigned suspsts:1;+		/** Enumerated Speed */+		unsigned enumspd:2;+#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0+#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1+#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ		   2+#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ		   3+		/** Erratic Error */+		unsigned errticerr:1;+		unsigned reserved4_7:4;+		/** Frame or Microframe Number of the received SOF */+		unsigned soffn:14;+		unsigned reserved22_31:10;+	} b;+} dsts_data_t;++/**+ * This union represents the bit fields in the Device IN EP Interrupt+ * Register and the Device IN EP Common Mask Register.+ *+ * - Read the register into the <i>d32</i> member then set/clear the+ *	 bits using the <i>b</i>it elements.+ */+typedef union diepint_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		/** Transfer complete mask */+		unsigned xfercompl:1;+		/** Endpoint disable mask */+		unsigned epdisabled:1;+		/** AHB Error mask */+		unsigned ahberr:1;+		/** TimeOUT Handshake mask (non-ISOC EPs) */+		unsigned timeout:1;+		/** IN Token received with TxF Empty mask */+		unsigned intktxfemp:1;+		/** IN Token Received with EP mismatch mask */+		unsigned intknepmis:1;+		/** IN Endpoint NAK Effective mask */+		unsigned inepnakeff:1;+		/** Reserved */+		unsigned emptyintr:1;++		unsigned txfifoundrn:1;++		/** BNA Interrupt mask */+		unsigned bna:1;++		unsigned reserved10_12:3;+		/** BNA Interrupt mask */+		unsigned nak:1;++		unsigned reserved14_31:18;+	} b;+} diepint_data_t;++/**+ * This union represents the bit fields in the Device IN EP+ * Common/Dedicated Interrupt Mask Register.+ */+typedef union diepint_data diepmsk_data_t;++/**+ * This union represents the bit fields in the Device OUT EP Interrupt+ * Registerand Device OUT EP Common Interrupt Mask Register.+ *+ * - Read the register into the <i>d32</i> member then set/clear the+ *	 bits using the <i>b</i>it elements.+ */+typedef union doepint_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		/** Transfer complete */+		unsigned xfercompl:1;+		/** Endpoint disable  */+		unsigned epdisabled:1;+		/** AHB Error */+		unsigned ahberr:1;+		/** Setup Phase Done (contorl EPs) */+		unsigned setup:1;+		/** OUT Token Received when Endpoint Disabled */+		unsigned outtknepdis:1;++		unsigned stsphsercvd:1;+		/** Back-to-Back SETUP Packets Received */+		unsigned back2backsetup:1;++		unsigned reserved7:1;+		/** OUT packet Error */+		unsigned outpkterr:1;+		/** BNA Interrupt */+		unsigned bna:1;++		unsigned reserved10:1;+		/** Packet Drop Status */+		unsigned pktdrpsts:1;+		/** Babble Interrupt */+		unsigned babble:1;+		/** NAK Interrupt */+		unsigned nak:1;+		/** NYET Interrupt */+		unsigned nyet:1;+		/** Bit indicating setup packet received */+		unsigned sr:1;++		unsigned reserved16_31:16;+	} b;+} doepint_data_t;++/**+ * This union represents the bit fields in the Device OUT EP+ * Common/Dedicated Interrupt Mask Register.+ */+typedef union doepint_data doepmsk_data_t;++/**+ * This union represents the bit fields in the Device All EP Interrupt+ * and Mask Registers.+ * - Read the register into the <i>d32</i> member then set/clear the+ *	 bits using the <i>b</i>it elements.+ */+typedef union daint_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		/** IN Endpoint bits */+		unsigned in:16;+		/** OUT Endpoint bits */+		unsigned out:16;+	} ep;+	struct {+		/** IN Endpoint bits */+		unsigned inep0:1;+		unsigned inep1:1;+		unsigned inep2:1;+		unsigned inep3:1;+		unsigned inep4:1;+		unsigned inep5:1;+		unsigned inep6:1;+		unsigned inep7:1;+		unsigned inep8:1;+		unsigned inep9:1;+		unsigned inep10:1;+		unsigned inep11:1;+		unsigned inep12:1;+		unsigned inep13:1;+		unsigned inep14:1;+		unsigned inep15:1;+		/** OUT Endpoint bits */+		unsigned outep0:1;+		unsigned outep1:1;+		unsigned outep2:1;+		unsigned outep3:1;+		unsigned outep4:1;+		unsigned outep5:1;+		unsigned outep6:1;+		unsigned outep7:1;+		unsigned outep8:1;+		unsigned outep9:1;+		unsigned outep10:1;+		unsigned outep11:1;+		unsigned outep12:1;+		unsigned outep13:1;+		unsigned outep14:1;+		unsigned outep15:1;+	} b;+} daint_data_t;++/**+ * This union represents the bit fields in the Device IN Token Queue+ * Read Registers.+ * - Read the register into the <i>d32</i> member.+ * - READ-ONLY Register+ */+typedef union dtknq1_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		/** In Token Queue Write Pointer */+		unsigned intknwptr:5;+		/** Reserved */+		unsigned reserved05_06:2;+		/** write pointer has wrapped. */+		unsigned wrap_bit:1;+		/** EP Numbers of IN Tokens 0 ... 4 */+		unsigned epnums0_5:24;+	} b;+} dtknq1_data_t;++/**+ * This union represents Threshold control Register+ * - Read and write the register into the <i>d32</i> member.+ * - READ-WRITABLE Register+ */+typedef union dthrctl_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		/** non ISO Tx Thr. Enable */+		unsigned non_iso_thr_en:1;+		/** ISO Tx Thr. Enable */+		unsigned iso_thr_en:1;+		/** Tx Thr. Length */+		unsigned tx_thr_len:9;+		/** AHB Threshold ratio */+		unsigned ahb_thr_ratio:2;+		/** Reserved */+		unsigned reserved13_15:3;+		/** Rx Thr. Enable */+		unsigned rx_thr_en:1;+		/** Rx Thr. Length */+		unsigned rx_thr_len:9;+		unsigned reserved26:1;+		/** Arbiter Parking Enable*/+		unsigned arbprken:1;+		/** Reserved */+		unsigned reserved28_31:4;+	} b;+} dthrctl_data_t;++/**+ * Device Logical IN Endpoint-Specific Registers. <i>Offsets+ * 900h-AFCh</i>+ *+ * There will be one set of endpoint registers per logical endpoint+ * implemented.+ *+ * <i>These registers are visible only in Device mode and must not be+ * accessed in Host mode, as the results are unknown.</i>+ */+typedef struct dwc_otg_dev_in_ep_regs {+	/** Device IN Endpoint Control Register. <i>Offset:900h ++	 * (ep_num * 20h) + 00h</i> */+	volatile uint32_t diepctl;+	/** Reserved. <i>Offset:900h + (ep_num * 20h) + 04h</i> */+	uint32_t reserved04;+	/** Device IN Endpoint Interrupt Register. <i>Offset:900h ++	 * (ep_num * 20h) + 08h</i> */+	volatile uint32_t diepint;+	/** Reserved. <i>Offset:900h + (ep_num * 20h) + 0Ch</i> */+	uint32_t reserved0C;+	/** Device IN Endpoint Transfer Size+	 * Register. <i>Offset:900h + (ep_num * 20h) + 10h</i> */+	volatile uint32_t dieptsiz;+	/** Device IN Endpoint DMA Address Register. <i>Offset:900h ++	 * (ep_num * 20h) + 14h</i> */+	volatile uint32_t diepdma;+	/** Device IN Endpoint Transmit FIFO Status Register. <i>Offset:900h ++	 * (ep_num * 20h) + 18h</i> */+	volatile uint32_t dtxfsts;+	/** Device IN Endpoint DMA Buffer Register. <i>Offset:900h ++	 * (ep_num * 20h) + 1Ch</i> */+	volatile uint32_t diepdmab;+} dwc_otg_dev_in_ep_regs_t;++/**+ * Device Logical OUT Endpoint-Specific Registers. <i>Offsets:+ * B00h-CFCh</i>+ *+ * There will be one set of endpoint registers per logical endpoint+ * implemented.+ *+ * <i>These registers are visible only in Device mode and must not be+ * accessed in Host mode, as the results are unknown.</i>+ */+typedef struct dwc_otg_dev_out_ep_regs {+	/** Device OUT Endpoint Control Register. <i>Offset:B00h ++	 * (ep_num * 20h) + 00h</i> */+	volatile uint32_t doepctl;+	/** Reserved. <i>Offset:B00h + (ep_num * 20h) + 04h</i> */+	uint32_t reserved04;+	/** Device OUT Endpoint Interrupt Register. <i>Offset:B00h ++	 * (ep_num * 20h) + 08h</i> */+	volatile uint32_t doepint;+	/** Reserved. <i>Offset:B00h + (ep_num * 20h) + 0Ch</i> */+	uint32_t reserved0C;+	/** Device OUT Endpoint Transfer Size Register. <i>Offset:+	 * B00h + (ep_num * 20h) + 10h</i> */+	volatile uint32_t doeptsiz;+	/** Device OUT Endpoint DMA Address Register. <i>Offset:B00h+	 * + (ep_num * 20h) + 14h</i> */+	volatile uint32_t doepdma;+	/** Reserved. <i>Offset:B00h + 	 * (ep_num * 20h) + 18h</i> */+	uint32_t unused;+	/** Device OUT Endpoint DMA Buffer Register. <i>Offset:B00h+	 * + (ep_num * 20h) + 1Ch</i> */+	uint32_t doepdmab;+} dwc_otg_dev_out_ep_regs_t;++/**+ * This union represents the bit fields in the Device EP Control+ * Register.  Read the register into the <i>d32</i> member then+ * set/clear the bits using the <i>b</i>it elements.+ */+typedef union depctl_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		/** Maximum Packet Size+		 * IN/OUT EPn+		 * IN/OUT EP0 - 2 bits+		 *	 2'b00: 64 Bytes+		 *	 2'b01: 32+		 *	 2'b10: 16+		 *	 2'b11: 8 */+		unsigned mps:11;+#define DWC_DEP0CTL_MPS_64	 0+#define DWC_DEP0CTL_MPS_32	 1+#define DWC_DEP0CTL_MPS_16	 2+#define DWC_DEP0CTL_MPS_8	 3++		/** Next Endpoint+		 * IN EPn/IN EP0+		 * OUT EPn/OUT EP0 - reserved */+		unsigned nextep:4;++		/** USB Active Endpoint */+		unsigned usbactep:1;++		/** Endpoint DPID (INTR/Bulk IN and OUT endpoints)+		 * This field contains the PID of the packet going to+		 * be received or transmitted on this endpoint. The+		 * application should program the PID of the first+		 * packet going to be received or transmitted on this+		 * endpoint , after the endpoint is+		 * activated. Application use the SetD1PID and+		 * SetD0PID fields of this register to program either+		 * D0 or D1 PID.+		 *+		 * The encoding for this field is+		 *	 - 0: D0+		 *	 - 1: D1+		 */+		unsigned dpid:1;++		/** NAK Status */+		unsigned naksts:1;++		/** Endpoint Type+		 *	2'b00: Control+		 *	2'b01: Isochronous+		 *	2'b10: Bulk+		 *	2'b11: Interrupt */+		unsigned eptype:2;++		/** Snoop Mode+		 * OUT EPn/OUT EP0+		 * IN EPn/IN EP0 - reserved */+		unsigned snp:1;++		/** Stall Handshake */+		unsigned stall:1;++		/** Tx Fifo Number+		 * IN EPn/IN EP0+		 * OUT EPn/OUT EP0 - reserved */+		unsigned txfnum:4;++		/** Clear NAK */+		unsigned cnak:1;+		/** Set NAK */+		unsigned snak:1;+		/** Set DATA0 PID (INTR/Bulk IN and OUT endpoints)+		 * Writing to this field sets the Endpoint DPID (DPID)+		 * field in this register to DATA0. Set Even+		 * (micro)frame (SetEvenFr) (ISO IN and OUT Endpoints)+		 * Writing to this field sets the Even/Odd+		 * (micro)frame (EO_FrNum) field to even (micro)+		 * frame.+		 */+		unsigned setd0pid:1;+		/** Set DATA1 PID (INTR/Bulk IN and OUT endpoints)+		 * Writing to this field sets the Endpoint DPID (DPID)+		 * field in this register to DATA1 Set Odd+		 * (micro)frame (SetOddFr) (ISO IN and OUT Endpoints)+		 * Writing to this field sets the Even/Odd+		 * (micro)frame (EO_FrNum) field to odd (micro) frame.+		 */+		unsigned setd1pid:1;++		/** Endpoint Disable */+		unsigned epdis:1;+		/** Endpoint Enable */+		unsigned epena:1;+	} b;+} depctl_data_t;++/**+ * This union represents the bit fields in the Device EP Transfer+ * Size Register.  Read the register into the <i>d32</i> member then+ * set/clear the bits using the <i>b</i>it elements.+ */+typedef union deptsiz_data {+		/** raw register data */+	uint32_t d32;+		/** register bits */+	struct {+		/** Transfer size */+		unsigned xfersize:19;+/** Max packet count for EP (pow(2,10)-1) */+#define MAX_PKT_CNT 1023+		/** Packet Count */+		unsigned pktcnt:10;+		/** Multi Count - Periodic IN endpoints */+		unsigned mc:2;+		unsigned reserved:1;+	} b;+} deptsiz_data_t;++/**+ * This union represents the bit fields in the Device EP 0 Transfer+ * Size Register.  Read the register into the <i>d32</i> member then+ * set/clear the bits using the <i>b</i>it elements.+ */+typedef union deptsiz0_data {+		/** raw register data */+	uint32_t d32;+		/** register bits */+	struct {+		/** Transfer size */+		unsigned xfersize:7;+				/** Reserved */+		unsigned reserved7_18:12;+		/** Packet Count */+		unsigned pktcnt:2;+				/** Reserved */+		unsigned reserved21_28:8;+				/**Setup Packet Count (DOEPTSIZ0 Only) */+		unsigned supcnt:2;+		unsigned reserved31;+	} b;+} deptsiz0_data_t;++/////////////////////////////////////////////////+// DMA Descriptor Specific Structures+//++/** Buffer status definitions */++#define BS_HOST_READY	0x0+#define BS_DMA_BUSY		0x1+#define BS_DMA_DONE		0x2+#define BS_HOST_BUSY	0x3++/** Receive/Transmit status definitions */++#define RTS_SUCCESS		0x0+#define RTS_BUFFLUSH	0x1+#define RTS_RESERVED	0x2+#define RTS_BUFERR		0x3++/**+ * This union represents the bit fields in the DMA Descriptor+ * status quadlet. Read the quadlet into the <i>d32</i> member then+ * set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and+ * <i>b_iso_in</i> elements.+ */+typedef union dev_dma_desc_sts {+		/** raw register data */+	uint32_t d32;+		/** quadlet bits */+	struct {+		/** Received number of bytes */+		unsigned bytes:16;+		/** NAK bit - only for OUT EPs */+		unsigned nak:1;+		unsigned reserved17_22:6;+		/** Multiple Transfer - only for OUT EPs */+		unsigned mtrf:1;+		/** Setup Packet received - only for OUT EPs */+		unsigned sr:1;+		/** Interrupt On Complete */+		unsigned ioc:1;+		/** Short Packet */+		unsigned sp:1;+		/** Last */+		unsigned l:1;+		/** Receive Status */+		unsigned sts:2;+		/** Buffer Status */+		unsigned bs:2;+	} b;++//#ifdef DWC_EN_ISOC+		/** iso out quadlet bits */+	struct {+		/** Received number of bytes */+		unsigned rxbytes:11;++		unsigned reserved11:1;+		/** Frame Number */+		unsigned framenum:11;+		/** Received ISO Data PID */+		unsigned pid:2;+		/** Interrupt On Complete */+		unsigned ioc:1;+		/** Short Packet */+		unsigned sp:1;+		/** Last */+		unsigned l:1;+		/** Receive Status */+		unsigned rxsts:2;+		/** Buffer Status */+		unsigned bs:2;+	} b_iso_out;++		/** iso in quadlet bits */+	struct {+		/** Transmited number of bytes */+		unsigned txbytes:12;+		/** Frame Number */+		unsigned framenum:11;+		/** Transmited ISO Data PID */+		unsigned pid:2;+		/** Interrupt On Complete */+		unsigned ioc:1;+		/** Short Packet */+		unsigned sp:1;+		/** Last */+		unsigned l:1;+		/** Transmit Status */+		unsigned txsts:2;+		/** Buffer Status */+		unsigned bs:2;+	} b_iso_in;+//#endif                                /* DWC_EN_ISOC */+} dev_dma_desc_sts_t;++/**+ * DMA Descriptor structure+ *+ * DMA Descriptor structure contains two quadlets:+ * Status quadlet and Data buffer pointer.+ */+typedef struct dwc_otg_dev_dma_desc {+	/** DMA Descriptor status quadlet */+	dev_dma_desc_sts_t status;+	/** DMA Descriptor data buffer pointer */+	uint32_t buf;+} dwc_otg_dev_dma_desc_t;++/**+ * The dwc_otg_dev_if structure contains information needed to manage+ * the DWC_otg controller acting in device mode. It represents the+ * programming view of the device-specific aspects of the controller.+ */+typedef struct dwc_otg_dev_if {+	/** Pointer to device Global registers.+	 * Device Global Registers starting at offset 800h+	 */+	dwc_otg_device_global_regs_t *dev_global_regs;+#define DWC_DEV_GLOBAL_REG_OFFSET 0x800++	/**+	 * Device Logical IN Endpoint-Specific Registers 900h-AFCh+	 */+	dwc_otg_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS];+#define DWC_DEV_IN_EP_REG_OFFSET 0x900+#define DWC_EP_REG_OFFSET 0x20++	/** Device Logical OUT Endpoint-Specific Registers B00h-CFCh */+	dwc_otg_dev_out_ep_regs_t *out_ep_regs[MAX_EPS_CHANNELS];+#define DWC_DEV_OUT_EP_REG_OFFSET 0xB00++	/* Device configuration information */+	uint8_t speed;				 /**< Device Speed	0: Unknown, 1: LS, 2:FS, 3: HS */+	uint8_t num_in_eps;		 /**< Number # of Tx EP range: 0-15 exept ep0 */+	uint8_t num_out_eps;		 /**< Number # of Rx EP range: 0-15 exept ep 0*/++	/** Size of periodic FIFOs (Bytes) */+	uint16_t perio_tx_fifo_size[MAX_PERIO_FIFOS];++	/** Size of Tx FIFOs (Bytes) */+	uint16_t tx_fifo_size[MAX_TX_FIFOS];++	/** Thresholding enable flags and length varaiables **/+	uint16_t rx_thr_en;+	uint16_t iso_tx_thr_en;+	uint16_t non_iso_tx_thr_en;++	uint16_t rx_thr_length;+	uint16_t tx_thr_length;++	/**+	 * Pointers to the DMA Descriptors for EP0 Control+	 * transfers (virtual and physical)+	 */++	/** 2 descriptors for SETUP packets */+	dwc_dma_t dma_setup_desc_addr[2];+	dwc_otg_dev_dma_desc_t *setup_desc_addr[2];++	/** Pointer to Descriptor with latest SETUP packet */+	dwc_otg_dev_dma_desc_t *psetup;++	/** Index of current SETUP handler descriptor */+	uint32_t setup_desc_index;++	/** Descriptor for Data In or Status In phases */+	dwc_dma_t dma_in_desc_addr;+	dwc_otg_dev_dma_desc_t *in_desc_addr;++	/** Descriptor for Data Out or Status Out phases */+	dwc_dma_t dma_out_desc_addr;+	dwc_otg_dev_dma_desc_t *out_desc_addr;++	/** Setup Packet Detected - if set clear NAK when queueing */+	uint32_t spd;+	/** Isoc ep pointer on which incomplete happens */+	void *isoc_ep;++} dwc_otg_dev_if_t;++/////////////////////////////////////////////////+// Host Mode Register Structures+//+/**+ * The Host Global Registers structure defines the size and relative+ * field offsets for the Host Mode Global Registers.  Host Global+ * Registers offsets 400h-7FFh.+*/+typedef struct dwc_otg_host_global_regs {+	/** Host Configuration Register.   <i>Offset: 400h</i> */+	volatile uint32_t hcfg;+	/** Host Frame Interval Register.	<i>Offset: 404h</i> */+	volatile uint32_t hfir;+	/** Host Frame Number / Frame Remaining Register. <i>Offset: 408h</i> */+	volatile uint32_t hfnum;+	/** Reserved.	<i>Offset: 40Ch</i> */+	uint32_t reserved40C;+	/** Host Periodic Transmit FIFO/ Queue Status Register. <i>Offset: 410h</i> */+	volatile uint32_t hptxsts;+	/** Host All Channels Interrupt Register. <i>Offset: 414h</i> */+	volatile uint32_t haint;+	/** Host All Channels Interrupt Mask Register. <i>Offset: 418h</i> */+	volatile uint32_t haintmsk;+	/** Host Frame List Base Address Register . <i>Offset: 41Ch</i> */+	volatile uint32_t hflbaddr;+} dwc_otg_host_global_regs_t;++/**+ * This union represents the bit fields in the Host Configuration Register.+ * Read the register into the <i>d32</i> member then set/clear the bits using+ * the <i>b</i>it elements. Write the <i>d32</i> member to the hcfg register.+ */+typedef union hcfg_data {+	/** raw register data */+	uint32_t d32;++	/** register bits */+	struct {+		/** FS/LS Phy Clock Select */+		unsigned fslspclksel:2;+#define DWC_HCFG_30_60_MHZ 0+#define DWC_HCFG_48_MHZ	   1+#define DWC_HCFG_6_MHZ	   2++		/** FS/LS Only Support */+		unsigned fslssupp:1;+		unsigned reserved3_6:4;+		/** Enable 32-KHz Suspend Mode */+		unsigned ena32khzs:1;+		/** Resume Validation Periiod */+		unsigned resvalid:8;+		unsigned reserved16_22:7;+		/** Enable Scatter/gather DMA in Host mode */+		unsigned descdma:1;+		/** Frame List Entries */+		unsigned frlisten:2;+		/** Enable Periodic Scheduling */+		unsigned perschedena:1;+		unsigned reserved27_30:4;+		unsigned modechtimen:1;+	} b;+} hcfg_data_t;++/**+ * This union represents the bit fields in the Host Frame Remaing/Number+ * Register.+ */+typedef union hfir_data {+	/** raw register data */+	uint32_t d32;++	/** register bits */+	struct {+		unsigned frint:16;+		unsigned hfirrldctrl:1;+		unsigned reserved:15;+	} b;+} hfir_data_t;++/**+ * This union represents the bit fields in the Host Frame Remaing/Number+ * Register.+ */+typedef union hfnum_data {+	/** raw register data */+	uint32_t d32;++	/** register bits */+	struct {+		unsigned frnum:16;+#define DWC_HFNUM_MAX_FRNUM 0x3FFF+		unsigned frrem:16;+	} b;+} hfnum_data_t;++typedef union hptxsts_data {+	/** raw register data */+	uint32_t d32;++	/** register bits */+	struct {+		unsigned ptxfspcavail:16;+		unsigned ptxqspcavail:8;+		/** Top of the Periodic Transmit Request Queue+		 *	- bit 24 - Terminate (last entry for the selected channel)+		 *	- bits 26:25 - Token Type+		 *	  - 2'b00 - Zero length+		 *	  - 2'b01 - Ping+		 *	  - 2'b10 - Disable+		 *	- bits 30:27 - Channel Number+		 *	- bit 31 - Odd/even microframe+		 */+		unsigned ptxqtop_terminate:1;+		unsigned ptxqtop_token:2;+		unsigned ptxqtop_chnum:4;+		unsigned ptxqtop_odd:1;+	} b;+} hptxsts_data_t;++/**+ * This union represents the bit fields in the Host Port Control and Status+ * Register. Read the register into the <i>d32</i> member then set/clear the+ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the+ * hprt0 register.+ */+typedef union hprt0_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned prtconnsts:1;+		unsigned prtconndet:1;+		unsigned prtena:1;+		unsigned prtenchng:1;+		unsigned prtovrcurract:1;+		unsigned prtovrcurrchng:1;+		unsigned prtres:1;+		unsigned prtsusp:1;+		unsigned prtrst:1;+		unsigned reserved9:1;+		unsigned prtlnsts:2;+		unsigned prtpwr:1;+		unsigned prttstctl:4;+		unsigned prtspd:2;+#define DWC_HPRT0_PRTSPD_HIGH_SPEED 0+#define DWC_HPRT0_PRTSPD_FULL_SPEED 1+#define DWC_HPRT0_PRTSPD_LOW_SPEED	2+		unsigned reserved19_31:13;+	} b;+} hprt0_data_t;++/**+ * This union represents the bit fields in the Host All Interrupt+ * Register.+ */+typedef union haint_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned ch0:1;+		unsigned ch1:1;+		unsigned ch2:1;+		unsigned ch3:1;+		unsigned ch4:1;+		unsigned ch5:1;+		unsigned ch6:1;+		unsigned ch7:1;+		unsigned ch8:1;+		unsigned ch9:1;+		unsigned ch10:1;+		unsigned ch11:1;+		unsigned ch12:1;+		unsigned ch13:1;+		unsigned ch14:1;+		unsigned ch15:1;+		unsigned reserved:16;+	} b;++	struct {+		unsigned chint:16;+		unsigned reserved:16;+	} b2;+} haint_data_t;++/**+ * This union represents the bit fields in the Host All Interrupt+ * Register.+ */+typedef union haintmsk_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned ch0:1;+		unsigned ch1:1;+		unsigned ch2:1;+		unsigned ch3:1;+		unsigned ch4:1;+		unsigned ch5:1;+		unsigned ch6:1;+		unsigned ch7:1;+		unsigned ch8:1;+		unsigned ch9:1;+		unsigned ch10:1;+		unsigned ch11:1;+		unsigned ch12:1;+		unsigned ch13:1;+		unsigned ch14:1;+		unsigned ch15:1;+		unsigned reserved:16;+	} b;++	struct {+		unsigned chint:16;+		unsigned reserved:16;+	} b2;+} haintmsk_data_t;++/**+ * Host Channel Specific Registers. <i>500h-5FCh</i>+ */+typedef struct dwc_otg_hc_regs {+	/** Host Channel 0 Characteristic Register. <i>Offset: 500h + (chan_num * 20h) + 00h</i> */+	volatile uint32_t hcchar;+	/** Host Channel 0 Split Control Register. <i>Offset: 500h + (chan_num * 20h) + 04h</i> */+	volatile uint32_t hcsplt;+	/** Host Channel 0 Interrupt Register. <i>Offset: 500h + (chan_num * 20h) + 08h</i> */+	volatile uint32_t hcint;+	/** Host Channel 0 Interrupt Mask Register. <i>Offset: 500h + (chan_num * 20h) + 0Ch</i> */+	volatile uint32_t hcintmsk;+	/** Host Channel 0 Transfer Size Register. <i>Offset: 500h + (chan_num * 20h) + 10h</i> */+	volatile uint32_t hctsiz;+	/** Host Channel 0 DMA Address Register. <i>Offset: 500h + (chan_num * 20h) + 14h</i> */+	volatile uint32_t hcdma;+	volatile uint32_t reserved;+	/** Host Channel 0 DMA Buffer Address Register. <i>Offset: 500h + (chan_num * 20h) + 1Ch</i> */+	volatile uint32_t hcdmab;+} dwc_otg_hc_regs_t;++/**+ * This union represents the bit fields in the Host Channel Characteristics+ * Register. Read the register into the <i>d32</i> member then set/clear the+ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the+ * hcchar register.+ */+typedef union hcchar_data {+	/** raw register data */+	uint32_t d32;++	/** register bits */+	struct {+		/** Maximum packet size in bytes */+		unsigned mps:11;++		/** Endpoint number */+		unsigned epnum:4;++		/** 0: OUT, 1: IN */+		unsigned epdir:1;++		unsigned reserved:1;++		/** 0: Full/high speed device, 1: Low speed device */+		unsigned lspddev:1;++		/** 0: Control, 1: Isoc, 2: Bulk, 3: Intr */+		unsigned eptype:2;++		/** Packets per frame for periodic transfers. 0 is reserved. */+		unsigned multicnt:2;++		/** Device address */+		unsigned devaddr:7;++		/**+		 * Frame to transmit periodic transaction.+		 * 0: even, 1: odd+		 */+		unsigned oddfrm:1;++		/** Channel disable */+		unsigned chdis:1;++		/** Channel enable */+		unsigned chen:1;+	} b;+} hcchar_data_t;++typedef union hcsplt_data {+	/** raw register data */+	uint32_t d32;++	/** register bits */+	struct {+		/** Port Address */+		unsigned prtaddr:7;++		/** Hub Address */+		unsigned hubaddr:7;++		/** Transaction Position */+		unsigned xactpos:2;+#define DWC_HCSPLIT_XACTPOS_MID 0+#define DWC_HCSPLIT_XACTPOS_END 1+#define DWC_HCSPLIT_XACTPOS_BEGIN 2+#define DWC_HCSPLIT_XACTPOS_ALL 3++		/** Do Complete Split */+		unsigned compsplt:1;++		/** Reserved */+		unsigned reserved:14;++		/** Split Enble */+		unsigned spltena:1;+	} b;+} hcsplt_data_t;++/**+ * This union represents the bit fields in the Host All Interrupt+ * Register.+ */+typedef union hcint_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		/** Transfer Complete */+		unsigned xfercomp:1;+		/** Channel Halted */+		unsigned chhltd:1;+		/** AHB Error */+		unsigned ahberr:1;+		/** STALL Response Received */+		unsigned stall:1;+		/** NAK Response Received */+		unsigned nak:1;+		/** ACK Response Received */+		unsigned ack:1;+		/** NYET Response Received */+		unsigned nyet:1;+		/** Transaction Err */+		unsigned xacterr:1;+		/** Babble Error */+		unsigned bblerr:1;+		/** Frame Overrun */+		unsigned frmovrun:1;+		/** Data Toggle Error */+		unsigned datatglerr:1;+		/** Buffer Not Available (only for DDMA mode) */+		unsigned bna:1;+		/** Exessive transaction error (only for DDMA mode) */+		unsigned xcs_xact:1;+		/** Frame List Rollover interrupt */+		unsigned frm_list_roll:1;+		/** Reserved */+		unsigned reserved14_31:18;+	} b;+} hcint_data_t;++/**+ * This union represents the bit fields in the Host Channel Interrupt Mask+ * Register. Read the register into the <i>d32</i> member then set/clear the+ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the+ * hcintmsk register.+ */+typedef union hcintmsk_data {+	/** raw register data */+	uint32_t d32;++	/** register bits */+	struct {+		unsigned xfercompl:1;+		unsigned chhltd:1;+		unsigned ahberr:1;+		unsigned stall:1;+		unsigned nak:1;+		unsigned ack:1;+		unsigned nyet:1;+		unsigned xacterr:1;+		unsigned bblerr:1;+		unsigned frmovrun:1;+		unsigned datatglerr:1;+		unsigned bna:1;+		unsigned xcs_xact:1;+		unsigned frm_list_roll:1;+		unsigned reserved14_31:18;+	} b;+} hcintmsk_data_t;++/**+ * This union represents the bit fields in the Host Channel Transfer Size+ * Register. Read the register into the <i>d32</i> member then set/clear the+ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the+ * hcchar register.+ */++typedef union hctsiz_data {+	/** raw register data */+	uint32_t d32;++	/** register bits */+	struct {+		/** Total transfer size in bytes */+		unsigned xfersize:19;++		/** Data packets to transfer */+		unsigned pktcnt:10;++		/**+		 * Packet ID for next data packet+		 * 0: DATA0+		 * 1: DATA2+		 * 2: DATA1+		 * 3: MDATA (non-Control), SETUP (Control)+		 */+		unsigned pid:2;+#define DWC_HCTSIZ_DATA0 0+#define DWC_HCTSIZ_DATA1 2+#define DWC_HCTSIZ_DATA2 1+#define DWC_HCTSIZ_MDATA 3+#define DWC_HCTSIZ_SETUP 3++		/** Do PING protocol when 1 */+		unsigned dopng:1;+	} b;++	/** register bits */+	struct {+		/** Scheduling information */+		unsigned schinfo:8;++		/** Number of transfer descriptors.+		 * Max value:+		 * 64 in general,+		 * 256 only for HS isochronous endpoint.+		 */+		unsigned ntd:8;++		/** Data packets to transfer */+		unsigned reserved16_28:13;++		/**+		 * Packet ID for next data packet+		 * 0: DATA0+		 * 1: DATA2+		 * 2: DATA1+		 * 3: MDATA (non-Control)+		 */+		unsigned pid:2;++		/** Do PING protocol when 1 */+		unsigned dopng:1;+	} b_ddma;+} hctsiz_data_t;++/**+ * This union represents the bit fields in the Host DMA Address+ * Register used in Descriptor DMA mode.+ */+typedef union hcdma_data {+	/** raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		unsigned reserved0_2:3;+		/** Current Transfer Descriptor. Not used for ISOC */+		unsigned ctd:8;+		/** Start Address of Descriptor List */+		unsigned dma_addr:21;+	} b;+} hcdma_data_t;++/**+ * This union represents the bit fields in the DMA Descriptor+ * status quadlet for host mode. Read the quadlet into the <i>d32</i> member then+ * set/clear the bits using the <i>b</i>it elements.+ */+typedef union host_dma_desc_sts {+	/** raw register data */+	uint32_t d32;+	/** quadlet bits */++	/* for non-isochronous  */+	struct {+		/** Number of bytes */+		unsigned n_bytes:17;+		/** QTD offset to jump when Short Packet received - only for IN EPs */+		unsigned qtd_offset:6;+		/**+		 * Set to request the core to jump to alternate QTD if+		 * Short Packet received - only for IN EPs+		 */+		unsigned a_qtd:1;+		 /**+		  * Setup Packet bit. When set indicates that buffer contains+		  * setup packet.+		  */+		unsigned sup:1;+		/** Interrupt On Complete */+		unsigned ioc:1;+		/** End of List */+		unsigned eol:1;+		unsigned reserved27:1;+		/** Rx/Tx Status */+		unsigned sts:2;+#define DMA_DESC_STS_PKTERR	1+		unsigned reserved30:1;+		/** Active Bit */+		unsigned a:1;+	} b;+	/* for isochronous */+	struct {+		/** Number of bytes */+		unsigned n_bytes:12;+		unsigned reserved12_24:13;+		/** Interrupt On Complete */+		unsigned ioc:1;+		unsigned reserved26_27:2;+		/** Rx/Tx Status */+		unsigned sts:2;+		unsigned reserved30:1;+		/** Active Bit */+		unsigned a:1;+	} b_isoc;+} host_dma_desc_sts_t;++#define	MAX_DMA_DESC_SIZE		131071+#define MAX_DMA_DESC_NUM_GENERIC	64+#define MAX_DMA_DESC_NUM_HS_ISOC	256+#define MAX_FRLIST_EN_NUM		64+/**+ * Host-mode DMA Descriptor structure+ *+ * DMA Descriptor structure contains two quadlets:+ * Status quadlet and Data buffer pointer.+ */+typedef struct dwc_otg_host_dma_desc {+	/** DMA Descriptor status quadlet */+	host_dma_desc_sts_t status;+	/** DMA Descriptor data buffer pointer */+	uint32_t buf;+} dwc_otg_host_dma_desc_t;++/** OTG Host Interface Structure.+ *+ * The OTG Host Interface Structure structure contains information+ * needed to manage the DWC_otg controller acting in host mode. It+ * represents the programming view of the host-specific aspects of the+ * controller.+ */+typedef struct dwc_otg_host_if {+	/** Host Global Registers starting at offset 400h.*/+	dwc_otg_host_global_regs_t *host_global_regs;+#define DWC_OTG_HOST_GLOBAL_REG_OFFSET 0x400++	/** Host Port 0 Control and Status Register */+	volatile uint32_t *hprt0;+#define DWC_OTG_HOST_PORT_REGS_OFFSET 0x440++	/** Host Channel Specific Registers at offsets 500h-5FCh. */+	dwc_otg_hc_regs_t *hc_regs[MAX_EPS_CHANNELS];+#define DWC_OTG_HOST_CHAN_REGS_OFFSET 0x500+#define DWC_OTG_CHAN_REGS_OFFSET 0x20++	/* Host configuration information */+	/** Number of Host Channels (range: 1-16) */+	uint8_t num_host_channels;+	/** Periodic EPs supported (0: no, 1: yes) */+	uint8_t perio_eps_supported;+	/** Periodic Tx FIFO Size (Only 1 host periodic Tx FIFO) */+	uint16_t perio_tx_fifo_size;++} dwc_otg_host_if_t;++/**+ * This union represents the bit fields in the Power and Clock Gating Control+ * Register. Read the register into the <i>d32</i> member then set/clear the+ * bits using the <i>b</i>it elements.+ */+typedef union pcgcctl_data {+	/** raw register data */+	uint32_t d32;++	/** register bits */+	struct {+		/** Stop Pclk */+		unsigned stoppclk:1;+		/** Gate Hclk */+		unsigned gatehclk:1;+		/** Power Clamp */+		unsigned pwrclmp:1;+		/** Reset Power Down Modules */+		unsigned rstpdwnmodule:1;+		/** Reserved */+		unsigned reserved:1;+		/** Enable Sleep Clock Gating (Enbl_L1Gating) */+		unsigned enbl_sleep_gating:1;+		/** PHY In Sleep (PhySleep) */+		unsigned phy_in_sleep:1;+		/** Deep Sleep*/+		unsigned deep_sleep:1;+		unsigned resetaftsusp:1;+		unsigned restoremode:1;+		unsigned enbl_extnd_hiber:1;+		unsigned extnd_hiber_pwrclmp:1;+		unsigned extnd_hiber_switch:1;+		unsigned ess_reg_restored:1;+		unsigned prt_clk_sel:2;+		unsigned port_power:1;+		unsigned max_xcvrselect:2;+		unsigned max_termsel:1;+		unsigned mac_dev_addr:7;+		unsigned p2hd_dev_enum_spd:2;+		unsigned p2hd_prt_spd:2;+		unsigned if_dev_mode:1;+	} b;+} pcgcctl_data_t;++/**+ * This union represents the bit fields in the Global Data FIFO Software+ * Configuration Register. Read the register into the <i>d32</i> member then+ * set/clear the bits using the <i>b</i>it elements.+ */+typedef union gdfifocfg_data {+	/* raw register data */+	uint32_t d32;+	/** register bits */+	struct {+		/** OTG Data FIFO depth */+		unsigned gdfifocfg:16;+		/** Start address of EP info controller */+		unsigned epinfobase:16;+	} b;+} gdfifocfg_data_t;++/**+ * This union represents the bit fields in the Global Power Down Register+ * Register. Read the register into the <i>d32</i> member then set/clear the+ * bits using the <i>b</i>it elements.+ */+typedef union gpwrdn_data {+	/* raw register data */+	uint32_t d32;++	/** register bits */+	struct {+		/** PMU Interrupt Select */+		unsigned pmuintsel:1;+		/** PMU Active */+		unsigned pmuactv:1;+		/** Restore */+		unsigned restore:1;+		/** Power Down Clamp */+		unsigned pwrdnclmp:1;+		/** Power Down Reset */+		unsigned pwrdnrstn:1;+		/** Power Down Switch */+		unsigned pwrdnswtch:1;+		/** Disable VBUS */+		unsigned dis_vbus:1;+		/** Line State Change */+		unsigned lnstschng:1;+		/** Line state change mask */+		unsigned lnstchng_msk:1;+		/** Reset Detected */+		unsigned rst_det:1;+		/** Reset Detect mask */+		unsigned rst_det_msk:1;+		/** Disconnect Detected */+		unsigned disconn_det:1;+		/** Disconnect Detect mask */+		unsigned disconn_det_msk:1;+		/** Connect Detected*/+		unsigned connect_det:1;+		/** Connect Detected Mask*/+		unsigned connect_det_msk:1;+		/** SRP Detected */+		unsigned srp_det:1;+		/** SRP Detect mask */+		unsigned srp_det_msk:1;+		/** Status Change Interrupt */+		unsigned sts_chngint:1;+		/** Status Change Interrupt Mask */+		unsigned sts_chngint_msk:1;+		/** Line State */+		unsigned linestate:2;+		/** Indicates current mode(status of IDDIG signal) */+		unsigned idsts:1;+		/** B Session Valid signal status*/+		unsigned bsessvld:1;+		/** ADP Event Detected */+		unsigned adp_int:1;+		/** Multi Valued ID pin */+		unsigned mult_val_id_bc:5;+		/** Reserved 24_31 */+		unsigned reserved29_31:3;+	} b;+} gpwrdn_data_t;++#endifdiff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/Makefile linux-3.11.10/drivers/usb/host/dwc_otg/Makefile--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/Makefile	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/Makefile	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,81 @@+#+# Makefile for DWC_otg Highspeed USB controller driver+#++ifneq ($(KERNELRELEASE),)++# Use the BUS_INTERFACE variable to compile the software for either+# PCI(PCI_INTERFACE) or LM(LM_INTERFACE) bus.+ifeq ($(BUS_INTERFACE),)+#	BUS_INTERFACE = -DPCI_INTERFACE+#	BUS_INTERFACE = -DLM_INTERFACE+        BUS_INTERFACE = -DPLATFORM_INTERFACE+endif++#EXTRA_CFLAGS	+= -DDEBUG+#EXTRA_CFLAGS	+= -DDWC_OTG_DEBUGLEV=1 # reduce common debug msgs++# Use one of the following flags to compile the software in host-only or+# device-only mode.+#EXTRA_CFLAGS        += -DDWC_HOST_ONLY+#EXTRA_CFLAGS        += -DDWC_DEVICE_ONLY++EXTRA_CFLAGS	+= -Dlinux -DDWC_HS_ELECT_TST+#EXTRA_CFLAGS	+= -DDWC_EN_ISOC+EXTRA_CFLAGS   	+= -I$(obj)/../dwc_common_port+#EXTRA_CFLAGS   	+= -I$(PORTLIB)+EXTRA_CFLAGS   	+= -DDWC_LINUX+EXTRA_CFLAGS   	+= $(CFI)+EXTRA_CFLAGS	+= $(BUS_INTERFACE)+#EXTRA_CFLAGS	+= -DDWC_DEV_SRPCAP++obj-$(CONFIG_USB_DWCOTG) += dwc_otg.o++dwc_otg-objs	:= dwc_otg_driver.o dwc_otg_attr.o+dwc_otg-objs	+= dwc_otg_cil.o dwc_otg_cil_intr.o+dwc_otg-objs	+= dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o+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+dwc_otg-objs	+= dwc_otg_adp.o+dwc_otg-objs	+= dwc_otg_mphi_fix.o+ifneq ($(CFI),)+dwc_otg-objs	+= dwc_otg_cfi.o+endif++kernrelwd := $(subst ., ,$(KERNELRELEASE))+kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))++ifneq ($(kernrel3),2.6.20)+EXTRA_CFLAGS += $(CPPFLAGS)+endif++else++PWD		:= $(shell pwd)+PORTLIB		:= $(PWD)/../dwc_common_port++# Command paths+CTAGS		:= $(CTAGS)+DOXYGEN		:= $(DOXYGEN)++default: portlib+	$(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules++install: default+	$(MAKE) -C$(KDIR) M=$(PORTLIB) modules_install+	$(MAKE) -C$(KDIR) M=$(PWD) modules_install++portlib:+	$(MAKE) -C$(KDIR) M=$(PORTLIB) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules+	cp $(PORTLIB)/Module.symvers $(PWD)/++docs:	$(wildcard *.[hc]) doc/doxygen.cfg+	$(DOXYGEN) doc/doxygen.cfg++tags:	$(wildcard *.[hc])+	$(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)+++clean:+	rm -rf   *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers++endifdiff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm linux-3.11.10/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,337 @@+package dwc_otg_test;++use strict;+use Exporter ();++use vars qw(@ISA @EXPORT+$sysfsdir $paramdir $errors $params+);++@ISA = qw(Exporter);++#+# Globals+#+$sysfsdir = "/sys/devices/lm0";+$paramdir = "/sys/module/dwc_otg";+$errors = 0;++$params = [+	   {+	    NAME => "otg_cap",+	    DEFAULT => 0,+	    ENUM => [],+	    LOW => 0,+	    HIGH => 2+	   },+	   {+	    NAME => "dma_enable",+	    DEFAULT => 0,+	    ENUM => [],+	    LOW => 0,+	    HIGH => 1+	   },+	   {+	    NAME => "dma_burst_size",+	    DEFAULT => 32,+	    ENUM => [1, 4, 8, 16, 32, 64, 128, 256],+	    LOW => 1,+	    HIGH => 256+	   },+	   {+	    NAME => "host_speed",+	    DEFAULT => 0,+	    ENUM => [],+	    LOW => 0,+	    HIGH => 1+	   },+	   {+	    NAME => "host_support_fs_ls_low_power",+	    DEFAULT => 0,+	    ENUM => [],+	    LOW => 0,+	    HIGH => 1+	   },+	   {+	    NAME => "host_ls_low_power_phy_clk",+	    DEFAULT => 0,+	    ENUM => [],+	    LOW => 0,+	    HIGH => 1+	   },+	   {+	    NAME => "dev_speed",+	    DEFAULT => 0,+	    ENUM => [],+	    LOW => 0,+	    HIGH => 1+	   },+	   {+	    NAME => "enable_dynamic_fifo",+	    DEFAULT => 1,+	    ENUM => [],+	    LOW => 0,+	    HIGH => 1+	   },+	   {+	    NAME => "data_fifo_size",+	    DEFAULT => 8192,+	    ENUM => [],+	    LOW => 32,+	    HIGH => 32768+	   },+	   {+	    NAME => "dev_rx_fifo_size",+	    DEFAULT => 1064,+	    ENUM => [],+	    LOW => 16,+	    HIGH => 32768+	   },+	   {+	    NAME => "dev_nperio_tx_fifo_size",+	    DEFAULT => 1024,+	    ENUM => [],+	    LOW => 16,+	    HIGH => 32768+	   },+	   {+	    NAME => "dev_perio_tx_fifo_size_1",+	    DEFAULT => 256,+	    ENUM => [],+	    LOW => 4,+	    HIGH => 768+	   },+	   {+	    NAME => "dev_perio_tx_fifo_size_2",+	    DEFAULT => 256,+	    ENUM => [],+	    LOW => 4,+	    HIGH => 768+	   },+	   {+	    NAME => "dev_perio_tx_fifo_size_3",+	    DEFAULT => 256,+	    ENUM => [],+	    LOW => 4,+	    HIGH => 768+	   },+	   {+	    NAME => "dev_perio_tx_fifo_size_4",+	    DEFAULT => 256,+	    ENUM => [],+	    LOW => 4,+	    HIGH => 768+	   },+	   {+	    NAME => "dev_perio_tx_fifo_size_5",+	    DEFAULT => 256,+	    ENUM => [],+	    LOW => 4,+	    HIGH => 768+	   },+	   {+	    NAME => "dev_perio_tx_fifo_size_6",+	    DEFAULT => 256,+	    ENUM => [],+	    LOW => 4,+	    HIGH => 768+	   },+	   {+	    NAME => "dev_perio_tx_fifo_size_7",+	    DEFAULT => 256,+	    ENUM => [],+	    LOW => 4,+	    HIGH => 768+	   },+	   {+	    NAME => "dev_perio_tx_fifo_size_8",+	    DEFAULT => 256,+	    ENUM => [],+	    LOW => 4,+	    HIGH => 768+	   },+	   {+	    NAME => "dev_perio_tx_fifo_size_9",+	    DEFAULT => 256,+	    ENUM => [],+	    LOW => 4,+	    HIGH => 768+	   },+	   {+	    NAME => "dev_perio_tx_fifo_size_10",+	    DEFAULT => 256,+	    ENUM => [],+	    LOW => 4,+	    HIGH => 768+	   },+	   {+	    NAME => "dev_perio_tx_fifo_size_11",+	    DEFAULT => 256,+	    ENUM => [],+	    LOW => 4,+	    HIGH => 768+	   },+	   {+	    NAME => "dev_perio_tx_fifo_size_12",+	    DEFAULT => 256,+	    ENUM => [],+	    LOW => 4,+	    HIGH => 768+	   },+	   {+	    NAME => "dev_perio_tx_fifo_size_13",+	    DEFAULT => 256,+	    ENUM => [],+	    LOW => 4,+	    HIGH => 768+	   },+	   {+	    NAME => "dev_perio_tx_fifo_size_14",+	    DEFAULT => 256,+	    ENUM => [],+	    LOW => 4,+	    HIGH => 768+	   },+	   {+	    NAME => "dev_perio_tx_fifo_size_15",+	    DEFAULT => 256,+	    ENUM => [],+	    LOW => 4,+	    HIGH => 768+	   },+	   {+	    NAME => "host_rx_fifo_size",+	    DEFAULT => 1024,+	    ENUM => [],+	    LOW => 16,+	    HIGH => 32768+	   },+	   {+	    NAME => "host_nperio_tx_fifo_size",+	    DEFAULT => 1024,+	    ENUM => [],+	    LOW => 16,+	    HIGH => 32768+	   },+	   {+	    NAME => "host_perio_tx_fifo_size",+	    DEFAULT => 1024,+	    ENUM => [],+	    LOW => 16,+	    HIGH => 32768+	   },+	   {+	    NAME => "max_transfer_size",+	    DEFAULT => 65535,+	    ENUM => [],+	    LOW => 2047,+	    HIGH => 65535+	   },+	   {+	    NAME => "max_packet_count",+	    DEFAULT => 511,+	    ENUM => [],+	    LOW => 15,+	    HIGH => 511+	   },+	   {+	    NAME => "host_channels",+	    DEFAULT => 12,+	    ENUM => [],+	    LOW => 1,+	    HIGH => 16+	   },+	   {+	    NAME => "dev_endpoints",+	    DEFAULT => 6,+	    ENUM => [],+	    LOW => 1,+	    HIGH => 15+	   },+	   {+	    NAME => "phy_type",+	    DEFAULT => 1,+	    ENUM => [],+	    LOW => 0,+	    HIGH => 2+	   },+	   {+	    NAME => "phy_utmi_width",+	    DEFAULT => 16,+	    ENUM => [8, 16],+	    LOW => 8,+	    HIGH => 16+	   },+	   {+	    NAME => "phy_ulpi_ddr",+	    DEFAULT => 0,+	    ENUM => [],+	    LOW => 0,+	    HIGH => 1+	   },+	  ];+++#+#+sub check_arch {+  $_ = `uname -m`;+  chomp;+  unless (m/armv4tl/) {+    warn "# \n# Can't execute on $_.  Run on integrator platform.\n# \n";+    return 0;+  }+  return 1;+}++#+#+sub load_module {+  my $params = shift;+  print "\nRemoving Module\n";+  system "rmmod dwc_otg";+  print "Loading Module\n";+  if ($params ne "") {+    print "Module Parameters: $params\n";+  }+  if (system("modprobe dwc_otg $params")) {+    warn "Unable to load module\n";+    return 0;+  }+  return 1;+}++#+#+sub test_status {+  my $arg = shift;++  print "\n";++  if (defined $arg) {+    warn "WARNING: $arg\n";+  }++  if ($errors > 0) {+    warn "TEST FAILED with $errors errors\n";+    return 0;+  } else {+    print "TEST PASSED\n";+    return 0 if (defined $arg);+  }+  return 1;+}++#+#+@EXPORT = qw(+$sysfsdir+$paramdir+$params+$errors+check_arch+load_module+test_status+);++1;diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/test/Makefile linux-3.11.10/drivers/usb/host/dwc_otg/test/Makefile--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/test/Makefile	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/test/Makefile	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,16 @@++PERL=/usr/bin/perl+PL_TESTS=test_sysfs.pl test_mod_param.pl++.PHONY : test+test : perl_tests++perl_tests :+	@echo+	@echo Running perl tests+	@for test in $(PL_TESTS); do \+	  if $(PERL) ./$$test ; then \+	    echo "=======> $$test, PASSED" ; \+	  else echo "=======> $$test, FAILED" ; \+	  fi \+	donediff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/test/test_mod_param.pl linux-3.11.10/drivers/usb/host/dwc_otg/test/test_mod_param.pl--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/test/test_mod_param.pl	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/test/test_mod_param.pl	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,133 @@+#!/usr/bin/perl -w+#+# Run this program on the integrator.+#+# - Tests module parameter default values.+# - Tests setting of valid module parameter values via modprobe.+# - Tests invalid module parameter values.+# -----------------------------------------------------------------------------+use strict;+use dwc_otg_test;++check_arch() or die;++#+#+sub test {+  my ($param,$expected) = @_;+  my $value = get($param);++  if ($value == $expected) {+    print "$param = $value, okay\n";+  }++  else {+    warn "ERROR: value of $param != $expected, $value\n";+    $errors ++;+  }+}++#+#+sub get {+  my $param = shift;+  my $tmp = `cat $paramdir/$param`;+  chomp $tmp;+  return $tmp;+}++#+#+sub test_main {++  print "\nTesting Module Parameters\n";++  load_module("") or die;++  # Test initial values+  print "\nTesting Default Values\n";+  foreach (@{$params}) {+    test ($_->{NAME}, $_->{DEFAULT});+  }++  # Test low value+  print "\nTesting Low Value\n";+  my $cmd_params = "";+  foreach (@{$params}) {+    $cmd_params = $cmd_params . "$_->{NAME}=$_->{LOW} ";+  }+  load_module($cmd_params) or die;++  foreach (@{$params}) {+    test ($_->{NAME}, $_->{LOW});+  }++  # Test high value+  print "\nTesting High Value\n";+  $cmd_params = "";+  foreach (@{$params}) {+    $cmd_params = $cmd_params . "$_->{NAME}=$_->{HIGH} ";+  }+  load_module($cmd_params) or die;++  foreach (@{$params}) {+    test ($_->{NAME}, $_->{HIGH});+  }++  # Test Enum+  print "\nTesting Enumerated\n";+  foreach (@{$params}) {+    if (defined $_->{ENUM}) {+      my $value;+      foreach $value (@{$_->{ENUM}}) {+	$cmd_params = "$_->{NAME}=$value";+	load_module($cmd_params) or die;+	test ($_->{NAME}, $value);+      }+    }+  }++  # Test Invalid Values+  print "\nTesting Invalid Values\n";+  $cmd_params = "";+  foreach (@{$params}) {+    $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{LOW}-1;+  }+  load_module($cmd_params) or die;++  foreach (@{$params}) {+    test ($_->{NAME}, $_->{DEFAULT});+  }++  $cmd_params = "";+  foreach (@{$params}) {+    $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{HIGH}+1;+  }+  load_module($cmd_params) or die;++  foreach (@{$params}) {+    test ($_->{NAME}, $_->{DEFAULT});+  }++  print "\nTesting Enumerated\n";+  foreach (@{$params}) {+    if (defined $_->{ENUM}) {+      my $value;+      foreach $value (@{$_->{ENUM}}) {+	$value = $value + 1;+	$cmd_params = "$_->{NAME}=$value";+	load_module($cmd_params) or die;+	test ($_->{NAME}, $_->{DEFAULT});+	$value = $value - 2;+	$cmd_params = "$_->{NAME}=$value";+	load_module($cmd_params) or die;+	test ($_->{NAME}, $_->{DEFAULT});+      }+    }+  }++  test_status() or die;+}++test_main();+0;diff -Nur linux-3.11.10.orig/drivers/usb/host/dwc_otg/test/test_sysfs.pl linux-3.11.10/drivers/usb/host/dwc_otg/test/test_sysfs.pl--- linux-3.11.10.orig/drivers/usb/host/dwc_otg/test/test_sysfs.pl	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/usb/host/dwc_otg/test/test_sysfs.pl	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,193 @@+#!/usr/bin/perl -w+#+# Run this program on the integrator+# - Tests select sysfs attributes.+# - Todo ... test more attributes, hnp/srp, buspower/bussuspend, etc.+# -----------------------------------------------------------------------------+use strict;+use dwc_otg_test;++check_arch() or die;++#+#+sub test {+  my ($attr,$expected) = @_;+  my $string = get($attr);++  if ($string eq $expected) {+    printf("$attr = $string, okay\n");+  }+  else {+    warn "ERROR: value of $attr != $expected, $string\n";+    $errors ++;+  }+}++#+#+sub set {+  my ($reg, $value) = @_;+  system "echo $value > $sysfsdir/$reg";+}++#+#+sub get {+  my $attr = shift;+  my $string = `cat $sysfsdir/$attr`;+  chomp $string;+  if ($string =~ m/\s\=\s/) {+    my $tmp;+    ($tmp, $string) = split /\s=\s/, $string;+  }+  return $string;+}++#+#+sub test_main {+  print("\nTesting Sysfs Attributes\n");++  load_module("") or die;++  # Test initial values of regoffset/regvalue/guid/gsnpsid+  print("\nTesting Default Values\n");++  test("regoffset", "0xffffffff");+  test("regvalue", "invalid offset");+  test("guid", "0x12345678");	# this will fail if it has been changed+  test("gsnpsid", "0x4f54200a");++  # Test operation of regoffset/regvalue+  print("\nTesting regoffset\n");+  set('regoffset', '5a5a5a5a');+  test("regoffset", "0xffffffff");++  set('regoffset', '0');+  test("regoffset", "0x00000000");++  set('regoffset', '40000');+  test("regoffset", "0x00000000");++  set('regoffset', '3ffff');+  test("regoffset", "0x0003ffff");++  set('regoffset', '1');+  test("regoffset", "0x00000001");++  print("\nTesting regvalue\n");+  set('regoffset', '3c');+  test("regvalue", "0x12345678");+  set('regvalue', '5a5a5a5a');+  test("regvalue", "0x5a5a5a5a");+  set('regvalue','a5a5a5a5');+  test("regvalue", "0xa5a5a5a5");+  set('guid','12345678');++  # Test HNP Capable+  print("\nTesting HNP Capable bit\n");+  set('hnpcapable', '1');+  test("hnpcapable", "0x1");+  set('hnpcapable','0');+  test("hnpcapable", "0x0");++  set('regoffset','0c');++  my $old = get('gusbcfg');+  print("setting hnpcapable\n");+  set('hnpcapable', '1');+  test("hnpcapable", "0x1");+  test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<9)));+  test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<9)));++  $old = get('gusbcfg');+  print("clearing hnpcapable\n");+  set('hnpcapable', '0');+  test("hnpcapable", "0x0");+  test ('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<9)));+  test ('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<9)));++  # Test SRP Capable+  print("\nTesting SRP Capable bit\n");+  set('srpcapable', '1');+  test("srpcapable", "0x1");+  set('srpcapable','0');+  test("srpcapable", "0x0");++  set('regoffset','0c');++  $old = get('gusbcfg');+  print("setting srpcapable\n");+  set('srpcapable', '1');+  test("srpcapable", "0x1");+  test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<8)));+  test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<8)));++  $old = get('gusbcfg');+  print("clearing srpcapable\n");+  set('srpcapable', '0');+  test("srpcapable", "0x0");+  test('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<8)));+  test('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<8)));++  # Test GGPIO+  print("\nTesting GGPIO\n");+  set('ggpio','5a5a5a5a');+  test('ggpio','0x5a5a0000');+  set('ggpio','a5a5a5a5');+  test('ggpio','0xa5a50000');+  set('ggpio','11110000');+  test('ggpio','0x11110000');+  set('ggpio','00001111');+  test('ggpio','0x00000000');++  # Test DEVSPEED+  print("\nTesting DEVSPEED\n");+  set('regoffset','800');+  $old = get('regvalue');+  set('devspeed','0');+  test('devspeed','0x0');+  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3)));+  set('devspeed','1');+  test('devspeed','0x1');+  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1));+  set('devspeed','2');+  test('devspeed','0x2');+  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 2));+  set('devspeed','3');+  test('devspeed','0x3');+  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 3));+  set('devspeed','4');+  test('devspeed','0x0');+  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3)));+  set('devspeed','5');+  test('devspeed','0x1');+  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1));+++  #  mode	Returns the current mode:0 for device mode1 for host mode	Read+  #  hnp	Initiate the Host Negotiation Protocol.  Read returns the status.	Read/Write+  #  srp	Initiate the Session Request Protocol.  Read returns the status.	Read/Write+  #  buspower	Get or Set the Power State of the bus (0 - Off or 1 - On) 	Read/Write+  #  bussuspend	Suspend the USB bus.	Read/Write+  #  busconnected	Get the connection status of the bus 	Read++  #  gotgctl	Get or set the Core Control Status Register.	Read/Write+  ##  gusbcfg	Get or set the Core USB Configuration Register	Read/Write+  #  grxfsiz	Get or set the Receive FIFO Size Register	Read/Write+  #  gnptxfsiz	Get or set the non-periodic Transmit Size Register	Read/Write+  #  gpvndctl	Get or set the PHY Vendor Control Register	Read/Write+  ##  ggpio	Get the value in the lower 16-bits of the General Purpose IO Register or Set the upper 16 bits.	Read/Write+  ##  guid	Get or set the value of the User ID Register	Read/Write+  ##  gsnpsid	Get the value of the Synopsys ID Regester	Read+  ##  devspeed	Get or set the device speed setting in the DCFG register	Read/Write+  #  enumspeed	Gets the device enumeration Speed.	Read+  #  hptxfsiz	Get the value of the Host Periodic Transmit FIFO	Read+  #  hprt0	Get or Set the value in the Host Port Control and Status Register	Read/Write++  test_status("TEST NYI") or die;+}++test_main();+0;diff -Nur linux-3.11.10.orig/drivers/usb/host/Kconfig linux-3.11.10/drivers/usb/host/Kconfig--- linux-3.11.10.orig/drivers/usb/host/Kconfig	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/usb/host/Kconfig	2014-02-07 19:57:30.000000000 +0100@@ -671,6 +671,19 @@ 	  To compile this driver a module, choose M here: the module 	  will be called "hwa-hc". +config USB_DWCOTG+	tristate "Synopsis DWC host support"+	depends on USB+	help+	  The Synopsis DWC controller is a dual-role+	  host/peripheral/OTG ("On The Go") USB controllers.++	  Enable this option to support this IP in host controller mode.+	  If unsure, say N.++	  To compile this driver as a module, choose M here: the+	  modules built will be called dwc_otg and dwc_common_port.+ config USB_IMX21_HCD        tristate "i.MX21 HCD support"        depends on ARM && ARCH_MXCdiff -Nur linux-3.11.10.orig/drivers/usb/host/Makefile linux-3.11.10/drivers/usb/host/Makefile--- linux-3.11.10.orig/drivers/usb/host/Makefile	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/usb/host/Makefile	2014-02-07 19:57:30.000000000 +0100@@ -52,6 +52,8 @@ obj-$(CONFIG_USB_R8A66597_HCD)	+= r8a66597-hcd.o obj-$(CONFIG_USB_ISP1760_HCD)	+= isp1760.o obj-$(CONFIG_USB_HWA_HCD)	+= hwa-hc.o++obj-$(CONFIG_USB_DWCOTG)        += dwc_otg/ dwc_common_port/ obj-$(CONFIG_USB_IMX21_HCD)	+= imx21-hcd.o obj-$(CONFIG_USB_FSL_MPH_DR_OF)	+= fsl-mph-dr-of.o obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.odiff -Nur linux-3.11.10.orig/drivers/usb/Makefile linux-3.11.10/drivers/usb/Makefile--- linux-3.11.10.orig/drivers/usb/Makefile	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/usb/Makefile	2014-02-07 19:57:30.000000000 +0100@@ -23,6 +23,7 @@ obj-$(CONFIG_USB_R8A66597_HCD)	+= host/ obj-$(CONFIG_USB_HWA_HCD)	+= host/ obj-$(CONFIG_USB_ISP1760_HCD)	+= host/+obj-$(CONFIG_USB_DWCOTG)	+= host/ obj-$(CONFIG_USB_IMX21_HCD)	+= host/ obj-$(CONFIG_USB_FSL_MPH_DR_OF)	+= host/ obj-$(CONFIG_USB_FUSBH200_HCD)	+= host/diff -Nur linux-3.11.10.orig/drivers/video/bcm2708_fb.c linux-3.11.10/drivers/video/bcm2708_fb.c--- linux-3.11.10.orig/drivers/video/bcm2708_fb.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/video/bcm2708_fb.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,647 @@+/*+ *  linux/drivers/video/bcm2708_fb.c+ *+ * Copyright (C) 2010 Broadcom+ *+ * This file is subject to the terms and conditions of the GNU General Public+ * License.  See the file COPYING in the main directory of this archive+ * for more details.+ *+ * Broadcom simple framebuffer driver+ *+ * This file is derived from cirrusfb.c+ * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>+ *+ */+#include <linux/module.h>+#include <linux/kernel.h>+#include <linux/errno.h>+#include <linux/string.h>+#include <linux/slab.h>+#include <linux/mm.h>+#include <linux/fb.h>+#include <linux/init.h>+#include <linux/ioport.h>+#include <linux/list.h>+#include <linux/platform_device.h>+#include <linux/clk.h>+#include <linux/printk.h>+#include <linux/console.h>++#include <mach/dma.h>+#include <mach/platform.h>+#include <mach/vcio.h>++#include <asm/sizes.h>+#include <linux/io.h>+#include <linux/dma-mapping.h>++#ifdef BCM2708_FB_DEBUG+#define print_debug(fmt,...) pr_debug("%s:%s:%d: "fmt, MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__)+#else+#define print_debug(fmt,...)+#endif++/* This is limited to 16 characters when displayed by X startup */+static const char *bcm2708_name = "BCM2708 FB";++#define DRIVER_NAME "bcm2708_fb"++/* this data structure describes each frame buffer device we find */++struct fbinfo_s {+	u32 xres, yres, xres_virtual, yres_virtual;+	u32 pitch, bpp;+	u32 xoffset, yoffset;+	u32 base;+	u32 screen_size;+	u16 cmap[256];+};++struct bcm2708_fb {+	struct fb_info fb;+	struct platform_device *dev;+	struct fbinfo_s *info;+	dma_addr_t dma;+	u32 cmap[16];+	int dma_chan;+	int dma_irq;+	void __iomem *dma_chan_base;+	void *cb_base;		/* DMA control blocks */+	dma_addr_t cb_handle;+};++#define to_bcm2708(info)	container_of(info, struct bcm2708_fb, fb)++static int bcm2708_fb_set_bitfields(struct fb_var_screeninfo *var)+{+	int ret = 0;++	memset(&var->transp, 0, sizeof(var->transp));++	var->red.msb_right = 0;+	var->green.msb_right = 0;+	var->blue.msb_right = 0;++	switch (var->bits_per_pixel) {+	case 1:+	case 2:+	case 4:+	case 8:+		var->red.length = var->bits_per_pixel;+		var->red.offset = 0;+		var->green.length = var->bits_per_pixel;+		var->green.offset = 0;+		var->blue.length = var->bits_per_pixel;+		var->blue.offset = 0;+		break;+	case 16:+		var->red.length = 5;+		var->blue.length = 5;+		/*+		 * Green length can be 5 or 6 depending whether+		 * we're operating in RGB555 or RGB565 mode.+		 */+		if (var->green.length != 5 && var->green.length != 6)+			var->green.length = 6;+		break;+	case 24:+		var->red.length = 8;+		var->blue.length = 8;+		var->green.length = 8;+		break;+	case 32:+		var->red.length = 8;+		var->green.length = 8;+		var->blue.length = 8;+		var->transp.length = 8;+		break;+	default:+		ret = -EINVAL;+		break;+	}++	/*+	 * >= 16bpp displays have separate colour component bitfields+	 * encoded in the pixel data.  Calculate their position from+	 * the bitfield length defined above.+	 */+	if (ret == 0 && var->bits_per_pixel >= 24) {+		var->red.offset = 0;+		var->green.offset = var->red.offset + var->red.length;+		var->blue.offset = var->green.offset + var->green.length;+		var->transp.offset = var->blue.offset + var->blue.length;+	} else if (ret == 0 && var->bits_per_pixel >= 16) {+		var->blue.offset = 0;+		var->green.offset = var->blue.offset + var->blue.length;+		var->red.offset = var->green.offset + var->green.length;+		var->transp.offset = var->red.offset + var->red.length;+	}++	return ret;+}++static int bcm2708_fb_check_var(struct fb_var_screeninfo *var,+				struct fb_info *info)+{+	/* info input, var output */+	int yres;++	/* info input, var output */+	print_debug("bcm2708_fb_check_var info(%p) %dx%d (%dx%d), %d, %d\n", info,+		info->var.xres, info->var.yres, info->var.xres_virtual,+		info->var.yres_virtual, (int)info->screen_size,+		info->var.bits_per_pixel);+	print_debug("bcm2708_fb_check_var var(%p) %dx%d (%dx%d), %d\n", var,+		var->xres, var->yres, var->xres_virtual, var->yres_virtual,+		var->bits_per_pixel);++	if (!var->bits_per_pixel)+		var->bits_per_pixel = 16;++	if (bcm2708_fb_set_bitfields(var) != 0) {+		pr_err("bcm2708_fb_check_var: invalid bits_per_pixel %d\n",+		     var->bits_per_pixel);+		return -EINVAL;+	}+++	if (var->xres_virtual < var->xres)+		var->xres_virtual = var->xres;+	/* use highest possible virtual resolution */+	if (var->yres_virtual == -1) {+		var->yres_virtual = 480;++		pr_err+		    ("bcm2708_fb_check_var: virtual resolution set to maximum of %dx%d\n",+		     var->xres_virtual, var->yres_virtual);+	}+	if (var->yres_virtual < var->yres)+		var->yres_virtual = var->yres;++	if (var->xoffset < 0)+		var->xoffset = 0;+	if (var->yoffset < 0)+		var->yoffset = 0;++	/* truncate xoffset and yoffset to maximum if too high */+	if (var->xoffset > var->xres_virtual - var->xres)+		var->xoffset = var->xres_virtual - var->xres - 1;+	if (var->yoffset > var->yres_virtual - var->yres)+		var->yoffset = var->yres_virtual - var->yres - 1;++	yres = var->yres;+	if (var->vmode & FB_VMODE_DOUBLE)+		yres *= 2;+	else if (var->vmode & FB_VMODE_INTERLACED)+		yres = (yres + 1) / 2;++	if (yres > 1200) {+		pr_err("bcm2708_fb_check_var: ERROR: VerticalTotal >= 1200; "+		       "special treatment required! (TODO)\n");+		return -EINVAL;+	}++	return 0;+}++static int bcm2708_fb_set_par(struct fb_info *info)+{+	uint32_t val = 0;+	struct bcm2708_fb *fb = to_bcm2708(info);+	volatile struct fbinfo_s *fbinfo = fb->info;+	fbinfo->xres = info->var.xres;+	fbinfo->yres = info->var.yres;+	fbinfo->xres_virtual = info->var.xres_virtual;+	fbinfo->yres_virtual = info->var.yres_virtual;+	fbinfo->bpp = info->var.bits_per_pixel;+	fbinfo->xoffset = info->var.xoffset;+	fbinfo->yoffset = info->var.yoffset;+	fbinfo->base = 0;	/* filled in by VC */+	fbinfo->pitch = 0;	/* filled in by VC */++	print_debug("bcm2708_fb_set_par info(%p) %dx%d (%dx%d), %d, %d\n", info,+		info->var.xres, info->var.yres, info->var.xres_virtual,+		info->var.yres_virtual, (int)info->screen_size,+		info->var.bits_per_pixel);++	/* ensure last write to fbinfo is visible to GPU */+	wmb();++	/* inform vc about new framebuffer */+	bcm_mailbox_write(MBOX_CHAN_FB, fb->dma);++	/* TODO: replace fb driver with vchiq version */+	/* wait for response */+	bcm_mailbox_read(MBOX_CHAN_FB, &val);++	/* ensure GPU writes are visible to us */+	rmb();++        if (val == 0) {+		fb->fb.fix.line_length = fbinfo->pitch;++		if (info->var.bits_per_pixel <= 8)+			fb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;+		else+			fb->fb.fix.visual = FB_VISUAL_TRUECOLOR;++		fb->fb.fix.smem_start = fbinfo->base;+		fb->fb.fix.smem_len = fbinfo->pitch * fbinfo->yres_virtual;+		fb->fb.screen_size = fbinfo->screen_size;+		if (fb->fb.screen_base)+			iounmap(fb->fb.screen_base);+		fb->fb.screen_base =+			(void *)ioremap_wc(fb->fb.fix.smem_start, fb->fb.screen_size);+		if (!fb->fb.screen_base) {+			/* the console may currently be locked */+			console_trylock();+			console_unlock();++			BUG();		/* what can we do here */+		}+	}+	print_debug+	    ("BCM2708FB: start = %p,%p width=%d, height=%d, bpp=%d, pitch=%d size=%d success=%d\n",+	     (void *)fb->fb.screen_base, (void *)fb->fb.fix.smem_start,+	     fbinfo->xres, fbinfo->yres, fbinfo->bpp,+	     fbinfo->pitch, (int)fb->fb.screen_size, val);++	return val;+}++static inline u32 convert_bitfield(int val, struct fb_bitfield *bf)+{+	unsigned int mask = (1 << bf->length) - 1;++	return (val >> (16 - bf->length) & mask) << bf->offset;+}+++static int bcm2708_fb_setcolreg(unsigned int regno, unsigned int red,+				unsigned int green, unsigned int blue,+				unsigned int transp, struct fb_info *info)+{+	struct bcm2708_fb *fb = to_bcm2708(info);++	/*print_debug("BCM2708FB: setcolreg %d:(%02x,%02x,%02x,%02x) %x\n", regno, red, green, blue, transp, fb->fb.fix.visual);*/+	if (fb->fb.var.bits_per_pixel <= 8) {+		if (regno < 256) {+			/* blue [0:4], green [5:10], red [11:15] */+			fb->info->cmap[regno] = ((red   >> (16-5)) & 0x1f) << 11 |+						((green >> (16-6)) & 0x3f) << 5 |+						((blue  >> (16-5)) & 0x1f) << 0;+		}+		/* Hack: we need to tell GPU the palette has changed, but currently bcm2708_fb_set_par takes noticable time when called for every (256) colour */+		/* So just call it for what looks like the last colour in a list for now. */+		if (regno == 15 || regno == 255)+			bcm2708_fb_set_par(info);+        } else if (regno < 16) {+		fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |+		    convert_bitfield(blue, &fb->fb.var.blue) |+		    convert_bitfield(green, &fb->fb.var.green) |+		    convert_bitfield(red, &fb->fb.var.red);+	}+	return regno > 255;+}++static int bcm2708_fb_blank(int blank_mode, struct fb_info *info)+{+	/*print_debug("bcm2708_fb_blank\n"); */+	return -1;+}++static void bcm2708_fb_fillrect(struct fb_info *info,+				const struct fb_fillrect *rect)+{+	/* (is called) print_debug("bcm2708_fb_fillrect\n"); */+	cfb_fillrect(info, rect);+}++/* A helper function for configuring dma control block */+static void set_dma_cb(struct bcm2708_dma_cb *cb,+		       int        burst_size,+		       dma_addr_t dst,+		       int        dst_stride,+		       dma_addr_t src,+		       int        src_stride,+		       int        w,+		       int        h)+{+	cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH |+		   BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH |+		   BCM2708_DMA_D_INC | BCM2708_DMA_TDMODE;+	cb->dst = dst;+	cb->src = src;+	/*+	 * This is not really obvious from the DMA documentation,+	 * but the top 16 bits must be programmmed to "height -1"+	 * and not "height" in 2D mode.+	 */+	cb->length = ((h - 1) << 16) | w;+	cb->stride = ((dst_stride - w) << 16) | (u16)(src_stride - w);+	cb->pad[0] = 0;+	cb->pad[1] = 0;+}++static void bcm2708_fb_copyarea(struct fb_info *info,+				const struct fb_copyarea *region)+{+	struct bcm2708_fb *fb = to_bcm2708(info);+	struct bcm2708_dma_cb *cb = fb->cb_base;+	int bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3;+	/* Channel 0 supports larger bursts and is a bit faster */+	int burst_size = (fb->dma_chan == 0) ? 8 : 2;++	/* Fallback to cfb_copyarea() if we don't like something */+	if (bytes_per_pixel > 4 ||+	    info->var.xres > 1920 || info->var.yres > 1200 ||+	    region->width <= 0 || region->width > info->var.xres ||+	    region->height <= 0 || region->height > info->var.yres ||+	    region->sx < 0 || region->sx >= info->var.xres ||+	    region->sy < 0 || region->sy >= info->var.yres ||+	    region->dx < 0 || region->dx >= info->var.xres ||+	    region->dy < 0 || region->dy >= info->var.yres ||+	    region->sx + region->width > info->var.xres ||+	    region->dx + region->width > info->var.xres ||+	    region->sy + region->height > info->var.yres ||+	    region->dy + region->height > info->var.yres) {+		cfb_copyarea(info, region);+		return;+	}++	if (region->dy == region->sy && region->dx > region->sx) {+		/*+		 * A difficult case of overlapped copy. Because DMA can't+		 * copy individual scanlines in backwards direction, we need+		 * two-pass processing. We do it by programming a chain of dma+		 * control blocks in the first 16K part of the buffer and use+		 * the remaining 48K as the intermediate temporary scratch+		 * buffer. The buffer size is sufficient to handle up to+		 * 1920x1200 resolution at 32bpp pixel depth.+		 */+		int y;+		dma_addr_t control_block_pa = fb->cb_handle;+		dma_addr_t scratchbuf = fb->cb_handle + 16 * 1024;+		int scanline_size = bytes_per_pixel * region->width;+		int scanlines_per_cb = (64 * 1024 - 16 * 1024) / scanline_size;++		for (y = 0; y < region->height; y += scanlines_per_cb) {+			dma_addr_t src =+				fb->fb.fix.smem_start ++				bytes_per_pixel * region->sx ++				(region->sy + y) * fb->fb.fix.line_length;+			dma_addr_t dst =+				fb->fb.fix.smem_start ++				bytes_per_pixel * region->dx ++				(region->dy + y) * fb->fb.fix.line_length;++			if (region->height - y < scanlines_per_cb)+				scanlines_per_cb = region->height - y;++			set_dma_cb(cb, burst_size, scratchbuf, scanline_size,+				   src, fb->fb.fix.line_length,+				   scanline_size, scanlines_per_cb);+			control_block_pa += sizeof(struct bcm2708_dma_cb);+			cb->next = control_block_pa;+			cb++;++			set_dma_cb(cb, burst_size, dst, fb->fb.fix.line_length,+				   scratchbuf, scanline_size,+				   scanline_size, scanlines_per_cb);+			control_block_pa += sizeof(struct bcm2708_dma_cb);+			cb->next = control_block_pa;+			cb++;+		}+		/* move the pointer back to the last dma control block */+		cb--;+	} else {+		/* A single dma control block is enough. */+		int sy, dy, stride;+		if (region->dy <= region->sy) {+			/* processing from top to bottom */+			dy = region->dy;+			sy = region->sy;+			stride = fb->fb.fix.line_length;+		} else {+			/* processing from bottom to top */+			dy = region->dy + region->height - 1;+			sy = region->sy + region->height - 1;+			stride = -fb->fb.fix.line_length;+		}+		set_dma_cb(cb, burst_size,+			   fb->fb.fix.smem_start + dy * fb->fb.fix.line_length ++						   bytes_per_pixel * region->dx,+			   stride,+			   fb->fb.fix.smem_start + sy * fb->fb.fix.line_length ++						   bytes_per_pixel * region->sx,+			   stride,+			   region->width * bytes_per_pixel,+			   region->height);+	}++	/* end of dma control blocks chain */+	cb->next = 0;++	bcm_dma_start(fb->dma_chan_base, fb->cb_handle);+	bcm_dma_wait_idle(fb->dma_chan_base);+}++static void bcm2708_fb_imageblit(struct fb_info *info,+				 const struct fb_image *image)+{+	/* (is called) print_debug("bcm2708_fb_imageblit\n"); */+	cfb_imageblit(info, image);+}++static struct fb_ops bcm2708_fb_ops = {+	.owner = THIS_MODULE,+	.fb_check_var = bcm2708_fb_check_var,+	.fb_set_par = bcm2708_fb_set_par,+	.fb_setcolreg = bcm2708_fb_setcolreg,+	.fb_blank = bcm2708_fb_blank,+	.fb_fillrect = bcm2708_fb_fillrect,+	.fb_copyarea = bcm2708_fb_copyarea,+	.fb_imageblit = bcm2708_fb_imageblit,+};++static int fbwidth = 800;	/* module parameter */+static int fbheight = 480;	/* module parameter */+static int fbdepth = 16;	/* module parameter */++static int bcm2708_fb_register(struct bcm2708_fb *fb)+{+	int ret;+	dma_addr_t dma;+	void *mem;++	mem =+	    dma_alloc_coherent(NULL, PAGE_ALIGN(sizeof(*fb->info)), &dma,+			       GFP_KERNEL);++	if (NULL == mem) {+		pr_err(": unable to allocate fbinfo buffer\n");+		ret = -ENOMEM;+	} else {+		fb->info = (struct fbinfo_s *)mem;+		fb->dma = dma;+	}+	fb->fb.fbops = &bcm2708_fb_ops;+	fb->fb.flags = FBINFO_FLAG_DEFAULT | FBINFO_HWACCEL_COPYAREA;+	fb->fb.pseudo_palette = fb->cmap;++	strncpy(fb->fb.fix.id, bcm2708_name, sizeof(fb->fb.fix.id));+	fb->fb.fix.type = FB_TYPE_PACKED_PIXELS;+	fb->fb.fix.type_aux = 0;+	fb->fb.fix.xpanstep = 0;+	fb->fb.fix.ypanstep = 0;+	fb->fb.fix.ywrapstep = 0;+	fb->fb.fix.accel = FB_ACCEL_NONE;++	fb->fb.var.xres = fbwidth;+	fb->fb.var.yres = fbheight;+	fb->fb.var.xres_virtual = fbwidth;+	fb->fb.var.yres_virtual = fbheight;+	fb->fb.var.bits_per_pixel = fbdepth;+	fb->fb.var.vmode = FB_VMODE_NONINTERLACED;+	fb->fb.var.activate = FB_ACTIVATE_NOW;+	fb->fb.var.nonstd = 0;+	fb->fb.var.height = -1;		/* height of picture in mm    */+	fb->fb.var.width = -1;		/* width of picture in mm    */+	fb->fb.var.accel_flags = 0;++	fb->fb.monspecs.hfmin = 0;+	fb->fb.monspecs.hfmax = 100000;+	fb->fb.monspecs.vfmin = 0;+	fb->fb.monspecs.vfmax = 400;+	fb->fb.monspecs.dclkmin = 1000000;+	fb->fb.monspecs.dclkmax = 100000000;++	bcm2708_fb_set_bitfields(&fb->fb.var);++	/*+	 * Allocate colourmap.+	 */++	fb_set_var(&fb->fb, &fb->fb.var);++	print_debug("BCM2708FB: registering framebuffer (%dx%d@%d)\n", fbwidth,+		fbheight, fbdepth);++	ret = register_framebuffer(&fb->fb);+	print_debug("BCM2708FB: register framebuffer (%d)\n", ret);+	if (ret == 0)+		goto out;++	print_debug("BCM2708FB: cannot register framebuffer (%d)\n", ret);+out:+	return ret;+}++static int bcm2708_fb_probe(struct platform_device *dev)+{+	struct bcm2708_fb *fb;+	int ret;++	fb = kmalloc(sizeof(struct bcm2708_fb), GFP_KERNEL);+	if (!fb) {+		dev_err(&dev->dev,+			"could not allocate new bcm2708_fb struct\n");+		ret = -ENOMEM;+		goto free_region;+	}+	memset(fb, 0, sizeof(struct bcm2708_fb));++	fb->cb_base = dma_alloc_writecombine(&dev->dev, SZ_64K,+					     &fb->cb_handle, GFP_KERNEL);+	if (!fb->cb_base) {+		dev_err(&dev->dev, "cannot allocate DMA CBs\n");+		ret = -ENOMEM;+		goto free_fb;+	}++	pr_info("BCM2708FB: allocated DMA memory %08x\n",+	       fb->cb_handle);++	ret = bcm_dma_chan_alloc(BCM_DMA_FEATURE_BULK,+				 &fb->dma_chan_base, &fb->dma_irq);+	if (ret < 0) {+		dev_err(&dev->dev, "couldn't allocate a DMA channel\n");+		goto free_cb;+	}+	fb->dma_chan = ret;++	pr_info("BCM2708FB: allocated DMA channel %d @ %p\n",+	       fb->dma_chan, fb->dma_chan_base);++	fb->dev = dev;++	ret = bcm2708_fb_register(fb);+	if (ret == 0) {+		platform_set_drvdata(dev, fb);+		goto out;+	}++free_cb:+	dma_free_writecombine(&dev->dev, SZ_64K, fb->cb_base, fb->cb_handle);+free_fb:+	kfree(fb);+free_region:+	dev_err(&dev->dev, "probe failed, err %d\n", ret);+out:+	return ret;+}++static int bcm2708_fb_remove(struct platform_device *dev)+{+	struct bcm2708_fb *fb = platform_get_drvdata(dev);++	platform_set_drvdata(dev, NULL);++	if (fb->fb.screen_base)+		iounmap(fb->fb.screen_base);+	unregister_framebuffer(&fb->fb);++	dma_free_writecombine(&dev->dev, SZ_64K, fb->cb_base, fb->cb_handle);+	bcm_dma_chan_free(fb->dma_chan);++	dma_free_coherent(NULL, PAGE_ALIGN(sizeof(*fb->info)), (void *)fb->info,+			  fb->dma);+	kfree(fb);++	return 0;+}++static struct platform_driver bcm2708_fb_driver = {+	.probe = bcm2708_fb_probe,+	.remove = bcm2708_fb_remove,+	.driver = {+		   .name = DRIVER_NAME,+		   .owner = THIS_MODULE,+		   },+};++static int __init bcm2708_fb_init(void)+{+	return platform_driver_register(&bcm2708_fb_driver);+}++module_init(bcm2708_fb_init);++static void __exit bcm2708_fb_exit(void)+{+	platform_driver_unregister(&bcm2708_fb_driver);+}++module_exit(bcm2708_fb_exit);++module_param(fbwidth, int, 0644);+module_param(fbheight, int, 0644);+module_param(fbdepth, int, 0644);++MODULE_DESCRIPTION("BCM2708 framebuffer driver");+MODULE_LICENSE("GPL");++MODULE_PARM_DESC(fbwidth, "Width of ARM Framebuffer");+MODULE_PARM_DESC(fbheight, "Height of ARM Framebuffer");+MODULE_PARM_DESC(fbdepth, "Bit depth of ARM Framebuffer");diff -Nur linux-3.11.10.orig/drivers/video/cfbimgblt.c linux-3.11.10/drivers/video/cfbimgblt.c--- linux-3.11.10.orig/drivers/video/cfbimgblt.c	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/video/cfbimgblt.c	2014-02-07 19:57:30.000000000 +0100@@ -28,6 +28,11 @@  *  *  Also need to add code to deal with cards endians that are different than  *  the native cpu endians. I also need to deal with MSB position in the word.+ *  Modified by Harm Hanemaaijer (fgenfb@yahoo.com) 2013:+ *  - Provide optimized versions of fast_imageblit for 16 and 32bpp that are+ *    significantly faster than the previous implementation.+ *  - Simplify the fast/slow_imageblit selection code, avoiding integer+ *    divides.  */ #include <linux/module.h> #include <linux/string.h>@@ -262,6 +267,133 @@ 	} }	 	+/*+ * Optimized fast_imageblit for bpp == 16. ppw = 2, bit_mask = 3 folded+ * into the code, main loop unrolled.+ */++static inline void fast_imageblit16(const struct fb_image *image,+				    struct fb_info *p, u8 __iomem * dst1,+				    u32 fgcolor, u32 bgcolor)+{+	u32 fgx = fgcolor, bgx = bgcolor;+	u32 spitch = (image->width + 7) / 8;+	u32 end_mask, eorx;+	const char *s = image->data, *src;+	u32 __iomem *dst;+	const u32 *tab = NULL;+	int i, j, k;++	tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;++	fgx <<= 16;+	bgx <<= 16;+	fgx |= fgcolor;+	bgx |= bgcolor;++	eorx = fgx ^ bgx;+	k = image->width / 2;++	for (i = image->height; i--;) {+		dst = (u32 __iomem *) dst1;+		src = s;++		j = k;+		while (j >= 4) {+			u8 bits = *src;+			end_mask = tab[(bits >> 6) & 3];+			FB_WRITEL((end_mask & eorx) ^ bgx, dst++);+			end_mask = tab[(bits >> 4) & 3];+			FB_WRITEL((end_mask & eorx) ^ bgx, dst++);+			end_mask = tab[(bits >> 2) & 3];+			FB_WRITEL((end_mask & eorx) ^ bgx, dst++);+			end_mask = tab[bits & 3];+			FB_WRITEL((end_mask & eorx) ^ bgx, dst++);+			src++;+			j -= 4;+		}+		if (j != 0) {+			u8 bits = *src;+			end_mask = tab[(bits >> 6) & 3];+			FB_WRITEL((end_mask & eorx) ^ bgx, dst++);+			if (j >= 2) {+				end_mask = tab[(bits >> 4) & 3];+				FB_WRITEL((end_mask & eorx) ^ bgx, dst++);+				if (j == 3) {+					end_mask = tab[(bits >> 2) & 3];+					FB_WRITEL((end_mask & eorx) ^ bgx, dst);+				}+			}+		}+		dst1 += p->fix.line_length;+		s += spitch;+	}+}++/*+ * Optimized fast_imageblit for bpp == 32. ppw = 1, bit_mask = 1 folded+ * into the code, main loop unrolled.+ */++static inline void fast_imageblit32(const struct fb_image *image,+				    struct fb_info *p, u8 __iomem * dst1,+				    u32 fgcolor, u32 bgcolor)+{+	u32 fgx = fgcolor, bgx = bgcolor;+	u32 spitch = (image->width + 7) / 8;+	u32 end_mask, eorx;+	const char *s = image->data, *src;+	u32 __iomem *dst;+	const u32 *tab = NULL;+	int i, j, k;++	tab = cfb_tab32;++	eorx = fgx ^ bgx;+	k = image->width;++	for (i = image->height; i--;) {+		dst = (u32 __iomem *) dst1;+		src = s;++		j = k;+		while (j >= 8) {+			u8 bits = *src;+			end_mask = tab[(bits >> 7) & 1];+			FB_WRITEL((end_mask & eorx) ^ bgx, dst++);+			end_mask = tab[(bits >> 6) & 1];+			FB_WRITEL((end_mask & eorx) ^ bgx, dst++);+			end_mask = tab[(bits >> 5) & 1];+			FB_WRITEL((end_mask & eorx) ^ bgx, dst++);+			end_mask = tab[(bits >> 4) & 1];+			FB_WRITEL((end_mask & eorx) ^ bgx, dst++);+			end_mask = tab[(bits >> 3) & 1];+			FB_WRITEL((end_mask & eorx) ^ bgx, dst++);+			end_mask = tab[(bits >> 2) & 1];+			FB_WRITEL((end_mask & eorx) ^ bgx, dst++);+			end_mask = tab[(bits >> 1) & 1];+			FB_WRITEL((end_mask & eorx) ^ bgx, dst++);+			end_mask = tab[bits & 1];+			FB_WRITEL((end_mask & eorx) ^ bgx, dst++);+			src++;+			j -= 8;+		}+		if (j != 0) {+			u32 bits = (u32) * src;+			while (j > 1) {+				end_mask = tab[(bits >> 7) & 1];+				FB_WRITEL((end_mask & eorx) ^ bgx, dst++);+				bits <<= 1;+				j--;+			}+			end_mask = tab[(bits >> 7) & 1];+			FB_WRITEL((end_mask & eorx) ^ bgx, dst);+		}+		dst1 += p->fix.line_length;+		s += spitch;+	}+}+ void cfb_imageblit(struct fb_info *p, const struct fb_image *image) { 	u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;@@ -294,11 +426,21 @@ 			bgcolor = image->bg_color; 		}	 		-		if (32 % bpp == 0 && !start_index && !pitch_index && -		    ((width & (32/bpp-1)) == 0) &&-		    bpp >= 8 && bpp <= 32) 			-			fast_imageblit(image, p, dst1, fgcolor, bgcolor);-		else +		if (!start_index && !pitch_index) {+			if (bpp == 32)+				fast_imageblit32(image, p, dst1, fgcolor,+						 bgcolor);+			else if (bpp == 16 && (width & 1) == 0)+				fast_imageblit16(image, p, dst1, fgcolor,+						 bgcolor);+			else if (bpp == 8 && (width & 3) == 0)+				fast_imageblit(image, p, dst1, fgcolor,+					       bgcolor);+			else+				slow_imageblit(image, p, dst1, fgcolor,+					       bgcolor,+					       start_index, pitch_index);+		} else 			slow_imageblit(image, p, dst1, fgcolor, bgcolor, 					start_index, pitch_index); 	} elsediff -Nur linux-3.11.10.orig/drivers/video/fbmem.c linux-3.11.10/drivers/video/fbmem.c--- linux-3.11.10.orig/drivers/video/fbmem.c	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/video/fbmem.c	2014-02-07 19:57:30.000000000 +0100@@ -1074,6 +1074,25 @@  	return ret; } +static int fb_copyarea_user(struct fb_info *info,+			    struct fb_copyarea *copy)+{+	int ret = 0;+	if (!lock_fb_info(info))+		return -ENODEV;+	if (copy->dx + copy->width > info->var.xres ||+	    copy->sx + copy->width > info->var.xres ||+	    copy->dy + copy->height > info->var.yres ||+	    copy->sy + copy->height > info->var.yres) {+		ret = -EINVAL;+		goto out;+	}+	info->fbops->fb_copyarea(info, copy);+out:+	unlock_fb_info(info);+	return ret;+}+ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, 			unsigned long arg) {@@ -1084,6 +1103,7 @@ 	struct fb_cmap cmap_from; 	struct fb_cmap_user cmap; 	struct fb_event event;+	struct fb_copyarea copy; 	void __user *argp = (void __user *)arg; 	long ret = 0; @@ -1193,6 +1213,15 @@ 		console_unlock(); 		unlock_fb_info(info); 		break;+	case FBIOCOPYAREA:+		if (info->flags & FBINFO_HWACCEL_COPYAREA) {+			/* only provide this ioctl if it is accelerated */+			if (copy_from_user(©, argp, sizeof(copy)))+				return -EFAULT;+			ret = fb_copyarea_user(info, ©);+			break;+		}+		/* fall through */ 	default: 		if (!lock_fb_info(info)) 			return -ENODEV;@@ -1347,6 +1376,7 @@ 	case FBIOPAN_DISPLAY: 	case FBIOGET_CON2FBMAP: 	case FBIOPUT_CON2FBMAP:+	case FBIOCOPYAREA: 		arg = (unsigned long) compat_ptr(arg); 	case FBIOBLANK: 		ret = do_fb_ioctl(info, cmd, arg);diff -Nur linux-3.11.10.orig/drivers/video/Kconfig linux-3.11.10/drivers/video/Kconfig--- linux-3.11.10.orig/drivers/video/Kconfig	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/video/Kconfig	2014-02-07 19:57:30.000000000 +0100@@ -310,6 +310,20 @@ 	help 	  Support the Permedia2 FIFO disconnect feature. +config FB_BCM2708+	tristate "BCM2708 framebuffer support"+	depends on FB && ARM+	select FB_CFB_FILLRECT+	select FB_CFB_COPYAREA+	select FB_CFB_IMAGEBLIT+	help+	  This framebuffer device driver is for the BCM2708 framebuffer.++	  If you want to compile this as a module (=code which can be+	  inserted into and removed from the running kernel), say M+	  here and read <file:Documentation/kbuild/modules.txt>.  The module+	  will be called bcm2708_fb.+ config FB_ARMCLCD 	tristate "ARM PrimeCell PL110 support" 	depends on FB && ARM && ARM_AMBAdiff -Nur linux-3.11.10.orig/drivers/video/logo/logo_linux_clut224.ppm linux-3.11.10/drivers/video/logo/logo_linux_clut224.ppm--- linux-3.11.10.orig/drivers/video/logo/logo_linux_clut224.ppm	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/video/logo/logo_linux_clut224.ppm	2014-02-07 19:57:30.000000000 +0100@@ -1,883 +1,883 @@ P3-80 80+63 80 255-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 11 15 17 33 49 54 59 85 92 73 97 106 -83 116 129 105 131 142 115 114 122 74 88 93 20 29 31 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 6 6 6 10 10 10 10 10 10 -10 10 10 6 6 6 6 6 6 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 2 3 3 17 23 26 50 67 72 73 97 106 59 85 92 73 97 106 -105 131 142 124 127 131 105 131 142 105 131 142 53 75 83 6 8 8 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 6 6 6 10 10 10 14 14 14 22 22 22 26 26 26 30 30 30 34 34 34 -30 30 30 30 30 30 26 26 26 18 18 18 14 14 14 10 10 10 6 6 6 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 -0 0 0 1 1 1 26 35 39 59 85 92 59 85 92 59 85 92 29 43 47 53 75 83 -108 122 132 132 98 104 108 122 132 105 131 142 101 101 101 43 45 48 6 8 8 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6 6 6 14 14 14 26 26 26 42 42 42 54 54 54 66 66 66 78 78 78 78 78 78 -78 78 78 74 74 74 66 66 66 54 54 54 42 42 42 26 26 26 18 18 18 10 10 10 -6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 -11 15 17 27 40 45 59 85 92 59 85 92 27 40 45 31 45 49 73 97 106 93 121 133 -108 122 132 108 122 132 105 131 142 108 122 132 105 131 142 73 97 106 26 35 39 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 -22 22 22 42 42 42 66 66 66 86 86 86 66 66 66 38 38 38 38 38 38 22 22 22 -26 26 26 34 34 34 54 54 54 66 66 66 86 86 86 70 70 70 46 46 46 26 26 26 -14 14 14 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 7 12 13 21 31 35 42 59 64 -53 75 83 53 75 83 50 67 72 42 59 64 32 40 45 42 59 64 73 97 106 116 116 116 -132 98 104 116 116 116 108 122 132 117 104 110 105 131 142 83 116 129 50 67 72 7 12 13 -1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 26 26 26 -50 50 50 82 82 82 58 58 58 6 6 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 2 2 6 2 2 6 6 6 6 54 54 54 86 86 86 66 66 66 -38 38 38 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 1 1 1 6 8 8 15 22 25 26 35 39 36 54 60 53 75 83 59 85 92 -59 85 92 48 63 69 15 22 25 12 17 20 52 67 79 94 94 94 132 98 104 132 98 104 -117 104 110 108 122 132 108 122 132 115 114 122 105 131 142 77 105 114 59 85 92 36 54 60 -7 12 13 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 22 22 22 50 50 50 -78 78 78 34 34 34 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 6 6 6 70 70 70 -78 78 78 46 46 46 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 15 22 25 29 43 47 36 54 60 42 59 64 42 59 64 48 63 69 21 31 35 -6 8 8 29 43 47 36 50 56 43 45 48 79 78 84 132 98 104 165 78 79 132 98 104 -108 122 132 117 104 110 117 104 110 108 122 132 77 105 114 73 97 106 95 131 149 78 102 129 -36 50 56 0 0 0 0 0 0 0 0 0 6 6 6 18 18 18 42 42 42 82 82 82 -26 26 26 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 2 2 6 14 14 14 46 46 46 34 34 34 6 6 6 2 2 6 -42 42 42 78 78 78 42 42 42 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --27 40 45 53 75 83 48 63 69 24 31 37 6 8 12 0 0 0 18 25 28 26 35 39 -12 17 20 26 35 39 65 78 84 112 81 86 152 81 83 137 83 86 132 98 104 117 104 110 -117 104 110 132 98 104 132 98 104 115 114 122 73 97 106 53 75 83 95 131 149 93 124 152 -68 78 128 15 22 25 0 0 0 0 0 0 10 10 10 30 30 30 66 66 66 58 58 58 -2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 2 2 6 26 26 26 86 86 86 101 101 101 46 46 46 10 10 10 -2 2 6 58 58 58 70 70 70 34 34 34 10 10 10 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --36 50 56 21 30 33 4 7 7 0 0 0 1 1 1 17 12 12 69 31 31 68 59 64 -57 59 63 21 31 35 32 40 45 86 73 69 152 81 83 152 81 83 117 104 110 132 98 104 -152 81 83 132 98 104 108 122 132 77 105 114 77 105 114 93 121 133 95 131 149 93 124 152 -95 131 149 53 75 83 11 15 17 0 0 0 14 14 14 42 42 42 86 86 86 10 10 10 -2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 2 2 6 30 30 30 94 94 94 94 94 94 58 58 58 26 26 26 -2 2 6 6 6 6 78 78 78 54 54 54 22 22 22 6 6 6 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --17 23 26 2 3 3 0 0 0 17 12 12 69 31 31 123 55 55 123 55 55 152 81 83 -86 73 69 17 23 26 7 12 13 45 54 57 101 101 101 137 83 86 132 98 104 132 98 104 -137 83 86 117 104 110 77 105 114 42 59 64 50 67 72 78 102 129 91 117 157 91 117 157 -95 131 149 83 116 129 40 48 73 6 6 6 22 22 22 62 62 62 62 62 62 2 2 6 -2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 2 2 6 26 26 26 54 54 54 38 38 38 18 18 18 10 10 10 -2 2 6 2 2 6 34 34 34 82 82 82 38 38 38 14 14 14 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --1 1 1 1 2 2 2 3 3 28 12 12 123 55 55 174 79 79 174 79 79 174 79 79 -152 81 83 68 59 64 26 35 39 27 40 45 79 78 84 137 83 86 165 78 79 137 83 86 -94 94 94 48 63 69 36 50 56 50 67 72 73 97 106 93 121 133 93 124 152 93 124 152 -95 131 149 91 118 149 78 102 129 27 40 45 30 30 30 78 78 78 30 30 30 2 2 6 -2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 2 2 6 10 10 10 10 10 10 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 2 2 6 78 78 78 50 50 50 18 18 18 6 6 6 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --4 5 3 24 53 24 19 31 15 8 7 3 90 61 47 165 78 79 174 79 79 174 79 79 -174 79 79 137 83 86 60 52 57 7 12 13 17 23 26 70 70 70 132 98 104 112 81 86 -79 78 84 31 45 49 15 22 25 53 75 83 91 118 149 86 106 160 91 117 157 93 124 152 -91 117 157 93 124 152 95 131 149 53 75 83 50 50 50 86 86 86 14 14 14 2 2 6 -2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 2 2 6 54 54 54 66 66 66 26 26 26 6 6 6 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --19 31 15 34 76 34 34 76 34 19 31 15 28 12 12 123 55 55 174 79 79 174 79 79 -174 79 79 165 78 79 112 81 86 32 40 45 15 22 25 38 53 58 65 78 84 29 31 32 -21 30 33 42 59 64 60 80 103 78 102 129 87 112 149 84 96 162 91 117 157 93 124 152 -91 117 157 93 124 152 93 121 133 59 85 92 57 68 71 82 85 86 2 2 6 2 2 6 -2 2 6 6 6 6 10 10 10 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 2 2 6 6 6 6 14 14 14 10 10 10 2 2 6 2 2 6 -2 2 6 2 2 6 2 2 6 18 18 18 82 82 82 34 34 34 10 10 10 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --34 76 34 40 89 40 40 89 40 34 76 34 8 15 6 48 26 18 123 55 55 174 79 79 -174 79 79 174 79 79 137 83 86 68 59 64 32 40 45 21 30 33 31 45 49 21 31 35 -12 17 20 48 63 69 78 102 129 81 88 166 84 96 162 91 117 157 93 124 152 91 117 157 -93 124 152 95 131 149 83 116 129 59 85 92 57 68 71 86 86 86 2 2 6 2 2 6 -6 6 6 6 6 6 22 22 22 34 34 34 6 6 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 18 18 18 34 34 34 10 10 10 50 50 50 22 22 22 2 2 6 -2 2 6 2 2 6 2 2 6 10 10 10 86 86 86 42 42 42 14 14 14 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --40 89 40 40 89 40 40 89 40 40 89 40 24 53 24 6 6 6 69 31 31 123 55 55 -123 55 55 90 61 47 69 31 31 36 32 33 21 31 35 7 12 13 18 25 28 48 63 69 -60 80 103 68 78 128 84 101 153 84 96 162 84 96 162 91 117 157 91 117 157 84 96 162 -91 117 157 73 97 106 48 63 69 50 67 72 57 59 63 86 86 86 2 2 6 2 2 6 -38 38 38 116 116 116 94 94 94 22 22 22 22 22 22 2 2 6 2 2 6 2 2 6 -14 14 14 86 86 86 124 131 137 170 170 170 151 151 151 38 38 38 26 26 26 6 6 6 -2 2 6 2 2 6 2 2 6 2 2 6 86 86 86 46 46 46 14 14 14 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --34 76 34 40 89 40 40 89 40 40 89 40 34 76 34 19 31 15 17 12 12 48 26 18 -48 26 18 8 7 3 10 10 22 23 29 47 51 61 92 42 59 64 21 30 33 34 45 54 -68 78 128 81 88 166 81 82 173 86 106 160 86 106 160 84 96 162 86 106 160 87 112 149 -91 118 149 77 105 114 52 67 79 32 40 45 50 50 50 86 86 86 2 2 6 14 14 14 -124 131 137 198 198 198 195 195 195 116 116 116 10 10 10 2 2 6 2 2 6 6 6 6 -101 98 89 187 187 187 210 210 210 218 218 218 214 214 214 124 131 137 14 14 14 6 6 6 -2 2 6 2 2 6 2 2 6 2 2 6 86 86 86 50 50 50 18 18 18 6 6 6 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --19 31 15 34 76 34 40 89 40 40 89 40 40 89 40 24 53 24 8 7 3 0 0 0 -6 8 12 28 32 52 51 61 92 54 54 122 74 77 160 68 78 128 26 35 39 6 8 8 -34 45 54 68 78 128 84 96 162 86 106 160 86 106 160 81 88 166 84 96 162 87 112 149 -73 97 106 36 50 56 33 49 54 18 18 18 46 46 46 86 86 86 2 2 6 54 54 54 -218 218 218 195 195 195 226 226 226 246 246 246 58 58 58 2 2 6 2 2 6 30 30 30 -210 210 210 253 253 253 170 170 170 124 127 131 221 221 221 234 234 234 74 74 74 2 2 6 -2 2 6 2 2 6 2 2 6 2 2 6 70 70 70 58 58 58 22 22 22 6 6 6 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --4 5 3 24 53 24 40 89 40 40 89 40 34 76 34 12 22 15 4 5 3 4 5 3 -13 17 26 54 54 122 78 78 174 78 78 174 78 78 174 74 77 160 51 61 92 21 31 35 -26 35 39 53 75 83 84 101 153 81 82 173 81 88 166 84 101 153 60 80 103 60 80 103 -53 75 83 38 53 58 42 59 64 22 22 22 46 46 46 82 82 82 2 2 6 106 106 106 -170 170 170 26 26 26 86 86 86 226 226 226 124 127 131 10 10 10 14 14 14 46 46 46 -231 231 231 190 190 190 6 6 6 70 70 70 90 90 90 238 238 238 151 151 151 2 2 6 -2 2 6 2 2 6 2 2 6 2 2 6 70 70 70 58 58 58 22 22 22 6 6 6 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --1 2 2 8 15 6 24 53 24 34 76 34 19 31 15 8 15 6 63 55 20 63 55 20 -18 18 18 40 48 73 74 77 160 78 78 174 78 78 174 81 82 173 74 77 160 52 67 79 -17 23 26 21 31 35 60 80 103 81 88 166 74 77 160 78 102 129 36 54 60 12 17 20 -42 59 64 48 63 69 21 31 35 18 18 18 42 42 42 86 86 86 6 6 6 116 116 116 -106 106 106 6 6 6 70 70 70 151 151 151 124 127 131 18 18 18 38 38 38 54 54 54 -221 221 221 106 106 106 2 2 6 14 14 14 46 46 46 190 190 190 198 198 198 2 2 6 -2 2 6 2 2 6 2 2 6 2 2 6 74 74 74 62 62 62 22 22 22 6 6 6 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --11 15 17 0 0 0 12 22 15 19 31 15 8 15 6 63 55 20 149 139 69 149 139 69 -63 55 20 10 10 22 54 54 122 78 78 174 78 78 174 78 78 174 81 82 173 68 78 128 -24 31 37 6 6 6 36 50 56 60 80 103 51 61 92 42 59 64 36 50 56 31 45 49 -29 43 47 27 40 45 6 8 8 14 14 14 42 42 42 94 94 94 14 14 14 101 101 101 -124 127 131 2 2 6 18 18 18 116 116 116 106 107 48 121 92 8 121 92 8 98 70 6 -170 170 170 106 106 106 2 2 6 2 2 6 2 2 6 195 195 195 195 195 195 6 6 6 -2 2 6 2 2 6 2 2 6 2 2 6 74 74 74 62 62 62 22 22 22 6 6 6 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --26 35 39 3 5 6 1 1 1 2 3 3 35 31 12 133 118 54 175 176 80 175 176 80 -133 118 54 35 31 12 23 29 47 54 54 122 78 78 174 78 78 174 74 77 160 68 78 128 -51 61 92 31 45 49 26 35 39 36 50 56 29 43 47 7 12 13 21 30 33 42 59 64 -18 25 28 7 12 13 1 1 1 10 10 10 38 38 38 90 90 90 14 14 14 58 58 58 -210 210 210 26 26 26 62 42 6 154 114 10 226 170 11 237 188 10 220 174 15 184 138 11 -220 174 15 174 140 55 35 31 12 2 2 6 70 70 70 246 246 246 124 131 137 2 2 6 -2 2 6 2 2 6 2 2 6 2 2 6 70 70 70 66 66 66 26 26 26 6 6 6 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --27 40 45 17 23 26 2 3 3 1 1 1 56 77 35 165 152 80 175 176 80 175 176 80 -175 176 80 106 107 48 22 22 22 28 32 52 54 54 122 54 54 122 51 61 92 28 32 52 -20 27 34 31 45 49 11 15 17 7 12 13 36 50 56 31 45 49 29 43 47 36 50 56 -6 8 8 0 0 0 0 0 0 10 10 10 38 38 38 86 86 86 14 14 14 10 10 10 -195 195 195 198 179 130 192 133 9 220 174 15 239 182 13 237 188 10 232 195 16 239 207 25 -237 201 50 241 208 19 232 195 16 184 138 11 198 179 130 208 206 196 42 42 42 2 2 6 -2 2 6 2 2 6 2 2 6 2 2 6 50 50 50 74 74 74 30 30 30 6 6 6 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --15 22 25 26 35 39 15 22 25 0 0 0 35 31 12 133 118 54 175 176 80 175 176 80 -175 176 80 165 152 80 56 77 35 6 8 12 23 29 47 13 17 26 2 2 6 0 0 0 -1 2 2 26 35 39 26 35 39 26 35 39 42 59 64 42 59 64 20 29 31 6 8 8 -0 0 0 0 0 0 0 0 0 10 10 10 34 34 34 86 86 86 14 14 14 2 2 6 -121 92 8 192 133 9 219 162 10 239 182 13 237 188 10 232 195 16 241 208 19 237 201 50 -237 201 50 239 207 25 241 208 19 241 208 19 241 208 19 230 187 11 121 92 8 2 2 6 -2 2 6 2 2 6 2 2 6 2 2 6 50 50 50 82 82 82 34 34 34 10 10 10 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --1 2 2 15 22 25 31 45 49 6 8 12 4 5 3 63 55 20 149 139 69 175 176 80 -175 176 80 175 176 80 106 107 48 20 16 6 1 1 1 0 0 0 2 3 3 11 15 17 -21 30 33 36 50 56 36 50 56 24 31 37 15 22 25 6 8 8 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 10 10 10 34 34 34 82 82 82 30 30 30 62 42 6 -180 123 7 206 145 10 230 174 11 239 182 13 237 188 10 238 202 15 241 208 19 237 201 50 -239 207 25 241 208 19 241 208 19 241 208 19 230 187 11 220 174 15 184 138 11 6 6 6 -2 2 6 2 2 6 2 2 6 2 2 6 26 26 26 94 94 94 42 42 42 14 14 14 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 1 2 2 29 43 47 26 35 39 3 5 6 8 7 3 106 107 48 165 152 80 -175 176 80 149 139 69 63 55 20 4 5 3 2 3 3 12 17 20 26 35 39 26 35 39 -17 23 26 7 12 13 6 8 8 3 5 6 1 2 2 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 10 10 10 30 30 30 78 78 78 50 50 50 104 69 6 -192 133 9 216 158 10 236 178 12 237 188 10 232 195 16 241 208 19 237 201 50 237 201 50 -241 208 19 241 208 19 241 208 19 204 160 10 200 144 11 216 158 10 156 118 10 2 2 6 -2 2 6 2 2 6 2 2 6 2 2 6 6 6 6 90 90 90 54 54 54 18 18 18 -6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 12 17 20 27 40 45 18 25 28 1 1 1 35 31 12 106 107 48 -149 139 69 56 77 35 8 7 3 1 2 2 12 17 20 26 35 39 21 31 35 11 15 17 -3 5 6 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 10 10 10 30 30 30 78 78 78 46 46 46 22 22 22 -137 92 6 204 160 10 239 182 13 237 188 10 238 202 15 241 208 19 241 208 19 241 208 19 -241 208 19 204 160 10 184 138 11 210 150 10 216 158 10 210 150 10 98 70 6 2 2 6 -6 6 6 54 54 54 14 14 14 2 2 6 2 2 6 62 62 62 74 74 74 30 30 30 -10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 1 1 1 15 22 25 33 49 54 12 17 20 2 3 3 35 31 12 -56 77 35 20 16 6 1 1 1 18 25 28 21 31 35 11 15 17 1 1 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 10 10 10 34 34 34 78 78 78 50 50 50 6 6 6 -88 55 22 139 102 15 190 146 13 230 187 11 239 207 25 232 195 16 220 174 15 190 146 13 -171 120 8 192 133 9 210 150 10 213 154 11 185 146 40 165 152 80 101 98 89 2 2 6 -2 2 6 78 78 78 116 116 116 58 58 58 2 2 6 22 22 22 90 90 90 46 46 46 -18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 1 1 1 27 40 45 29 43 47 3 5 6 2 3 3 -8 7 3 1 1 1 17 23 26 31 45 49 15 22 25 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 10 10 10 38 38 38 86 86 86 50 50 50 6 6 6 -124 127 131 168 158 138 156 107 11 171 120 8 204 160 10 184 138 11 197 138 11 200 144 11 -206 145 10 206 145 10 197 138 11 198 179 130 195 195 195 198 198 198 170 170 170 14 14 14 -2 2 6 22 22 22 116 116 116 116 116 116 22 22 22 2 2 6 74 74 74 70 70 70 -30 30 30 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 11 15 17 31 45 49 26 35 39 3 5 6 -0 0 0 7 12 13 27 40 45 18 25 28 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 6 6 6 18 18 18 50 50 50 101 101 101 26 26 26 10 10 10 -124 131 137 190 190 190 168 158 138 156 107 11 197 138 11 200 144 11 197 138 11 192 133 9 -180 123 7 185 146 40 198 179 130 187 187 187 202 202 202 221 221 221 214 214 214 66 66 66 -2 2 6 2 2 6 50 50 50 62 62 62 6 6 6 2 2 6 10 10 10 90 90 90 -50 50 50 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 15 22 25 36 54 60 18 25 28 -0 0 0 21 30 33 27 40 45 2 3 3 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 10 10 10 34 34 34 74 74 74 74 74 74 2 2 6 6 6 6 -151 151 151 198 198 198 190 190 190 168 158 138 148 132 55 156 107 11 156 107 11 169 125 40 -168 158 138 187 187 187 190 190 190 210 210 210 246 246 246 253 253 253 253 253 253 180 180 180 -6 6 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 62 62 62 -74 74 74 34 34 34 14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 27 40 45 35 52 58 -18 25 28 35 52 58 17 23 26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 10 10 10 22 22 22 54 54 54 94 94 94 18 18 18 2 2 6 46 46 46 -234 234 234 221 221 221 190 190 190 190 190 190 190 190 190 187 187 187 187 187 187 190 190 190 -190 190 190 195 195 195 214 214 214 242 242 242 253 253 253 253 253 253 253 253 253 253 253 253 -82 82 82 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 14 14 14 -86 86 86 54 54 54 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 12 13 33 49 54 -52 72 81 36 54 60 6 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6 6 6 18 18 18 46 46 46 90 90 90 46 46 46 18 18 18 6 6 6 180 180 180 -253 253 253 246 246 246 202 202 202 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 -202 202 202 231 231 231 250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -202 202 202 14 14 14 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -42 42 42 86 86 86 42 42 42 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 17 20 -36 54 60 29 43 47 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 -14 14 14 38 38 38 74 74 74 66 66 66 2 2 6 6 6 6 90 90 90 250 250 250 -253 253 253 253 253 253 238 238 238 198 198 198 190 190 190 190 190 190 195 195 195 221 221 221 -246 246 246 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 82 82 82 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 78 78 78 70 70 70 34 34 34 14 14 14 6 6 6 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -21 30 33 35 52 58 6 8 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 14 14 -34 34 34 66 66 66 78 78 78 6 6 6 2 2 6 18 18 18 218 218 218 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 226 226 226 231 231 231 246 246 246 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 180 180 180 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 18 18 18 90 90 90 62 62 62 30 30 30 10 10 10 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -12 17 20 36 54 60 29 43 47 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 26 26 26 -58 58 58 90 90 90 18 18 18 2 2 6 2 2 6 106 106 106 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 231 231 231 18 18 18 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 18 18 18 94 94 94 54 54 54 26 26 26 10 10 10 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 21 30 33 35 52 58 6 8 12 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 22 22 22 50 50 50 -90 90 90 26 26 26 2 2 6 2 2 6 14 14 14 195 195 195 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 242 242 242 54 54 54 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 2 2 6 38 38 38 86 86 86 50 50 50 22 22 22 6 6 6 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 12 17 20 36 54 60 29 43 47 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 14 14 14 38 38 38 82 82 82 -34 34 34 2 2 6 2 2 6 2 2 6 42 42 42 195 195 195 246 246 246 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 242 242 242 242 242 242 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 250 250 250 246 246 246 238 238 238 -226 226 226 231 231 231 101 101 101 6 6 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 2 2 6 2 2 6 38 38 38 82 82 82 42 42 42 14 14 14 -6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 30 33 35 52 58 6 8 12 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 26 26 26 62 62 62 66 66 66 -2 2 6 2 2 6 2 2 6 6 6 6 70 70 70 170 170 170 202 202 202 234 234 234 -246 246 246 250 250 250 250 250 250 238 238 238 226 226 226 231 231 231 238 238 238 250 250 250 -250 250 250 250 250 250 246 246 246 231 231 231 214 214 214 202 202 202 202 202 202 202 202 202 -198 198 198 202 202 202 180 180 180 18 18 18 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 62 62 62 66 66 66 30 30 30 -10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 12 17 20 36 54 60 29 43 47 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 14 14 14 42 42 42 82 82 82 18 18 18 -2 2 6 2 2 6 2 2 6 10 10 10 94 94 94 180 180 180 218 218 218 242 242 242 -250 250 250 253 253 253 253 253 253 250 250 250 234 234 234 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 238 238 238 226 226 226 210 210 210 202 202 202 -195 195 195 195 195 195 210 210 210 151 151 151 6 6 6 14 14 14 50 50 50 14 14 14 -2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 6 6 6 86 86 86 46 46 46 -18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 21 30 33 35 52 58 6 8 12 0 0 0 -0 0 0 0 0 0 0 0 0 6 6 6 22 22 22 54 54 54 70 70 70 2 2 6 -2 2 6 10 10 10 2 2 6 22 22 22 170 170 170 231 231 231 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 242 242 242 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 246 246 246 -231 231 231 202 202 202 198 198 198 226 226 226 94 94 94 2 2 6 6 6 6 38 38 38 -30 30 30 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 62 62 62 66 66 66 -26 26 26 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 6 8 8 33 49 54 29 43 47 6 8 12 -0 0 0 0 0 0 0 0 0 10 10 10 30 30 30 74 74 74 50 50 50 2 2 6 -26 26 26 26 26 26 2 2 6 106 106 106 238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 246 246 246 218 218 218 202 202 202 210 210 210 14 14 14 2 2 6 2 2 6 -30 30 30 22 22 22 2 2 6 2 2 6 2 2 6 2 2 6 18 18 18 86 86 86 -42 42 42 14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 17 20 33 49 54 17 23 26 -0 0 0 0 0 0 0 0 0 14 14 14 42 42 42 90 90 90 22 22 22 2 2 6 -42 42 42 2 2 6 18 18 18 218 218 218 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 250 250 250 221 221 221 218 218 218 101 101 101 2 2 6 14 14 14 -18 18 18 38 38 38 10 10 10 2 2 6 2 2 6 2 2 6 2 2 6 78 78 78 -58 58 58 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 22 25 36 54 60 -0 0 0 0 0 0 0 0 0 18 18 18 54 54 54 82 82 82 2 2 6 26 26 26 -22 22 22 2 2 6 124 127 131 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 238 238 238 198 198 198 6 6 6 38 38 38 -58 58 58 26 26 26 38 38 38 2 2 6 2 2 6 2 2 6 2 2 6 46 46 46 -78 78 78 30 30 30 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 30 33 -36 54 60 0 0 0 0 0 0 30 30 30 74 74 74 58 58 58 2 2 6 42 42 42 -2 2 6 22 22 22 231 231 231 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 246 246 246 46 46 46 38 38 38 -42 42 42 14 14 14 38 38 38 14 14 14 2 2 6 2 2 6 2 2 6 6 6 6 -86 86 86 46 46 46 14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -36 54 60 0 0 0 0 0 0 42 42 42 90 90 90 18 18 18 18 18 18 26 26 26 -2 2 6 116 116 116 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 250 250 250 238 238 238 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 94 94 94 6 6 6 -2 2 6 2 2 6 10 10 10 34 34 34 2 2 6 2 2 6 2 2 6 2 2 6 -74 74 74 58 58 58 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 36 54 60 26 26 26 66 66 66 82 82 82 2 2 6 38 38 38 6 6 6 -14 14 14 210 210 210 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 246 246 246 242 242 242 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 151 151 151 2 2 6 -2 2 6 2 2 6 2 2 6 46 46 46 2 2 6 2 2 6 2 2 6 2 2 6 -42 42 42 74 74 74 30 30 30 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6 6 6 36 54 60 21 30 33 90 90 90 26 26 26 6 6 6 42 42 42 2 2 6 -74 74 74 250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 242 242 242 242 242 242 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 180 180 180 2 2 6 -2 2 6 2 2 6 2 2 6 46 46 46 2 2 6 2 2 6 2 2 6 2 2 6 -10 10 10 86 86 86 38 38 38 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -10 10 10 26 26 26 36 54 60 82 82 82 2 2 6 22 22 22 18 18 18 2 2 6 -151 151 151 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 202 202 202 2 2 6 -2 2 6 2 2 6 2 2 6 38 38 38 2 2 6 2 2 6 2 2 6 2 2 6 -6 6 6 86 86 86 46 46 46 14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 -18 18 18 46 46 46 86 86 86 36 54 60 2 2 6 34 34 34 10 10 10 6 6 6 -210 210 210 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 221 221 6 6 6 -2 2 6 2 2 6 6 6 6 30 30 30 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 82 82 82 54 54 54 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 -26 26 26 66 66 66 62 62 62 2 2 6 2 2 6 38 38 38 10 10 10 26 26 26 -238 238 238 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 238 238 238 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 231 231 231 6 6 6 -2 2 6 2 2 6 10 10 10 30 30 30 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 66 66 66 58 58 58 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 -38 38 38 78 78 78 6 6 6 2 2 6 2 2 6 46 46 46 14 14 14 42 42 42 -246 246 246 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 242 242 242 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 234 234 234 10 10 10 -2 2 6 2 2 6 22 22 22 14 14 14 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 66 66 66 62 62 62 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 18 18 18 -50 50 50 74 74 74 2 2 6 2 2 6 14 14 14 70 70 70 34 34 34 62 62 62 -250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 234 234 234 14 14 14 -2 2 6 2 2 6 30 30 30 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 66 66 66 62 62 62 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 18 18 18 -54 54 54 62 62 62 2 2 6 2 2 6 2 2 6 30 30 30 46 46 46 70 70 70 -250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 226 226 226 10 10 10 -2 2 6 6 6 6 30 30 30 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 66 66 66 58 58 58 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 22 22 22 -58 58 58 62 62 62 2 2 6 2 2 6 2 2 6 2 2 6 30 30 30 78 78 78 -250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 202 202 202 2 2 6 -22 22 22 34 34 34 20 16 6 22 22 22 26 26 26 18 18 18 6 6 6 2 2 6 -2 2 6 82 82 82 54 54 54 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 26 26 26 -62 62 62 106 106 106 63 55 20 184 138 11 204 160 10 121 92 8 6 6 6 62 62 62 -238 238 238 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 151 151 151 18 18 18 -14 14 14 2 2 6 2 2 6 2 2 6 6 6 6 18 18 18 66 66 66 38 38 38 -6 6 6 94 94 94 50 50 50 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 6 6 6 10 10 10 10 10 10 18 18 18 38 38 38 -78 78 78 138 132 106 216 158 10 242 186 14 246 190 14 246 190 14 156 118 10 10 10 10 -90 90 90 238 238 238 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 230 190 214 187 87 214 187 87 185 146 40 35 31 12 -2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 38 38 38 46 46 46 -26 26 26 106 106 106 54 54 54 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 6 6 6 14 14 14 22 22 22 30 30 30 38 38 38 50 50 50 70 70 70 -106 106 106 185 146 40 226 170 11 242 186 14 246 190 14 246 190 14 246 190 14 154 114 10 -6 6 6 74 74 74 226 226 226 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 237 201 50 241 196 14 241 208 19 232 195 16 35 31 12 -2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 6 6 6 30 30 30 26 26 26 -204 160 10 165 152 80 66 66 66 26 26 26 6 6 6 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6 6 6 18 18 18 38 38 38 58 58 58 78 78 78 86 86 86 101 101 101 124 127 131 -174 140 55 210 150 10 234 174 13 246 186 14 246 190 14 246 190 14 246 190 14 237 188 10 -98 70 6 2 2 6 46 46 46 198 198 198 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 214 187 87 242 186 14 241 196 14 204 160 10 20 16 6 -2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 6 6 6 121 92 8 -238 202 15 232 195 16 82 82 82 34 34 34 10 10 10 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -14 14 14 38 38 38 70 70 70 148 132 55 185 146 40 200 144 11 197 138 11 197 138 11 -213 154 11 226 170 11 242 186 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -220 174 15 35 31 12 2 2 6 22 22 22 151 151 151 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 242 242 242 214 187 87 239 182 13 237 188 10 213 154 11 35 31 12 -2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 62 42 6 220 174 15 -237 188 10 237 188 10 113 101 86 42 42 42 14 14 14 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 -22 22 22 54 54 54 148 132 55 213 154 11 226 170 11 230 174 11 226 170 11 226 170 11 -236 178 12 242 186 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -241 196 14 184 138 11 10 10 10 2 2 6 6 6 6 116 116 116 242 242 242 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 231 231 231 198 198 198 213 164 39 236 178 12 236 178 12 210 150 10 137 92 6 -20 16 6 2 2 6 2 2 6 2 2 6 6 6 6 62 42 6 200 144 11 236 178 12 -239 182 13 239 182 13 124 112 88 58 58 58 22 22 22 6 6 6 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 -30 30 30 70 70 70 169 125 40 226 170 11 239 182 13 242 186 14 242 186 14 246 186 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 232 195 16 98 70 6 2 2 6 2 2 6 2 2 6 66 66 66 221 221 221 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 202 202 202 198 198 198 213 164 39 230 174 11 230 174 11 216 158 10 192 133 9 -163 110 8 120 80 7 98 70 6 120 80 7 167 114 7 197 138 11 226 170 11 239 182 13 -242 186 14 242 186 14 165 152 80 78 78 78 34 34 34 14 14 14 6 6 6 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 -30 30 30 78 78 78 185 146 40 226 170 11 239 182 13 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 241 196 14 204 160 10 20 16 6 2 2 6 2 2 6 2 2 6 38 38 38 -218 218 218 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 202 202 202 198 198 198 213 164 39 226 170 11 236 178 12 224 166 10 210 150 10 -200 144 11 197 138 11 192 133 9 197 138 11 210 150 10 226 170 11 242 186 14 246 190 14 -246 190 14 246 186 14 220 174 15 124 112 88 62 62 62 30 30 30 14 14 14 6 6 6 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 -30 30 30 78 78 78 174 140 55 224 166 10 239 182 13 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 241 196 14 139 102 15 2 2 6 2 2 6 2 2 6 2 2 6 -78 78 78 250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 214 214 214 198 198 198 185 146 40 219 162 10 236 178 12 234 174 13 224 166 10 -216 158 10 213 154 11 213 154 11 216 158 10 226 170 11 239 182 13 246 190 14 246 190 14 -246 190 14 246 190 14 242 186 14 213 164 39 101 101 101 58 58 58 30 30 30 14 14 14 -6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 -30 30 30 74 74 74 174 140 55 216 158 10 236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 241 196 14 230 187 11 62 42 6 2 2 6 2 2 6 2 2 6 -22 22 22 238 238 238 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 226 226 226 187 187 187 169 125 40 216 158 10 236 178 12 239 182 13 236 178 12 -230 174 11 226 170 11 226 170 11 230 174 11 236 178 12 242 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 186 14 239 182 13 213 164 39 106 106 106 66 66 66 34 34 34 -14 14 14 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 -26 26 26 70 70 70 149 139 69 213 154 11 236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 241 196 14 190 146 13 20 16 6 2 2 6 2 2 6 -46 46 46 246 246 246 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 221 221 221 86 86 86 156 107 11 216 158 10 236 178 12 242 186 14 246 186 14 -242 186 14 239 182 13 239 182 13 242 186 14 242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 242 186 14 220 174 15 149 139 69 66 66 66 -30 30 30 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 -26 26 26 70 70 70 149 139 69 210 150 10 236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 232 195 16 121 92 8 34 34 34 106 106 106 -221 221 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -242 242 242 82 82 82 20 16 6 163 110 8 216 158 10 236 178 12 242 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 242 186 14 149 139 69 -46 46 46 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 -30 30 30 78 78 78 149 139 69 210 150 10 236 178 12 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 241 196 14 220 174 15 198 179 130 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 218 218 218 -58 58 58 2 2 6 20 16 6 167 114 7 216 158 10 236 178 12 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 186 14 242 186 14 185 146 40 -54 54 54 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 14 14 -38 38 38 86 86 86 169 125 40 213 154 11 236 178 12 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 232 195 16 190 146 13 214 214 214 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 250 250 250 170 170 170 26 26 26 -2 2 6 2 2 6 35 31 12 163 110 8 219 162 10 239 182 13 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 186 14 236 178 12 224 166 10 149 139 69 -46 46 46 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 18 18 18 -50 50 50 113 101 86 192 133 9 224 166 10 242 186 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 242 186 14 230 187 11 204 160 10 133 118 54 -226 226 226 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 198 198 198 66 66 66 2 2 6 2 2 6 -2 2 6 2 2 6 62 42 6 156 107 11 219 162 10 239 182 13 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 242 186 14 234 174 13 213 154 11 148 132 55 66 66 66 -30 30 30 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 22 22 22 -58 58 58 148 132 55 206 145 10 234 174 13 242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 186 14 236 178 12 204 160 10 163 110 8 -62 42 6 124 131 137 218 218 218 250 250 250 253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 210 210 210 151 151 151 66 66 66 6 6 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 62 42 6 163 110 8 216 158 10 236 178 12 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 239 182 13 230 174 11 216 158 10 185 146 40 124 112 88 70 70 70 38 38 38 -18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 22 22 22 -62 62 62 169 125 40 206 145 10 224 166 10 236 178 12 239 182 13 242 186 14 242 186 14 -246 186 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 236 178 12 216 158 10 171 120 8 -85 57 6 2 2 6 6 6 6 30 30 30 54 54 54 62 62 62 50 50 50 38 38 38 -14 14 14 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 6 6 6 85 57 6 167 114 7 213 154 11 236 178 12 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 242 186 14 239 182 13 239 182 13 -230 174 11 210 150 10 174 140 55 124 112 88 82 82 82 54 54 54 34 34 34 18 18 18 -6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 18 18 18 -50 50 50 169 125 40 192 133 9 200 144 11 216 158 10 219 162 10 224 166 10 226 170 11 -230 174 11 236 178 12 239 182 13 239 182 13 242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 246 186 14 230 174 11 210 150 10 163 110 8 -104 69 6 10 10 10 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 6 6 6 85 57 6 167 114 7 206 145 10 230 174 11 242 186 14 246 190 14 -246 190 14 246 190 14 246 186 14 242 186 14 239 182 13 230 174 11 224 166 10 213 154 11 -169 125 40 124 112 88 86 86 86 58 58 58 38 38 38 22 22 22 10 10 10 6 6 6 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 14 14 -34 34 34 70 70 70 133 118 54 169 125 40 167 114 7 180 123 7 192 133 9 197 138 11 -200 144 11 206 145 10 213 154 11 219 162 10 224 166 10 230 174 11 239 182 13 242 186 14 -246 186 14 246 186 14 246 186 14 246 186 14 239 182 13 216 158 10 184 138 11 152 99 6 -104 69 6 20 16 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 -2 2 6 6 6 6 85 57 6 152 99 6 192 133 9 219 162 10 236 178 12 239 182 13 -246 186 14 242 186 14 239 182 13 236 178 12 224 166 10 206 145 10 192 133 9 148 132 55 -94 94 94 62 62 62 42 42 42 22 22 22 14 14 14 6 6 6 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 -18 18 18 34 34 34 58 58 58 78 78 78 101 98 89 124 112 88 133 118 54 156 107 11 -163 110 8 167 114 7 171 120 8 180 123 7 184 138 11 197 138 11 210 150 10 219 162 10 -226 170 11 236 178 12 236 178 12 234 174 13 219 162 10 197 138 11 163 110 8 134 84 6 -85 57 6 10 10 10 2 2 6 2 2 6 18 18 18 38 38 38 38 38 38 38 38 38 -38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 26 26 26 2 2 6 -2 2 6 6 6 6 62 42 6 137 92 6 171 120 8 200 144 11 219 162 10 230 174 11 -234 174 13 230 174 11 219 162 10 210 150 10 192 133 9 163 110 8 124 112 88 82 82 82 -50 50 50 30 30 30 14 14 14 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6 6 6 14 14 14 22 22 22 34 34 34 42 42 42 58 58 58 74 74 74 86 86 86 -101 98 89 113 101 86 133 118 54 121 92 8 137 92 6 152 99 6 163 110 8 180 123 7 -184 138 11 197 138 11 206 145 10 200 144 11 180 123 7 156 107 11 134 84 6 104 69 6 -62 42 6 54 54 54 106 106 106 101 98 89 86 86 86 82 82 82 78 78 78 78 78 78 -78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 82 82 82 86 86 86 94 94 94 -106 106 106 101 101 101 90 61 47 120 80 7 156 107 11 180 123 7 192 133 9 200 144 11 -206 145 10 200 144 11 192 133 9 171 120 8 139 102 15 113 101 86 70 70 70 42 42 42 -22 22 22 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 6 6 6 10 10 10 14 14 14 22 22 22 30 30 30 38 38 38 -50 50 50 62 62 62 74 74 74 90 90 90 101 98 89 113 101 86 121 92 8 120 80 7 -137 92 6 152 99 6 152 99 6 152 99 6 134 84 6 120 80 7 98 70 6 88 55 22 -101 98 89 82 82 82 58 58 58 46 46 46 38 38 38 34 34 34 34 34 34 34 34 34 -34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 38 38 38 42 42 42 -54 54 54 82 82 82 94 86 71 85 57 6 134 84 6 156 107 11 167 114 7 171 120 8 -171 120 8 167 114 7 152 99 6 121 92 8 101 98 89 62 62 62 34 34 34 18 18 18 -6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 6 6 6 10 10 10 -18 18 18 22 22 22 30 30 30 42 42 42 50 50 50 66 66 66 86 86 86 101 98 89 -94 86 71 98 70 6 104 69 6 104 69 6 104 69 6 85 57 6 88 55 22 90 90 90 -62 62 62 38 38 38 22 22 22 14 14 14 10 10 10 10 10 10 10 10 10 10 10 10 -10 10 10 10 10 10 6 6 6 10 10 10 10 10 10 10 10 10 10 10 10 14 14 14 -22 22 22 42 42 42 70 70 70 94 86 71 85 57 6 104 69 6 120 80 7 137 92 6 -134 84 6 120 80 7 94 86 71 86 86 86 58 58 58 30 30 30 14 14 14 6 6 6 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 6 6 6 10 10 10 14 14 14 18 18 18 26 26 26 38 38 38 54 54 54 -70 70 70 86 86 86 94 86 71 94 86 71 94 86 71 86 86 86 74 74 74 50 50 50 -30 30 30 14 14 14 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6 6 6 18 18 18 34 34 34 58 58 58 82 82 82 94 86 71 94 86 71 94 86 71 -94 86 71 94 86 71 74 74 74 50 50 50 26 26 26 14 14 14 6 6 6 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 6 6 6 14 14 14 18 18 18 -30 30 30 38 38 38 46 46 46 54 54 54 50 50 50 42 42 42 30 30 30 18 18 18 -10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 6 6 6 14 14 14 26 26 26 38 38 38 50 50 50 58 58 58 58 58 58 -54 54 54 42 42 42 30 30 30 18 18 18 10 10 10 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 --0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 -6 6 6 10 10 10 14 14 14 18 18 18 18 18 18 14 14 14 10 10 10 6 6 6 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 6 6 6 14 14 14 18 18 18 22 22 22 22 22 22 -18 18 18 14 14 14 10 10 10 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 1 0  0 0 0  0 0 0  1 1 0+0 1 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  1 1 0  0 0 0  0 0 0+0 1 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  1 1 0+10 15 3  2 3 1  12 18 4  42 61 14  19 27 6  11 16 4+38 55 13  10 15 3  3 4 1  10 15 3  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  2 3 1+12 18 4  1 1 0  23 34 8  31 45 11  10 15 3  32 47 11+34 49 12  3 4 1  3 4 1  3 4 1  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  10 15 3  29 42 10  26 37 9  12 18 4+55 80 19  81 118 28  55 80 19  92 132 31  106 153 36  69 100 23+100 144 34  80 116 27  42 61 14  81 118 28  23 34 8  27 40 9+15 21 5  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  1 1 0  29 42 10  15 21 5  50 72 17+74 107 25  45 64 15  102 148 35  80 116 27  84 121 28  111 160 38+69 100 23  65 94 22  81 118 28  29 42 10  17 25 6  29 42 10+23 34 8  2 3 1  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  3 4 1+15 21 5  15 21 5  34 49 12  101 146 34  111 161 38  97 141 33+97 141 33  119 172 41  117 170 40  116 167 40  118 170 40  118 171 40+117 169 40  118 170 40  111 160 38  118 170 40  96 138 32  89 128 30+81 118 28  11 16 4  10 15 3  1 1 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+3 4 1  3 4 1  34 49 12  101 146 34  79 115 27  111 160 38+114 165 39  113 163 39  118 170 40  117 169 40  118 171 40  117 169 40+116 167 40  119 172 41  113 163 39  92 132 31  105 151 36  113 163 39+75 109 26  19 27 6  16 23 5  11 16 4  0 1 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  10 15 3+80 116 27  106 153 36  105 151 36  114 165 39  118 170 40  118 171 40+118 171 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 170 40  117 169 40  118 170 40  118 170 40+117 170 40  75 109 26  75 109 26  34 49 12  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  3 4 1+64 92 22  65 94 22  100 144 34  118 171 40  118 170 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  118 171 41  118 170 40  117 169 40+109 158 37  105 151 36  104 150 35  47 69 16  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+42 61 14  115 167 39  118 170 40  117 169 40  117 169 40  117 169 40+117 170 40  117 170 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  118 170 40  96 138 32  17 25 6  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  47 69 16+114 165 39  117 168 40  117 170 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  118 170 40  117 169 40  117 169 40  117 169 40+117 170 40  119 172 41  96 138 32  12 18 4  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  10 15 3+32 47 11  105 151 36  118 170 40  117 169 40  117 169 40  116 168 40+109 157 37  111 160 38  117 169 40  118 171 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  118 171 40  69 100 23  2 3 1+0 0 0  0 0 0  0 0 0  0 0 0  19 27 6  101 146 34+118 171 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 170 40+118 171 40  115 166 39  107 154 36  111 161 38  117 169 40  117 169 40+117 169 40  118 171 40  75 109 26  19 27 6  2 3 1  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  16 23 5+89 128 30  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+111 160 38  92 132 31  79 115 27  96 138 32  115 166 39  119 171 41+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  118 170 40  109 157 37  26 37 9+0 0 0  0 0 0  0 0 0  0 0 0  64 92 22  118 171 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  118 170 40  118 171 40  109 157 37+89 128 30  81 118 28  100 144 34  115 166 39  117 169 40  117 169 40+117 169 40  117 170 40  113 163 39  60 86 20  1 1 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+27 40 9  96 138 32  118 170 40  117 169 40  117 169 40  117 169 40+117 170 40  117 169 40  101 146 34  67 96 23  55 80 19  84 121 28+113 163 39  119 171 41  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  119 171 41  65 94 22+0 0 0  0 0 0  0 0 0  15 21 5  101 146 34  118 171 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  118 170 40  118 171 40  104 150 35  69 100 23  53 76 18+81 118 28  111 160 38  118 170 40  117 169 40  117 169 40  117 169 40+117 169 40  114 165 39  69 100 23  10 15 3  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  1 1 0+31 45 11  77 111 26  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  118 170 40  116 168 40  92 132 31  47 69 16+38 55 13  81 118 28  113 163 39  119 171 41  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  118 171 41  92 132 31+10 15 3  0 0 0  0 0 0  36 52 12  115 166 39  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  118 170 40+118 171 40  102 148 35  64 92 22  34 49 12  65 94 22  106 153 36+118 171 40  117 170 40  117 169 40  117 169 40  117 169 40  117 169 40+118 170 40  107 154 36  55 80 19  15 21 5  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+29 42 10  101 146 34  118 171 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  118 171 40  113 163 39+75 109 26  27 40 9  36 52 12  89 128 30  116 167 40  118 171 40+117 169 40  117 169 40  117 169 40  117 169 40  118 170 40  104 150 35+16 23 5  0 0 0  0 0 0  53 76 18  118 171 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  119 171 41  109 157 37+67 96 23  23 34 8  42 61 14  96 138 32  118 170 40  118 170 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  74 107 25  10 15 3  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  31 45 11  101 146 34  118 170 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+119 171 41  102 148 35  47 69 16  14 20 5  50 72 17  102 148 35+118 171 40  117 169 40  117 169 40  117 169 40  118 170 40  102 148 35+15 21 5  0 0 0  0 0 0  50 72 17  118 170 40  117 169 40+117 169 40  117 169 40  118 170 40  116 167 40  84 121 28  27 40 9+19 27 6  74 107 25  114 165 39  118 171 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  75 109 26  10 15 4  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  38 55 13  102 148 35  118 171 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  118 170 40  115 167 39  77 111 26  17 25 6  19 27 6+77 111 26  115 166 39  118 170 40  117 169 40  119 172 41  81 118 28+3 4 1  0 0 0  0 0 0  27 40 9  111 160 38  118 170 40+117 169 40  118 171 40  105 151 36  50 72 17  10 15 3  38 55 13+100 144 34  118 171 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  79 115 27  15 21 5  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  10 15 3  64 92 22  111 160 38  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  118 171 40  96 138 32  32 47 11+3 4 1  50 72 17  107 154 36  120 173 41  105 151 36  31 45 11+0 0 0  0 0 0  0 0 0  3 4 1  65 94 22  117 169 40+118 170 40  89 128 30  26 37 9  3 4 1  60 86 20  111 161 38+118 171 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+97 141 33  36 52 12  1 1 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  14 20 5  75 109 26  117 168 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  118 171 40  107 154 36+45 64 15  2 3 1  31 45 11  75 109 26  32 47 11  0 1 0+0 0 0  0 0 0  0 0 0  0 0 0  10 15 3  55 80 19+65 94 22  11 16 4  11 16 4  75 109 26  116 168 40  118 170 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  118 170 40  107 154 36+47 69 16  3 4 1  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  12 18 4  69 100 23  111 161 38  118 171 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  118 170 40+111 160 38  50 72 17  2 3 1  2 3 1  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  1 1 0+1 1 0  12 18 4  81 118 28  118 170 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 170 40  118 171 40  101 146 34+42 61 14  2 3 1  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  3 4 1  36 52 12  89 128 30+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+118 171 41  101 146 34  14 20 5  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  47 69 16  118 170 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 170 40  111 160 38  69 100 23  19 27 6+0 1 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  11 16 4  69 100 23+115 167 39  119 172 41  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+119 172 41  75 109 26  3 4 1  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  23 34 8  106 153 36  118 170 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+117 169 40  118 170 40  119 172 41  105 151 36  42 61 14  2 3 1+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  1 1 0  15 21 5+45 64 15  80 116 27  114 165 39  118 170 40  117 169 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  119 172 41+97 141 33  20 30 7  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  1 1 0  53 76 18  114 165 39  118 171 40  117 169 40+117 169 40  117 169 40  117 169 40  117 169 40  117 169 40  117 169 40+118 171 40  104 150 35  64 92 22  31 45 11  10 15 3  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  36 52 12  97 141 33  109 158 37  113 163 39  116 168 40+117 169 40  117 170 40  118 170 40  119 172 41  115 167 39  84 121 28+23 34 8  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  3 4 1  50 72 17  102 148 35  118 171 40+119 171 41  118 170 40  117 169 40  117 169 40  115 166 39  111 161 38+109 157 37  79 115 27  12 18 4  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  3 4 1  15 21 5  23 34 8  45 64 15  106 153 36+116 167 40  111 160 38  101 146 34  79 115 27  42 61 14  10 15 3+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  1 1 0  20 30 7  60 86 20+89 128 30  106 153 36  113 163 39  117 169 40  84 121 28  29 42 10+19 27 6  10 15 3  2 3 1  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  16 23 5  38 55 13+36 52 12  26 37 9  12 18 4  2 3 1  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  1 0 0  19 2 7  52 5 18+78 7 27  88 8 31  81 7 29  56 5 19  25 2 9  3 0 1+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+3 4 1  19 27 6  31 45 11  38 55 13  32 47 11  3 4 1+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  3 0 1+9 0 3  12 1 4  9 0 3  4 0 1  0 0 0  0 0 0+0 0 0  0 0 0  28 3 10  99 9 35  156 14 55  182 16 64+189 17 66  190 17 67  189 17 66  184 17 65  166 15 58  118 13 41+45 4 16  3 0 1  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  11 1 4  52 5 18  101 9 35  134 12 47+151 14 53  154 14 54  151 14 53  113 10 40  11 1 4  0 0 0+3 0 1  67 6 24  159 14 56  190 17 67  190 17 67  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  190 17 67  191 17 67+174 16 61  101 9 35  14 1 5  0 0 0  35 3 12  108 10 38+122 11 43  122 11 43  112 10 39  87 8 30  50 5 17  13 1 5+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+3 0 1  56 5 19  141 13 49  182 16 64  191 17 67  191 17 67+190 17 67  190 17 67  191 17 67  113 10 40  3 0 1  1 0 0+79 7 28  180 16 63  190 17 67  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+189 17 66  188 17 66  122 11 43  11 1 4  41 4 14  176 16 62+191 17 67  191 17 67  191 17 67  190 17 67  181 16 63  146 13 51+75 7 26  10 1 4  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  7 1 2+90 8 32  178 16 62  191 17 67  188 17 66  188 17 66  188 17 66+188 17 66  190 17 67  141 13 49  22 2 8  0 0 0  41 4 14+173 16 61  190 17 67  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  88 8 31  1 0 0  89 8 31+185 17 65  189 17 66  188 17 66  188 17 66  189 17 66  191 17 67+186 17 65  124 11 43  25 2 9  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  2 0 1  89 8 31+184 17 65  189 17 66  188 17 66  188 17 66  188 17 66  188 17 66+190 17 67  151 14 53  34 3 12  0 0 0  0 0 0  79 7 28+190 17 67  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  191 17 67  146 13 51  9 1 3  7 1 2+108 10 38  187 17 66  189 17 66  188 17 66  188 17 66  188 17 66+188 17 66  190 17 67  141 13 49  22 2 8  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  52 5 18  176 16 62+189 17 66  188 17 66  188 17 66  188 17 66  188 17 66  190 17 67+151 14 53  38 3 13  0 0 0  0 0 0  0 0 0  50 5 17+180 16 63  189 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  191 17 67  141 13 49  7 1 3  0 0 0+11 1 4  112 10 39  187 17 66  189 17 66  188 17 66  188 17 66+188 17 66  188 17 66  190 17 67  113 10 40  5 0 2  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  7 1 3  132 12 46  191 17 67+188 17 66  188 17 66  188 17 66  188 17 66  190 17 67  146 13 51+35 3 12  0 0 0  0 0 0  0 0 0  0 0 0  5 0 2+101 9 35  185 17 65  190 17 67  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  190 17 67  180 16 63  67 6 24  0 0 0  0 0 0+0 0 0  11 1 4  108 10 38  186 17 65  189 17 66  188 17 66+188 17 66  188 17 66  189 17 66  180 16 63  56 5 19  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  44 4 15  177 16 62  189 17 66+188 17 66  188 17 66  189 17 66  189 17 66  134 12 47  28 3 10+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+8 1 3  79 7 28  159 14 56  188 17 66  191 17 67  190 17 67+189 17 66  189 17 66  189 17 66  189 17 66  190 17 67  191 17 67+188 17 66  158 14 55  72 7 25  4 0 1  0 0 0  0 0 0+0 0 0  0 0 0  8 1 3  95 9 33  182 16 64  189 17 67+188 17 66  188 17 66  188 17 66  191 17 67  122 11 43  3 0 1+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  88 8 31  190 17 67  188 17 66+188 17 66  189 17 66  185 17 65  113 10 40  18 2 6  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  1 0 0  24 2 8  77 7 27  124 11 43  154 14 54+168 15 59  173 16 61  173 16 61  168 15 59  154 14 54  124 11 43+77 7 27  22 2 8  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  5 0 2  77 7 27  173 16 61+190 17 67  188 17 66  188 17 66  190 17 67  164 15 57  23 2 8+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  1 0 0  118 13 41  191 17 67  188 17 66+190 17 67  174 16 61  87 8 30  8 1 3  0 0 0  0 0 0+0 0 0  0 0 0  10 1 4  29 3 10  40 4 14  36 3 13+18 2 6  2 0 1  0 0 0  0 0 0  3 0 1  14 1 5+26 2 9  33 3 11  32 3 11  25 2 9  13 1 5  3 0 1+0 0 0  14 1 5  56 5 19  95 9 33  109 10 38  101 9 35+77 7 27  35 3 12  5 0 2  0 0 0  1 0 0  56 5 19+156 14 55  190 17 67  188 17 66  188 17 66  182 16 64  50 5 17+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  5 0 2  134 12 47  191 17 67  189 17 66+151 14 53  52 5 18  2 0 1  0 0 0  0 0 0  1 0 0+28 3 10  90 8 32  146 13 51  170 15 60  178 16 62  174 16 61+158 14 55  112 10 39  40 4 14  1 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  3 0 1+56 5 19  146 13 51  183 17 64  191 17 67  191 17 67  191 17 67+188 17 66  173 16 61  122 11 43  41 4 14  1 0 0  0 0 0+30 3 10  124 11 43  185 17 65  190 17 67  187 17 66  67 6 24+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  6 1 2  134 12 47  168 15 59  99 9 35+21 2 7  0 0 0  0 0 0  0 0 0  6 1 2  77 7 27+162 15 57  190 17 67  191 17 67  189 17 66  189 17 66  189 17 66+190 17 67  191 17 67  169 15 59  75 7 26  3 0 1  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  2 0 1  79 7 28+178 16 62  191 17 67  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  189 17 66  191 17 67  170 15 60  79 7 28  5 0 2+0 0 0  10 1 3  78 7 27  159 14 56  188 17 66  75 7 26+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  1 0 0  35 3 12  29 3 10  2 0 1+0 0 0  0 0 0  0 0 0  9 1 3  101 9 35  183 17 64+190 17 67  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  190 17 67  178 16 63  67 6 23  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  52 5 18  174 16 61+190 17 67  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  190 17 67  182 16 64  89 8 31+4 0 1  0 0 0  0 0 0  25 2 9  73 7 26  31 3 11+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  4 0 1  98 9 34  187 17 66  189 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  190 17 67  158 14 55  25 2 9+0 0 0  0 0 0  0 0 0  8 1 3  134 12 47  191 17 67+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  189 17 66  180 16 63+68 6 24  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  6 1 2  19 2 7  3 0 1  0 0 0  0 0 0+0 0 0  0 0 0  65 6 23  180 16 63  189 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  189 17 66  83 8 29+0 0 0  0 0 0  0 0 0  41 4 14  177 16 62  189 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  190 17 67+159 14 56  28 3 10  0 0 0  0 0 0  0 0 0  23 2 8+41 4 14  5 0 2  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+23 2 8  113 10 40  159 14 56  65 6 23  0 0 0  0 0 0+0 0 0  16 1 6  146 13 51  191 17 67  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  191 17 67  132 12 46+5 0 2  0 0 0  0 0 0  77 7 27  189 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+190 17 67  98 9 34  0 0 0  0 0 0  12 1 4  134 12 47+178 16 63  108 10 38  16 1 6  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  30 3 10+141 13 49  190 17 67  191 17 67  134 12 47  6 1 2  0 0 0+0 0 0  68 6 24  186 17 65  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  190 17 67  156 14 55+14 1 5  0 0 0  0 0 0  98 9 34  191 17 67  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+190 17 67  156 14 55  19 2 7  0 0 0  47 4 16  181 16 63+190 17 67  189 17 66  126 14 44  17 2 6  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  16 1 6  134 12 47+191 17 67  188 17 66  190 17 67  162 15 57  19 2 7  0 0 0+3 0 1  123 11 43  191 17 67  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  190 17 67  163 15 57+20 2 7  0 0 0  0 0 0  101 9 35  191 17 67  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  182 16 64  52 5 18  0 0 0  73 7 26  188 17 66+188 17 66  188 17 66  189 17 66  109 10 38  5 0 2  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  95 9 33  189 17 66+188 17 66  188 17 66  189 17 66  171 15 60  29 3 10  0 0 0+16 1 6  156 14 55  190 17 67  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  190 17 67  158 14 55+17 2 6  0 0 0  0 0 0  85 8 30  190 17 67  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  189 17 66  81 7 29  0 0 0  85 8 30  190 17 67+188 17 66  188 17 66  189 17 66  180 16 63  56 5 19  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  25 2 9  162 15 57  190 17 67+188 17 66  188 17 66  189 17 66  173 16 61  31 3 11  0 0 0+30 3 10  171 15 60  189 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  191 17 67  141 13 49+7 1 2  0 0 0  0 0 0  56 5 19  183 17 64  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  191 17 67  98 9 34  0 0 0  88 8 31  190 17 67+188 17 66  188 17 66  188 17 66  191 17 67  124 11 43  5 0 2+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  68 6 24  187 17 66  188 17 66+188 17 66  188 17 66  189 17 66  170 15 60  28 3 10  0 0 0+34 3 12  174 16 61  189 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  191 17 67  101 9 35+0 0 0  0 0 0  0 0 0  21 2 7  159 14 56  190 17 67+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  191 17 67  98 9 34  0 0 0  81 7 29  189 17 66+188 17 66  188 17 66  188 17 66  189 17 66  168 15 59  28 3 10+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  109 10 38  191 17 67  188 17 66+188 17 66  188 17 66  190 17 67  163 15 57  21 2 7  0 0 0+26 2 9  168 15 59  189 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  189 17 66  180 16 63  47 4 16+0 0 0  0 0 0  0 0 0  0 0 0  108 10 38  190 17 67+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  189 17 66  78 7 27  0 0 0  68 6 24  187 17 66+188 17 66  188 17 66  188 17 66  188 17 66  183 17 64  56 5 19+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  3 0 1  131 12 46  191 17 67  188 17 66+188 17 66  188 17 66  190 17 67  151 14 53  12 1 4  0 0 0+11 1 4  146 13 51  190 17 67  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  191 17 67  126 14 44  7 1 2+0 0 0  0 0 0  0 0 0  0 0 0  32 3 11  164 15 58+190 17 67  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+189 17 66  178 16 62  44 4 15  0 0 0  50 5 17  182 16 64+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  72 7 25+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  5 0 2  134 12 47  191 17 67  188 17 66+188 17 66  188 17 66  191 17 67  131 12 46  3 0 1  0 0 0+0 0 0  101 9 35  190 17 67  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  190 17 67  170 15 60  44 4 15  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  77 7 27+183 17 64  189 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+191 17 67  134 12 47  9 1 3  0 0 0  31 3 11  171 15 60+189 17 66  188 17 66  188 17 66  188 17 66  188 17 66  72 7 25+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  2 0 1  124 11 43  191 17 67  188 17 66+188 17 66  188 17 66  191 17 67  101 9 35  0 0 0  0 0 0+0 0 0  35 3 12  168 15 59  190 17 67  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  189 17 66  182 16 64  77 7 27  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  6 1 2+99 9 35  185 17 65  189 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  189 17 66+177 16 62  56 5 19  0 0 0  0 0 0  13 1 5  151 14 53+190 17 67  188 17 66  188 17 66  188 17 66  185 17 65  56 5 19+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  99 9 35  191 17 67  188 17 66+188 17 66  188 17 66  186 17 65  65 6 23  0 0 0  0 0 0+0 0 0  0 0 0  79 7 28  182 16 64  190 17 67  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+191 17 67  177 16 62  83 8 29  4 0 1  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+8 1 3  89 8 31  175 16 62  191 17 67  189 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  190 17 67  181 16 63+85 8 30  3 0 1  0 0 0  0 0 0  1 0 0  118 13 41+191 17 67  188 17 66  188 17 66  189 17 66  173 16 61  34 3 12+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  56 5 19  183 17 64  188 17 66+188 17 66  189 17 66  169 15 59  30 3 10  0 0 0  0 0 0+0 0 0  0 0 0  5 0 2  83 8 29  173 16 61  191 17 67+190 17 67  189 17 66  189 17 66  190 17 67  191 17 67  187 17 66+151 14 53  56 5 19  3 0 1  0 0 0  16 1 6  50 5 17+79 7 28  95 9 33  95 9 33  75 7 26  41 4 14  10 1 4+0 0 0  2 0 1  50 5 17  132 12 46  178 16 62  190 17 67+191 17 67  191 17 67  191 17 67  186 17 65  154 14 54  68 6 24+4 0 1  0 0 0  0 0 0  0 0 0  0 0 0  72 7 25+187 17 66  188 17 66  188 17 66  191 17 67  141 13 49  9 1 3+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  14 1 5  151 14 53  190 17 67+188 17 66  191 17 67  131 12 46  5 0 2  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  2 0 1  44 4 15  113 10 40+156 14 55  173 16 61  174 16 61  164 15 58  134 12 47  77 7 27+18 2 6  0 0 0  16 1 6  85 8 30  151 14 53  182 16 64+189 17 66  191 17 67  190 17 67  188 17 66  177 16 62  141 13 49+68 6 24  8 1 3  0 0 0  8 1 3  44 4 15  88 8 31+113 10 40  122 11 43  108 10 38  67 6 24  20 2 7  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  28 3 10+166 15 58  190 17 67  188 17 66  187 17 66  79 7 28  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  73 7 26  185 17 65+189 17 66  184 17 65  65 6 23  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  2 0 1+17 2 6  32 3 11  34 3 12  22 2 8  6 1 2  0 0 0+0 0 0  38 3 13  141 13 49  188 17 66  190 17 67  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  189 17 66  191 17 67+184 17 65  122 11 43  21 2 7  0 0 0  0 0 0  0 0 0+0 0 0  1 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  1 0 0+108 10 38  191 17 67  191 17 67  141 13 49  16 1 6  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  8 1 3  112 10 39+186 17 65  124 11 43  10 1 4  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+36 3 13  156 14 55  191 17 67  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+189 17 66  190 17 67  134 12 47  18 2 6  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  7 1 2  41 4 14  75 7 26  66 5 23  19 2 7+26 2 9  144 13 50  154 14 54  40 4 14  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  13 1 5+56 5 19  19 2 7  0 0 0  7 1 2  29 3 10  35 3 12+19 2 7  2 0 1  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  13 1 5+134 12 47  191 17 67  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  189 17 67  108 10 38  3 0 1  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  1 0 0+40 4 14  124 11 43  177 16 62  188 17 66  187 17 66  144 13 50+24 2 8  17 2 6  22 2 8  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  19 2 7  122 11 43  171 15 60  175 16 62+159 14 56  112 10 39  40 4 14  2 0 1  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  72 7 25+186 17 65  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  189 17 66  174 16 61  41 4 14  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  3 0 1  72 7 25+168 15 59  191 17 67  189 17 66  188 17 66  188 17 66  190 17 67+95 9 33  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  95 9 33  191 17 67  189 17 66  189 17 66+190 17 67  191 17 67  171 15 60  90 8 32  12 1 4  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  5 0 2  132 12 46+191 17 67  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  190 17 67  98 9 34  0 0 0+0 0 0  0 0 0  0 0 0  5 0 2  88 8 31  180 16 63+190 17 67  188 17 66  188 17 66  188 17 66  188 17 66  191 17 67+146 13 51  11 1 4  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  9 1 3  144 13 50  191 17 67  188 17 66  188 17 66+188 17 66  188 17 66  189 17 66  187 17 66  123 11 43  20 2 7+0 0 0  0 0 0  0 0 0  0 0 0  21 2 7  163 15 57+190 17 67  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  191 17 67  134 12 47  5 0 2+0 0 0  0 0 0  3 0 1  88 8 31  182 16 64  189 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  189 17 66+171 15 60  31 3 11  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  20 2 7  162 15 57  190 17 67  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  190 17 67  132 12 46+20 2 7  0 0 0  0 0 0  0 0 0  32 3 11  173 16 61+189 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  190 17 67  151 14 53  12 1 4+0 0 0  0 0 0  72 7 25  180 16 63  189 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+181 16 63  47 4 16  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  21 2 7  163 15 57  190 17 67  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  190 17 67+122 11 43  9 1 3  0 0 0  0 0 0  30 3 10  171 15 60+189 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  190 17 67  146 13 51  10 1 4+0 0 0  38 3 13  166 15 58  190 17 67  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+183 17 64  52 5 18  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  13 1 5  154 14 54  190 17 67  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+186 17 65  79 7 28  0 0 0  0 0 0  14 1 5  156 14 54+190 17 67  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  191 17 67  124 11 43  2 0 1+5 0 2  122 11 43  191 17 67  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+182 16 64  47 4 16  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  3 0 1  126 14 44  191 17 67  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+190 17 67  158 14 55  23 2 8  0 0 0  1 0 0  113 10 40+191 17 67  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  78 7 27  0 0 0+47 4 16  177 16 62  189 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  189 17 66+173 16 61  34 3 12  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  85 8 30  189 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  79 7 28  0 0 0  0 0 0  47 4 16+175 16 62  189 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  190 17 67  156 14 55  22 2 8  0 0 0+109 10 38  191 17 67  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  190 17 67+151 14 53  13 1 5  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  35 3 12  173 16 61  189 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  191 17 67  134 12 47  7 1 2  0 0 0  3 0 1+99 9 35  188 17 66  189 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  189 17 66  181 16 63  68 6 24  0 0 0  18 2 6+156 14 55  190 17 67  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  190 17 67+101 9 35  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  3 0 1  118 13 41  191 17 67  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  189 17 66  168 15 59  28 3 10  0 0 0  0 0 0+12 1 4  113 10 40  187 17 66  189 17 67  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+190 17 67  180 16 63  88 8 31  4 0 1  0 0 0  47 4 16+180 16 63  189 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  190 17 67  168 15 59+36 3 13  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  38 3 13  164 15 58  190 17 67+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  182 16 64  50 5 17  0 0 0  0 0 0+0 0 0  11 1 4  90 8 32  169 15 59  190 17 67  190 17 67+189 17 66  189 17 66  189 17 66  189 17 66  191 17 67  189 17 66+158 14 55  68 6 24  4 0 1  0 0 0  0 0 0  73 7 26+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  189 17 66  185 17 65  83 8 29+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  65 6 23  174 16 61+190 17 67  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  185 17 65  56 5 19  0 0 0  0 0 0+0 0 0  0 0 0  2 0 1  35 3 12  99 9 35  146 13 51+170 15 60  177 16 62  177 16 62  166 15 58  141 13 49  85 8 30+24 2 8  0 0 0  0 0 0  0 0 0  0 0 0  85 8 30+190 17 67  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  189 17 66  112 10 39  8 1 3+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  1 0 0  68 6 24+170 15 60  191 17 67  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  182 16 64  50 5 17  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  1 0 0  11 1 4+28 3 10  40 4 14  38 3 13  25 2 9  8 1 3  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  78 7 27+189 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  189 17 66  187 17 66  113 10 40  14 1 5  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  1 0 0+47 4 16  141 13 49  186 17 65  191 17 67  190 17 67  189 17 66+189 17 66  191 17 67  156 14 55  20 2 7  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  44 4 15+178 16 62  190 17 67  188 17 66  188 17 66  188 17 66  190 17 67+191 17 67  173 16 61  90 8 32  10 1 4  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  14 1 5  68 6 24  131 12 46  162 15 57  174 16 61+171 15 60  146 13 51  56 5 19  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  3 0 1  14 1 5  29 3 10+41 4 14  47 4 16  50 5 17  45 4 16  34 3 12  18 2 6+5 0 2  0 0 0  0 0 0  0 0 0  0 0 0  5 0 2+90 8 32  169 15 59  185 17 65  187 17 66  182 16 64  163 15 57+113 10 40  41 4 14  2 0 1  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  5 0 2  21 2 7  34 3 12+29 3 10  11 1 4  0 0 0  0 0 0  0 0 0  0 0 0+3 0 1  32 3 11  79 7 28  124 11 43  154 14 54  171 15 60+180 16 63  182 16 64  182 16 64  180 16 63  174 16 61  159 14 56+132 12 46  88 8 31  34 3 12  3 0 1  0 0 0  0 0 0+3 0 1  29 3 10  56 5 19  65 6 23  50 5 17  23 2 8+3 0 1  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  25 2 9+109 10 38  169 15 59  189 17 66  191 17 67  190 17 67  189 17 66+189 17 66  188 17 66  188 17 66  188 17 66  189 17 66  190 17 67+191 17 67  190 17 67  171 15 60  98 9 34  10 1 3  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  14 1 5  141 13 49+191 17 67  189 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  189 17 67  186 17 65  65 6 23  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  23 2 8  166 15 58+190 17 67  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  189 17 66  176 16 62  45 4 16  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  1 0 0  83 8 29+183 17 64  189 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+188 17 66  189 17 66  185 17 65  95 9 33  3 0 1  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  5 0 2+85 8 30  176 16 62  191 17 67  188 17 66  188 17 66  188 17 66+188 17 66  188 17 66  188 17 66  188 17 66  188 17 66  188 17 66+191 17 67  180 16 63  95 9 33  7 1 3  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+2 0 1  52 5 18  141 13 49  185 17 65  191 17 67  189 17 67+189 17 66  188 17 66  188 17 66  189 17 66  191 17 67  187 17 66+146 13 51  56 5 19  4 0 1  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  14 1 5  68 6 24  131 12 46  166 15 58+180 16 63  183 17 64  180 16 63  168 15 59  134 12 47  75 7 26+17 2 6  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  5 0 2  24 2 8+44 4 15  52 5 18  45 4 16  26 2 9  6 1 2  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0+0 0 0  0 0 0  0 0 0diff -Nur linux-3.11.10.orig/drivers/video/Makefile linux-3.11.10/drivers/video/Makefile--- linux-3.11.10.orig/drivers/video/Makefile	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/video/Makefile	2014-02-07 19:57:30.000000000 +0100@@ -100,6 +100,7 @@ obj-$(CONFIG_FB_VOODOO1)          += sstfb.o obj-$(CONFIG_FB_ARMCLCD)	  += amba-clcd.o obj-$(CONFIG_FB_GOLDFISH)         += goldfishfb.o+obj-$(CONFIG_FB_BCM2708)	  += bcm2708_fb.o obj-$(CONFIG_FB_68328)            += 68328fb.o obj-$(CONFIG_FB_GBE)              += gbefb.o obj-$(CONFIG_FB_CIRRUS)		  += cirrusfb.odiff -Nur linux-3.11.10.orig/drivers/w1/masters/w1-gpio.c linux-3.11.10/drivers/w1/masters/w1-gpio.c--- linux-3.11.10.orig/drivers/w1/masters/w1-gpio.c	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/w1/masters/w1-gpio.c	2014-02-07 19:57:30.000000000 +0100@@ -22,6 +22,9 @@ #include "../w1.h" #include "../w1_int.h" +static int w1_gpio_pullup = 0;+module_param_named(pullup, w1_gpio_pullup, int, 0);+ static void w1_gpio_write_bit_dir(void *data, u8 bit) { 	struct w1_gpio_platform_data *pdata = data;@@ -46,6 +49,16 @@ 	return gpio_get_value(pdata->pin) ? 1 : 0; } +static void w1_gpio_bitbang_pullup(void *data, u8 on)+{+	struct w1_gpio_platform_data *pdata = data;++	if (on)+		gpio_direction_output(pdata->pin, 1);+	else+		gpio_direction_input(pdata->pin);+}+ #if defined(CONFIG_OF) static struct of_device_id w1_gpio_dt_ids[] = { 	{ .compatible = "w1-gpio" },@@ -127,6 +140,13 @@ 		master->write_bit = w1_gpio_write_bit_dir; 	} +	if (w1_gpio_pullup)+		if (pdata->is_open_drain)+			printk(KERN_ERR "w1-gpio 'pullup' option "+			       "doesn't work with open drain GPIO\n");+		else+			master->bitbang_pullup = w1_gpio_bitbang_pullup;+ 	err = w1_add_master_device(master); 	if (err) { 		dev_err(&pdev->dev, "w1_add_master device failed\n");diff -Nur linux-3.11.10.orig/drivers/w1/w1.h linux-3.11.10/drivers/w1/w1.h--- linux-3.11.10.orig/drivers/w1/w1.h	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/w1/w1.h	2014-02-07 19:57:30.000000000 +0100@@ -148,6 +148,12 @@ 	 */ 	u8		(*set_pullup)(void *, int); +	/**+	 * Turns the pullup on/off in bitbanging mode, takes an on/off argument.+	 * @return -1=Error, 0=completed+	 */+	void (*bitbang_pullup) (void *, u8);+ 	/** Really nice hardware can handles the different types of ROM search 	 *  w1_master* is passed to the slave found callback. 	 */diff -Nur linux-3.11.10.orig/drivers/w1/w1_int.c linux-3.11.10/drivers/w1/w1_int.c--- linux-3.11.10.orig/drivers/w1/w1_int.c	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/w1/w1_int.c	2014-02-07 19:57:30.000000000 +0100@@ -117,19 +117,21 @@ 		printk(KERN_ERR "w1_add_master_device: invalid function set\n"); 		return(-EINVAL);         }-	/* While it would be electrically possible to make a device that-	 * generated a strong pullup in bit bang mode, only hardware that-	 * controls 1-wire time frames are even expected to support a strong-	 * pullup.  w1_io.c would need to support calling set_pullup before-	 * the last write_bit operation of a w1_write_8 which it currently-	 * doesn't.-	 */++	/* bitbanging hardware uses bitbang_pullup, other hardware uses set_pullup+	 * and takes care of timing itself */ 	if (!master->write_byte && !master->touch_bit && master->set_pullup) { 		printk(KERN_ERR "w1_add_master_device: set_pullup requires " 			"write_byte or touch_bit, disabling\n"); 		master->set_pullup = NULL; 	} +	if (master->set_pullup && master->bitbang_pullup) {+		printk(KERN_ERR "w1_add_master_device: set_pullup should not "+		       "be set when bitbang_pullup is used, disabling\n");+		master->set_pullup = NULL;+	}+ 	/* Lock until the device is added (or not) to w1_masters. */ 	mutex_lock(&w1_mlock); 	/* Search for the first available id (starting at 1). */diff -Nur linux-3.11.10.orig/drivers/w1/w1_io.c linux-3.11.10/drivers/w1/w1_io.c--- linux-3.11.10.orig/drivers/w1/w1_io.c	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/w1/w1_io.c	2014-02-07 19:57:30.000000000 +0100@@ -127,10 +127,22 @@ static void w1_post_write(struct w1_master *dev) { 	if (dev->pullup_duration) {-		if (dev->enable_pullup && dev->bus_master->set_pullup)-			dev->bus_master->set_pullup(dev->bus_master->data, 0);-		else+		if (dev->enable_pullup) {+			if (dev->bus_master->set_pullup) {+				dev->bus_master->set_pullup(dev->+							    bus_master->data,+							    0);+			} else if (dev->bus_master->bitbang_pullup) {+				dev->bus_master->+				    bitbang_pullup(dev->bus_master->data, 1); 			msleep(dev->pullup_duration);+				dev->bus_master->+				    bitbang_pullup(dev->bus_master->data, 0);+			}+		} else {+			msleep(dev->pullup_duration);+		}+ 		dev->pullup_duration = 0; 	} }diff -Nur linux-3.11.10.orig/drivers/watchdog/bcm2708_wdog.c linux-3.11.10/drivers/watchdog/bcm2708_wdog.c--- linux-3.11.10.orig/drivers/watchdog/bcm2708_wdog.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/drivers/watchdog/bcm2708_wdog.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,384 @@+/*+ *	Broadcom BCM2708 watchdog driver.+ *+ *	(c) Copyright 2010 Broadcom Europe Ltd+ *+ *	This program is free software; you can redistribute it and/or+ *	modify it under the terms of the GNU General Public License+ *	as published by the Free Software Foundation; either version+ *	2 of the License, or (at your option) any later version.+ *+ *      BCM2708 watchdog driver. Loosely based on wdt driver.+ */++#include <linux/interrupt.h>+#include <linux/module.h>+#include <linux/moduleparam.h>+#include <linux/types.h>+#include <linux/miscdevice.h>+#include <linux/watchdog.h>+#include <linux/fs.h>+#include <linux/ioport.h>+#include <linux/notifier.h>+#include <linux/reboot.h>+#include <linux/init.h>+#include <linux/io.h>+#include <linux/uaccess.h>+#include <mach/platform.h>++#include <asm/system.h>++#define SECS_TO_WDOG_TICKS(x) ((x) << 16)+#define WDOG_TICKS_TO_SECS(x) ((x) >> 16)++static unsigned long wdog_is_open;+static uint32_t wdog_ticks;	       /* Ticks to load into wdog timer */+static char expect_close;++/*+ *	Module parameters+ */++#define WD_TIMO 10		       /* Default heartbeat = 60 seconds */+static int heartbeat = WD_TIMO;	       /* Heartbeat in seconds */++module_param(heartbeat, int, 0);+MODULE_PARM_DESC(heartbeat,+	"Watchdog heartbeat in seconds. (0 < heartbeat < 65536, default="+				__MODULE_STRING(WD_TIMO) ")");++static int nowayout = WATCHDOG_NOWAYOUT;+module_param(nowayout, int, 0);+MODULE_PARM_DESC(nowayout,+	"Watchdog cannot be stopped once started (default="+				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");++static DEFINE_SPINLOCK(wdog_lock);++/**+ *	Start the watchdog driver.+ */++static int wdog_start(unsigned long timeout)+{+	uint32_t cur;+	unsigned long flags;+	spin_lock_irqsave(&wdog_lock, flags);++	/* enable the watchdog */+	iowrite32(PM_PASSWORD | (timeout & PM_WDOG_TIME_SET),+		  __io_address(PM_WDOG));+	cur = ioread32(__io_address(PM_RSTC));+	iowrite32(PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) |+		  PM_RSTC_WRCFG_FULL_RESET, __io_address(PM_RSTC));++	spin_unlock_irqrestore(&wdog_lock, flags);+	return 0;+}++/**+ *	Stop the watchdog driver.+ */++static int wdog_stop(void)+{+	iowrite32(PM_PASSWORD | PM_RSTC_RESET, __io_address(PM_RSTC));+	printk(KERN_INFO "watchdog stopped\n");+	return 0;+}++/**+ *	Reload counter one with the watchdog heartbeat. We don't bother+ *	reloading the cascade counter.+ */++static void wdog_ping(void)+{+	wdog_start(wdog_ticks);+}++/**+ *	@t:		the new heartbeat value that needs to be set.+ *+ *	Set a new heartbeat value for the watchdog device. If the heartbeat+ *	value is incorrect we keep the old value and return -EINVAL. If+ *	successful we return 0.+ */++static int wdog_set_heartbeat(int t)+{+	if (t < 1 || t > WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET))+		return -EINVAL;++	heartbeat = t;+	wdog_ticks = SECS_TO_WDOG_TICKS(t);+	return 0;+}++/**+ *	@file: file handle to the watchdog+ *	@buf: buffer to write (unused as data does not matter here+ *	@count: count of bytes+ *	@ppos: pointer to the position to write. No seeks allowed+ *+ *	A write to a watchdog device is defined as a keepalive signal.+ *+ *      if 'nowayout' is set then normally a close() is ignored. But+ *      if you write 'V' first then the close() will stop the timer.+ */++static ssize_t wdog_write(struct file *file, const char __user *buf,+						size_t count, loff_t *ppos)+{+	if (count) {+		if (!nowayout) {+			size_t i;++			/* In case it was set long ago */+			expect_close = 0;++			for (i = 0; i != count; i++) {+				char c;+				if (get_user(c, buf + i))+					return -EFAULT;+				if (c == 'V')+					expect_close = 42;+			}+		}+		wdog_ping();+	}+	return count;+}++static int wdog_get_status(void)+{+	unsigned long flags;+	int status = 0;+	spin_lock_irqsave(&wdog_lock, flags);+	/* FIXME: readback reset reason */+	spin_unlock_irqrestore(&wdog_lock, flags);+	return status;+}++static uint32_t wdog_get_remaining(void)+{+	uint32_t ret = ioread32(__io_address(PM_WDOG));+	return ret & PM_WDOG_TIME_SET;+}++/**+ *	@file: file handle to the device+ *	@cmd: watchdog command+ *	@arg: argument pointer+ *+ *	The watchdog API defines a common set of functions for all watchdogs+ *	according to their available features. We only actually usefully support+ *	querying capabilities and current status.+ */++static long wdog_ioctl(struct file *file, unsigned int cmd, unsigned long arg)+{+	void __user *argp = (void __user *)arg;+	int __user *p = argp;+	int new_heartbeat;+	int status;+	int options;+	uint32_t remaining;++	struct watchdog_info ident = {+		.options =		WDIOF_SETTIMEOUT|+					WDIOF_MAGICCLOSE|+					WDIOF_KEEPALIVEPING,+		.firmware_version =	1,+		.identity =		"BCM2708",+	};++	switch (cmd) {+	case WDIOC_GETSUPPORT:+		return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;+	case WDIOC_GETSTATUS:+		status = wdog_get_status();+		return put_user(status, p);+	case WDIOC_GETBOOTSTATUS:+		return put_user(0, p);+	case WDIOC_KEEPALIVE:+		wdog_ping();+		return 0;+	case WDIOC_SETTIMEOUT:+		if (get_user(new_heartbeat, p))+			return -EFAULT;+		if (wdog_set_heartbeat(new_heartbeat))+			return -EINVAL;+		wdog_ping();+		/* Fall */+	case WDIOC_GETTIMEOUT:+		return put_user(heartbeat, p);+	case WDIOC_GETTIMELEFT:+		remaining = WDOG_TICKS_TO_SECS(wdog_get_remaining());+		return put_user(remaining, p);+	case WDIOC_SETOPTIONS:+		if (get_user(options, p))+			return -EFAULT;+		if (options & WDIOS_DISABLECARD)+			wdog_stop();+		if (options & WDIOS_ENABLECARD)+			wdog_start(wdog_ticks);+		return 0;+	default:+		return -ENOTTY;+	}+}++/**+ *	@inode: inode of device+ *	@file: file handle to device+ *+ *	The watchdog device has been opened. The watchdog device is single+ *	open and on opening we load the counters.+ */++static int wdog_open(struct inode *inode, struct file *file)+{+	if (test_and_set_bit(0, &wdog_is_open))+		return -EBUSY;+	/*+	 *	Activate+	 */+	wdog_start(wdog_ticks);+	return nonseekable_open(inode, file);+}++/**+ *	@inode: inode to board+ *	@file: file handle to board+ *+ *	The watchdog has a configurable API. There is a religious dispute+ *	between people who want their watchdog to be able to shut down and+ *	those who want to be sure if the watchdog manager dies the machine+ *	reboots. In the former case we disable the counters, in the latter+ *	case you have to open it again very soon.+ */++static int wdog_release(struct inode *inode, struct file *file)+{+	if (expect_close == 42) {+		wdog_stop();+	} else {+		printk(KERN_CRIT+		 "wdt: WDT device closed unexpectedly.  WDT will not stop!\n");+		wdog_ping();+	}+	clear_bit(0, &wdog_is_open);+	expect_close = 0;+	return 0;+}++/**+ *	@this: our notifier block+ *	@code: the event being reported+ *	@unused: unused+ *+ *	Our notifier is called on system shutdowns. Turn the watchdog+ *	off so that it does not fire during the next reboot.+ */++static int wdog_notify_sys(struct notifier_block *this, unsigned long code,+	void *unused)+{+	if (code == SYS_DOWN || code == SYS_HALT)+		wdog_stop();+	return NOTIFY_DONE;+}++/*+ *	Kernel Interfaces+ */+++static const struct file_operations wdog_fops = {+	.owner		= THIS_MODULE,+	.llseek		= no_llseek,+	.write		= wdog_write,+	.unlocked_ioctl	= wdog_ioctl,+	.open		= wdog_open,+	.release	= wdog_release,+};++static struct miscdevice wdog_miscdev = {+	.minor	= WATCHDOG_MINOR,+	.name	= "watchdog",+	.fops	= &wdog_fops,+};++/*+ *	The WDT card needs to learn about soft shutdowns in order to+ *	turn the timebomb registers off.+ */++static struct notifier_block wdog_notifier = {+	.notifier_call = wdog_notify_sys,+};++/**+ *	cleanup_module:+ *+ *	Unload the watchdog. You cannot do this with any file handles open.+ *	If your watchdog is set to continue ticking on close and you unload+ *	it, well it keeps ticking. We won't get the interrupt but the board+ *	will not touch PC memory so all is fine. You just have to load a new+ *	module in 60 seconds or reboot.+ */++static void __exit wdog_exit(void)+{+	misc_deregister(&wdog_miscdev);+	unregister_reboot_notifier(&wdog_notifier);+}++static int __init wdog_init(void)+{+	int ret;++	/* Check that the heartbeat value is within it's range;+	   if not reset to the default */+	if (wdog_set_heartbeat(heartbeat)) {+		wdog_set_heartbeat(WD_TIMO);+		printk(KERN_INFO "bcm2708_wdog: heartbeat value must be "+			"0 < heartbeat < %d, using %d\n",+				WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET),+				WD_TIMO);+	}++	ret = register_reboot_notifier(&wdog_notifier);+	if (ret) {+		printk(KERN_ERR+		      "wdt: cannot register reboot notifier (err=%d)\n", ret);+		goto out_reboot;+	}++	ret = misc_register(&wdog_miscdev);+	if (ret) {+		printk(KERN_ERR+			"wdt: cannot register miscdev on minor=%d (err=%d)\n",+							WATCHDOG_MINOR, ret);+		goto out_misc;+	}++	printk(KERN_INFO "bcm2708 watchdog, heartbeat=%d sec (nowayout=%d)\n",+		heartbeat, nowayout);+	return 0;++out_misc:+	unregister_reboot_notifier(&wdog_notifier);+out_reboot:+	return ret;+}++module_init(wdog_init);+module_exit(wdog_exit);++MODULE_AUTHOR("Luke Diamand");+MODULE_DESCRIPTION("Driver for BCM2708 watchdog");+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);+MODULE_ALIAS_MISCDEV(TEMP_MINOR);+MODULE_LICENSE("GPL");diff -Nur linux-3.11.10.orig/drivers/watchdog/Kconfig linux-3.11.10/drivers/watchdog/Kconfig--- linux-3.11.10.orig/drivers/watchdog/Kconfig	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/watchdog/Kconfig	2014-02-07 19:57:30.000000000 +0100@@ -382,6 +382,12 @@ 	  To compile this driver as a module, choose M here: the 	  module will be called retu_wdt. +config BCM2708_WDT+	tristate "BCM2708 Watchdog"+	depends on ARCH_BCM2708+	help+	  Enables BCM2708 watchdog support.+ # AVR32 Architecture  config AT32AP700X_WDTdiff -Nur linux-3.11.10.orig/drivers/watchdog/Makefile linux-3.11.10/drivers/watchdog/Makefile--- linux-3.11.10.orig/drivers/watchdog/Makefile	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/drivers/watchdog/Makefile	2014-02-07 19:57:30.000000000 +0100@@ -53,6 +53,7 @@ obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o obj-$(CONFIG_RETU_WATCHDOG) += retu_wdt.o+obj-$(CONFIG_BCM2708_WDT) += bcm2708_wdog.o obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o  # AVR32 Architecturediff -Nur linux-3.11.10.orig/include/linux/broadcom/vc_cma.h linux-3.11.10/include/linux/broadcom/vc_cma.h--- linux-3.11.10.orig/include/linux/broadcom/vc_cma.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/include/linux/broadcom/vc_cma.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,29 @@+/*****************************************************************************+* Copyright 2012 Broadcom Corporation.  All rights reserved.+*+* Unless you and Broadcom execute a separate written software license+* agreement governing use of this software, this software is licensed to you+* under the terms of the GNU General Public License version 2, available at+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").+*+* Notwithstanding the above, under no circumstances may you combine this+* software in any way with any other Broadcom software provided under a+* license other than the GPL, without Broadcom's express prior written+* consent.+*****************************************************************************/++#if !defined( VC_CMA_H )+#define VC_CMA_H++#include <linux/ioctl.h>++#define VC_CMA_IOC_MAGIC 0xc5++#define VC_CMA_IOC_RESERVE _IO(VC_CMA_IOC_MAGIC, 0)++#ifdef __KERNEL__+extern void __init vc_cma_early_init(void);+extern void __init vc_cma_reserve(void);+#endif++#endif /* VC_CMA_H */diff -Nur linux-3.11.10.orig/include/linux/mmc/host.h linux-3.11.10/include/linux/mmc/host.h--- linux-3.11.10.orig/include/linux/mmc/host.h	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/include/linux/mmc/host.h	2014-02-07 19:57:30.000000000 +0100@@ -281,6 +281,7 @@ 				 MMC_CAP2_PACKED_WR) #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)	/* Don't power up before scan */ #define MMC_CAP2_SANITIZE	(1 << 15)		/* Support Sanitize */+#define MMC_CAP2_FORCE_MULTIBLOCK (1 << 31)	/* Always use multiblock transfers */  	mmc_pm_flag_t		pm_caps;	/* supported pm features */ diff -Nur linux-3.11.10.orig/include/linux/mmc/sdhci.h linux-3.11.10/include/linux/mmc/sdhci.h--- linux-3.11.10.orig/include/linux/mmc/sdhci.h	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/include/linux/mmc/sdhci.h	2014-02-07 19:57:30.000000000 +0100@@ -100,6 +100,7 @@ #define SDHCI_QUIRK2_BROKEN_HOST_CONTROL		(1<<5)  	int irq;		/* Device IRQ */+	int second_irq; 	/* Additional IRQ to disable/enable in low-latency mode */ 	void __iomem *ioaddr;	/* Mapped address */  	const struct sdhci_ops *ops;	/* Low level hw interface */@@ -131,6 +132,7 @@ #define SDHCI_SDIO_IRQ_ENABLED	(1<<9)	/* SDIO irq enabled */ #define SDHCI_SDR104_NEEDS_TUNING (1<<10)	/* SDR104/HS200 needs tuning */ #define SDHCI_USING_RETUNING_TIMER (1<<11)	/* Host is using a retuning timer for the card */+#define SDHCI_USE_PLATDMA       (1<<12) /* Host uses 3rd party DMA */  	unsigned int version;	/* SDHCI spec. version */ @@ -146,6 +148,7 @@  	struct mmc_request *mrq;	/* Current request */ 	struct mmc_command *cmd;	/* Current command */+	int	last_cmdop;	/* Opcode of last cmd sent */ 	struct mmc_data *data;	/* Current data request */ 	unsigned int data_early:1;	/* Data finished before cmd */ diff -Nur linux-3.11.10.orig/include/uapi/linux/fb.h linux-3.11.10/include/uapi/linux/fb.h--- linux-3.11.10.orig/include/uapi/linux/fb.h	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/include/uapi/linux/fb.h	2014-02-07 19:57:30.000000000 +0100@@ -34,6 +34,11 @@ #define FBIOPUT_MODEINFO        0x4617 #define FBIOGET_DISPINFO        0x4618 #define FBIO_WAITFORVSYNC	_IOW('F', 0x20, __u32)+/*+ * HACK: use 'z' in order not to clash with any other ioctl numbers which might+ * be concurrently added to the mainline kernel+ */+#define FBIOCOPYAREA		_IOW('z', 0x21, struct fb_copyarea)  #define FB_TYPE_PACKED_PIXELS		0	/* Packed Pixels	*/ #define FB_TYPE_PLANES			1	/* Non interleaved planes */diff -Nur linux-3.11.10.orig/sound/arm/bcm2835.c linux-3.11.10/sound/arm/bcm2835.c--- linux-3.11.10.orig/sound/arm/bcm2835.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/sound/arm/bcm2835.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,413 @@+/*****************************************************************************+* Copyright 2011 Broadcom Corporation.  All rights reserved.+*+* Unless you and Broadcom execute a separate written software license+* agreement governing use of this software, this software is licensed to you+* under the terms of the GNU General Public License version 2, available at+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").+*+* Notwithstanding the above, under no circumstances may you combine this+* software in any way with any other Broadcom software provided under a+* license other than the GPL, without Broadcom's express prior written+* consent.+*****************************************************************************/++#include <linux/platform_device.h>++#include <linux/init.h>+#include <linux/slab.h>+#include <linux/module.h>++#include "bcm2835.h"++/* module parameters (see "Module Parameters") */+/* SNDRV_CARDS: maximum number of cards supported by this module */+static int index[MAX_SUBSTREAMS] = {[0 ... (MAX_SUBSTREAMS - 1)] = -1 };+static char *id[MAX_SUBSTREAMS] = {[0 ... (MAX_SUBSTREAMS - 1)] = NULL };+static int enable[MAX_SUBSTREAMS] = {[0 ... (MAX_SUBSTREAMS - 1)] = 1 };++/* HACKY global pointers needed for successive probes to work : ssp+ * But compared against the changes we will have to do in VC audio_ipc code+ * to export 8 audio_ipc devices as a single IPC device and then monitor all+ * four devices in a thread, this gets things done quickly and should be easier+ * to debug if we run into issues+ */++static struct snd_card *g_card = NULL;+static bcm2835_chip_t *g_chip = NULL;++static int snd_bcm2835_free(bcm2835_chip_t * chip)+{+	kfree(chip);+	return 0;+}++/* component-destructor+ * (see "Management of Cards and Components")+ */+static int snd_bcm2835_dev_free(struct snd_device *device)+{+	return snd_bcm2835_free(device->device_data);+}++/* chip-specific constructor+ * (see "Management of Cards and Components")+ */+static int snd_bcm2835_create(struct snd_card *card,+					struct platform_device *pdev,+					bcm2835_chip_t ** rchip)+{+	bcm2835_chip_t *chip;+	int err;+	static struct snd_device_ops ops = {+		.dev_free = snd_bcm2835_dev_free,+	};++	*rchip = NULL;++	chip = kzalloc(sizeof(*chip), GFP_KERNEL);+	if (chip == NULL)+		return -ENOMEM;++	chip->card = card;++	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);+	if (err < 0) {+		snd_bcm2835_free(chip);+		return err;+	}++	*rchip = chip;+	return 0;+}++static int snd_bcm2835_alsa_probe(struct platform_device *pdev)+{+	static int dev;+	bcm2835_chip_t *chip;+	struct snd_card *card;+	int err;++	if (dev >= MAX_SUBSTREAMS)+		return -ENODEV;++	if (!enable[dev]) {+		dev++;+		return -ENOENT;+	}++	if (dev > 0)+		goto add_register_map;++	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &g_card);+	if (err < 0)+		goto out;++	snd_card_set_dev(g_card, &pdev->dev);+	strcpy(g_card->driver, "BRCM bcm2835 ALSA Driver");+	strcpy(g_card->shortname, "bcm2835 ALSA");+	sprintf(g_card->longname, "%s", g_card->shortname);++	err = snd_bcm2835_create(g_card, pdev, &chip);+	if (err < 0) {+		dev_err(&pdev->dev, "Failed to create bcm2835 chip\n");+		goto out_bcm2835_create;+	}++	g_chip = chip;+	err = snd_bcm2835_new_pcm(chip);+	if (err < 0) {+		dev_err(&pdev->dev, "Failed to create new BCM2835 pcm device\n");+		goto out_bcm2835_new_pcm;+	}++	err = snd_bcm2835_new_ctl(chip);+	if (err < 0) {+		dev_err(&pdev->dev, "Failed to create new BCM2835 ctl\n");+		goto out_bcm2835_new_ctl;+	}++add_register_map:+	card = g_card;+	chip = g_chip;++	BUG_ON(!(card && chip));++	chip->avail_substreams |= (1 << dev);+	chip->pdev[dev] = pdev;++	if (dev == 0) {+		err = snd_card_register(card);+		if (err < 0) {+			dev_err(&pdev->dev,+				"Failed to register bcm2835 ALSA card \n");+			goto out_card_register;+		}+		platform_set_drvdata(pdev, card);+		audio_info("bcm2835 ALSA card created!\n");+	} else {+		audio_info("bcm2835 ALSA chip created!\n");+		platform_set_drvdata(pdev, (void *)dev);+	}++	dev++;++	return 0;++out_card_register:+out_bcm2835_new_ctl:+out_bcm2835_new_pcm:+out_bcm2835_create:+	BUG_ON(!g_card);+	if (snd_card_free(g_card))+		dev_err(&pdev->dev, "Failed to free Registered alsa card\n");+	g_card = NULL;+out:+	dev = SNDRV_CARDS;	/* stop more avail_substreams from being probed */+	dev_err(&pdev->dev, "BCM2835 ALSA Probe failed !!\n");+	return err;+}++static int snd_bcm2835_alsa_remove(struct platform_device *pdev)+{+	uint32_t idx;+	void *drv_data;++	drv_data = platform_get_drvdata(pdev);++	if (drv_data == (void *)g_card) {+		/* This is the card device */+		snd_card_free((struct snd_card *)drv_data);+		g_card = NULL;+		g_chip = NULL;+	} else {+		idx = (uint32_t) drv_data;+		if (g_card != NULL) {+			BUG_ON(!g_chip);+			/* We pass chip device numbers in audio ipc devices+			 * other than the one we registered our card with+			 */+			idx = (uint32_t) drv_data;+			BUG_ON(!idx || idx > MAX_SUBSTREAMS);+			g_chip->avail_substreams &= ~(1 << idx);+			/* There should be atleast one substream registered+			 * after we are done here, as it wil be removed when+			 * the *remove* is called for the card device+			 */+			BUG_ON(!g_chip->avail_substreams);+		}+	}++	platform_set_drvdata(pdev, NULL);++	return 0;+}++#ifdef CONFIG_PM+static int snd_bcm2835_alsa_suspend(struct platform_device *pdev,+				    pm_message_t state)+{+	return 0;+}++static int snd_bcm2835_alsa_resume(struct platform_device *pdev)+{+	return 0;+}++#endif++static struct platform_driver bcm2835_alsa0_driver = {+	.probe = snd_bcm2835_alsa_probe,+	.remove = snd_bcm2835_alsa_remove,+#ifdef CONFIG_PM+	.suspend = snd_bcm2835_alsa_suspend,+	.resume = snd_bcm2835_alsa_resume,+#endif+	.driver = {+		   .name = "bcm2835_AUD0",+		   .owner = THIS_MODULE,+		   },+};++static struct platform_driver bcm2835_alsa1_driver = {+	.probe = snd_bcm2835_alsa_probe,+	.remove = snd_bcm2835_alsa_remove,+#ifdef CONFIG_PM+	.suspend = snd_bcm2835_alsa_suspend,+	.resume = snd_bcm2835_alsa_resume,+#endif+	.driver = {+		   .name = "bcm2835_AUD1",+		   .owner = THIS_MODULE,+		   },+};++static struct platform_driver bcm2835_alsa2_driver = {+	.probe = snd_bcm2835_alsa_probe,+	.remove = snd_bcm2835_alsa_remove,+#ifdef CONFIG_PM+	.suspend = snd_bcm2835_alsa_suspend,+	.resume = snd_bcm2835_alsa_resume,+#endif+	.driver = {+		   .name = "bcm2835_AUD2",+		   .owner = THIS_MODULE,+		   },+};++static struct platform_driver bcm2835_alsa3_driver = {+	.probe = snd_bcm2835_alsa_probe,+	.remove = snd_bcm2835_alsa_remove,+#ifdef CONFIG_PM+	.suspend = snd_bcm2835_alsa_suspend,+	.resume = snd_bcm2835_alsa_resume,+#endif+	.driver = {+		   .name = "bcm2835_AUD3",+		   .owner = THIS_MODULE,+		   },+};++static struct platform_driver bcm2835_alsa4_driver = {+	.probe = snd_bcm2835_alsa_probe,+	.remove = snd_bcm2835_alsa_remove,+#ifdef CONFIG_PM+	.suspend = snd_bcm2835_alsa_suspend,+	.resume = snd_bcm2835_alsa_resume,+#endif+	.driver = {+		   .name = "bcm2835_AUD4",+		   .owner = THIS_MODULE,+		   },+};++static struct platform_driver bcm2835_alsa5_driver = {+	.probe = snd_bcm2835_alsa_probe,+	.remove = snd_bcm2835_alsa_remove,+#ifdef CONFIG_PM+	.suspend = snd_bcm2835_alsa_suspend,+	.resume = snd_bcm2835_alsa_resume,+#endif+	.driver = {+		   .name = "bcm2835_AUD5",+		   .owner = THIS_MODULE,+		   },+};++static struct platform_driver bcm2835_alsa6_driver = {+	.probe = snd_bcm2835_alsa_probe,+	.remove = snd_bcm2835_alsa_remove,+#ifdef CONFIG_PM+	.suspend = snd_bcm2835_alsa_suspend,+	.resume = snd_bcm2835_alsa_resume,+#endif+	.driver = {+		   .name = "bcm2835_AUD6",+		   .owner = THIS_MODULE,+		   },+};++static struct platform_driver bcm2835_alsa7_driver = {+	.probe = snd_bcm2835_alsa_probe,+	.remove = snd_bcm2835_alsa_remove,+#ifdef CONFIG_PM+	.suspend = snd_bcm2835_alsa_suspend,+	.resume = snd_bcm2835_alsa_resume,+#endif+	.driver = {+		   .name = "bcm2835_AUD7",+		   .owner = THIS_MODULE,+		   },+};++static int bcm2835_alsa_device_init(void)+{+	int err;+	err = platform_driver_register(&bcm2835_alsa0_driver);+	if (err) {+		pr_err("Error registering bcm2835_alsa0_driver %d .\n", err);+		goto out;+	}++	err = platform_driver_register(&bcm2835_alsa1_driver);+	if (err) {+		pr_err("Error registering bcm2835_alsa0_driver %d .\n", err);+		goto unregister_0;+	}++	err = platform_driver_register(&bcm2835_alsa2_driver);+	if (err) {+		pr_err("Error registering bcm2835_alsa0_driver %d .\n", err);+		goto unregister_1;+	}++	err = platform_driver_register(&bcm2835_alsa3_driver);+	if (err) {+		pr_err("Error registering bcm2835_alsa0_driver %d .\n", err);+		goto unregister_2;+	}++	err = platform_driver_register(&bcm2835_alsa4_driver);+	if (err) {+		pr_err("Error registering bcm2835_alsa0_driver %d .\n", err);+		goto unregister_3;+	}++	err = platform_driver_register(&bcm2835_alsa5_driver);+	if (err) {+		pr_err("Error registering bcm2835_alsa0_driver %d .\n", err);+		goto unregister_4;+	}++	err = platform_driver_register(&bcm2835_alsa6_driver);+	if (err) {+		pr_err("Error registering bcm2835_alsa0_driver %d .\n", err);+		goto unregister_5;+	}++	err = platform_driver_register(&bcm2835_alsa7_driver);+	if (err) {+		pr_err("Error registering bcm2835_alsa0_driver %d .\n", err);+		goto unregister_6;+	}++	return 0;++unregister_6:+	platform_driver_unregister(&bcm2835_alsa6_driver);+unregister_5:+	platform_driver_unregister(&bcm2835_alsa5_driver);+unregister_4:+	platform_driver_unregister(&bcm2835_alsa4_driver);+unregister_3:+	platform_driver_unregister(&bcm2835_alsa3_driver);+unregister_2:+	platform_driver_unregister(&bcm2835_alsa2_driver);+unregister_1:+	platform_driver_unregister(&bcm2835_alsa1_driver);+unregister_0:+	platform_driver_unregister(&bcm2835_alsa0_driver);+out:+	return err;+}++static void bcm2835_alsa_device_exit(void)+{+	platform_driver_unregister(&bcm2835_alsa0_driver);+	platform_driver_unregister(&bcm2835_alsa1_driver);+	platform_driver_unregister(&bcm2835_alsa2_driver);+	platform_driver_unregister(&bcm2835_alsa3_driver);+	platform_driver_unregister(&bcm2835_alsa4_driver);+	platform_driver_unregister(&bcm2835_alsa5_driver);+	platform_driver_unregister(&bcm2835_alsa6_driver);+	platform_driver_unregister(&bcm2835_alsa7_driver);+}++late_initcall(bcm2835_alsa_device_init);+module_exit(bcm2835_alsa_device_exit);++MODULE_AUTHOR("Dom Cobley");+MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");+MODULE_LICENSE("GPL");+MODULE_ALIAS("platform:bcm2835_alsa");diff -Nur linux-3.11.10.orig/sound/arm/bcm2835-ctl.c linux-3.11.10/sound/arm/bcm2835-ctl.c--- linux-3.11.10.orig/sound/arm/bcm2835-ctl.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/sound/arm/bcm2835-ctl.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,200 @@+/*****************************************************************************+* Copyright 2011 Broadcom Corporation.  All rights reserved.+*+* Unless you and Broadcom execute a separate written software license+* agreement governing use of this software, this software is licensed to you+* under the terms of the GNU General Public License version 2, available at+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").+*+* Notwithstanding the above, under no circumstances may you combine this+* software in any way with any other Broadcom software provided under a+* license other than the GPL, without Broadcom's express prior written+* consent.+*****************************************************************************/++#include <linux/platform_device.h>+#include <linux/init.h>+#include <linux/io.h>+#include <linux/jiffies.h>+#include <linux/slab.h>+#include <linux/time.h>+#include <linux/wait.h>+#include <linux/delay.h>+#include <linux/moduleparam.h>+#include <linux/sched.h>++#include <sound/core.h>+#include <sound/control.h>+#include <sound/pcm.h>+#include <sound/pcm_params.h>+#include <sound/rawmidi.h>+#include <sound/initval.h>+#include <sound/tlv.h>++#include "bcm2835.h"++/* volume maximum and minimum in terms of 0.01dB */+#define CTRL_VOL_MAX 400+#define CTRL_VOL_MIN -10239 /* originally -10240 */+++static int snd_bcm2835_ctl_info(struct snd_kcontrol *kcontrol,+				struct snd_ctl_elem_info *uinfo)+{+	audio_info(" ... IN\n");+	if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {+		uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;+		uinfo->count = 1;+		uinfo->value.integer.min = CTRL_VOL_MIN;+		uinfo->value.integer.max = CTRL_VOL_MAX;      /* 2303 */+	} else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) {+		uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;+		uinfo->count = 1;+		uinfo->value.integer.min = 0;+		uinfo->value.integer.max = 1;+	} else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) {+		uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;+		uinfo->count = 1;+		uinfo->value.integer.min = 0;+		uinfo->value.integer.max = AUDIO_DEST_MAX-1;+	}+	audio_info(" ... OUT\n");+	return 0;+}++/* toggles mute on or off depending on the value of nmute, and returns+ * 1 if the mute value was changed, otherwise 0+ */+static int toggle_mute(struct bcm2835_chip *chip, int nmute)+{+	/* if settings are ok, just return 0 */+	if(chip->mute == nmute)+		return 0;++	/* if the sound is muted then we need to unmute */+	if(chip->mute == CTRL_VOL_MUTE)+	{+		chip->volume = chip->old_volume; /* copy the old volume back */+		audio_info("Unmuting, old_volume = %d, volume = %d ...\n", chip->old_volume, chip->volume);+	}+	else /* otherwise we mute */+	{+		chip->old_volume = chip->volume;+		chip->volume = 26214; /* set volume to minimum level AKA mute */+		audio_info("Muting, old_volume = %d, volume = %d ...\n", chip->old_volume, chip->volume);+	}++	chip->mute = nmute;+	return 1;+}++static int snd_bcm2835_ctl_get(struct snd_kcontrol *kcontrol,+			       struct snd_ctl_elem_value *ucontrol)+{+	struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);++	BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK));++	if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)+		ucontrol->value.integer.value[0] = chip2alsa(chip->volume);+	else if (kcontrol->private_value == PCM_PLAYBACK_MUTE)+		ucontrol->value.integer.value[0] = chip->mute;+	else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE)+		ucontrol->value.integer.value[0] = chip->dest;++	return 0;+}++static int snd_bcm2835_ctl_put(struct snd_kcontrol *kcontrol,+			       struct snd_ctl_elem_value *ucontrol)+{+	struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);+	int changed = 0;++	if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {+		audio_info("Volume change attempted.. volume = %d new_volume = %d\n", chip->volume, (int)ucontrol->value.integer.value[0]);+		if (chip->mute == CTRL_VOL_MUTE) {+			/* changed = toggle_mute(chip, CTRL_VOL_UNMUTE); */+			return 1; /* should return 0 to signify no change but the mixer takes this as the opposite sign (no idea why) */+		}+		if (changed+		    || (ucontrol->value.integer.value[0] != chip2alsa(chip->volume))) {++			chip->volume = alsa2chip(ucontrol->value.integer.value[0]);+			changed = 1;+		}++	} else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) {+		/* Now implemented */+		audio_info(" Mute attempted\n");+		changed = toggle_mute(chip, ucontrol->value.integer.value[0]);++	} else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) {+		if (ucontrol->value.integer.value[0] != chip->dest) {+			chip->dest = ucontrol->value.integer.value[0];+			changed = 1;+		}+	}++	if (changed) {+		if (bcm2835_audio_set_ctls(chip))+			printk(KERN_ERR "Failed to set ALSA controls..\n");+	}++	return changed;+}++static DECLARE_TLV_DB_SCALE(snd_bcm2835_db_scale, CTRL_VOL_MIN, 1, 1);++static struct snd_kcontrol_new snd_bcm2835_ctl[] = {+	{+	 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,+	 .name = "PCM Playback Volume",+	 .index = 0,+	 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,+	 .private_value = PCM_PLAYBACK_VOLUME,+	 .info = snd_bcm2835_ctl_info,+	 .get = snd_bcm2835_ctl_get,+	 .put = snd_bcm2835_ctl_put,+	 .count = 1,+	 .tlv = {.p = snd_bcm2835_db_scale}+	},+	{+	 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,+	 .name = "PCM Playback Switch",+	 .index = 0,+	 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,+	 .private_value = PCM_PLAYBACK_MUTE,+	 .info = snd_bcm2835_ctl_info,+	 .get = snd_bcm2835_ctl_get,+	 .put = snd_bcm2835_ctl_put,+	 .count = 1,+	 },+	{+	 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,+	 .name = "PCM Playback Route",+	 .index = 0,+	 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,+	 .private_value = PCM_PLAYBACK_DEVICE,+	 .info = snd_bcm2835_ctl_info,+	 .get = snd_bcm2835_ctl_get,+	 .put = snd_bcm2835_ctl_put,+	 .count = 1,+	},+};++int snd_bcm2835_new_ctl(bcm2835_chip_t * chip)+{+	int err;+	unsigned int idx;++	strcpy(chip->card->mixername, "Broadcom Mixer");+	for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_ctl); idx++) {+		err =+		    snd_ctl_add(chip->card,+				snd_ctl_new1(&snd_bcm2835_ctl[idx], chip));+		if (err < 0)+			return err;+	}+	return 0;+}diff -Nur linux-3.11.10.orig/sound/arm/bcm2835.h linux-3.11.10/sound/arm/bcm2835.h--- linux-3.11.10.orig/sound/arm/bcm2835.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/sound/arm/bcm2835.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,157 @@+/*****************************************************************************+* Copyright 2011 Broadcom Corporation.  All rights reserved.+*+* Unless you and Broadcom execute a separate written software license+* agreement governing use of this software, this software is licensed to you+* under the terms of the GNU General Public License version 2, available at+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").+*+* Notwithstanding the above, under no circumstances may you combine this+* software in any way with any other Broadcom software provided under a+* license other than the GPL, without Broadcom's express prior written+* consent.+*****************************************************************************/++#ifndef __SOUND_ARM_BCM2835_H+#define __SOUND_ARM_BCM2835_H++#include <linux/device.h>+#include <linux/list.h>+#include <linux/interrupt.h>+#include <linux/wait.h>+#include <sound/core.h>+#include <sound/initval.h>+#include <sound/pcm.h>+#include <sound/pcm_params.h>+#include <sound/pcm-indirect.h>+#include <linux/workqueue.h>++/*+#define AUDIO_DEBUG_ENABLE+#define AUDIO_VERBOSE_DEBUG_ENABLE+*/++/* Debug macros */++#ifdef AUDIO_DEBUG_ENABLE+#ifdef AUDIO_VERBOSE_DEBUG_ENABLE++#define audio_debug(fmt, arg...)	\+	printk(KERN_INFO"%s:%d " fmt, __func__, __LINE__, ##arg)++#define audio_info(fmt, arg...)	\+	printk(KERN_INFO"%s:%d " fmt, __func__, __LINE__, ##arg)++#else++#define audio_debug(fmt, arg...)++#define audio_info(fmt, arg...)++#endif /* AUDIO_VERBOSE_DEBUG_ENABLE */++#else++#define audio_debug(fmt, arg...)++#define audio_info(fmt, arg...)++#endif /* AUDIO_DEBUG_ENABLE */++#define audio_error(fmt, arg...)	\+	printk(KERN_ERR"%s:%d " fmt, __func__, __LINE__, ##arg)++#define audio_warning(fmt, arg...)	\+	printk(KERN_WARNING"%s:%d " fmt, __func__, __LINE__, ##arg)++#define audio_alert(fmt, arg...)	\+	printk(KERN_ALERT"%s:%d " fmt, __func__, __LINE__, ##arg)++#define MAX_SUBSTREAMS			(8)+#define AVAIL_SUBSTREAMS_MASK		(0xff)+enum {+	CTRL_VOL_MUTE,+	CTRL_VOL_UNMUTE+};++/* macros for alsa2chip and chip2alsa, instead of functions */++#define alsa2chip(vol) (uint)(-((vol << 8) / 100))	/* convert alsa to chip volume (defined as macro rather than function call) */+#define chip2alsa(vol) -((vol * 100) >> 8)			/* convert chip to alsa volume */++/* Some constants for values .. */+typedef enum {+	AUDIO_DEST_AUTO = 0,+	AUDIO_DEST_HEADPHONES = 1,+	AUDIO_DEST_HDMI = 2,+	AUDIO_DEST_MAX,+} SND_BCM2835_ROUTE_T;++typedef enum {+	PCM_PLAYBACK_VOLUME,+	PCM_PLAYBACK_MUTE,+	PCM_PLAYBACK_DEVICE,+} SND_BCM2835_CTRL_T;++/* definition of the chip-specific record */+typedef struct bcm2835_chip {+	struct snd_card *card;+	struct snd_pcm *pcm;+	/* Bitmat for valid reg_base and irq numbers */+	uint32_t avail_substreams;+	struct platform_device *pdev[MAX_SUBSTREAMS];+	struct bcm2835_alsa_stream *alsa_stream[MAX_SUBSTREAMS];++	int volume;+	int old_volume; /* stores the volume value whist muted */+	int dest;+	int mute;+} bcm2835_chip_t;++typedef struct bcm2835_alsa_stream {+	bcm2835_chip_t *chip;+	struct snd_pcm_substream *substream;+	struct snd_pcm_indirect pcm_indirect;++	struct semaphore buffers_update_sem;+	struct semaphore control_sem;+	spinlock_t lock;+	volatile uint32_t control;+	volatile uint32_t status;++	int open;+	int running;+	int draining;++	unsigned int pos;+	unsigned int buffer_size;+	unsigned int period_size;++	uint32_t enable_fifo_irq;+	irq_handler_t fifo_irq_handler;++	atomic_t retrieved;+	struct opaque_AUDIO_INSTANCE_T *instance;+	struct workqueue_struct *my_wq;+	int idx;+} bcm2835_alsa_stream_t;++int snd_bcm2835_new_ctl(bcm2835_chip_t * chip);+int snd_bcm2835_new_pcm(bcm2835_chip_t * chip);++int bcm2835_audio_open(bcm2835_alsa_stream_t * alsa_stream);+int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream);+int bcm2835_audio_set_params(bcm2835_alsa_stream_t * alsa_stream,+			     uint32_t channels, uint32_t samplerate,+			     uint32_t bps);+int bcm2835_audio_setup(bcm2835_alsa_stream_t * alsa_stream);+int bcm2835_audio_start(bcm2835_alsa_stream_t * alsa_stream);+int bcm2835_audio_stop(bcm2835_alsa_stream_t * alsa_stream);+int bcm2835_audio_set_ctls(bcm2835_chip_t * chip);+int bcm2835_audio_write(bcm2835_alsa_stream_t * alsa_stream, uint32_t count,+			void *src);+uint32_t bcm2835_audio_retrieve_buffers(bcm2835_alsa_stream_t * alsa_stream);+void bcm2835_audio_flush_buffers(bcm2835_alsa_stream_t * alsa_stream);+void bcm2835_audio_flush_playback_buffers(bcm2835_alsa_stream_t * alsa_stream);++#endif /* __SOUND_ARM_BCM2835_H */diff -Nur linux-3.11.10.orig/sound/arm/bcm2835-pcm.c linux-3.11.10/sound/arm/bcm2835-pcm.c--- linux-3.11.10.orig/sound/arm/bcm2835-pcm.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/sound/arm/bcm2835-pcm.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,426 @@+/*****************************************************************************+* Copyright 2011 Broadcom Corporation.  All rights reserved.+*+* Unless you and Broadcom execute a separate written software license+* agreement governing use of this software, this software is licensed to you+* under the terms of the GNU General Public License version 2, available at+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").+*+* Notwithstanding the above, under no circumstances may you combine this+* software in any way with any other Broadcom software provided under a+* license other than the GPL, without Broadcom's express prior written+* consent.+*****************************************************************************/++#include <linux/interrupt.h>+#include <linux/slab.h>++#include "bcm2835.h"++/* hardware definition */+static struct snd_pcm_hardware snd_bcm2835_playback_hw = {+	.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |+		 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),+	.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,+	.rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,+	.rate_min = 8000,+	.rate_max = 48000,+	.channels_min = 1,+	.channels_max = 2,+	.buffer_bytes_max = 128 * 1024,+	.period_bytes_min =   1 * 1024,+	.period_bytes_max = 128 * 1024,+	.periods_min = 1,+	.periods_max = 128,+};++static void snd_bcm2835_playback_free(struct snd_pcm_runtime *runtime)+{+	audio_info("Freeing up alsa stream here ..\n");+	if (runtime->private_data)+		kfree(runtime->private_data);+	runtime->private_data = NULL;+}++static irqreturn_t bcm2835_playback_fifo_irq(int irq, void *dev_id)+{+	bcm2835_alsa_stream_t *alsa_stream = (bcm2835_alsa_stream_t *) dev_id;+	uint32_t consumed = 0;+	int new_period = 0;++	audio_info(" .. IN\n");++	audio_info("alsa_stream=%p substream=%p\n", alsa_stream,+		   alsa_stream ? alsa_stream->substream : 0);++	if (alsa_stream->open)+		consumed = bcm2835_audio_retrieve_buffers(alsa_stream);++	/* We get called only if playback was triggered, So, the number of buffers we retrieve in+	 * each iteration are the buffers that have been played out already+	 */++	if (alsa_stream->period_size) {+		if ((alsa_stream->pos / alsa_stream->period_size) !=+		    ((alsa_stream->pos + consumed) / alsa_stream->period_size))+			new_period = 1;+	}+	audio_debug("updating pos cur: %d + %d max:%d period_bytes:%d, hw_ptr: %d new_period:%d\n",+		      alsa_stream->pos,+		      consumed,+		      alsa_stream->buffer_size,+			  (int)(alsa_stream->period_size*alsa_stream->substream->runtime->periods),+			  frames_to_bytes(alsa_stream->substream->runtime, alsa_stream->substream->runtime->status->hw_ptr),+			  new_period);+	if (alsa_stream->buffer_size) {+		alsa_stream->pos += consumed &~ (1<<30);+		alsa_stream->pos %= alsa_stream->buffer_size;+	}++	if (alsa_stream->substream) {+		if (new_period)+			snd_pcm_period_elapsed(alsa_stream->substream);+	} else {+		audio_warning(" unexpected NULL substream\n");+	}+	audio_info(" .. OUT\n");++	return IRQ_HANDLED;+}++/* open callback */+static int snd_bcm2835_playback_open(struct snd_pcm_substream *substream)+{+	bcm2835_chip_t *chip = snd_pcm_substream_chip(substream);+	struct snd_pcm_runtime *runtime = substream->runtime;+	bcm2835_alsa_stream_t *alsa_stream;+	int idx;+	int err;++	audio_info(" .. IN (%d)\n", substream->number);++	audio_info("Alsa open (%d)\n", substream->number);+	idx = substream->number;++	if (idx > MAX_SUBSTREAMS) {+		audio_error+		    ("substream(%d) device doesn't exist max(%d) substreams allowed\n",+		     idx, MAX_SUBSTREAMS);+		err = -ENODEV;+		goto out;+	}++	/* Check if we are ready */+	if (!(chip->avail_substreams & (1 << idx))) {+		/* We are not ready yet */+		audio_error("substream(%d) device is not ready yet\n", idx);+		err = -EAGAIN;+		goto out;+	}++	alsa_stream = kzalloc(sizeof(bcm2835_alsa_stream_t), GFP_KERNEL);+	if (alsa_stream == NULL) {+		return -ENOMEM;+	}++	/* Initialise alsa_stream */+	alsa_stream->chip = chip;+	alsa_stream->substream = substream;+	alsa_stream->idx = idx;+	chip->alsa_stream[idx] = alsa_stream;++	sema_init(&alsa_stream->buffers_update_sem, 0);+	sema_init(&alsa_stream->control_sem, 0);+	spin_lock_init(&alsa_stream->lock);++	/* Enabled in start trigger, called on each "fifo irq" after that */+	alsa_stream->enable_fifo_irq = 0;+	alsa_stream->fifo_irq_handler = bcm2835_playback_fifo_irq;++	runtime->private_data = alsa_stream;+	runtime->private_free = snd_bcm2835_playback_free;+	runtime->hw = snd_bcm2835_playback_hw;+	/* minimum 16 bytes alignment (for vchiq bulk transfers) */+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,+				   16);++	err = bcm2835_audio_open(alsa_stream);+	if (err != 0) {+		kfree(alsa_stream);+		return err;+	}++	alsa_stream->open = 1;+	alsa_stream->draining = 1;++out:+	audio_info(" .. OUT =%d\n", err);++	return err;+}++/* close callback */+static int snd_bcm2835_playback_close(struct snd_pcm_substream *substream)+{+	/* the hardware-specific codes will be here */++	struct snd_pcm_runtime *runtime = substream->runtime;+	bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;++	audio_info(" .. IN\n");+	audio_info("Alsa close\n");++	/*+	 * Call stop if it's still running. This happens when app+	 * is force killed and we don't get a stop trigger.+	 */+	if (alsa_stream->running) {+		int err;+		err = bcm2835_audio_stop(alsa_stream);+		alsa_stream->running = 0;+		if (err != 0)+			audio_error(" Failed to STOP alsa device\n");+	}++	alsa_stream->period_size = 0;+	alsa_stream->buffer_size = 0;++	if (alsa_stream->open) {+		alsa_stream->open = 0;+		bcm2835_audio_close(alsa_stream);+	}+	if (alsa_stream->chip)+		alsa_stream->chip->alsa_stream[alsa_stream->idx] = NULL;+	/*+	 * Do not free up alsa_stream here, it will be freed up by+	 * runtime->private_free callback we registered in *_open above+	 */++	audio_info(" .. OUT\n");++	return 0;+}++/* hw_params callback */+static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream,+				     struct snd_pcm_hw_params *params)+{+	int err;+	struct snd_pcm_runtime *runtime = substream->runtime;+	bcm2835_alsa_stream_t *alsa_stream =+	    (bcm2835_alsa_stream_t *) runtime->private_data;++	audio_info(" .. IN\n");++	err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));+	if (err < 0) {+		audio_error+		    (" pcm_lib_malloc failed to allocated pages for buffers\n");+		return err;+	}++	err = bcm2835_audio_set_params(alsa_stream, params_channels(params),+				       params_rate(params),+				       snd_pcm_format_width(params_format+							    (params)));+	if (err < 0) {+		audio_error(" error setting hw params\n");+	}++	bcm2835_audio_setup(alsa_stream);++	/* in preparation of the stream, set the controls (volume level) of the stream */+	bcm2835_audio_set_ctls(alsa_stream->chip);++	audio_info(" .. OUT\n");++	return err;+}++/* hw_free callback */+static int snd_bcm2835_pcm_hw_free(struct snd_pcm_substream *substream)+{+	audio_info(" .. IN\n");+	return snd_pcm_lib_free_pages(substream);+}++/* prepare callback */+static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream)+{+	struct snd_pcm_runtime *runtime = substream->runtime;+	bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;++	audio_info(" .. IN\n");++	memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));++	alsa_stream->pcm_indirect.hw_buffer_size =+	alsa_stream->pcm_indirect.sw_buffer_size =+		snd_pcm_lib_buffer_bytes(substream);++	alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream);+	alsa_stream->period_size = snd_pcm_lib_period_bytes(substream);+	alsa_stream->pos = 0;++	audio_debug("buffer_size=%d, period_size=%d pos=%d frame_bits=%d\n",+		      alsa_stream->buffer_size, alsa_stream->period_size,+		      alsa_stream->pos, runtime->frame_bits);++	audio_info(" .. OUT\n");+	return 0;+}++static void snd_bcm2835_pcm_transfer(struct snd_pcm_substream *substream,+				    struct snd_pcm_indirect *rec, size_t bytes)+{+	struct snd_pcm_runtime *runtime = substream->runtime;+	bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;+	void *src = (void *)(substream->runtime->dma_area + rec->sw_data);+	int err;++	err = bcm2835_audio_write(alsa_stream, bytes, src);+	if (err)+		audio_error(" Failed to transfer to alsa device (%d)\n", err);++}++static int snd_bcm2835_pcm_ack(struct snd_pcm_substream *substream)+{+	struct snd_pcm_runtime *runtime = substream->runtime;+	bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;+	struct snd_pcm_indirect *pcm_indirect = &alsa_stream->pcm_indirect;++	pcm_indirect->hw_queue_size = runtime->hw.buffer_bytes_max;+	snd_pcm_indirect_playback_transfer(substream, pcm_indirect,+					   snd_bcm2835_pcm_transfer);+	return 0;+}++/* trigger callback */+static int snd_bcm2835_pcm_trigger(struct snd_pcm_substream *substream, int cmd)+{+	struct snd_pcm_runtime *runtime = substream->runtime;+	bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;+	int err = 0;++	audio_info(" .. IN\n");++	switch (cmd) {+	case SNDRV_PCM_TRIGGER_START:+		audio_debug("bcm2835_AUDIO_TRIGGER_START running=%d\n",+			      alsa_stream->running);+		if (!alsa_stream->running) {+			err = bcm2835_audio_start(alsa_stream);+			if (err == 0) {+				alsa_stream->pcm_indirect.hw_io =+				alsa_stream->pcm_indirect.hw_data =+					bytes_to_frames(runtime,+							alsa_stream->pos);+				substream->ops->ack(substream);+				alsa_stream->running = 1;+				alsa_stream->draining = 1;+			} else {+				audio_error(" Failed to START alsa device (%d)\n", err);+			}+		}+		break;+	case SNDRV_PCM_TRIGGER_STOP:+		audio_debug+		    ("bcm2835_AUDIO_TRIGGER_STOP running=%d draining=%d\n",+			     alsa_stream->running, runtime->status->state == SNDRV_PCM_STATE_DRAINING);+		if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {+			audio_info("DRAINING\n");+			alsa_stream->draining = 1;+		} else {+			audio_info("DROPPING\n");+			alsa_stream->draining = 0;+		}+		if (alsa_stream->running) {+			err = bcm2835_audio_stop(alsa_stream);+			if (err != 0)+				audio_error(" Failed to STOP alsa device (%d)\n", err);+			alsa_stream->running = 0;+		}+		break;+	default:+		err = -EINVAL;+	}++	audio_info(" .. OUT\n");+	return err;+}++/* pointer callback */+static snd_pcm_uframes_t+snd_bcm2835_pcm_pointer(struct snd_pcm_substream *substream)+{+	struct snd_pcm_runtime *runtime = substream->runtime;+	bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;++	audio_info(" .. IN\n");++	audio_debug("pcm_pointer... (%d) hwptr=%d appl=%d pos=%d\n", 0,+		      frames_to_bytes(runtime, runtime->status->hw_ptr),+		      frames_to_bytes(runtime, runtime->control->appl_ptr),+		      alsa_stream->pos);++	audio_info(" .. OUT\n");+	return snd_pcm_indirect_playback_pointer(substream,+						 &alsa_stream->pcm_indirect,+						 alsa_stream->pos);+}++static int snd_bcm2835_pcm_lib_ioctl(struct snd_pcm_substream *substream,+				     unsigned int cmd, void *arg)+{+	int ret = snd_pcm_lib_ioctl(substream, cmd, arg);+	audio_info(" .. substream=%p, cmd=%d, arg=%p (%x) ret=%d\n", substream,+		    cmd, arg, arg ? *(unsigned *)arg : 0, ret);+	return ret;+}++/* operators */+static struct snd_pcm_ops snd_bcm2835_playback_ops = {+	.open = snd_bcm2835_playback_open,+	.close = snd_bcm2835_playback_close,+	.ioctl = snd_bcm2835_pcm_lib_ioctl,+	.hw_params = snd_bcm2835_pcm_hw_params,+	.hw_free = snd_bcm2835_pcm_hw_free,+	.prepare = snd_bcm2835_pcm_prepare,+	.trigger = snd_bcm2835_pcm_trigger,+	.pointer = snd_bcm2835_pcm_pointer,+	.ack = snd_bcm2835_pcm_ack,+};++/* create a pcm device */+int snd_bcm2835_new_pcm(bcm2835_chip_t * chip)+{+	struct snd_pcm *pcm;+	int err;++	audio_info(" .. IN\n");+	err =+	    snd_pcm_new(chip->card, "bcm2835 ALSA", 0, MAX_SUBSTREAMS, 0, &pcm);+	if (err < 0)+		return err;+	pcm->private_data = chip;+	strcpy(pcm->name, "bcm2835 ALSA");+	chip->pcm = pcm;+	chip->dest = AUDIO_DEST_AUTO;+	chip->volume = alsa2chip(0);+	chip->mute = CTRL_VOL_UNMUTE;	/*disable mute on startup */+	/* set operators */+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,+			&snd_bcm2835_playback_ops);++	/* pre-allocation of buffers */+	/* NOTE: this may fail */+	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,+					      snd_dma_continuous_data+					      (GFP_KERNEL), 64 * 1024,+					      64 * 1024);++	audio_info(" .. OUT\n");++	return 0;+}diff -Nur linux-3.11.10.orig/sound/arm/bcm2835-vchiq.c linux-3.11.10/sound/arm/bcm2835-vchiq.c--- linux-3.11.10.orig/sound/arm/bcm2835-vchiq.c	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/sound/arm/bcm2835-vchiq.c	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,879 @@+/*****************************************************************************+* Copyright 2011 Broadcom Corporation.  All rights reserved.+*+* Unless you and Broadcom execute a separate written software license+* agreement governing use of this software, this software is licensed to you+* under the terms of the GNU General Public License version 2, available at+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").+*+* Notwithstanding the above, under no circumstances may you combine this+* software in any way with any other Broadcom software provided under a+* license other than the GPL, without Broadcom's express prior written+* consent.+*****************************************************************************/++#include <linux/device.h>+#include <sound/core.h>+#include <sound/initval.h>+#include <sound/pcm.h>+#include <linux/io.h>+#include <linux/interrupt.h>+#include <linux/fs.h>+#include <linux/file.h>+#include <linux/mm.h>+#include <linux/syscalls.h>+#include <asm/uaccess.h>+#include <linux/slab.h>+#include <linux/delay.h>+#include <linux/atomic.h>+#include <linux/module.h>+#include <linux/completion.h>++#include "bcm2835.h"++/* ---- Include Files -------------------------------------------------------- */++#include "interface/vchi/vchi.h"+#include "vc_vchi_audioserv_defs.h"++/* ---- Private Constants and Types ------------------------------------------ */++#define BCM2835_AUDIO_STOP           0+#define BCM2835_AUDIO_START          1+#define BCM2835_AUDIO_WRITE          2++/* Logging macros (for remapping to other logging mechanisms, i.e., printf) */+#ifdef AUDIO_DEBUG_ENABLE+	#define LOG_ERR( fmt, arg... )   pr_err( "%s:%d " fmt, __func__, __LINE__, ##arg)+	#define LOG_WARN( fmt, arg... )  pr_info( "%s:%d " fmt, __func__, __LINE__, ##arg)+	#define LOG_INFO( fmt, arg... )  pr_info( "%s:%d " fmt, __func__, __LINE__, ##arg)+	#define LOG_DBG( fmt, arg... )   pr_info( "%s:%d " fmt, __func__, __LINE__, ##arg)+#else+	#define LOG_ERR( fmt, arg... )   pr_err( "%s:%d " fmt, __func__, __LINE__, ##arg)+	#define LOG_WARN( fmt, arg... )+	#define LOG_INFO( fmt, arg... )+	#define LOG_DBG( fmt, arg... )+#endif++typedef struct opaque_AUDIO_INSTANCE_T {+	uint32_t num_connections;+	VCHI_SERVICE_HANDLE_T vchi_handle[VCHI_MAX_NUM_CONNECTIONS];+	struct completion msg_avail_comp;+	struct mutex vchi_mutex;+	bcm2835_alsa_stream_t *alsa_stream;+	int32_t result;+	short peer_version;+} AUDIO_INSTANCE_T;++bool force_bulk = false;++/* ---- Private Variables ---------------------------------------------------- */++/* ---- Private Function Prototypes ------------------------------------------ */++/* ---- Private Functions ---------------------------------------------------- */++static int bcm2835_audio_stop_worker(bcm2835_alsa_stream_t * alsa_stream);+static int bcm2835_audio_start_worker(bcm2835_alsa_stream_t * alsa_stream);+static int bcm2835_audio_write_worker(bcm2835_alsa_stream_t *alsa_stream,+				      uint32_t count, void *src);++typedef struct {+	struct work_struct my_work;+	bcm2835_alsa_stream_t *alsa_stream;+	int cmd;+	void *src;+	uint32_t count;+} my_work_t;++static void my_wq_function(struct work_struct *work)+{+	my_work_t *w = (my_work_t *) work;+	int ret = -9;+	LOG_DBG(" .. IN %p:%d\n", w->alsa_stream, w->cmd);+	switch (w->cmd) {+	case BCM2835_AUDIO_START:+		ret = bcm2835_audio_start_worker(w->alsa_stream);+		break;+	case BCM2835_AUDIO_STOP:+		ret = bcm2835_audio_stop_worker(w->alsa_stream);+		break;+	case BCM2835_AUDIO_WRITE:+		ret = bcm2835_audio_write_worker(w->alsa_stream, w->count,+						 w->src);+		break;+	default:+		LOG_ERR(" Unexpected work: %p:%d\n", w->alsa_stream, w->cmd);+		break;+	}+	kfree((void *)work);+	LOG_DBG(" .. OUT %d\n", ret);+}++int bcm2835_audio_start(bcm2835_alsa_stream_t * alsa_stream)+{+	int ret = -1;+	LOG_DBG(" .. IN\n");+	if (alsa_stream->my_wq) {+		my_work_t *work = kmalloc(sizeof(my_work_t), GFP_ATOMIC);+		/*--- Queue some work (item 1) ---*/+		if (work) {+			INIT_WORK((struct work_struct *)work, my_wq_function);+			work->alsa_stream = alsa_stream;+			work->cmd = BCM2835_AUDIO_START;+			if (queue_work+			    (alsa_stream->my_wq, (struct work_struct *)work))+				ret = 0;+		} else+			LOG_ERR(" .. Error: NULL work kmalloc\n");+	}+	LOG_DBG(" .. OUT %d\n", ret);+	return ret;+}++int bcm2835_audio_stop(bcm2835_alsa_stream_t * alsa_stream)+{+	int ret = -1;+	LOG_DBG(" .. IN\n");+	if (alsa_stream->my_wq) {+		my_work_t *work = kmalloc(sizeof(my_work_t), GFP_ATOMIC);+		 /*--- Queue some work (item 1) ---*/+		if (work) {+			INIT_WORK((struct work_struct *)work, my_wq_function);+			work->alsa_stream = alsa_stream;+			work->cmd = BCM2835_AUDIO_STOP;+			if (queue_work+			    (alsa_stream->my_wq, (struct work_struct *)work))+				ret = 0;+		} else+			LOG_ERR(" .. Error: NULL work kmalloc\n");+	}+	LOG_DBG(" .. OUT %d\n", ret);+	return ret;+}++int bcm2835_audio_write(bcm2835_alsa_stream_t *alsa_stream,+			uint32_t count, void *src)+{+	int ret = -1;+	LOG_DBG(" .. IN\n");+	if (alsa_stream->my_wq) {+		my_work_t *work = kmalloc(sizeof(my_work_t), GFP_ATOMIC);+		 /*--- Queue some work (item 1) ---*/+		if (work) {+			INIT_WORK((struct work_struct *)work, my_wq_function);+			work->alsa_stream = alsa_stream;+			work->cmd = BCM2835_AUDIO_WRITE;+			work->src = src;+			work->count = count;+			if (queue_work+			    (alsa_stream->my_wq, (struct work_struct *)work))+				ret = 0;+		} else+			LOG_ERR(" .. Error: NULL work kmalloc\n");+	}+	LOG_DBG(" .. OUT %d\n", ret);+	return ret;+}++void my_workqueue_init(bcm2835_alsa_stream_t * alsa_stream)+{+	alsa_stream->my_wq = create_workqueue("my_queue");+	return;+}++void my_workqueue_quit(bcm2835_alsa_stream_t * alsa_stream)+{+	if (alsa_stream->my_wq) {+		flush_workqueue(alsa_stream->my_wq);+		destroy_workqueue(alsa_stream->my_wq);+		alsa_stream->my_wq = NULL;+	}+	return;+}++static void audio_vchi_callback(void *param,+				const VCHI_CALLBACK_REASON_T reason,+				void *msg_handle)+{+	AUDIO_INSTANCE_T *instance = (AUDIO_INSTANCE_T *) param;+	int32_t status;+	int32_t msg_len;+	VC_AUDIO_MSG_T m;+	bcm2835_alsa_stream_t *alsa_stream = 0;+	LOG_DBG(" .. IN instance=%p, param=%p, reason=%d, handle=%p\n",+		instance, param, reason, msg_handle);++	if (!instance || reason != VCHI_CALLBACK_MSG_AVAILABLE) {+		return;+	}+	alsa_stream = instance->alsa_stream;+	status = vchi_msg_dequeue(instance->vchi_handle[0],+				  &m, sizeof m, &msg_len, VCHI_FLAGS_NONE);+	if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {+		LOG_DBG+		    (" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_RESULT, success=%d\n",+		     instance, m.u.result.success);+		instance->result = m.u.result.success;+		complete(&instance->msg_avail_comp);+	} else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {+		irq_handler_t callback = (irq_handler_t) m.u.complete.callback;+		LOG_DBG+		    (" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_COMPLETE, complete=%d\n",+		     instance, m.u.complete.count);+		if (alsa_stream && callback) {+			atomic_add(m.u.complete.count, &alsa_stream->retrieved);+			callback(0, alsa_stream);+		} else {+			LOG_DBG(" .. unexpected alsa_stream=%p, callback=%p\n",+				alsa_stream, callback);+		}+	} else {+		LOG_DBG(" .. unexpected m.type=%d\n", m.type);+	}+	LOG_DBG(" .. OUT\n");+}++static AUDIO_INSTANCE_T *vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance,+					    VCHI_CONNECTION_T **+					    vchi_connections,+					    uint32_t num_connections)+{+	uint32_t i;+	AUDIO_INSTANCE_T *instance;+	int status;++	LOG_DBG("%s: start", __func__);++	if (num_connections > VCHI_MAX_NUM_CONNECTIONS) {+		LOG_ERR("%s: unsupported number of connections %u (max=%u)\n",+			__func__, num_connections, VCHI_MAX_NUM_CONNECTIONS);++		return NULL;+	}+	/* Allocate memory for this instance */+	instance = kmalloc(sizeof(*instance), GFP_KERNEL);++	memset(instance, 0, sizeof(*instance));+	instance->num_connections = num_connections;++	/* Create a lock for exclusive, serialized VCHI connection access */+	mutex_init(&instance->vchi_mutex);+	/* Open the VCHI service connections */+	for (i = 0; i < num_connections; i++) {+		SERVICE_CREATION_T params = {+			VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER),+			VC_AUDIO_SERVER_NAME,	// 4cc service code+			vchi_connections[i],	// passed in fn pointers+			0,	// rx fifo size (unused)+			0,	// tx fifo size (unused)+			audio_vchi_callback,	// service callback+			instance,	// service callback parameter+			1,	//TODO: remove VCOS_FALSE,   // unaligned bulk recieves+			1,	//TODO: remove VCOS_FALSE,   // unaligned bulk transmits+			0	// want crc check on bulk transfers+		};++		status = vchi_service_open(vchi_instance, ¶ms,+					   &instance->vchi_handle[i]);+		if (status) {+			LOG_ERR+			    ("%s: failed to open VCHI service connection (status=%d)\n",+			     __func__, status);++			goto err_close_services;+		}+		/* Finished with the service for now */+		vchi_service_release(instance->vchi_handle[i]);+	}++	return instance;++err_close_services:+	for (i = 0; i < instance->num_connections; i++) {+		vchi_service_close(instance->vchi_handle[i]);+	}++	kfree(instance);++	return NULL;+}++static int32_t vc_vchi_audio_deinit(AUDIO_INSTANCE_T * instance)+{+	uint32_t i;++	LOG_DBG(" .. IN\n");++	if (instance == NULL) {+		LOG_ERR("%s: invalid handle %p\n", __func__, instance);++		return -1;+	}++	LOG_DBG(" .. about to lock (%d)\n", instance->num_connections);+	if(mutex_lock_interruptible(&instance->vchi_mutex))+	{+		LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections);+		return -EINTR;+	}++	/* Close all VCHI service connections */+	for (i = 0; i < instance->num_connections; i++) {+		int32_t success;+		LOG_DBG(" .. %i:closing %p\n", i, instance->vchi_handle[i]);+		vchi_service_use(instance->vchi_handle[i]);++		success = vchi_service_close(instance->vchi_handle[i]);+		if (success != 0) {+			LOG_ERR+			    ("%s: failed to close VCHI service connection (status=%d)\n",+			     __func__, success);+		}+	}++	mutex_unlock(&instance->vchi_mutex);++	kfree(instance);++	LOG_DBG(" .. OUT\n");++	return 0;+}++static int bcm2835_audio_open_connection(bcm2835_alsa_stream_t * alsa_stream)+{+	static VCHI_INSTANCE_T vchi_instance;+	static VCHI_CONNECTION_T *vchi_connection;+	AUDIO_INSTANCE_T *instance = alsa_stream->instance;+	int ret;+	LOG_DBG(" .. IN\n");++	LOG_INFO("%s: start", __func__);+	//BUG_ON(instance);+	if (instance) {+		LOG_ERR("%s: VCHI instance already open (%p)\n",+			__func__, instance);+		instance->alsa_stream = alsa_stream;+		alsa_stream->instance = instance;+		ret = 0;	// xxx todo -1;+		goto err_free_mem;+	}++	/* Initialize and create a VCHI connection */+	ret = vchi_initialise(&vchi_instance);+	if (ret != 0) {+		LOG_ERR("%s: failed to initialise VCHI instance (ret=%d)\n",+			__func__, ret);++		ret = -EIO;+		goto err_free_mem;+	}+	ret = vchi_connect(NULL, 0, vchi_instance);+	if (ret != 0) {+		LOG_ERR("%s: failed to connect VCHI instance (ret=%d)\n",+			__func__, ret);++		ret = -EIO;+		goto err_free_mem;+	}++	/* Initialize an instance of the audio service */+	instance = vc_vchi_audio_init(vchi_instance, &vchi_connection, 1);++	if (instance == NULL /*|| audio_handle != instance */ ) {+		LOG_ERR("%s: failed to initialize audio service\n", __func__);++		ret = -EPERM;+		goto err_free_mem;+	}++	instance->alsa_stream = alsa_stream;+	alsa_stream->instance = instance;++	LOG_DBG(" success !\n");+err_free_mem:+	LOG_DBG(" .. OUT\n");++	return ret;+}++int bcm2835_audio_open(bcm2835_alsa_stream_t * alsa_stream)+{+	AUDIO_INSTANCE_T *instance;+	VC_AUDIO_MSG_T m;+	int32_t success;+	int ret;+	LOG_DBG(" .. IN\n");++	my_workqueue_init(alsa_stream);++	ret = bcm2835_audio_open_connection(alsa_stream);+	if (ret != 0) {+		ret = -1;+		goto exit;+	}+	instance = alsa_stream->instance;++	if(mutex_lock_interruptible(&instance->vchi_mutex))+	{+		LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections);+		return -EINTR;+	}+	vchi_service_use(instance->vchi_handle[0]);++	m.type = VC_AUDIO_MSG_TYPE_OPEN;++	/* Send the message to the videocore */+	success = vchi_msg_queue(instance->vchi_handle[0],+				 &m, sizeof m,+				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);++	if (success != 0) {+		LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",+			__func__, success);++		ret = -1;+		goto unlock;+	}++	ret = 0;++unlock:+	vchi_service_release(instance->vchi_handle[0]);+	mutex_unlock(&instance->vchi_mutex);+exit:+	LOG_DBG(" .. OUT\n");+	return ret;+}++static int bcm2835_audio_set_ctls_chan(bcm2835_alsa_stream_t * alsa_stream,+				       bcm2835_chip_t * chip)+{+	VC_AUDIO_MSG_T m;+	AUDIO_INSTANCE_T *instance = alsa_stream->instance;+	int32_t success;+	int ret;+	LOG_DBG(" .. IN\n");++	LOG_INFO+	    (" Setting ALSA dest(%d), volume(%d)\n", chip->dest, chip->volume);++	if(mutex_lock_interruptible(&instance->vchi_mutex))+	{+		LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections);+		return -EINTR;+	}+	vchi_service_use(instance->vchi_handle[0]);++	instance->result = -1;++	m.type = VC_AUDIO_MSG_TYPE_CONTROL;+	m.u.control.dest = chip->dest;+	m.u.control.volume = chip->volume;++	/* Create the message available completion */+	init_completion(&instance->msg_avail_comp);++	/* Send the message to the videocore */+	success = vchi_msg_queue(instance->vchi_handle[0],+				 &m, sizeof m,+				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);++	if (success != 0) {+		LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",+			__func__, success);++		ret = -1;+		goto unlock;+	}++	/* We are expecting a reply from the videocore */+	ret = wait_for_completion_interruptible(&instance->msg_avail_comp);+	if (ret) {+		LOG_ERR("%s: failed on waiting for event (status=%d)\n",+			__func__, success);+		goto unlock;+	}++	if (instance->result != 0) {+		LOG_ERR("%s: result=%d\n", __func__, instance->result);++		ret = -1;+		goto unlock;+	}++	ret = 0;++unlock:+	vchi_service_release(instance->vchi_handle[0]);+	mutex_unlock(&instance->vchi_mutex);++	LOG_DBG(" .. OUT\n");+	return ret;+}++int bcm2835_audio_set_ctls(bcm2835_chip_t * chip)+{+	int i;+	int ret = 0;+	LOG_DBG(" .. IN\n");++	/* change ctls for all substreams */+	for (i = 0; i < MAX_SUBSTREAMS; i++) {+		if (chip->avail_substreams & (1 << i)) {+			if (!chip->alsa_stream[i])+			{+				LOG_DBG(" No ALSA stream available?! %i:%p (%x)\n", i, chip->alsa_stream[i], chip->avail_substreams);+				ret = 0;+			}+			else if (bcm2835_audio_set_ctls_chan /* returns 0 on success */+				 (chip->alsa_stream[i], chip) != 0)+				 {+					LOG_DBG("Couldn't set the controls for stream %d\n", i);+					ret = -1;+				 }+			else LOG_DBG(" Controls set for stream %d\n", i);+		}+	}+	LOG_DBG(" .. OUT ret=%d\n", ret);+	return ret;+}++int bcm2835_audio_set_params(bcm2835_alsa_stream_t * alsa_stream,+			     uint32_t channels, uint32_t samplerate,+			     uint32_t bps)+{+	VC_AUDIO_MSG_T m;+	AUDIO_INSTANCE_T *instance = alsa_stream->instance;+	int32_t success;+	int ret;+	LOG_DBG(" .. IN\n");++	LOG_INFO+	    (" Setting ALSA channels(%d), samplerate(%d), bits-per-sample(%d)\n",+	     channels, samplerate, bps);++	/* resend ctls - alsa_stream may not have been open when first send */+	ret = bcm2835_audio_set_ctls_chan(alsa_stream, alsa_stream->chip);+	if (ret != 0) {+		LOG_ERR(" Alsa controls not supported\n");+		return -EINVAL;+	}++	if(mutex_lock_interruptible(&instance->vchi_mutex))+	{+		LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections);+		return -EINTR;+	}+	vchi_service_use(instance->vchi_handle[0]);++	instance->result = -1;++	m.type = VC_AUDIO_MSG_TYPE_CONFIG;+	m.u.config.channels = channels;+	m.u.config.samplerate = samplerate;+	m.u.config.bps = bps;++	/* Create the message available completion */+	init_completion(&instance->msg_avail_comp);++	/* Send the message to the videocore */+	success = vchi_msg_queue(instance->vchi_handle[0],+				 &m, sizeof m,+				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);++	if (success != 0) {+		LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",+			__func__, success);++		ret = -1;+		goto unlock;+	}++	/* We are expecting a reply from the videocore */+	ret = wait_for_completion_interruptible(&instance->msg_avail_comp);+	if (ret) {+		LOG_ERR("%s: failed on waiting for event (status=%d)\n",+			__func__, success);+		goto unlock;+	}++	if (instance->result != 0) {+		LOG_ERR("%s: result=%d", __func__, instance->result);++		ret = -1;+		goto unlock;+	}++	ret = 0;++unlock:+	vchi_service_release(instance->vchi_handle[0]);+	mutex_unlock(&instance->vchi_mutex);++	LOG_DBG(" .. OUT\n");+	return ret;+}++int bcm2835_audio_setup(bcm2835_alsa_stream_t * alsa_stream)+{+	LOG_DBG(" .. IN\n");++	LOG_DBG(" .. OUT\n");++	return 0;+}++static int bcm2835_audio_start_worker(bcm2835_alsa_stream_t * alsa_stream)+{+	VC_AUDIO_MSG_T m;+	AUDIO_INSTANCE_T *instance = alsa_stream->instance;+	int32_t success;+	int ret;+	LOG_DBG(" .. IN\n");++	if(mutex_lock_interruptible(&instance->vchi_mutex))+	{+		LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections);+		return -EINTR;+	}+	vchi_service_use(instance->vchi_handle[0]);++	m.type = VC_AUDIO_MSG_TYPE_START;++	/* Send the message to the videocore */+	success = vchi_msg_queue(instance->vchi_handle[0],+				 &m, sizeof m,+				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);++	if (success != 0) {+		LOG_ERR("%s: failed on vchi_msg_queue (status=%d)",+			__func__, success);++		ret = -1;+		goto unlock;+	}++	ret = 0;++unlock:+	vchi_service_release(instance->vchi_handle[0]);+	mutex_unlock(&instance->vchi_mutex);+	LOG_DBG(" .. OUT\n");+	return ret;+}++static int bcm2835_audio_stop_worker(bcm2835_alsa_stream_t * alsa_stream)+{+	VC_AUDIO_MSG_T m;+	AUDIO_INSTANCE_T *instance = alsa_stream->instance;+	int32_t success;+	int ret;+	LOG_DBG(" .. IN\n");++	if(mutex_lock_interruptible(&instance->vchi_mutex))+	{+		LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections);+		return -EINTR;+	}+	vchi_service_use(instance->vchi_handle[0]);++	m.type = VC_AUDIO_MSG_TYPE_STOP;+	m.u.stop.draining = alsa_stream->draining;++	/* Send the message to the videocore */+	success = vchi_msg_queue(instance->vchi_handle[0],+				 &m, sizeof m,+				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);++	if (success != 0) {+		LOG_ERR("%s: failed on vchi_msg_queue (status=%d)",+			__func__, success);++		ret = -1;+		goto unlock;+	}++	ret = 0;++unlock:+	vchi_service_release(instance->vchi_handle[0]);+	mutex_unlock(&instance->vchi_mutex);+	LOG_DBG(" .. OUT\n");+	return ret;+}++int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream)+{+	VC_AUDIO_MSG_T m;+	AUDIO_INSTANCE_T *instance = alsa_stream->instance;+	int32_t success;+	int ret;+	LOG_DBG(" .. IN\n");++	my_workqueue_quit(alsa_stream);++	if(mutex_lock_interruptible(&instance->vchi_mutex))+	{+		LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections);+		return -EINTR;+	}+	vchi_service_use(instance->vchi_handle[0]);++	m.type = VC_AUDIO_MSG_TYPE_CLOSE;++	/* Create the message available completion */+	init_completion(&instance->msg_avail_comp);++	/* Send the message to the videocore */+	success = vchi_msg_queue(instance->vchi_handle[0],+				 &m, sizeof m,+				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);++	if (success != 0) {+		LOG_ERR("%s: failed on vchi_msg_queue (status=%d)",+			__func__, success);+		ret = -1;+		goto unlock;+	}++	ret = wait_for_completion_interruptible(&instance->msg_avail_comp);+	if (ret) {+		LOG_ERR("%s: failed on waiting for event (status=%d)",+			__func__, success);+		goto unlock;+	}+	if (instance->result != 0) {+		LOG_ERR("%s: failed result (status=%d)",+			__func__, instance->result);++		ret = -1;+		goto unlock;+	}++	ret = 0;++unlock:+	vchi_service_release(instance->vchi_handle[0]);+	mutex_unlock(&instance->vchi_mutex);++	/* Stop the audio service */+	if (instance) {+		vc_vchi_audio_deinit(instance);+		alsa_stream->instance = NULL;+	}+	LOG_DBG(" .. OUT\n");+	return ret;+}++int bcm2835_audio_write_worker(bcm2835_alsa_stream_t *alsa_stream,+			       uint32_t count, void *src)+{+	VC_AUDIO_MSG_T m;+	AUDIO_INSTANCE_T *instance = alsa_stream->instance;+	int32_t success;+	int ret;++	LOG_DBG(" .. IN\n");++	LOG_INFO(" Writing %d bytes from %p\n", count, src);++	if(mutex_lock_interruptible(&instance->vchi_mutex))+	{+		LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections);+		return -EINTR;+	}+	vchi_service_use(instance->vchi_handle[0]);++	if ( instance->peer_version==0 && vchi_get_peer_version(instance->vchi_handle[0], &instance->peer_version) == 0 ) {+		LOG_DBG("%s: client version %d connected\n", __func__, instance->peer_version);+	}+	m.type = VC_AUDIO_MSG_TYPE_WRITE;+	m.u.write.count = count;+	// old version uses bulk, new version uses control+	m.u.write.max_packet = instance->peer_version < 2 || force_bulk ? 0:4000;+	m.u.write.callback = alsa_stream->fifo_irq_handler;+	m.u.write.cookie = alsa_stream;+	m.u.write.silence = src == NULL;++	/* Send the message to the videocore */+	success = vchi_msg_queue(instance->vchi_handle[0],+				 &m, sizeof m,+				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);++	if (success != 0) {+		LOG_ERR("%s: failed on vchi_msg_queue (status=%d)",+			__func__, success);++		ret = -1;+		goto unlock;+	}+	if (!m.u.write.silence) {+		if (m.u.write.max_packet == 0) {+			/* Send the message to the videocore */+			success = vchi_bulk_queue_transmit(instance->vchi_handle[0],+							   src, count,+							   0 *+							   VCHI_FLAGS_BLOCK_UNTIL_QUEUED+							   ++							   1 *+							   VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,+							   NULL);+		} else {+			while (count > 0) {+				int bytes = min((int)m.u.write.max_packet, (int)count);+				success = vchi_msg_queue(instance->vchi_handle[0],+							 src, bytes,+							 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);+				src = (char *)src + bytes;+				count -= bytes;+			}+		}+		if (success != 0) {+			LOG_ERR+			    ("%s: failed on vchi_bulk_queue_transmit (status=%d)",+			     __func__, success);++			ret = -1;+			goto unlock;+		}+	}+	ret = 0;++unlock:+	vchi_service_release(instance->vchi_handle[0]);+	mutex_unlock(&instance->vchi_mutex);+	LOG_DBG(" .. OUT\n");+	return ret;+}++/**+  * Returns all buffers from arm->vc+  */+void bcm2835_audio_flush_buffers(bcm2835_alsa_stream_t * alsa_stream)+{+	LOG_DBG(" .. IN\n");+	LOG_DBG(" .. OUT\n");+	return;+}++/**+  * Forces VC to flush(drop) its filled playback buffers and+  * return them the us. (VC->ARM)+  */+void bcm2835_audio_flush_playback_buffers(bcm2835_alsa_stream_t * alsa_stream)+{+	LOG_DBG(" .. IN\n");+	LOG_DBG(" .. OUT\n");+}++uint32_t bcm2835_audio_retrieve_buffers(bcm2835_alsa_stream_t * alsa_stream)+{+	uint32_t count = atomic_read(&alsa_stream->retrieved);+	atomic_sub(count, &alsa_stream->retrieved);+	return count;+}++module_param(force_bulk, bool, 0444);+MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio");diff -Nur linux-3.11.10.orig/sound/arm/Kconfig linux-3.11.10/sound/arm/Kconfig--- linux-3.11.10.orig/sound/arm/Kconfig	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/sound/arm/Kconfig	2014-02-07 19:57:30.000000000 +0100@@ -39,5 +39,12 @@ 	  Say Y or M if you want to support any AC97 codec attached to 	  the PXA2xx AC97 interface. +config SND_BCM2835+	tristate "BCM2835 ALSA driver"+	depends on ARCH_BCM2708 && BCM2708_VCHIQ && SND+	select SND_PCM+	help+	  Say Y or M if you want to support BCM2835 Alsa pcm card driver+ endif	# SND_ARM diff -Nur linux-3.11.10.orig/sound/arm/Makefile linux-3.11.10/sound/arm/Makefile--- linux-3.11.10.orig/sound/arm/Makefile	2013-11-29 19:42:37.000000000 +0100+++ linux-3.11.10/sound/arm/Makefile	2014-02-07 19:57:30.000000000 +0100@@ -14,3 +14,8 @@  obj-$(CONFIG_SND_PXA2XX_AC97)	+= snd-pxa2xx-ac97.o snd-pxa2xx-ac97-objs		:= pxa2xx-ac97.o++obj-$(CONFIG_SND_BCM2835)	+= snd-bcm2835.o+snd-bcm2835-objs		:= bcm2835.o bcm2835-ctl.o bcm2835-pcm.o bcm2835-vchiq.o++EXTRA_CFLAGS += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000diff -Nur linux-3.11.10.orig/sound/arm/vc_vchi_audioserv_defs.h linux-3.11.10/sound/arm/vc_vchi_audioserv_defs.h--- linux-3.11.10.orig/sound/arm/vc_vchi_audioserv_defs.h	1970-01-01 01:00:00.000000000 +0100+++ linux-3.11.10/sound/arm/vc_vchi_audioserv_defs.h	2014-02-07 19:57:30.000000000 +0100@@ -0,0 +1,116 @@+/*****************************************************************************+* Copyright 2011 Broadcom Corporation.  All rights reserved.+*+* Unless you and Broadcom execute a separate written software license+* agreement governing use of this software, this software is licensed to you+* under the terms of the GNU General Public License version 2, available at+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").+*+* Notwithstanding the above, under no circumstances may you combine this+* software in any way with any other Broadcom software provided under a+* license other than the GPL, without Broadcom's express prior written+* consent.+*****************************************************************************/++#ifndef _VC_AUDIO_DEFS_H_+#define _VC_AUDIO_DEFS_H_++#define VC_AUDIOSERV_MIN_VER 1+#define VC_AUDIOSERV_VER 2++// FourCC code used for VCHI connection+#define VC_AUDIO_SERVER_NAME  MAKE_FOURCC("AUDS")++// Maximum message length+#define VC_AUDIO_MAX_MSG_LEN  (sizeof( VC_AUDIO_MSG_T ))++// List of screens that are currently supported+// All message types supported for HOST->VC direction+typedef enum {+	VC_AUDIO_MSG_TYPE_RESULT,	// Generic result+	VC_AUDIO_MSG_TYPE_COMPLETE,	// Generic result+	VC_AUDIO_MSG_TYPE_CONFIG,	// Configure audio+	VC_AUDIO_MSG_TYPE_CONTROL,	// Configure audio+	VC_AUDIO_MSG_TYPE_OPEN,	// Configure audio+	VC_AUDIO_MSG_TYPE_CLOSE,	// Configure audio+	VC_AUDIO_MSG_TYPE_START,	// Configure audio+	VC_AUDIO_MSG_TYPE_STOP,	// Configure audio+	VC_AUDIO_MSG_TYPE_WRITE,	// Configure audio+	VC_AUDIO_MSG_TYPE_MAX+} VC_AUDIO_MSG_TYPE;++// configure the audio+typedef struct {+	uint32_t channels;+	uint32_t samplerate;+	uint32_t bps;++} VC_AUDIO_CONFIG_T;++typedef struct {+	uint32_t volume;+	uint32_t dest;++} VC_AUDIO_CONTROL_T;++// audio+typedef struct {+	uint32_t dummy;++} VC_AUDIO_OPEN_T;++// audio+typedef struct {+	uint32_t dummy;++} VC_AUDIO_CLOSE_T;+// audio+typedef struct {+	uint32_t dummy;++} VC_AUDIO_START_T;+// audio+typedef struct {+	uint32_t draining;++} VC_AUDIO_STOP_T;++// configure the write audio samples+typedef struct {+	uint32_t count;		// in bytes+	void *callback;+	void *cookie;+	uint16_t silence;+	uint16_t max_packet;+} VC_AUDIO_WRITE_T;++// Generic result for a request (VC->HOST)+typedef struct {+	int32_t success;	// Success value++} VC_AUDIO_RESULT_T;++// Generic result for a request (VC->HOST)+typedef struct {+	int32_t count;		// Success value+	void *callback;+	void *cookie;+} VC_AUDIO_COMPLETE_T;++// Message header for all messages in HOST->VC direction+typedef struct {+	int32_t type;		// Message type (VC_AUDIO_MSG_TYPE)+	union {+		VC_AUDIO_CONFIG_T config;+		VC_AUDIO_CONTROL_T control;+		VC_AUDIO_OPEN_T open;+		VC_AUDIO_CLOSE_T close;+		VC_AUDIO_START_T start;+		VC_AUDIO_STOP_T stop;+		VC_AUDIO_WRITE_T write;+		VC_AUDIO_RESULT_T result;+		VC_AUDIO_COMPLETE_T complete;+	} u;+} VC_AUDIO_MSG_T;++#endif // _VC_AUDIO_DEFS_H_
 |