100-olpc.patch 187 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880
  1. Index: linux-2.6.23.17/arch/i386/Kconfig
  2. ===================================================================
  3. --- linux-2.6.23.17.orig/arch/i386/Kconfig
  4. +++ linux-2.6.23.17/arch/i386/Kconfig
  5. @@ -796,6 +796,15 @@ config SECCOMP
  6. If unsure, say Y. Only embedded should say N here.
  7. +config VGA_NOPROBE
  8. + bool "Don't probe VGA at boot" if EMBEDDED
  9. + default n
  10. + help
  11. + Saying Y here will cause the kernel to not probe VGA at boot time.
  12. + This will break everything that depends on the probed screen
  13. + data. Say N here unless you are absolutely sure this is what you
  14. + want.
  15. +
  16. source kernel/Kconfig.hz
  17. config KEXEC
  18. @@ -1120,6 +1129,9 @@ config PCI_GODIRECT
  19. config PCI_GOANY
  20. bool "Any"
  21. +config PCI_GOOLPC
  22. + bool "OLPC"
  23. +
  24. endchoice
  25. config PCI_BIOS
  26. @@ -1129,7 +1141,7 @@ config PCI_BIOS
  27. config PCI_DIRECT
  28. bool
  29. - depends on PCI && ((PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
  30. + depends on PCI && ((PCI_GODIRECT || PCI_GOANY || PCI_GOOLPC) || X86_VISWS)
  31. default y
  32. config PCI_MMCONFIG
  33. @@ -1137,6 +1149,11 @@ config PCI_MMCONFIG
  34. depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
  35. default y
  36. +config PCI_OLPC
  37. + bool
  38. + depends on PCI && PCI_GOOLPC
  39. + default y
  40. +
  41. source "drivers/pci/pcie/Kconfig"
  42. source "drivers/pci/Kconfig"
  43. @@ -1206,10 +1223,43 @@ config SCx200HR_TIMER
  44. processor goes idle (as is done by the scheduler). The
  45. other workaround is idle=poll boot option.
  46. +config GEODE_MFGPT_TIMER
  47. + bool "Geode Multi-Function General Purpose Timer (mfgpt) Support"
  48. + depends on MGEODE_LX && GENERIC_TIME && GENERIC_CLOCKEVENTS
  49. + default y
  50. + help
  51. + This driver provides a clock event source based on the MFGPT
  52. + timer(s) in the CS5535 and CS5536 companion chip for the geode.
  53. + MFGPTs have a better resolution and max interval than the
  54. + generic PIT, and are suitable for use as high-res timers.
  55. +
  56. config K8_NB
  57. def_bool y
  58. depends on AGP_AMD64
  59. +config OLPC
  60. + bool "OLPC Support"
  61. + default n
  62. + help
  63. + Add support for detecting the unique features of the OLPC
  64. + Childrens Machine
  65. +
  66. +config OLPC_PM
  67. + tristate "OLPC power management support"
  68. + default y
  69. + depends on OLPC
  70. + help
  71. + Add support for the Geode power management facilities on the
  72. + OLPC Childrens Machine
  73. +
  74. +config OPEN_FIRMWARE
  75. + bool "Support for Open Firmware"
  76. + default y if OLPC
  77. + help
  78. + This option adds support for the implementation of Open Firmware
  79. + that is used on the OLPC Children's Machine.
  80. + If unsure, say N here.
  81. +
  82. source "drivers/pcmcia/Kconfig"
  83. source "drivers/pci/hotplug/Kconfig"
  84. Index: linux-2.6.23.17/arch/i386/kernel/Makefile
  85. ===================================================================
  86. --- linux-2.6.23.17.orig/arch/i386/kernel/Makefile
  87. +++ linux-2.6.23.17/arch/i386/kernel/Makefile
  88. @@ -39,13 +39,17 @@ obj-$(CONFIG_VM86) += vm86.o
  89. obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
  90. obj-$(CONFIG_HPET_TIMER) += hpet.o
  91. obj-$(CONFIG_K8_NB) += k8.o
  92. -obj-$(CONFIG_MGEODE_LX) += geode.o
  93. +obj-$(CONFIG_MGEODE_LX) += geode.o mfgpt.o
  94. obj-$(CONFIG_VMI) += vmi.o vmiclock.o
  95. obj-$(CONFIG_PARAVIRT) += paravirt.o
  96. obj-y += pcspeaker.o
  97. obj-$(CONFIG_SCx200) += scx200.o
  98. +obj-$(CONFIG_OLPC) += olpc.o
  99. +obj-$(CONFIG_OLPC_PM) += olpc-pm.o olpc-wakeup.o
  100. +obj-$(CONFIG_OPEN_FIRMWARE) += ofw.o
  101. +obj-$(CONFIG_PROMFS_FS) += prom.o
  102. # vsyscall.o contains the vsyscall DSO images as __initdata.
  103. # We must build both images before we can assemble it.
  104. Index: linux-2.6.23.17/arch/i386/kernel/geode.c
  105. ===================================================================
  106. --- linux-2.6.23.17.orig/arch/i386/kernel/geode.c
  107. +++ linux-2.6.23.17/arch/i386/kernel/geode.c
  108. @@ -145,10 +145,14 @@ EXPORT_SYMBOL_GPL(geode_gpio_setup_event
  109. static int __init geode_southbridge_init(void)
  110. {
  111. + int timers;
  112. +
  113. if (!is_geode())
  114. return -ENODEV;
  115. init_lbars();
  116. + timers = geode_mfgpt_detect();
  117. + printk(KERN_INFO "geode-mfgpt: %d timers available.\n", timers);
  118. return 0;
  119. }
  120. Index: linux-2.6.23.17/arch/i386/kernel/head.S
  121. ===================================================================
  122. --- linux-2.6.23.17.orig/arch/i386/kernel/head.S
  123. +++ linux-2.6.23.17/arch/i386/kernel/head.S
  124. @@ -117,8 +117,34 @@ ENTRY(startup_32)
  125. movl $(COMMAND_LINE_SIZE/4),%ecx
  126. rep
  127. movsl
  128. +
  129. +#ifdef CONFIG_OPEN_FIRMWARE
  130. +/*
  131. + * If Open Firmware booted us, save the OFW client interface callback address
  132. + * and preserve the OFW page mappings by priming the kernel's new page
  133. + * directory area with a copy of the OFW page directory. That lets OFW stay
  134. + * resident in high memory (high in both the virtual and physical spaces)
  135. + * for at least long enough to copy out the device tree.
  136. + */
  137. 1:
  138. + movl $(boot_params - __PAGE_OFFSET + OFW_INFO_OFFSET), %ebp
  139. + cmpl $0x2057464F, (%ebp) /* Magic number "OFW " */
  140. + jne 1f
  141. +
  142. + mov 0x8(%ebp), %eax /* Save callback address */
  143. + mov %eax, call_firmware - __PAGE_OFFSET
  144. +
  145. + /* Copy the OFW pdir into swapper_pg_dir */
  146. + movl %esi, %edx /* save %esi */
  147. + movl $(swapper_pg_dir - __PAGE_OFFSET), %edi
  148. + movl %cr3, %esi /* Source is current pg_dir base address */
  149. + movl $1024, %ecx /* Number of page directory entries */
  150. + rep
  151. + movsl
  152. + movl %edx, %esi /* restore %esi */
  153. +#endif
  154. +1:
  155. /*
  156. * Initialize page tables. This creates a PDE and a set of page
  157. * tables, which are located immediately beyond _end. The variable
  158. @@ -129,6 +155,7 @@ ENTRY(startup_32)
  159. * Warning: don't use %esi or the stack in this code. However, %esp
  160. * can be used as a GPR if you really need it...
  161. */
  162. +
  163. page_pde_offset = (__PAGE_OFFSET >> 20);
  164. movl $(pg0 - __PAGE_OFFSET), %edi
  165. Index: linux-2.6.23.17/arch/i386/kernel/setup.c
  166. ===================================================================
  167. --- linux-2.6.23.17.orig/arch/i386/kernel/setup.c
  168. +++ linux-2.6.23.17/arch/i386/kernel/setup.c
  169. @@ -362,8 +362,10 @@ void __init zone_sizes_init(void)
  170. {
  171. unsigned long max_zone_pfns[MAX_NR_ZONES];
  172. memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
  173. +#ifdef CONFIG_ZONE_DMA
  174. max_zone_pfns[ZONE_DMA] =
  175. virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
  176. +#endif
  177. max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
  178. #ifdef CONFIG_HIGHMEM
  179. max_zone_pfns[ZONE_HIGHMEM] = highend_pfn;
  180. @@ -428,6 +430,9 @@ void __init setup_bootmem_allocator(void
  181. */
  182. acpi_reserve_bootmem();
  183. #endif
  184. +#ifdef CONFIG_OLPC_PM
  185. + reserve_bootmem(0xf0000, PAGE_SIZE);
  186. +#endif
  187. #ifdef CONFIG_X86_FIND_SMP_CONFIG
  188. /*
  189. * Find and reserve possible boot-time SMP configuration:
  190. Index: linux-2.6.23.17/arch/i386/pci/Makefile
  191. ===================================================================
  192. --- linux-2.6.23.17.orig/arch/i386/pci/Makefile
  193. +++ linux-2.6.23.17/arch/i386/pci/Makefile
  194. @@ -3,6 +3,7 @@ obj-y := i386.o init.o
  195. obj-$(CONFIG_PCI_BIOS) += pcbios.o
  196. obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o mmconfig-shared.o
  197. obj-$(CONFIG_PCI_DIRECT) += direct.o
  198. +obj-$(CONFIG_PCI_OLPC) += olpc.o
  199. pci-y := fixup.o
  200. pci-$(CONFIG_ACPI) += acpi.o
  201. Index: linux-2.6.23.17/arch/i386/pci/init.c
  202. ===================================================================
  203. --- linux-2.6.23.17.orig/arch/i386/pci/init.c
  204. +++ linux-2.6.23.17/arch/i386/pci/init.c
  205. @@ -14,6 +14,9 @@ static __init int pci_access_init(void)
  206. #ifdef CONFIG_PCI_MMCONFIG
  207. pci_mmcfg_init(type);
  208. #endif
  209. +#ifdef CONFIG_PCI_OLPC
  210. + pci_olpc_init();
  211. +#endif
  212. if (raw_pci_ops)
  213. return 0;
  214. #ifdef CONFIG_PCI_BIOS
  215. Index: linux-2.6.23.17/arch/i386/pci/pci.h
  216. ===================================================================
  217. --- linux-2.6.23.17.orig/arch/i386/pci/pci.h
  218. +++ linux-2.6.23.17/arch/i386/pci/pci.h
  219. @@ -93,6 +93,7 @@ extern void pci_direct_init(int type);
  220. extern void pci_pcbios_init(void);
  221. extern void pci_mmcfg_init(int type);
  222. extern void pcibios_sort(void);
  223. +extern void pci_olpc_init(void);
  224. /* pci-mmconfig.c */
  225. Index: linux-2.6.23.17/drivers/Makefile
  226. ===================================================================
  227. --- linux-2.6.23.17.orig/drivers/Makefile
  228. +++ linux-2.6.23.17/drivers/Makefile
  229. @@ -23,6 +23,8 @@ obj-y += char/
  230. obj-$(CONFIG_CONNECTOR) += connector/
  231. +obj-$(CONFIG_SYSPROF) += sysprof/
  232. +
  233. # i810fb and intelfb depend on char/agp/
  234. obj-$(CONFIG_FB_I810) += video/i810/
  235. obj-$(CONFIG_FB_INTEL) += video/intelfb/
  236. Index: linux-2.6.23.17/drivers/char/vt_ioctl.c
  237. ===================================================================
  238. --- linux-2.6.23.17.orig/drivers/char/vt_ioctl.c
  239. +++ linux-2.6.23.17/drivers/char/vt_ioctl.c
  240. @@ -37,6 +37,9 @@
  241. char vt_dont_switch;
  242. extern struct tty_driver *console_driver;
  243. +/* Add a notifier chain to inform drivers of a VT_TEXT/VT_GRAPHICS switch */
  244. +RAW_NOTIFIER_HEAD(console_notifier_list);
  245. +
  246. #define VT_IS_IN_USE(i) (console_driver->ttys[i] && console_driver->ttys[i]->count)
  247. #define VT_BUSY(i) (VT_IS_IN_USE(i) || i == fg_console || vc_cons[i].d == sel_cons)
  248. @@ -491,6 +494,14 @@ int vt_ioctl(struct tty_struct *tty, str
  249. vc->vc_mode = (unsigned char) arg;
  250. if (console != fg_console)
  251. return 0;
  252. +
  253. + /* Notify listeners if the current fg_console has switched */
  254. +
  255. + raw_notifier_call_chain(&console_notifier_list,
  256. + (arg == KD_TEXT) ?
  257. + CONSOLE_EVENT_SWITCH_TEXT :
  258. + CONSOLE_EVENT_SWITCH_GRAPHICS, 0);
  259. +
  260. /*
  261. * explicitly blank/unblank the screen if switching modes
  262. */
  263. Index: linux-2.6.23.17/drivers/i2c/busses/scx200_acb.c
  264. ===================================================================
  265. --- linux-2.6.23.17.orig/drivers/i2c/busses/scx200_acb.c
  266. +++ linux-2.6.23.17/drivers/i2c/busses/scx200_acb.c
  267. @@ -46,6 +46,10 @@ static int base[MAX_DEVICES] = { 0x820,
  268. module_param_array(base, int, NULL, 0);
  269. MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers");
  270. +static unsigned int smbclk = 0x70;
  271. +module_param(smbclk, uint, 0);
  272. +MODULE_PARM_DESC(smbclk, "Specify the SMB_CLK value");
  273. +
  274. #define POLL_TIMEOUT (HZ/5)
  275. enum scx200_acb_state {
  276. @@ -108,6 +112,7 @@ struct scx200_acb_iface {
  277. #define ACBADDR (iface->base + 4)
  278. #define ACBCTL2 (iface->base + 5)
  279. #define ACBCTL2_ENABLE 0x01
  280. +#define ACBCTL3 (iface->base + 6)
  281. /************************************************************************/
  282. @@ -392,11 +397,13 @@ static __init int scx200_acb_probe(struc
  283. {
  284. u8 val;
  285. - /* Disable the ACCESS.bus device and Configure the SCL
  286. - frequency: 16 clock cycles */
  287. - outb(0x70, ACBCTL2);
  288. + /* Disable the ACCESS.bus device and Configure the SCL */
  289. +
  290. + outb((smbclk & 0x7F) << 1, ACBCTL2);
  291. +
  292. + outb((smbclk >> 7) & 0xFF, ACBCTL3);
  293. - if (inb(ACBCTL2) != 0x70) {
  294. + if (inb(ACBCTL2) != ((smbclk & 0x7F) << 1)) {
  295. pr_debug(NAME ": ACBCTL2 readback failed\n");
  296. return -ENXIO;
  297. }
  298. Index: linux-2.6.23.17/drivers/input/keyboard/atkbd.c
  299. ===================================================================
  300. --- linux-2.6.23.17.orig/drivers/input/keyboard/atkbd.c
  301. +++ linux-2.6.23.17/drivers/input/keyboard/atkbd.c
  302. @@ -63,12 +63,25 @@ static int atkbd_extra;
  303. module_param_named(extra, atkbd_extra, bool, 0);
  304. MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards");
  305. +#define ATKBD_KEY_UNKNOWN 0
  306. +#define ATKBD_KEY_NULL 0xFF0000FF
  307. +
  308. +#define ATKBD_SCR_1 0xFF0000FE
  309. +#define ATKBD_SCR_2 0xFF0000FD
  310. +#define ATKBD_SCR_4 0xFF0000FC
  311. +#define ATKBD_SCR_8 0xFF0000FB
  312. +#define ATKBD_SCR_CLICK 0xFF0000FA
  313. +#define ATKBD_SCR_LEFT 0xFF0000F9
  314. +#define ATKBD_SCR_RIGHT 0xFF0000F8
  315. +
  316. +#define ATKBD_SPECIAL 0xFF0000F8
  317. +
  318. /*
  319. * Scancode to keycode tables. These are just the default setting, and
  320. * are loadable via an userland utility.
  321. */
  322. -static unsigned char atkbd_set2_keycode[512] = {
  323. +static unsigned int atkbd_set2_keycode[512] = {
  324. #ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES
  325. @@ -87,11 +100,17 @@ static unsigned char atkbd_set2_keycode[
  326. 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
  327. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  328. - 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
  329. +
  330. + 217,100,ATKBD_KEY_NULL, 0, 97,165, 0, 0,
  331. + 156, 0, 0, 0, 0, 0, 0,125,
  332. +
  333. 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
  334. 159, 0,115, 0,164, 0, 0,116,158, 0,172,166, 0, 0, 0,142,
  335. 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
  336. - 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
  337. +
  338. + 226, 0, 0, 0, 0, 0, 0, 0,
  339. + 0,ATKBD_KEY_NULL, 96, 0, 0, 0,143, 0,
  340. +
  341. 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
  342. 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0,
  343. @@ -150,19 +169,6 @@ static unsigned char atkbd_unxlate_table
  344. #define ATKBD_RET_HANGEUL 0xf2
  345. #define ATKBD_RET_ERR 0xff
  346. -#define ATKBD_KEY_UNKNOWN 0
  347. -#define ATKBD_KEY_NULL 255
  348. -
  349. -#define ATKBD_SCR_1 254
  350. -#define ATKBD_SCR_2 253
  351. -#define ATKBD_SCR_4 252
  352. -#define ATKBD_SCR_8 251
  353. -#define ATKBD_SCR_CLICK 250
  354. -#define ATKBD_SCR_LEFT 249
  355. -#define ATKBD_SCR_RIGHT 248
  356. -
  357. -#define ATKBD_SPECIAL 248
  358. -
  359. #define ATKBD_LED_EVENT_BIT 0
  360. #define ATKBD_REP_EVENT_BIT 1
  361. @@ -174,7 +180,7 @@ static unsigned char atkbd_unxlate_table
  362. #define ATKBD_XL_HANJA 0x20
  363. static struct {
  364. - unsigned char keycode;
  365. + unsigned int keycode;
  366. unsigned char set2;
  367. } atkbd_scroll_keys[] = {
  368. { ATKBD_SCR_1, 0xc5 },
  369. @@ -200,7 +206,7 @@ struct atkbd {
  370. char phys[32];
  371. unsigned short id;
  372. - unsigned char keycode[512];
  373. + unsigned int keycode[512];
  374. unsigned char set;
  375. unsigned char translated;
  376. unsigned char extra;
  377. @@ -351,7 +357,7 @@ static irqreturn_t atkbd_interrupt(struc
  378. unsigned int code = data;
  379. int scroll = 0, hscroll = 0, click = -1, add_release_event = 0;
  380. int value;
  381. - unsigned char keycode;
  382. + unsigned int keycode;
  383. #ifdef ATKBD_DEBUG
  384. printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags);
  385. @@ -856,9 +862,11 @@ static void atkbd_set_keycode_table(stru
  386. atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j].keycode;
  387. }
  388. } else if (atkbd->set == 3) {
  389. - memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
  390. + for (i = 0; i < ARRAY_SIZE(atkbd_set3_keycode); i++)
  391. + atkbd->keycode[i] = atkbd_set3_keycode[i];
  392. } else {
  393. - memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
  394. + for (i = 0; i < ARRAY_SIZE(atkbd_set2_keycode); i++)
  395. + atkbd->keycode[i] = atkbd_set2_keycode[i];
  396. if (atkbd->scroll)
  397. for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++)
  398. @@ -925,8 +933,8 @@ static void atkbd_set_device_attrs(struc
  399. }
  400. input_dev->keycode = atkbd->keycode;
  401. - input_dev->keycodesize = sizeof(unsigned char);
  402. - input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
  403. + input_dev->keycodesize = sizeof(unsigned int);
  404. + input_dev->keycodemax = ARRAY_SIZE(atkbd->keycode);
  405. for (i = 0; i < 512; i++)
  406. if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
  407. @@ -1017,6 +1025,10 @@ static int atkbd_connect(struct serio *s
  408. return err;
  409. }
  410. +#ifdef CONFIG_OLPC
  411. +#include <asm/olpc.h>
  412. +#endif
  413. +
  414. /*
  415. * atkbd_reconnect() tries to restore keyboard into a sane state and is
  416. * most likely called on resume.
  417. @@ -1027,6 +1039,12 @@ static int atkbd_reconnect(struct serio
  418. struct atkbd *atkbd = serio_get_drvdata(serio);
  419. struct serio_driver *drv = serio->drv;
  420. +#ifdef CONFIG_OLPC
  421. + if (olpc_rev_after(OLPC_REV_B2))
  422. + if (serio->dev.power.power_state.event != PM_EVENT_ON)
  423. + return 0;
  424. +#endif
  425. +
  426. if (!atkbd || !drv) {
  427. printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
  428. return -1;
  429. Index: linux-2.6.23.17/drivers/input/mouse/Kconfig
  430. ===================================================================
  431. --- linux-2.6.23.17.orig/drivers/input/mouse/Kconfig
  432. +++ linux-2.6.23.17/drivers/input/mouse/Kconfig
  433. @@ -96,6 +96,16 @@ config MOUSE_PS2_TOUCHKIT
  434. If unsure, say N.
  435. +config MOUSE_PS2_OLPC
  436. + bool "OLPC PS/2 mouse protocol extension" if EMBEDDED
  437. + default n
  438. + depends on MOUSE_PS2 && OLPC
  439. + ---help---
  440. + Say Y here if you have an OLPC PS/2 touchpad connected to
  441. + your system.
  442. +
  443. + If unsure, say N.
  444. +
  445. config MOUSE_SERIAL
  446. tristate "Serial mouse"
  447. select SERIO
  448. Index: linux-2.6.23.17/drivers/input/mouse/Makefile
  449. ===================================================================
  450. --- linux-2.6.23.17.orig/drivers/input/mouse/Makefile
  451. +++ linux-2.6.23.17/drivers/input/mouse/Makefile
  452. @@ -24,3 +24,4 @@ psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) +=
  453. psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o
  454. psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o
  455. psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o
  456. +psmouse-$(CONFIG_MOUSE_PS2_OLPC) += olpc.o
  457. Index: linux-2.6.23.17/drivers/input/mouse/psmouse-base.c
  458. ===================================================================
  459. --- linux-2.6.23.17.orig/drivers/input/mouse/psmouse-base.c
  460. +++ linux-2.6.23.17/drivers/input/mouse/psmouse-base.c
  461. @@ -26,6 +26,7 @@
  462. #include "synaptics.h"
  463. #include "logips2pp.h"
  464. #include "alps.h"
  465. +#include "olpc.h"
  466. #include "lifebook.h"
  467. #include "trackpoint.h"
  468. #include "touchkit_ps2.h"
  469. @@ -103,7 +104,7 @@ static struct attribute_group psmouse_at
  470. */
  471. static DEFINE_MUTEX(psmouse_mutex);
  472. -static struct workqueue_struct *kpsmoused_wq;
  473. +struct workqueue_struct *kpsmoused_wq;
  474. struct psmouse_protocol {
  475. enum psmouse_type type;
  476. @@ -320,7 +321,7 @@ static irqreturn_t psmouse_interrupt(str
  477. goto out;
  478. }
  479. - if (psmouse->packet[1] == PSMOUSE_RET_ID) {
  480. + if (psmouse->packet[1] == PSMOUSE_RET_ID || psmouse->packet[1] == PSMOUSE_RET_BAT) {
  481. __psmouse_set_state(psmouse, PSMOUSE_IGNORE);
  482. serio_reconnect(serio);
  483. goto out;
  484. @@ -631,8 +632,21 @@ static int psmouse_extensions(struct psm
  485. }
  486. }
  487. +/*
  488. + * Try OLPC touchpad.
  489. + */
  490. if (max_proto > PSMOUSE_IMEX) {
  491. + if (olpc_detect(psmouse, set_properties) == 0) {
  492. + if (!set_properties || olpc_init(psmouse) == 0)
  493. + return PSMOUSE_OLPC;
  494. +/*
  495. + * Init failed, try basic relative protocols
  496. + */
  497. + max_proto = PSMOUSE_IMEX;
  498. + }
  499. + }
  500. + if (max_proto > PSMOUSE_IMEX) {
  501. if (genius_detect(psmouse, set_properties) == 0)
  502. return PSMOUSE_GENPS;
  503. @@ -762,6 +776,14 @@ static const struct psmouse_protocol psm
  504. .detect = touchkit_ps2_detect,
  505. },
  506. #endif
  507. +#ifdef CONFIG_MOUSE_PS2_OLPC
  508. + {
  509. + .type = PSMOUSE_OLPC,
  510. + .name = "OLPC",
  511. + .alias = "olpc",
  512. + .detect = olpc_detect,
  513. + },
  514. +#endif
  515. {
  516. .type = PSMOUSE_CORTRON,
  517. .name = "CortronPS/2",
  518. Index: linux-2.6.23.17/drivers/input/mouse/psmouse.h
  519. ===================================================================
  520. --- linux-2.6.23.17.orig/drivers/input/mouse/psmouse.h
  521. +++ linux-2.6.23.17/drivers/input/mouse/psmouse.h
  522. @@ -89,6 +89,7 @@ enum psmouse_type {
  523. PSMOUSE_TRACKPOINT,
  524. PSMOUSE_TOUCHKIT_PS2,
  525. PSMOUSE_CORTRON,
  526. + PSMOUSE_OLPC,
  527. PSMOUSE_AUTO /* This one should always be last */
  528. };
  529. @@ -96,6 +97,7 @@ int psmouse_sliced_command(struct psmous
  530. int psmouse_reset(struct psmouse *psmouse);
  531. void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
  532. +extern struct workqueue_struct *kpsmoused_wq;
  533. struct psmouse_attribute {
  534. struct device_attribute dattr;
  535. Index: linux-2.6.23.17/drivers/input/serio/i8042.c
  536. ===================================================================
  537. --- linux-2.6.23.17.orig/drivers/input/serio/i8042.c
  538. +++ linux-2.6.23.17/drivers/input/serio/i8042.c
  539. @@ -868,6 +868,11 @@ static long i8042_panic_blink(long count
  540. #undef DELAY
  541. #ifdef CONFIG_PM
  542. +
  543. +#ifdef CONFIG_OLPC
  544. +#include <asm/olpc.h>
  545. +#endif
  546. +
  547. /*
  548. * Here we try to restore the original BIOS settings. We only want to
  549. * do that once, when we really suspend, not when we taking memory
  550. @@ -878,8 +883,15 @@ static long i8042_panic_blink(long count
  551. static int i8042_suspend(struct platform_device *dev, pm_message_t state)
  552. {
  553. if (dev->dev.power.power_state.event != state.event) {
  554. +#ifdef CONFIG_OLPC
  555. + /* Anything newer than B2 remains powered; no reset needed */
  556. + if (olpc_rev_before(OLPC_REV_PRE_B3)) {
  557. +#endif
  558. if (state.event == PM_EVENT_SUSPEND)
  559. i8042_controller_reset();
  560. +#ifdef CONFIG_OLPC
  561. + }
  562. +#endif
  563. dev->dev.power.power_state = state;
  564. }
  565. @@ -902,9 +914,15 @@ static int i8042_resume(struct platform_
  566. if (dev->dev.power.power_state.event == PM_EVENT_ON)
  567. return 0;
  568. +#ifdef CONFIG_OLPC
  569. + if (olpc_rev_before(OLPC_REV_PRE_B3)) {
  570. +#endif
  571. error = i8042_controller_check();
  572. if (error)
  573. return error;
  574. +#ifdef CONFIG_OLPC
  575. + }
  576. +#endif
  577. error = i8042_controller_selftest();
  578. if (error)
  579. Index: linux-2.6.23.17/drivers/input/serio/serio.c
  580. ===================================================================
  581. --- linux-2.6.23.17.orig/drivers/input/serio/serio.c
  582. +++ linux-2.6.23.17/drivers/input/serio/serio.c
  583. @@ -916,11 +916,22 @@ static int serio_uevent(struct device *d
  584. #endif /* CONFIG_HOTPLUG */
  585. #ifdef CONFIG_PM
  586. +
  587. +#ifdef CONFIG_OLPC
  588. +#include <asm/olpc.h>
  589. +#endif
  590. +
  591. static int serio_suspend(struct device *dev, pm_message_t state)
  592. {
  593. if (dev->power.power_state.event != state.event) {
  594. +#ifdef CONFIG_OLPC
  595. + if (olpc_rev_before(OLPC_REV_PRE_B3)) {
  596. +#endif
  597. if (state.event == PM_EVENT_SUSPEND)
  598. serio_cleanup(to_serio_port(dev));
  599. +#ifdef CONFIG_OLPC
  600. + }
  601. +#endif
  602. dev->power.power_state = state;
  603. }
  604. Index: linux-2.6.23.17/drivers/media/video/cafe_ccic.c
  605. ===================================================================
  606. --- linux-2.6.23.17.orig/drivers/media/video/cafe_ccic.c
  607. +++ linux-2.6.23.17/drivers/media/video/cafe_ccic.c
  608. @@ -63,13 +63,13 @@ MODULE_SUPPORTED_DEVICE("Video");
  609. */
  610. #define MAX_DMA_BUFS 3
  611. -static int alloc_bufs_at_load = 0;
  612. -module_param(alloc_bufs_at_load, bool, 0444);
  613. -MODULE_PARM_DESC(alloc_bufs_at_load,
  614. - "Non-zero value causes DMA buffers to be allocated at module "
  615. - "load time. This increases the chances of successfully getting "
  616. - "those buffers, but at the cost of nailing down the memory from "
  617. - "the outset.");
  618. +static int alloc_bufs_at_read = 0;
  619. +module_param(alloc_bufs_at_read, bool, 0444);
  620. +MODULE_PARM_DESC(alloc_bufs_at_read,
  621. + "Non-zero value causes DMA buffers to be allocated when the "
  622. + "video capture device is read, rather than at module load "
  623. + "time. This saves memory, but decreases the chances of "
  624. + "successfully getting those buffers.");
  625. static int n_dma_bufs = 3;
  626. module_param(n_dma_bufs, uint, 0644);
  627. @@ -370,6 +370,10 @@ static int cafe_smbus_write_data(struct
  628. rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR);
  629. cafe_reg_write(cam, REG_TWSIC1, rval);
  630. spin_unlock_irqrestore(&cam->dev_lock, flags);
  631. + mdelay(2); /* It'll probably take about 900µs anyway, and the
  632. + CAFÉ is apparently quite sensitive to being poked
  633. + at this point. If we can work out precisely what's
  634. + going on and reduce this delay, it would be nice. */
  635. /*
  636. * Time to wait for the write to complete. THIS IS A RACY
  637. @@ -1503,7 +1507,7 @@ static int cafe_v4l_release(struct inode
  638. }
  639. if (cam->users == 0) {
  640. cafe_ctlr_power_down(cam);
  641. - if (! alloc_bufs_at_load)
  642. + if (alloc_bufs_at_read)
  643. cafe_free_dma_bufs(cam);
  644. }
  645. mutex_unlock(&cam->s_mutex);
  646. @@ -2162,7 +2166,7 @@ static int cafe_pci_probe(struct pci_dev
  647. /*
  648. * If so requested, try to get our DMA buffers now.
  649. */
  650. - if (alloc_bufs_at_load) {
  651. + if (!alloc_bufs_at_read) {
  652. if (cafe_alloc_dma_bufs(cam, 1))
  653. cam_warn(cam, "Unable to alloc DMA buffers at load"
  654. " will try again later.");
  655. Index: linux-2.6.23.17/drivers/misc/Kconfig
  656. ===================================================================
  657. --- linux-2.6.23.17.orig/drivers/misc/Kconfig
  658. +++ linux-2.6.23.17/drivers/misc/Kconfig
  659. @@ -202,5 +202,10 @@ config THINKPAD_ACPI_BAY
  660. If you are not sure, say Y here.
  661. +config EEPROM_93CX6
  662. + tristate "EEPROM 93CX6 support"
  663. + ---help---
  664. + This is a driver for the EEPROM chipsets 93c46 and 93c66.
  665. + The driver supports both read as well as write commands.
  666. endif # MISC_DEVICES
  667. Index: linux-2.6.23.17/drivers/mmc/host/sdhci.c
  668. ===================================================================
  669. --- linux-2.6.23.17.orig/drivers/mmc/host/sdhci.c
  670. +++ linux-2.6.23.17/drivers/mmc/host/sdhci.c
  671. @@ -411,6 +411,12 @@ static void sdhci_prepare_data(struct sd
  672. break;
  673. }
  674. + /*
  675. + * There's an off-by-one error in the hw that we need to
  676. + * compensate for.
  677. + */
  678. + count++;
  679. +
  680. if (count >= 0xF) {
  681. printk(KERN_WARNING "%s: Too large timeout requested!\n",
  682. mmc_hostname(host->mmc));
  683. @@ -676,19 +682,17 @@ static void sdhci_set_power(struct sdhci
  684. if (!(host->chip->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
  685. writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
  686. - pwr = SDHCI_POWER_ON;
  687. -
  688. switch (1 << power) {
  689. case MMC_VDD_165_195:
  690. - pwr |= SDHCI_POWER_180;
  691. + pwr = SDHCI_POWER_180;
  692. break;
  693. case MMC_VDD_29_30:
  694. case MMC_VDD_30_31:
  695. - pwr |= SDHCI_POWER_300;
  696. + pwr = SDHCI_POWER_300;
  697. break;
  698. case MMC_VDD_32_33:
  699. case MMC_VDD_33_34:
  700. - pwr |= SDHCI_POWER_330;
  701. + pwr = SDHCI_POWER_330;
  702. break;
  703. default:
  704. BUG();
  705. @@ -696,6 +700,10 @@ static void sdhci_set_power(struct sdhci
  706. writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL);
  707. + pwr |= SDHCI_POWER_ON;
  708. +
  709. + writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL);
  710. +
  711. out:
  712. host->power = power;
  713. }
  714. Index: linux-2.6.23.17/drivers/mtd/Kconfig
  715. ===================================================================
  716. --- linux-2.6.23.17.orig/drivers/mtd/Kconfig
  717. +++ linux-2.6.23.17/drivers/mtd/Kconfig
  718. @@ -288,6 +288,14 @@ config SSFDC
  719. This enables read only access to SmartMedia formatted NAND
  720. flash. You can mount it with FAT file system.
  721. +config MTD_OOPS
  722. + tristate "Log panic/oops to an MTD buffer"
  723. + depends on MTD
  724. + help
  725. + This enables panic and oops messages to be logged to a circular
  726. + buffer in a flash partition where it can be read back at some
  727. + later point.
  728. +
  729. source "drivers/mtd/chips/Kconfig"
  730. source "drivers/mtd/maps/Kconfig"
  731. Index: linux-2.6.23.17/drivers/mtd/Makefile
  732. ===================================================================
  733. --- linux-2.6.23.17.orig/drivers/mtd/Makefile
  734. +++ linux-2.6.23.17/drivers/mtd/Makefile
  735. @@ -22,6 +22,7 @@ obj-$(CONFIG_NFTL) += nftl.o
  736. obj-$(CONFIG_INFTL) += inftl.o
  737. obj-$(CONFIG_RFD_FTL) += rfd_ftl.o
  738. obj-$(CONFIG_SSFDC) += ssfdc.o
  739. +obj-$(CONFIG_MTD_OOPS) += mtdoops.o
  740. nftl-objs := nftlcore.o nftlmount.o
  741. inftl-objs := inftlcore.o inftlmount.o
  742. Index: linux-2.6.23.17/drivers/mtd/chips/cfi_cmdset_0001.c
  743. ===================================================================
  744. --- linux-2.6.23.17.orig/drivers/mtd/chips/cfi_cmdset_0001.c
  745. +++ linux-2.6.23.17/drivers/mtd/chips/cfi_cmdset_0001.c
  746. @@ -526,7 +526,7 @@ static int cfi_intelext_partition_fixup(
  747. struct cfi_pri_intelext *extp = cfi->cmdset_priv;
  748. /*
  749. - * Probing of multi-partition flash ships.
  750. + * Probing of multi-partition flash chips.
  751. *
  752. * To support multiple partitions when available, we simply arrange
  753. * for each of them to have their own flchip structure even if they
  754. @@ -1781,7 +1781,7 @@ static int __xipram do_erase_oneblock(st
  755. return ret;
  756. }
  757. -int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
  758. +static int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
  759. {
  760. unsigned long ofs, len;
  761. int ret;
  762. @@ -1931,7 +1931,7 @@ static int cfi_intelext_lock(struct mtd_
  763. printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
  764. __FUNCTION__, ofs, len);
  765. cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
  766. - ofs, len, 0);
  767. + ofs, len, NULL);
  768. #endif
  769. ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
  770. @@ -1941,7 +1941,7 @@ static int cfi_intelext_lock(struct mtd_
  771. printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
  772. __FUNCTION__, ret);
  773. cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
  774. - ofs, len, 0);
  775. + ofs, len, NULL);
  776. #endif
  777. return ret;
  778. @@ -1955,7 +1955,7 @@ static int cfi_intelext_unlock(struct mt
  779. printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
  780. __FUNCTION__, ofs, len);
  781. cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
  782. - ofs, len, 0);
  783. + ofs, len, NULL);
  784. #endif
  785. ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
  786. @@ -1965,7 +1965,7 @@ static int cfi_intelext_unlock(struct mt
  787. printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
  788. __FUNCTION__, ret);
  789. cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
  790. - ofs, len, 0);
  791. + ofs, len, NULL);
  792. #endif
  793. return ret;
  794. @@ -2256,7 +2256,7 @@ static void cfi_intelext_save_locks(stru
  795. adr = region->offset + block * len;
  796. status = cfi_varsize_frob(mtd,
  797. - do_getlockstatus_oneblock, adr, len, 0);
  798. + do_getlockstatus_oneblock, adr, len, NULL);
  799. if (status)
  800. set_bit(block, region->lockmap);
  801. else
  802. Index: linux-2.6.23.17/drivers/mtd/chips/cfi_cmdset_0002.c
  803. ===================================================================
  804. --- linux-2.6.23.17.orig/drivers/mtd/chips/cfi_cmdset_0002.c
  805. +++ linux-2.6.23.17/drivers/mtd/chips/cfi_cmdset_0002.c
  806. @@ -1617,7 +1617,7 @@ static int __xipram do_erase_oneblock(st
  807. }
  808. -int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
  809. +static int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
  810. {
  811. unsigned long ofs, len;
  812. int ret;
  813. Index: linux-2.6.23.17/drivers/mtd/chips/jedec_probe.c
  814. ===================================================================
  815. --- linux-2.6.23.17.orig/drivers/mtd/chips/jedec_probe.c
  816. +++ linux-2.6.23.17/drivers/mtd/chips/jedec_probe.c
  817. @@ -70,6 +70,7 @@
  818. /* Fujitsu */
  819. #define MBM29F040C 0x00A4
  820. +#define MBM29F800BA 0x2258
  821. #define MBM29LV650UE 0x22D7
  822. #define MBM29LV320TE 0x22F6
  823. #define MBM29LV320BE 0x22F9
  824. @@ -129,6 +130,7 @@
  825. #define LH28F640BF 0x00b0
  826. /* ST - www.st.com */
  827. +#define M29F800AB 0x0058
  828. #define M29W800DT 0x00D7
  829. #define M29W800DB 0x005B
  830. #define M29W160DT 0x22C4
  831. @@ -646,6 +648,23 @@ static const struct amd_flash_info jedec
  832. }
  833. }, {
  834. .mfr_id = MANUFACTURER_FUJITSU,
  835. + .dev_id = MBM29F800BA,
  836. + .name = "Fujitsu MBM29F800BA",
  837. + .uaddr = {
  838. + [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
  839. + [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
  840. + },
  841. + .DevSize = SIZE_1MiB,
  842. + .CmdSet = P_ID_AMD_STD,
  843. + .NumEraseRegions= 4,
  844. + .regions = {
  845. + ERASEINFO(0x04000,1),
  846. + ERASEINFO(0x02000,2),
  847. + ERASEINFO(0x08000,1),
  848. + ERASEINFO(0x10000,15),
  849. + }
  850. + }, {
  851. + .mfr_id = MANUFACTURER_FUJITSU,
  852. .dev_id = MBM29LV650UE,
  853. .name = "Fujitsu MBM29LV650UE",
  854. .uaddr = {
  855. @@ -1510,6 +1529,23 @@ static const struct amd_flash_info jedec
  856. ERASEINFO(0x1000,256)
  857. }
  858. + }, {
  859. + .mfr_id = MANUFACTURER_ST,
  860. + .dev_id = M29F800AB,
  861. + .name = "ST M29F800AB",
  862. + .uaddr = {
  863. + [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
  864. + [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
  865. + },
  866. + .DevSize = SIZE_1MiB,
  867. + .CmdSet = P_ID_AMD_STD,
  868. + .NumEraseRegions= 4,
  869. + .regions = {
  870. + ERASEINFO(0x04000,1),
  871. + ERASEINFO(0x02000,2),
  872. + ERASEINFO(0x08000,1),
  873. + ERASEINFO(0x10000,15),
  874. + }
  875. }, {
  876. .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */
  877. .dev_id = M29W800DT,
  878. Index: linux-2.6.23.17/drivers/mtd/devices/Kconfig
  879. ===================================================================
  880. --- linux-2.6.23.17.orig/drivers/mtd/devices/Kconfig
  881. +++ linux-2.6.23.17/drivers/mtd/devices/Kconfig
  882. @@ -69,12 +69,21 @@ config MTD_DATAFLASH26
  883. If you have such a board and such a DataFlash, say 'Y'.
  884. config MTD_M25P80
  885. - tristate "Support for M25 SPI Flash"
  886. + tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)"
  887. depends on SPI_MASTER && EXPERIMENTAL
  888. help
  889. - This enables access to ST M25P80 and similar SPI flash chips,
  890. - used for program and data storage. Set up your spi devices
  891. - with the right board-specific platform data.
  892. + This enables access to most modern SPI flash chips, used for
  893. + program and data storage. Series supported include Atmel AT26DF,
  894. + Spansion S25SL, SST 25VF, ST M25P, and Winbond W25X. Other chips
  895. + are supported as well. See the driver source for the current list,
  896. + or to add other chips.
  897. +
  898. + Note that the original DataFlash chips (AT45 series, not AT26DF),
  899. + need an entirely different driver.
  900. +
  901. + Set up your spi devices with the right board-specific platform data,
  902. + if you want to specify device partitioning or to use a device which
  903. + doesn't support the JEDEC ID instruction.
  904. config MTD_SLRAM
  905. tristate "Uncached system RAM"
  906. Index: linux-2.6.23.17/drivers/mtd/devices/m25p80.c
  907. ===================================================================
  908. --- linux-2.6.23.17.orig/drivers/mtd/devices/m25p80.c
  909. +++ linux-2.6.23.17/drivers/mtd/devices/m25p80.c
  910. @@ -1,5 +1,5 @@
  911. /*
  912. - * MTD SPI driver for ST M25Pxx flash chips
  913. + * MTD SPI driver for ST M25Pxx (and similar) serial flash chips
  914. *
  915. * Author: Mike Lavender, [email protected]
  916. *
  917. @@ -19,33 +19,32 @@
  918. #include <linux/module.h>
  919. #include <linux/device.h>
  920. #include <linux/interrupt.h>
  921. -#include <linux/interrupt.h>
  922. +#include <linux/mutex.h>
  923. +
  924. #include <linux/mtd/mtd.h>
  925. #include <linux/mtd/partitions.h>
  926. +
  927. #include <linux/spi/spi.h>
  928. #include <linux/spi/flash.h>
  929. -#include <asm/semaphore.h>
  930. -
  931. -
  932. -/* NOTE: AT 25F and SST 25LF series are very similar,
  933. - * but commands for sector erase and chip id differ...
  934. - */
  935. #define FLASH_PAGESIZE 256
  936. /* Flash opcodes. */
  937. -#define OPCODE_WREN 6 /* Write enable */
  938. -#define OPCODE_RDSR 5 /* Read status register */
  939. -#define OPCODE_READ 3 /* Read data bytes */
  940. -#define OPCODE_PP 2 /* Page program */
  941. -#define OPCODE_SE 0xd8 /* Sector erase */
  942. -#define OPCODE_RES 0xab /* Read Electronic Signature */
  943. +#define OPCODE_WREN 0x06 /* Write enable */
  944. +#define OPCODE_RDSR 0x05 /* Read status register */
  945. +#define OPCODE_READ 0x03 /* Read data bytes (low frequency) */
  946. +#define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */
  947. +#define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */
  948. +#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
  949. +#define OPCODE_BE_32K 0x52 /* Erase 32KiB block */
  950. +#define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */
  951. #define OPCODE_RDID 0x9f /* Read JEDEC ID */
  952. /* Status Register bits. */
  953. #define SR_WIP 1 /* Write in progress */
  954. #define SR_WEL 2 /* Write enable latch */
  955. +/* meaning of other SR_* bits may differ between vendors */
  956. #define SR_BP0 4 /* Block protect 0 */
  957. #define SR_BP1 8 /* Block protect 1 */
  958. #define SR_BP2 0x10 /* Block protect 2 */
  959. @@ -65,9 +64,10 @@
  960. struct m25p {
  961. struct spi_device *spi;
  962. - struct semaphore lock;
  963. + struct mutex lock;
  964. struct mtd_info mtd;
  965. - unsigned partitioned;
  966. + unsigned partitioned:1;
  967. + u8 erase_opcode;
  968. u8 command[4];
  969. };
  970. @@ -150,8 +150,9 @@ static int wait_till_ready(struct m25p *
  971. */
  972. static int erase_sector(struct m25p *flash, u32 offset)
  973. {
  974. - DEBUG(MTD_DEBUG_LEVEL3, "%s: %s at 0x%08x\n", flash->spi->dev.bus_id,
  975. - __FUNCTION__, offset);
  976. + DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n",
  977. + flash->spi->dev.bus_id, __FUNCTION__,
  978. + flash->mtd.erasesize / 1024, offset);
  979. /* Wait until finished previous write command. */
  980. if (wait_till_ready(flash))
  981. @@ -161,7 +162,7 @@ static int erase_sector(struct m25p *fla
  982. write_enable(flash);
  983. /* Set up command buffer. */
  984. - flash->command[0] = OPCODE_SE;
  985. + flash->command[0] = flash->erase_opcode;
  986. flash->command[1] = offset >> 16;
  987. flash->command[2] = offset >> 8;
  988. flash->command[3] = offset;
  989. @@ -201,13 +202,17 @@ static int m25p80_erase(struct mtd_info
  990. addr = instr->addr;
  991. len = instr->len;
  992. - down(&flash->lock);
  993. + mutex_lock(&flash->lock);
  994. +
  995. + /* REVISIT in some cases we could speed up erasing large regions
  996. + * by using OPCODE_SE instead of OPCODE_BE_4K
  997. + */
  998. /* now erase those sectors */
  999. while (len) {
  1000. if (erase_sector(flash, addr)) {
  1001. instr->state = MTD_ERASE_FAILED;
  1002. - up(&flash->lock);
  1003. + mutex_unlock(&flash->lock);
  1004. return -EIO;
  1005. }
  1006. @@ -215,7 +220,7 @@ static int m25p80_erase(struct mtd_info
  1007. len -= mtd->erasesize;
  1008. }
  1009. - up(&flash->lock);
  1010. + mutex_unlock(&flash->lock);
  1011. instr->state = MTD_ERASE_DONE;
  1012. mtd_erase_callback(instr);
  1013. @@ -260,16 +265,19 @@ static int m25p80_read(struct mtd_info *
  1014. if (retlen)
  1015. *retlen = 0;
  1016. - down(&flash->lock);
  1017. + mutex_lock(&flash->lock);
  1018. /* Wait till previous write/erase is done. */
  1019. if (wait_till_ready(flash)) {
  1020. /* REVISIT status return?? */
  1021. - up(&flash->lock);
  1022. + mutex_unlock(&flash->lock);
  1023. return 1;
  1024. }
  1025. - /* NOTE: OPCODE_FAST_READ (if available) is faster... */
  1026. + /* FIXME switch to OPCODE_FAST_READ. It's required for higher
  1027. + * clocks; and at this writing, every chip this driver handles
  1028. + * supports that opcode.
  1029. + */
  1030. /* Set up the write data buffer. */
  1031. flash->command[0] = OPCODE_READ;
  1032. @@ -281,7 +289,7 @@ static int m25p80_read(struct mtd_info *
  1033. *retlen = m.actual_length - sizeof(flash->command);
  1034. - up(&flash->lock);
  1035. + mutex_unlock(&flash->lock);
  1036. return 0;
  1037. }
  1038. @@ -323,7 +331,7 @@ static int m25p80_write(struct mtd_info
  1039. t[1].tx_buf = buf;
  1040. spi_message_add_tail(&t[1], &m);
  1041. - down(&flash->lock);
  1042. + mutex_lock(&flash->lock);
  1043. /* Wait until finished previous write command. */
  1044. if (wait_till_ready(flash))
  1045. @@ -381,10 +389,10 @@ static int m25p80_write(struct mtd_info
  1046. if (retlen)
  1047. *retlen += m.actual_length
  1048. - sizeof(flash->command);
  1049. - }
  1050. - }
  1051. + }
  1052. + }
  1053. - up(&flash->lock);
  1054. + mutex_unlock(&flash->lock);
  1055. return 0;
  1056. }
  1057. @@ -398,24 +406,118 @@ static int m25p80_write(struct mtd_info
  1058. struct flash_info {
  1059. char *name;
  1060. - u8 id;
  1061. - u16 jedec_id;
  1062. +
  1063. + /* JEDEC id zero means "no ID" (most older chips); otherwise it has
  1064. + * a high byte of zero plus three data bytes: the manufacturer id,
  1065. + * then a two byte device id.
  1066. + */
  1067. + u32 jedec_id;
  1068. +
  1069. + /* The size listed here is what works with OPCODE_SE, which isn't
  1070. + * necessarily called a "sector" by the vendor.
  1071. + */
  1072. unsigned sector_size;
  1073. - unsigned n_sectors;
  1074. + u16 n_sectors;
  1075. +
  1076. + u16 flags;
  1077. +#define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */
  1078. };
  1079. +
  1080. +/* NOTE: double check command sets and memory organization when you add
  1081. + * more flash chips. This current list focusses on newer chips, which
  1082. + * have been converging on command sets which including JEDEC ID.
  1083. + */
  1084. static struct flash_info __devinitdata m25p_data [] = {
  1085. - /* REVISIT: fill in JEDEC ids, for parts that have them */
  1086. - { "m25p05", 0x05, 0x2010, 32 * 1024, 2 },
  1087. - { "m25p10", 0x10, 0x2011, 32 * 1024, 4 },
  1088. - { "m25p20", 0x11, 0x2012, 64 * 1024, 4 },
  1089. - { "m25p40", 0x12, 0x2013, 64 * 1024, 8 },
  1090. - { "m25p80", 0x13, 0x0000, 64 * 1024, 16 },
  1091. - { "m25p16", 0x14, 0x2015, 64 * 1024, 32 },
  1092. - { "m25p32", 0x15, 0x2016, 64 * 1024, 64 },
  1093. - { "m25p64", 0x16, 0x2017, 64 * 1024, 128 },
  1094. +
  1095. + /* Atmel -- some are (confusingly) marketed as "DataFlash" */
  1096. + { "at25fs010", 0x1f6601, 32 * 1024, 4, SECT_4K, },
  1097. + { "at25fs040", 0x1f6604, 64 * 1024, 8, SECT_4K, },
  1098. +
  1099. + { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, },
  1100. +
  1101. + { "at26f004", 0x1f0400, 64 * 1024, 8, SECT_4K, },
  1102. + { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, },
  1103. + { "at26df161a", 0x1f4601, 64 * 1024, 32, SECT_4K, },
  1104. + { "at26df321", 0x1f4701, 64 * 1024, 64, SECT_4K, },
  1105. +
  1106. + /* Spansion -- single (large) sector size only, at least
  1107. + * for the chips listed here (without boot sectors).
  1108. + */
  1109. + { "s25sl004a", 0x010212, 64 * 1024, 8, },
  1110. + { "s25sl008a", 0x010213, 64 * 1024, 16, },
  1111. + { "s25sl016a", 0x010214, 64 * 1024, 32, },
  1112. + { "s25sl032a", 0x010215, 64 * 1024, 64, },
  1113. + { "s25sl064a", 0x010216, 64 * 1024, 128, },
  1114. +
  1115. + /* SST -- large erase sizes are "overlays", "sectors" are 4K */
  1116. + { "sst25vf040b", 0xbf258d, 64 * 1024, 8, SECT_4K, },
  1117. + { "sst25vf080b", 0xbf258e, 64 * 1024, 16, SECT_4K, },
  1118. + { "sst25vf016b", 0xbf2541, 64 * 1024, 32, SECT_4K, },
  1119. + { "sst25vf032b", 0xbf254a, 64 * 1024, 64, SECT_4K, },
  1120. +
  1121. + /* ST Microelectronics -- newer production may have feature updates */
  1122. + { "m25p05", 0x202010, 32 * 1024, 2, },
  1123. + { "m25p10", 0x202011, 32 * 1024, 4, },
  1124. + { "m25p20", 0x202012, 64 * 1024, 4, },
  1125. + { "m25p40", 0x202013, 64 * 1024, 8, },
  1126. + { "m25p80", 0, 64 * 1024, 16, },
  1127. + { "m25p16", 0x202015, 64 * 1024, 32, },
  1128. + { "m25p32", 0x202016, 64 * 1024, 64, },
  1129. + { "m25p64", 0x202017, 64 * 1024, 128, },
  1130. + { "m25p128", 0x202018, 256 * 1024, 64, },
  1131. +
  1132. + { "m45pe80", 0x204014, 64 * 1024, 16, },
  1133. + { "m45pe16", 0x204015, 64 * 1024, 32, },
  1134. +
  1135. + { "m25pe80", 0x208014, 64 * 1024, 16, },
  1136. + { "m25pe16", 0x208015, 64 * 1024, 32, SECT_4K, },
  1137. +
  1138. + /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
  1139. + { "w25x10", 0xef3011, 64 * 1024, 2, SECT_4K, },
  1140. + { "w25x20", 0xef3012, 64 * 1024, 4, SECT_4K, },
  1141. + { "w25x40", 0xef3013, 64 * 1024, 8, SECT_4K, },
  1142. + { "w25x80", 0xef3014, 64 * 1024, 16, SECT_4K, },
  1143. + { "w25x16", 0xef3015, 64 * 1024, 32, SECT_4K, },
  1144. + { "w25x32", 0xef3016, 64 * 1024, 64, SECT_4K, },
  1145. + { "w25x64", 0xef3017, 64 * 1024, 128, SECT_4K, },
  1146. };
  1147. +static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
  1148. +{
  1149. + int tmp;
  1150. + u8 code = OPCODE_RDID;
  1151. + u8 id[3];
  1152. + u32 jedec;
  1153. + struct flash_info *info;
  1154. +
  1155. + /* JEDEC also defines an optional "extended device information"
  1156. + * string for after vendor-specific data, after the three bytes
  1157. + * we use here. Supporting some chips might require using it.
  1158. + */
  1159. + tmp = spi_write_then_read(spi, &code, 1, id, 3);
  1160. + if (tmp < 0) {
  1161. + DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
  1162. + spi->dev.bus_id, tmp);
  1163. + return NULL;
  1164. + }
  1165. + jedec = id[0];
  1166. + jedec = jedec << 8;
  1167. + jedec |= id[1];
  1168. + jedec = jedec << 8;
  1169. + jedec |= id[2];
  1170. +
  1171. + for (tmp = 0, info = m25p_data;
  1172. + tmp < ARRAY_SIZE(m25p_data);
  1173. + tmp++, info++) {
  1174. + if (info->jedec_id == jedec)
  1175. + return info;
  1176. + }
  1177. + dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
  1178. + return NULL;
  1179. +}
  1180. +
  1181. +
  1182. /*
  1183. * board specific setup should have ensured the SPI clock used here
  1184. * matches what the READ command supports, at least until this driver
  1185. @@ -429,37 +531,51 @@ static int __devinit m25p_probe(struct s
  1186. unsigned i;
  1187. /* Platform data helps sort out which chip type we have, as
  1188. - * well as how this board partitions it.
  1189. + * well as how this board partitions it. If we don't have
  1190. + * a chip ID, try the JEDEC id commands; they'll work for most
  1191. + * newer chips, even if we don't recognize the particular chip.
  1192. */
  1193. data = spi->dev.platform_data;
  1194. - if (!data || !data->type) {
  1195. - /* FIXME some chips can identify themselves with RES
  1196. - * or JEDEC get-id commands. Try them ...
  1197. - */
  1198. - DEBUG(MTD_DEBUG_LEVEL1, "%s: no chip id\n",
  1199. - spi->dev.bus_id);
  1200. - return -ENODEV;
  1201. - }
  1202. + if (data && data->type) {
  1203. + for (i = 0, info = m25p_data;
  1204. + i < ARRAY_SIZE(m25p_data);
  1205. + i++, info++) {
  1206. + if (strcmp(data->type, info->name) == 0)
  1207. + break;
  1208. + }
  1209. - for (i = 0, info = m25p_data; i < ARRAY_SIZE(m25p_data); i++, info++) {
  1210. - if (strcmp(data->type, info->name) == 0)
  1211. - break;
  1212. - }
  1213. - if (i == ARRAY_SIZE(m25p_data)) {
  1214. - DEBUG(MTD_DEBUG_LEVEL1, "%s: unrecognized id %s\n",
  1215. - spi->dev.bus_id, data->type);
  1216. + /* unrecognized chip? */
  1217. + if (i == ARRAY_SIZE(m25p_data)) {
  1218. + DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n",
  1219. + spi->dev.bus_id, data->type);
  1220. + info = NULL;
  1221. +
  1222. + /* recognized; is that chip really what's there? */
  1223. + } else if (info->jedec_id) {
  1224. + struct flash_info *chip = jedec_probe(spi);
  1225. +
  1226. + if (!chip || chip != info) {
  1227. + dev_warn(&spi->dev, "found %s, expected %s\n",
  1228. + chip ? chip->name : "UNKNOWN",
  1229. + info->name);
  1230. + info = NULL;
  1231. + }
  1232. + }
  1233. + } else
  1234. + info = jedec_probe(spi);
  1235. +
  1236. + if (!info)
  1237. return -ENODEV;
  1238. - }
  1239. flash = kzalloc(sizeof *flash, GFP_KERNEL);
  1240. if (!flash)
  1241. return -ENOMEM;
  1242. flash->spi = spi;
  1243. - init_MUTEX(&flash->lock);
  1244. + mutex_init(&flash->lock);
  1245. dev_set_drvdata(&spi->dev, flash);
  1246. - if (data->name)
  1247. + if (data && data->name)
  1248. flash->mtd.name = data->name;
  1249. else
  1250. flash->mtd.name = spi->dev.bus_id;
  1251. @@ -468,17 +584,25 @@ static int __devinit m25p_probe(struct s
  1252. flash->mtd.writesize = 1;
  1253. flash->mtd.flags = MTD_CAP_NORFLASH;
  1254. flash->mtd.size = info->sector_size * info->n_sectors;
  1255. - flash->mtd.erasesize = info->sector_size;
  1256. flash->mtd.erase = m25p80_erase;
  1257. flash->mtd.read = m25p80_read;
  1258. flash->mtd.write = m25p80_write;
  1259. + /* prefer "small sector" erase if possible */
  1260. + if (info->flags & SECT_4K) {
  1261. + flash->erase_opcode = OPCODE_BE_4K;
  1262. + flash->mtd.erasesize = 4096;
  1263. + } else {
  1264. + flash->erase_opcode = OPCODE_SE;
  1265. + flash->mtd.erasesize = info->sector_size;
  1266. + }
  1267. +
  1268. dev_info(&spi->dev, "%s (%d Kbytes)\n", info->name,
  1269. flash->mtd.size / 1024);
  1270. DEBUG(MTD_DEBUG_LEVEL2,
  1271. - "mtd .name = %s, .size = 0x%.8x (%uM) "
  1272. - ".erasesize = 0x%.8x (%uK) .numeraseregions = %d\n",
  1273. + "mtd .name = %s, .size = 0x%.8x (%uMiB) "
  1274. + ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
  1275. flash->mtd.name,
  1276. flash->mtd.size, flash->mtd.size / (1024*1024),
  1277. flash->mtd.erasesize, flash->mtd.erasesize / 1024,
  1278. @@ -488,7 +612,7 @@ static int __devinit m25p_probe(struct s
  1279. for (i = 0; i < flash->mtd.numeraseregions; i++)
  1280. DEBUG(MTD_DEBUG_LEVEL2,
  1281. "mtd.eraseregions[%d] = { .offset = 0x%.8x, "
  1282. - ".erasesize = 0x%.8x (%uK), "
  1283. + ".erasesize = 0x%.8x (%uKiB), "
  1284. ".numblocks = %d }\n",
  1285. i, flash->mtd.eraseregions[i].offset,
  1286. flash->mtd.eraseregions[i].erasesize,
  1287. @@ -516,14 +640,14 @@ static int __devinit m25p_probe(struct s
  1288. }
  1289. if (nr_parts > 0) {
  1290. - for (i = 0; i < data->nr_parts; i++) {
  1291. + for (i = 0; i < nr_parts; i++) {
  1292. DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
  1293. "{.name = %s, .offset = 0x%.8x, "
  1294. - ".size = 0x%.8x (%uK) }\n",
  1295. - i, data->parts[i].name,
  1296. - data->parts[i].offset,
  1297. - data->parts[i].size,
  1298. - data->parts[i].size / 1024);
  1299. + ".size = 0x%.8x (%uKiB) }\n",
  1300. + i, parts[i].name,
  1301. + parts[i].offset,
  1302. + parts[i].size,
  1303. + parts[i].size / 1024);
  1304. }
  1305. flash->partitioned = 1;
  1306. return add_mtd_partitions(&flash->mtd, parts, nr_parts);
  1307. @@ -560,6 +684,11 @@ static struct spi_driver m25p80_driver =
  1308. },
  1309. .probe = m25p_probe,
  1310. .remove = __devexit_p(m25p_remove),
  1311. +
  1312. + /* REVISIT: many of these chips have deep power-down modes, which
  1313. + * should clearly be entered on suspend() to minimize power use.
  1314. + * And also when they're otherwise idle...
  1315. + */
  1316. };
  1317. Index: linux-2.6.23.17/drivers/mtd/devices/mtd_dataflash.c
  1318. ===================================================================
  1319. --- linux-2.6.23.17.orig/drivers/mtd/devices/mtd_dataflash.c
  1320. +++ linux-2.6.23.17/drivers/mtd/devices/mtd_dataflash.c
  1321. @@ -14,6 +14,7 @@
  1322. #include <linux/slab.h>
  1323. #include <linux/delay.h>
  1324. #include <linux/device.h>
  1325. +#include <linux/mutex.h>
  1326. #include <linux/spi/spi.h>
  1327. #include <linux/spi/flash.h>
  1328. @@ -89,7 +90,7 @@ struct dataflash {
  1329. unsigned short page_offset; /* offset in flash address */
  1330. unsigned int page_size; /* of bytes per page */
  1331. - struct semaphore lock;
  1332. + struct mutex lock;
  1333. struct spi_device *spi;
  1334. struct mtd_info mtd;
  1335. @@ -167,7 +168,7 @@ static int dataflash_erase(struct mtd_in
  1336. x.len = 4;
  1337. spi_message_add_tail(&x, &msg);
  1338. - down(&priv->lock);
  1339. + mutex_lock(&priv->lock);
  1340. while (instr->len > 0) {
  1341. unsigned int pageaddr;
  1342. int status;
  1343. @@ -210,7 +211,7 @@ static int dataflash_erase(struct mtd_in
  1344. instr->len -= priv->page_size;
  1345. }
  1346. }
  1347. - up(&priv->lock);
  1348. + mutex_unlock(&priv->lock);
  1349. /* Inform MTD subsystem that erase is complete */
  1350. instr->state = MTD_ERASE_DONE;
  1351. @@ -266,7 +267,7 @@ static int dataflash_read(struct mtd_inf
  1352. x[1].len = len;
  1353. spi_message_add_tail(&x[1], &msg);
  1354. - down(&priv->lock);
  1355. + mutex_lock(&priv->lock);
  1356. /* Continuous read, max clock = f(car) which may be less than
  1357. * the peak rate available. Some chips support commands with
  1358. @@ -279,7 +280,7 @@ static int dataflash_read(struct mtd_inf
  1359. /* plus 4 "don't care" bytes */
  1360. status = spi_sync(priv->spi, &msg);
  1361. - up(&priv->lock);
  1362. + mutex_unlock(&priv->lock);
  1363. if (status >= 0) {
  1364. *retlen = msg.actual_length - 8;
  1365. @@ -336,7 +337,7 @@ static int dataflash_write(struct mtd_in
  1366. else
  1367. writelen = len;
  1368. - down(&priv->lock);
  1369. + mutex_lock(&priv->lock);
  1370. while (remaining > 0) {
  1371. DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n",
  1372. pageaddr, offset, writelen);
  1373. @@ -441,7 +442,7 @@ static int dataflash_write(struct mtd_in
  1374. else
  1375. writelen = remaining;
  1376. }
  1377. - up(&priv->lock);
  1378. + mutex_unlock(&priv->lock);
  1379. return status;
  1380. }
  1381. @@ -463,7 +464,7 @@ add_dataflash(struct spi_device *spi, ch
  1382. if (!priv)
  1383. return -ENOMEM;
  1384. - init_MUTEX(&priv->lock);
  1385. + mutex_init(&priv->lock);
  1386. priv->spi = spi;
  1387. priv->page_size = pagesize;
  1388. priv->page_offset = pageoffset;
  1389. Index: linux-2.6.23.17/drivers/mtd/devices/pmc551.c
  1390. ===================================================================
  1391. --- linux-2.6.23.17.orig/drivers/mtd/devices/pmc551.c
  1392. +++ linux-2.6.23.17/drivers/mtd/devices/pmc551.c
  1393. @@ -30,8 +30,8 @@
  1394. *
  1395. * Notes:
  1396. * Due to what I assume is more buggy SROM, the 64M PMC551 I
  1397. - * have available claims that all 4 of it's DRAM banks have 64M
  1398. - * of ram configured (making a grand total of 256M onboard).
  1399. + * have available claims that all 4 of its DRAM banks have 64MiB
  1400. + * of ram configured (making a grand total of 256MiB onboard).
  1401. * This is slightly annoying since the BAR0 size reflects the
  1402. * aperture size, not the dram size, and the V370PDC supplies no
  1403. * other method for memory size discovery. This problem is
  1404. @@ -70,7 +70,7 @@
  1405. * made the memory unusable, added a fix to code to touch up
  1406. * the DRAM some.
  1407. *
  1408. - * Bugs/FIXME's:
  1409. + * Bugs/FIXMEs:
  1410. * * MUST fix the init function to not spin on a register
  1411. * waiting for it to set .. this does not safely handle busted
  1412. * devices that never reset the register correctly which will
  1413. @@ -562,10 +562,10 @@ static u32 fixup_pmc551(struct pci_dev *
  1414. /*
  1415. * Some screen fun
  1416. */
  1417. - printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at "
  1418. + printk(KERN_DEBUG "pmc551: %d%sB (0x%x) of %sprefetchable memory at "
  1419. "0x%llx\n", (size < 1024) ? size : (size < 1048576) ?
  1420. size >> 10 : size >> 20,
  1421. - (size < 1024) ? 'B' : (size < 1048576) ? 'K' : 'M', size,
  1422. + (size < 1024) ? "" : (size < 1048576) ? "Ki" : "Mi", size,
  1423. ((dcmd & (0x1 << 3)) == 0) ? "non-" : "",
  1424. (unsigned long long)pci_resource_start(dev, 0));
  1425. @@ -649,14 +649,10 @@ MODULE_DESCRIPTION(PMC551_VERSION);
  1426. * Stuff these outside the ifdef so as to not bust compiled in driver support
  1427. */
  1428. static int msize = 0;
  1429. -#if defined(CONFIG_MTD_PMC551_APERTURE_SIZE)
  1430. -static int asize = CONFIG_MTD_PMC551_APERTURE_SIZE;
  1431. -#else
  1432. static int asize = 0;
  1433. -#endif
  1434. module_param(msize, int, 0);
  1435. -MODULE_PARM_DESC(msize, "memory size in Megabytes [1 - 1024]");
  1436. +MODULE_PARM_DESC(msize, "memory size in MiB [1 - 1024]");
  1437. module_param(asize, int, 0);
  1438. MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]");
  1439. @@ -799,8 +795,7 @@ static int __init init_pmc551(void)
  1440. mtd->owner = THIS_MODULE;
  1441. if (add_mtd_device(mtd)) {
  1442. - printk(KERN_NOTICE "pmc551: Failed to register new "
  1443. - "device\n");
  1444. + printk(KERN_NOTICE "pmc551: Failed to register new device\n");
  1445. pci_iounmap(PCI_Device, priv->start);
  1446. kfree(mtd->priv);
  1447. kfree(mtd);
  1448. @@ -811,13 +806,13 @@ static int __init init_pmc551(void)
  1449. pci_dev_get(PCI_Device);
  1450. printk(KERN_NOTICE "Registered pmc551 memory device.\n");
  1451. - printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n",
  1452. + printk(KERN_NOTICE "Mapped %dMiB of memory from 0x%p to 0x%p\n",
  1453. priv->asize >> 20,
  1454. priv->start, priv->start + priv->asize);
  1455. - printk(KERN_NOTICE "Total memory is %d%c\n",
  1456. + printk(KERN_NOTICE "Total memory is %d%sB\n",
  1457. (length < 1024) ? length :
  1458. (length < 1048576) ? length >> 10 : length >> 20,
  1459. - (length < 1024) ? 'B' : (length < 1048576) ? 'K' : 'M');
  1460. + (length < 1024) ? "" : (length < 1048576) ? "Ki" : "Mi");
  1461. priv->nextpmc551 = pmc551list;
  1462. pmc551list = mtd;
  1463. found++;
  1464. @@ -850,7 +845,7 @@ static void __exit cleanup_pmc551(void)
  1465. pmc551list = priv->nextpmc551;
  1466. if (priv->start) {
  1467. - printk(KERN_DEBUG "pmc551: unmapping %dM starting at "
  1468. + printk(KERN_DEBUG "pmc551: unmapping %dMiB starting at "
  1469. "0x%p\n", priv->asize >> 20, priv->start);
  1470. pci_iounmap(priv->dev, priv->start);
  1471. }
  1472. Index: linux-2.6.23.17/drivers/mtd/maps/nettel.c
  1473. ===================================================================
  1474. --- linux-2.6.23.17.orig/drivers/mtd/maps/nettel.c
  1475. +++ linux-2.6.23.17/drivers/mtd/maps/nettel.c
  1476. @@ -158,68 +158,11 @@ static struct notifier_block nettel_noti
  1477. nettel_reboot_notifier, NULL, 0
  1478. };
  1479. -/*
  1480. - * Erase the configuration file system.
  1481. - * Used to support the software reset button.
  1482. - */
  1483. -static void nettel_erasecallback(struct erase_info *done)
  1484. -{
  1485. - wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
  1486. - wake_up(wait_q);
  1487. -}
  1488. -
  1489. -static struct erase_info nettel_erase;
  1490. -
  1491. -int nettel_eraseconfig(void)
  1492. -{
  1493. - struct mtd_info *mtd;
  1494. - DECLARE_WAITQUEUE(wait, current);
  1495. - wait_queue_head_t wait_q;
  1496. - int ret;
  1497. -
  1498. - init_waitqueue_head(&wait_q);
  1499. - mtd = get_mtd_device(NULL, 2);
  1500. - if (!IS_ERR(mtd)) {
  1501. - nettel_erase.mtd = mtd;
  1502. - nettel_erase.callback = nettel_erasecallback;
  1503. - nettel_erase.callback = NULL;
  1504. - nettel_erase.addr = 0;
  1505. - nettel_erase.len = mtd->size;
  1506. - nettel_erase.priv = (u_long) &wait_q;
  1507. - nettel_erase.priv = 0;
  1508. -
  1509. - set_current_state(TASK_INTERRUPTIBLE);
  1510. - add_wait_queue(&wait_q, &wait);
  1511. -
  1512. - ret = mtd->erase(mtd, &nettel_erase);
  1513. - if (ret) {
  1514. - set_current_state(TASK_RUNNING);
  1515. - remove_wait_queue(&wait_q, &wait);
  1516. - put_mtd_device(mtd);
  1517. - return(ret);
  1518. - }
  1519. -
  1520. - schedule(); /* Wait for erase to finish. */
  1521. - remove_wait_queue(&wait_q, &wait);
  1522. -
  1523. - put_mtd_device(mtd);
  1524. - }
  1525. -
  1526. - return(0);
  1527. -}
  1528. -
  1529. -#else
  1530. -
  1531. -int nettel_eraseconfig(void)
  1532. -{
  1533. - return(0);
  1534. -}
  1535. -
  1536. #endif
  1537. /****************************************************************************/
  1538. -int __init nettel_init(void)
  1539. +static int __init nettel_init(void)
  1540. {
  1541. volatile unsigned long *amdpar;
  1542. unsigned long amdaddr, maxsize;
  1543. @@ -421,10 +364,6 @@ int __init nettel_init(void)
  1544. intel_mtd->owner = THIS_MODULE;
  1545. -#ifndef CONFIG_BLK_DEV_INITRD
  1546. - ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 1);
  1547. -#endif
  1548. -
  1549. num_intel_partitions = sizeof(nettel_intel_partitions) /
  1550. sizeof(nettel_intel_partitions[0]);
  1551. @@ -477,7 +416,7 @@ out_unmap2:
  1552. /****************************************************************************/
  1553. -void __exit nettel_cleanup(void)
  1554. +static void __exit nettel_cleanup(void)
  1555. {
  1556. #ifdef CONFIG_MTD_CFI_INTELEXT
  1557. unregister_reboot_notifier(&nettel_notifier_block);
  1558. Index: linux-2.6.23.17/drivers/mtd/maps/pmcmsp-ramroot.c
  1559. ===================================================================
  1560. --- linux-2.6.23.17.orig/drivers/mtd/maps/pmcmsp-ramroot.c
  1561. +++ linux-2.6.23.17/drivers/mtd/maps/pmcmsp-ramroot.c
  1562. @@ -79,7 +79,6 @@ static int __init init_rrmap(void)
  1563. rr_mtd->owner = THIS_MODULE;
  1564. add_mtd_device(rr_mtd);
  1565. - ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, rr_mtd->index);
  1566. return 0;
  1567. }
  1568. Index: linux-2.6.23.17/drivers/mtd/mtd_blkdevs.c
  1569. ===================================================================
  1570. --- linux-2.6.23.17.orig/drivers/mtd/mtd_blkdevs.c
  1571. +++ linux-2.6.23.17/drivers/mtd/mtd_blkdevs.c
  1572. @@ -24,10 +24,9 @@
  1573. #include <linux/kthread.h>
  1574. #include <asm/uaccess.h>
  1575. -static LIST_HEAD(blktrans_majors);
  1576. +#include "mtdcore.h"
  1577. -extern struct mutex mtd_table_mutex;
  1578. -extern struct mtd_info *mtd_table[];
  1579. +static LIST_HEAD(blktrans_majors);
  1580. struct mtd_blkcore_priv {
  1581. struct task_struct *thread;
  1582. @@ -202,7 +201,7 @@ static int blktrans_ioctl(struct inode *
  1583. }
  1584. }
  1585. -struct block_device_operations mtd_blktrans_ops = {
  1586. +static struct block_device_operations mtd_blktrans_ops = {
  1587. .owner = THIS_MODULE,
  1588. .open = blktrans_open,
  1589. .release = blktrans_release,
  1590. Index: linux-2.6.23.17/drivers/mtd/mtdchar.c
  1591. ===================================================================
  1592. --- linux-2.6.23.17.orig/drivers/mtd/mtdchar.c
  1593. +++ linux-2.6.23.17/drivers/mtd/mtdchar.c
  1594. @@ -137,7 +137,8 @@ static int mtd_close(struct inode *inode
  1595. DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
  1596. - if (mtd->sync)
  1597. + /* Only sync if opened RW */
  1598. + if ((file->f_mode & 2) && mtd->sync)
  1599. mtd->sync(mtd);
  1600. put_mtd_device(mtd);
  1601. Index: linux-2.6.23.17/drivers/mtd/mtdcore.c
  1602. ===================================================================
  1603. --- linux-2.6.23.17.orig/drivers/mtd/mtdcore.c
  1604. +++ linux-2.6.23.17/drivers/mtd/mtdcore.c
  1605. @@ -22,6 +22,8 @@
  1606. #include <linux/mtd/mtd.h>
  1607. +#include "mtdcore.h"
  1608. +
  1609. /* These are exported solely for the purpose of mtd_blkdevs.c. You
  1610. should not use them for _anything_ else */
  1611. DEFINE_MUTEX(mtd_table_mutex);
  1612. Index: linux-2.6.23.17/drivers/mtd/nand/Kconfig
  1613. ===================================================================
  1614. --- linux-2.6.23.17.orig/drivers/mtd/nand/Kconfig
  1615. +++ linux-2.6.23.17/drivers/mtd/nand/Kconfig
  1616. @@ -134,10 +134,10 @@ config MTD_NAND_S3C2410_HWECC
  1617. config MTD_NAND_NDFC
  1618. tristate "NDFC NanD Flash Controller"
  1619. - depends on 44x
  1620. + depends on 4xx
  1621. select MTD_NAND_ECC_SMC
  1622. help
  1623. - NDFC Nand Flash Controllers are integrated in EP44x SoCs
  1624. + NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
  1625. config MTD_NAND_S3C2410_CLKSTOP
  1626. bool "S3C2410 NAND IDLE clock stop"
  1627. @@ -237,7 +237,7 @@ config MTD_NAND_CAFE
  1628. select REED_SOLOMON
  1629. select REED_SOLOMON_DEC16
  1630. help
  1631. - Use NAND flash attached to the CAFÉ chip designed for the $100
  1632. + Use NAND flash attached to the CAFÉ chip designed for the OLPC
  1633. laptop.
  1634. config MTD_NAND_CS553X
  1635. Index: linux-2.6.23.17/drivers/mtd/nand/cafe_nand.c
  1636. ===================================================================
  1637. --- linux-2.6.23.17.orig/drivers/mtd/nand/cafe_nand.c
  1638. +++ linux-2.6.23.17/drivers/mtd/nand/cafe_nand.c
  1639. @@ -822,14 +822,53 @@ static struct pci_device_id cafe_nand_tb
  1640. MODULE_DEVICE_TABLE(pci, cafe_nand_tbl);
  1641. +static int cafe_nand_resume(struct pci_dev *pdev)
  1642. +{
  1643. + uint32_t timing1, timing2, timing3;
  1644. + uint32_t ctrl;
  1645. + struct mtd_info *mtd = pci_get_drvdata(pdev);
  1646. + struct cafe_priv *cafe = mtd->priv;
  1647. +
  1648. + timing1 = timing2 = timing3 = 0xffffffff;
  1649. + /* Start off by resetting the NAND controller completely */
  1650. + cafe_writel(cafe, 1, NAND_RESET);
  1651. + cafe_writel(cafe, 0, NAND_RESET);
  1652. + cafe_writel(cafe, timing1, NAND_TIMING1);
  1653. + cafe_writel(cafe, timing2, NAND_TIMING2);
  1654. + cafe_writel(cafe, timing3, NAND_TIMING3);
  1655. + cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
  1656. +
  1657. + /* Disable master reset, enable NAND clock */
  1658. + ctrl = cafe_readl(cafe, GLOBAL_CTRL);
  1659. + ctrl &= 0xffffeff0;
  1660. + ctrl |= 0x00007000;
  1661. + cafe_writel(cafe, ctrl | 0x05, GLOBAL_CTRL);
  1662. + cafe_writel(cafe, ctrl | 0x0a, GLOBAL_CTRL);
  1663. + cafe_writel(cafe, 0, NAND_DMA_CTRL);
  1664. + cafe_writel(cafe, 0x7006, GLOBAL_CTRL);
  1665. + cafe_writel(cafe, 0x700a, GLOBAL_CTRL);
  1666. +
  1667. + /* Set up DMA address */
  1668. + cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0);
  1669. + if (sizeof(cafe->dmaaddr) > 4)
  1670. + /* Shift in two parts to shut the compiler up */
  1671. + cafe_writel(cafe, (cafe->dmaaddr >> 16) >> 16, NAND_DMA_ADDR1);
  1672. + else
  1673. + cafe_writel(cafe, 0, NAND_DMA_ADDR1);
  1674. +
  1675. + /* Enable NAND IRQ in global IRQ mask register */
  1676. + cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
  1677. + return 0;
  1678. +}
  1679. +
  1680. static struct pci_driver cafe_nand_pci_driver = {
  1681. .name = "CAFÉ NAND",
  1682. .id_table = cafe_nand_tbl,
  1683. .probe = cafe_nand_probe,
  1684. .remove = __devexit_p(cafe_nand_remove),
  1685. + .resume = cafe_nand_resume,
  1686. #ifdef CONFIG_PMx
  1687. .suspend = cafe_nand_suspend,
  1688. - .resume = cafe_nand_resume,
  1689. #endif
  1690. };
  1691. Index: linux-2.6.23.17/drivers/mtd/nand/ndfc.c
  1692. ===================================================================
  1693. --- linux-2.6.23.17.orig/drivers/mtd/nand/ndfc.c
  1694. +++ linux-2.6.23.17/drivers/mtd/nand/ndfc.c
  1695. @@ -24,7 +24,11 @@
  1696. #include <linux/platform_device.h>
  1697. #include <asm/io.h>
  1698. +#ifdef CONFIG_40x
  1699. +#include <asm/ibm405.h>
  1700. +#else
  1701. #include <asm/ibm44x.h>
  1702. +#endif
  1703. struct ndfc_nand_mtd {
  1704. struct mtd_info mtd;
  1705. @@ -230,7 +234,11 @@ static int ndfc_nand_probe(struct platfo
  1706. struct ndfc_controller *ndfc = &ndfc_ctrl;
  1707. unsigned long long phys = settings->ndfc_erpn | res->start;
  1708. +#ifndef CONFIG_PHYS_64BIT
  1709. + ndfc->ndfcbase = ioremap((phys_addr_t)phys, res->end - res->start + 1);
  1710. +#else
  1711. ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1);
  1712. +#endif
  1713. if (!ndfc->ndfcbase) {
  1714. printk(KERN_ERR "NDFC: ioremap failed\n");
  1715. return -EIO;
  1716. Index: linux-2.6.23.17/drivers/mtd/onenand/Kconfig
  1717. ===================================================================
  1718. --- linux-2.6.23.17.orig/drivers/mtd/onenand/Kconfig
  1719. +++ linux-2.6.23.17/drivers/mtd/onenand/Kconfig
  1720. @@ -40,4 +40,27 @@ config MTD_ONENAND_OTP
  1721. OTP block is fully-guaranteed to be a valid block.
  1722. +config MTD_ONENAND_2X_PROGRAM
  1723. + bool "OneNAND 2X program support"
  1724. + help
  1725. + The 2X Program is an extension of Program Operation.
  1726. + Since the device is equipped with two DataRAMs, and two-plane NAND
  1727. + Flash memory array, these two component enables simultaneous program
  1728. + of 4KiB. Plane1 has only even blocks such as block0, block2, block4
  1729. + while Plane2 has only odd blocks such as block1, block3, block5.
  1730. + So MTD regards it as 4KiB page size and 256KiB block size
  1731. +
  1732. + Now the following chips support it. (KFXXX16Q2M)
  1733. + Demux: KFG2G16Q2M, KFH4G16Q2M, KFW8G16Q2M,
  1734. + Mux: KFM2G16Q2M, KFN4G16Q2M,
  1735. +
  1736. + And more recent chips
  1737. +
  1738. +config MTD_ONENAND_SIM
  1739. + tristate "OneNAND simulator support"
  1740. + depends on MTD_PARTITIONS
  1741. + help
  1742. + The simulator may simulate various OneNAND flash chips for the
  1743. + OneNAND MTD layer.
  1744. +
  1745. endif # MTD_ONENAND
  1746. Index: linux-2.6.23.17/drivers/mtd/onenand/Makefile
  1747. ===================================================================
  1748. --- linux-2.6.23.17.orig/drivers/mtd/onenand/Makefile
  1749. +++ linux-2.6.23.17/drivers/mtd/onenand/Makefile
  1750. @@ -8,4 +8,7 @@ obj-$(CONFIG_MTD_ONENAND) += onenand.o
  1751. # Board specific.
  1752. obj-$(CONFIG_MTD_ONENAND_GENERIC) += generic.o
  1753. +# Simulator
  1754. +obj-$(CONFIG_MTD_ONENAND_SIM) += onenand_sim.o
  1755. +
  1756. onenand-objs = onenand_base.o onenand_bbt.o
  1757. Index: linux-2.6.23.17/drivers/mtd/onenand/onenand_base.c
  1758. ===================================================================
  1759. --- linux-2.6.23.17.orig/drivers/mtd/onenand/onenand_base.c
  1760. +++ linux-2.6.23.17/drivers/mtd/onenand/onenand_base.c
  1761. @@ -206,6 +206,15 @@ static int onenand_command(struct mtd_in
  1762. default:
  1763. block = (int) (addr >> this->erase_shift);
  1764. page = (int) (addr >> this->page_shift);
  1765. +
  1766. + if (ONENAND_IS_2PLANE(this)) {
  1767. + /* Make the even block number */
  1768. + block &= ~1;
  1769. + /* Is it the odd plane? */
  1770. + if (addr & this->writesize)
  1771. + block++;
  1772. + page >>= 1;
  1773. + }
  1774. page &= this->page_mask;
  1775. break;
  1776. }
  1777. @@ -216,8 +225,12 @@ static int onenand_command(struct mtd_in
  1778. value = onenand_bufferram_address(this, block);
  1779. this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
  1780. - /* Switch to the next data buffer */
  1781. - ONENAND_SET_NEXT_BUFFERRAM(this);
  1782. + if (ONENAND_IS_2PLANE(this))
  1783. + /* It is always BufferRAM0 */
  1784. + ONENAND_SET_BUFFERRAM0(this);
  1785. + else
  1786. + /* Switch to the next data buffer */
  1787. + ONENAND_SET_NEXT_BUFFERRAM(this);
  1788. return 0;
  1789. }
  1790. @@ -247,6 +260,8 @@ static int onenand_command(struct mtd_in
  1791. break;
  1792. default:
  1793. + if (ONENAND_IS_2PLANE(this) && cmd == ONENAND_CMD_PROG)
  1794. + cmd = ONENAND_CMD_2X_PROG;
  1795. dataram = ONENAND_CURRENT_BUFFERRAM(this);
  1796. break;
  1797. }
  1798. @@ -445,8 +460,9 @@ static inline int onenand_bufferram_offs
  1799. struct onenand_chip *this = mtd->priv;
  1800. if (ONENAND_CURRENT_BUFFERRAM(this)) {
  1801. + /* Note: the 'this->writesize' is a real page size */
  1802. if (area == ONENAND_DATARAM)
  1803. - return mtd->writesize;
  1804. + return this->writesize;
  1805. if (area == ONENAND_SPARERAM)
  1806. return mtd->oobsize;
  1807. }
  1808. @@ -572,6 +588,30 @@ static int onenand_write_bufferram(struc
  1809. }
  1810. /**
  1811. + * onenand_get_2x_blockpage - [GENERIC] Get blockpage at 2x program mode
  1812. + * @param mtd MTD data structure
  1813. + * @param addr address to check
  1814. + * @return blockpage address
  1815. + *
  1816. + * Get blockpage address at 2x program mode
  1817. + */
  1818. +static int onenand_get_2x_blockpage(struct mtd_info *mtd, loff_t addr)
  1819. +{
  1820. + struct onenand_chip *this = mtd->priv;
  1821. + int blockpage, block, page;
  1822. +
  1823. + /* Calculate the even block number */
  1824. + block = (int) (addr >> this->erase_shift) & ~1;
  1825. + /* Is it the odd plane? */
  1826. + if (addr & this->writesize)
  1827. + block++;
  1828. + page = (int) (addr >> (this->page_shift + 1)) & this->page_mask;
  1829. + blockpage = (block << 7) | page;
  1830. +
  1831. + return blockpage;
  1832. +}
  1833. +
  1834. +/**
  1835. * onenand_check_bufferram - [GENERIC] Check BufferRAM information
  1836. * @param mtd MTD data structure
  1837. * @param addr address to check
  1838. @@ -585,7 +625,10 @@ static int onenand_check_bufferram(struc
  1839. int blockpage, found = 0;
  1840. unsigned int i;
  1841. - blockpage = (int) (addr >> this->page_shift);
  1842. + if (ONENAND_IS_2PLANE(this))
  1843. + blockpage = onenand_get_2x_blockpage(mtd, addr);
  1844. + else
  1845. + blockpage = (int) (addr >> this->page_shift);
  1846. /* Is there valid data? */
  1847. i = ONENAND_CURRENT_BUFFERRAM(this);
  1848. @@ -625,7 +668,10 @@ static void onenand_update_bufferram(str
  1849. int blockpage;
  1850. unsigned int i;
  1851. - blockpage = (int) (addr >> this->page_shift);
  1852. + if (ONENAND_IS_2PLANE(this))
  1853. + blockpage = onenand_get_2x_blockpage(mtd, addr);
  1854. + else
  1855. + blockpage = (int) (addr >> this->page_shift);
  1856. /* Invalidate another BufferRAM */
  1857. i = ONENAND_NEXT_BUFFERRAM(this);
  1858. @@ -734,6 +780,7 @@ static int onenand_read(struct mtd_info
  1859. int read = 0, column;
  1860. int thislen;
  1861. int ret = 0, boundary = 0;
  1862. + int writesize = this->writesize;
  1863. DEBUG(MTD_DEBUG_LEVEL3, "onenand_read: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
  1864. @@ -754,22 +801,22 @@ static int onenand_read(struct mtd_info
  1865. /* Do first load to bufferRAM */
  1866. if (read < len) {
  1867. if (!onenand_check_bufferram(mtd, from)) {
  1868. - this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
  1869. + this->command(mtd, ONENAND_CMD_READ, from, writesize);
  1870. ret = this->wait(mtd, FL_READING);
  1871. onenand_update_bufferram(mtd, from, !ret);
  1872. }
  1873. }
  1874. - thislen = min_t(int, mtd->writesize, len - read);
  1875. - column = from & (mtd->writesize - 1);
  1876. - if (column + thislen > mtd->writesize)
  1877. - thislen = mtd->writesize - column;
  1878. + thislen = min_t(int, writesize, len - read);
  1879. + column = from & (writesize - 1);
  1880. + if (column + thislen > writesize)
  1881. + thislen = writesize - column;
  1882. while (!ret) {
  1883. /* If there is more to load then start next load */
  1884. from += thislen;
  1885. if (read + thislen < len) {
  1886. - this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
  1887. + this->command(mtd, ONENAND_CMD_READ, from, writesize);
  1888. /*
  1889. * Chip boundary handling in DDP
  1890. * Now we issued chip 1 read and pointed chip 1
  1891. @@ -794,7 +841,7 @@ static int onenand_read(struct mtd_info
  1892. this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2);
  1893. ONENAND_SET_NEXT_BUFFERRAM(this);
  1894. buf += thislen;
  1895. - thislen = min_t(int, mtd->writesize, len - read);
  1896. + thislen = min_t(int, writesize, len - read);
  1897. column = 0;
  1898. cond_resched();
  1899. /* Now wait for load */
  1900. @@ -1079,7 +1126,7 @@ int onenand_bbt_read_oob(struct mtd_info
  1901. /* Read more? */
  1902. if (read < len) {
  1903. /* Update Page size */
  1904. - from += mtd->writesize;
  1905. + from += this->writesize;
  1906. column = 0;
  1907. }
  1908. }
  1909. @@ -1135,12 +1182,12 @@ static int onenand_verify(struct mtd_inf
  1910. int thislen, column;
  1911. while (len != 0) {
  1912. - thislen = min_t(int, mtd->writesize, len);
  1913. - column = addr & (mtd->writesize - 1);
  1914. - if (column + thislen > mtd->writesize)
  1915. - thislen = mtd->writesize - column;
  1916. + thislen = min_t(int, this->writesize, len);
  1917. + column = addr & (this->writesize - 1);
  1918. + if (column + thislen > this->writesize)
  1919. + thislen = this->writesize - column;
  1920. - this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
  1921. + this->command(mtd, ONENAND_CMD_READ, addr, this->writesize);
  1922. onenand_update_bufferram(mtd, addr, 0);
  1923. @@ -1236,6 +1283,10 @@ static int onenand_write(struct mtd_info
  1924. /* In partial page write we don't update bufferram */
  1925. onenand_update_bufferram(mtd, to, !ret && !subpage);
  1926. + if (ONENAND_IS_2PLANE(this)) {
  1927. + ONENAND_SET_BUFFERRAM1(this);
  1928. + onenand_update_bufferram(mtd, to + this->writesize, !ret && !subpage);
  1929. + }
  1930. if (ret) {
  1931. printk(KERN_ERR "onenand_write: write filaed %d\n", ret);
  1932. @@ -1384,6 +1435,10 @@ static int onenand_do_write_oob(struct m
  1933. this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);
  1934. onenand_update_bufferram(mtd, to, 0);
  1935. + if (ONENAND_IS_2PLANE(this)) {
  1936. + ONENAND_SET_BUFFERRAM1(this);
  1937. + onenand_update_bufferram(mtd, to + this->writesize, 0);
  1938. + }
  1939. ret = this->wait(mtd, FL_WRITING);
  1940. if (ret) {
  1941. @@ -2107,6 +2162,7 @@ static int onenand_lock_user_prot_reg(st
  1942. *
  1943. * Check and set OneNAND features
  1944. * - lock scheme
  1945. + * - two plane
  1946. */
  1947. static void onenand_check_features(struct mtd_info *mtd)
  1948. {
  1949. @@ -2118,19 +2174,35 @@ static void onenand_check_features(struc
  1950. process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT;
  1951. /* Lock scheme */
  1952. - if (density >= ONENAND_DEVICE_DENSITY_1Gb) {
  1953. + switch (density) {
  1954. + case ONENAND_DEVICE_DENSITY_4Gb:
  1955. + this->options |= ONENAND_HAS_2PLANE;
  1956. +
  1957. + case ONENAND_DEVICE_DENSITY_2Gb:
  1958. + /* 2Gb DDP don't have 2 plane */
  1959. + if (!ONENAND_IS_DDP(this))
  1960. + this->options |= ONENAND_HAS_2PLANE;
  1961. + this->options |= ONENAND_HAS_UNLOCK_ALL;
  1962. +
  1963. + case ONENAND_DEVICE_DENSITY_1Gb:
  1964. /* A-Die has all block unlock */
  1965. - if (process) {
  1966. - printk(KERN_DEBUG "Chip support all block unlock\n");
  1967. + if (process)
  1968. this->options |= ONENAND_HAS_UNLOCK_ALL;
  1969. - }
  1970. - } else {
  1971. - /* Some OneNAND has continues lock scheme */
  1972. - if (!process) {
  1973. - printk(KERN_DEBUG "Lock scheme is Continues Lock\n");
  1974. + break;
  1975. +
  1976. + default:
  1977. + /* Some OneNAND has continuous lock scheme */
  1978. + if (!process)
  1979. this->options |= ONENAND_HAS_CONT_LOCK;
  1980. - }
  1981. + break;
  1982. }
  1983. +
  1984. + if (this->options & ONENAND_HAS_CONT_LOCK)
  1985. + printk(KERN_DEBUG "Lock scheme is Continuous Lock\n");
  1986. + if (this->options & ONENAND_HAS_UNLOCK_ALL)
  1987. + printk(KERN_DEBUG "Chip support all block unlock\n");
  1988. + if (this->options & ONENAND_HAS_2PLANE)
  1989. + printk(KERN_DEBUG "Chip has 2 plane\n");
  1990. }
  1991. /**
  1992. @@ -2257,6 +2329,8 @@ static int onenand_probe(struct mtd_info
  1993. this->erase_shift = ffs(mtd->erasesize) - 1;
  1994. this->page_shift = ffs(mtd->writesize) - 1;
  1995. this->page_mask = (1 << (this->erase_shift - this->page_shift)) - 1;
  1996. + /* It's real page size */
  1997. + this->writesize = mtd->writesize;
  1998. /* REVIST: Multichip handling */
  1999. @@ -2265,6 +2339,17 @@ static int onenand_probe(struct mtd_info
  2000. /* Check OneNAND features */
  2001. onenand_check_features(mtd);
  2002. + /*
  2003. + * We emulate the 4KiB page and 256KiB erase block size
  2004. + * But oobsize is still 64 bytes.
  2005. + * It is only valid if you turn on 2X program support,
  2006. + * Otherwise it will be ignored by compiler.
  2007. + */
  2008. + if (ONENAND_IS_2PLANE(this)) {
  2009. + mtd->writesize <<= 1;
  2010. + mtd->erasesize <<= 1;
  2011. + }
  2012. +
  2013. return 0;
  2014. }
  2015. Index: linux-2.6.23.17/drivers/pci/quirks.c
  2016. ===================================================================
  2017. --- linux-2.6.23.17.orig/drivers/pci/quirks.c
  2018. +++ linux-2.6.23.17/drivers/pci/quirks.c
  2019. @@ -1396,6 +1396,17 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN
  2020. DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm);
  2021. /*
  2022. + * According to Tom Sylla, the Geode does not support PCI power management
  2023. + * transition, so we shouldn't need the D3hot delay.
  2024. + */
  2025. +static void __init quirk_geode_pci_pm(struct pci_dev *dev)
  2026. +{
  2027. + pci_pm_d3_delay = 0;
  2028. +}
  2029. +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, quirk_geode_pci_pm);
  2030. +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_geode_pci_pm);
  2031. +
  2032. +/*
  2033. * Toshiba TC86C001 IDE controller reports the standard 8-byte BAR0 size
  2034. * but the PIO transfers won't work if BAR0 falls at the odd 8 bytes.
  2035. * Re-allocate the region if needed...
  2036. Index: linux-2.6.23.17/drivers/video/Kconfig
  2037. ===================================================================
  2038. --- linux-2.6.23.17.orig/drivers/video/Kconfig
  2039. +++ linux-2.6.23.17/drivers/video/Kconfig
  2040. @@ -594,7 +594,7 @@ config FB_TGA
  2041. config FB_VESA
  2042. bool "VESA VGA graphics support"
  2043. - depends on (FB = y) && X86
  2044. + depends on (FB = y) && X86 && !VGA_NOPROBE
  2045. select FB_CFB_FILLRECT
  2046. select FB_CFB_COPYAREA
  2047. select FB_CFB_IMAGEBLIT
  2048. @@ -1028,7 +1028,7 @@ config FB_CARILLO_RANCH
  2049. config FB_INTEL
  2050. tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G support (EXPERIMENTAL)"
  2051. - depends on FB && EXPERIMENTAL && PCI && X86
  2052. + depends on FB && EXPERIMENTAL && PCI && X86 && !VGA_NOPROBE
  2053. select AGP
  2054. select AGP_INTEL
  2055. select FB_MODE_HELPERS
  2056. @@ -1383,7 +1383,7 @@ config FB_SAVAGE_ACCEL
  2057. config FB_SIS
  2058. tristate "SiS/XGI display support"
  2059. - depends on FB && PCI
  2060. + depends on FB && PCI && !VGA_NOPROBE
  2061. select FB_CFB_FILLRECT
  2062. select FB_CFB_COPYAREA
  2063. select FB_CFB_IMAGEBLIT
  2064. @@ -1822,6 +1822,15 @@ config FB_PS3_DEFAULT_SIZE_M
  2065. The default value can be overridden on the kernel command line
  2066. using the "ps3fb" option (e.g. "ps3fb=9M");
  2067. +config FB_OLPC_DCON
  2068. + tristate "One Laptop Per Child Display CONtroller support"
  2069. + depends on OLPC
  2070. + select I2C
  2071. + ---help---
  2072. + Add support for the OLPC DCON controller. This controller is only
  2073. + available on OLPC platforms. Unless you have one of these
  2074. + platforms, you will want to say 'N'.
  2075. +
  2076. config FB_XILINX
  2077. tristate "Xilinx frame buffer support"
  2078. depends on FB && XILINX_VIRTEX
  2079. Index: linux-2.6.23.17/drivers/video/Makefile
  2080. ===================================================================
  2081. --- linux-2.6.23.17.orig/drivers/video/Makefile
  2082. +++ linux-2.6.23.17/drivers/video/Makefile
  2083. @@ -111,6 +111,7 @@ obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx
  2084. obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
  2085. obj-$(CONFIG_FB_PS3) += ps3fb.o
  2086. obj-$(CONFIG_FB_SM501) += sm501fb.o
  2087. +obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon.o
  2088. obj-$(CONFIG_FB_XILINX) += xilinxfb.o
  2089. obj-$(CONFIG_FB_OMAP) += omap/
  2090. Index: linux-2.6.23.17/drivers/video/fbmem.c
  2091. ===================================================================
  2092. --- linux-2.6.23.17.orig/drivers/video/fbmem.c
  2093. +++ linux-2.6.23.17/drivers/video/fbmem.c
  2094. @@ -820,6 +820,53 @@ static void try_to_load(int fb)
  2095. #endif /* CONFIG_KMOD */
  2096. int
  2097. +fb_powerup(struct fb_info *info)
  2098. +{
  2099. + int ret = 0;
  2100. +
  2101. + if (!info || info->state == FBINFO_STATE_RUNNING)
  2102. + return 0;
  2103. +
  2104. + if (info->fbops->fb_powerup)
  2105. + ret = info->fbops->fb_powerup(info);
  2106. +
  2107. + if (!ret) {
  2108. + acquire_console_sem();
  2109. + fb_set_suspend(info, 0);
  2110. + release_console_sem();
  2111. + }
  2112. +
  2113. + return ret;
  2114. +}
  2115. +
  2116. +int
  2117. +fb_powerdown(struct fb_info *info)
  2118. +{
  2119. + int ret = 0;
  2120. +
  2121. + if (!info || info->state == FBINFO_STATE_SUSPENDED)
  2122. + return 0;
  2123. +
  2124. + /* Tell everybody that the fbdev is going down */
  2125. + acquire_console_sem();
  2126. + fb_set_suspend(info, 1);
  2127. + release_console_sem();
  2128. +
  2129. + if (info->fbops->fb_powerdown)
  2130. + ret = info->fbops->fb_powerdown(info);
  2131. +
  2132. + /* If the power down failed, then un-notify */
  2133. +
  2134. + if (ret) {
  2135. + acquire_console_sem();
  2136. + fb_set_suspend(info, 0);
  2137. + release_console_sem();
  2138. + }
  2139. +
  2140. + return ret;
  2141. +}
  2142. +
  2143. +int
  2144. fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
  2145. {
  2146. struct fb_fix_screeninfo *fix = &info->fix;
  2147. Index: linux-2.6.23.17/drivers/video/geode/Makefile
  2148. ===================================================================
  2149. --- linux-2.6.23.17.orig/drivers/video/geode/Makefile
  2150. +++ linux-2.6.23.17/drivers/video/geode/Makefile
  2151. @@ -5,5 +5,5 @@ obj-$(CONFIG_FB_GEODE_GX) += gxfb.o
  2152. obj-$(CONFIG_FB_GEODE_LX) += lxfb.o
  2153. gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o
  2154. -gxfb-objs := gxfb_core.o display_gx.o video_gx.o
  2155. +gxfb-objs := gxfb_core.o display_gx.o video_gx.o suspend_gx.o
  2156. lxfb-objs := lxfb_core.o lxfb_ops.o
  2157. Index: linux-2.6.23.17/drivers/video/geode/display_gx.c
  2158. ===================================================================
  2159. --- linux-2.6.23.17.orig/drivers/video/geode/display_gx.c
  2160. +++ linux-2.6.23.17/drivers/video/geode/display_gx.c
  2161. @@ -11,26 +11,44 @@
  2162. * Free Software Foundation; either version 2 of the License, or * (at your
  2163. * option) any later version.
  2164. */
  2165. +
  2166. +#include <linux/kernel.h>
  2167. #include <linux/spinlock.h>
  2168. #include <linux/fb.h>
  2169. #include <linux/delay.h>
  2170. #include <asm/io.h>
  2171. #include <asm/div64.h>
  2172. #include <asm/delay.h>
  2173. +#include <asm/olpc.h>
  2174. #include "geodefb.h"
  2175. #include "display_gx.h"
  2176. -#ifdef CONFIG_FB_GEODE_GX_SET_FBSIZE
  2177. -unsigned int gx_frame_buffer_size(void)
  2178. +static inline void rmwl(u32 val, u32 *reg)
  2179. {
  2180. - return CONFIG_FB_GEODE_GX_FBSIZE;
  2181. + u32 in = readl(reg);
  2182. + if (in != val)
  2183. + writel(val, reg);
  2184. }
  2185. -#else
  2186. +
  2187. unsigned int gx_frame_buffer_size(void)
  2188. {
  2189. unsigned int val;
  2190. +#ifdef CONFIG_OLPC
  2191. + if (machine_is_olpc() && !olpc_has_vsa()) {
  2192. + u32 hi,lo;
  2193. + rdmsr(GLIU0_P2D_RO0, lo, hi);
  2194. +
  2195. + /* Top page number */
  2196. + val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20);
  2197. +
  2198. + val -= (lo & 0x000fffff); /* Subtract bottom page number */
  2199. + val += 1; /* Adjust page count */
  2200. + return (val << 12);
  2201. + }
  2202. +#endif
  2203. +
  2204. /* FB size is reported by a virtual register */
  2205. /* Virtual register class = 0x02 */
  2206. /* VG_MEM_SIZE(512Kb units) = 0x00 */
  2207. @@ -41,7 +59,6 @@ unsigned int gx_frame_buffer_size(void)
  2208. val = (unsigned int)(inw(0xAC1E)) & 0xFFl;
  2209. return (val << 19);
  2210. }
  2211. -#endif
  2212. int gx_line_delta(int xres, int bpp)
  2213. {
  2214. @@ -63,23 +80,23 @@ static void gx_set_mode(struct fb_info *
  2215. gcfg = readl(par->dc_regs + DC_GENERAL_CFG);
  2216. dcfg = readl(par->dc_regs + DC_DISPLAY_CFG);
  2217. - /* Disable the timing generator. */
  2218. - dcfg &= ~(DC_DCFG_TGEN);
  2219. - writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
  2220. -
  2221. - /* Wait for pending memory requests before disabling the FIFO load. */
  2222. - udelay(100);
  2223. -
  2224. - /* Disable FIFO load and compression. */
  2225. - gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
  2226. - writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
  2227. -
  2228. - /* Setup DCLK and its divisor. */
  2229. - par->vid_ops->set_dclk(info);
  2230. -
  2231. - /*
  2232. - * Setup new mode.
  2233. - */
  2234. + /* Programming the clock is costly and ugly, so avoid if if we can */
  2235. +
  2236. + if (par->curdclk != info->var.pixclock) {
  2237. + /* Disable the timing generator. */
  2238. + dcfg &= ~(DC_DCFG_TGEN);
  2239. + writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
  2240. +
  2241. + /* Wait for pending memory requests before disabling the FIFO load. */
  2242. + udelay(100);
  2243. +
  2244. + /* Disable FIFO load and compression. */
  2245. + gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
  2246. + writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
  2247. +
  2248. + /* Setup DCLK and its divisor. */
  2249. + par->vid_ops->set_dclk(info);
  2250. + }
  2251. /* Clear all unused feature bits. */
  2252. gcfg &= DC_GCFG_YUVM | DC_GCFG_VDSE;
  2253. @@ -90,12 +107,13 @@ static void gx_set_mode(struct fb_info *
  2254. gcfg |= (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE;
  2255. /* Framebuffer start offset. */
  2256. - writel(0, par->dc_regs + DC_FB_ST_OFFSET);
  2257. + rmwl(0, par->dc_regs + DC_FB_ST_OFFSET);
  2258. /* Line delta and line buffer length. */
  2259. - writel(info->fix.line_length >> 3, par->dc_regs + DC_GFX_PITCH);
  2260. - writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
  2261. - par->dc_regs + DC_LINE_SIZE);
  2262. + rmwl(info->fix.line_length >> 3, par->dc_regs + DC_GFX_PITCH);
  2263. +
  2264. + rmwl(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
  2265. + par->dc_regs + DC_LINE_SIZE);
  2266. /* Enable graphics and video data and unmask address lines. */
  2267. @@ -134,17 +152,16 @@ static void gx_set_mode(struct fb_info *
  2268. vblankend = vsyncend + info->var.upper_margin;
  2269. vtotal = vblankend;
  2270. - writel((hactive - 1) | ((htotal - 1) << 16), par->dc_regs + DC_H_ACTIVE_TIMING);
  2271. - writel((hblankstart - 1) | ((hblankend - 1) << 16), par->dc_regs + DC_H_BLANK_TIMING);
  2272. - writel((hsyncstart - 1) | ((hsyncend - 1) << 16), par->dc_regs + DC_H_SYNC_TIMING);
  2273. -
  2274. - writel((vactive - 1) | ((vtotal - 1) << 16), par->dc_regs + DC_V_ACTIVE_TIMING);
  2275. - writel((vblankstart - 1) | ((vblankend - 1) << 16), par->dc_regs + DC_V_BLANK_TIMING);
  2276. - writel((vsyncstart - 1) | ((vsyncend - 1) << 16), par->dc_regs + DC_V_SYNC_TIMING);
  2277. + rmwl((hactive - 1) | ((htotal - 1) << 16), par->dc_regs + DC_H_ACTIVE_TIMING);
  2278. + rmwl((hblankstart - 1) | ((hblankend - 1) << 16), par->dc_regs + DC_H_BLANK_TIMING);
  2279. + rmwl((hsyncstart - 1) | ((hsyncend - 1) << 16), par->dc_regs + DC_H_SYNC_TIMING);
  2280. + rmwl((vactive - 1) | ((vtotal - 1) << 16), par->dc_regs + DC_V_ACTIVE_TIMING);
  2281. + rmwl((vblankstart - 1) | ((vblankend - 1) << 16), par->dc_regs + DC_V_BLANK_TIMING);
  2282. + rmwl((vsyncstart - 1) | ((vsyncend - 1) << 16), par->dc_regs + DC_V_SYNC_TIMING);
  2283. /* Write final register values. */
  2284. - writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
  2285. - writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
  2286. + rmwl(dcfg, par->dc_regs + DC_DISPLAY_CFG);
  2287. + rmwl(gcfg, par->dc_regs + DC_GENERAL_CFG);
  2288. par->vid_ops->configure_display(info);
  2289. Index: linux-2.6.23.17/drivers/video/geode/display_gx.h
  2290. ===================================================================
  2291. --- linux-2.6.23.17.orig/drivers/video/geode/display_gx.h
  2292. +++ linux-2.6.23.17/drivers/video/geode/display_gx.h
  2293. @@ -20,6 +20,9 @@ extern struct geode_dc_ops gx_dc_ops;
  2294. #define GLD_MSR_CONFIG 0xC0002001
  2295. #define GLD_MSR_CONFIG_DM_FP 0x40
  2296. +/* Used for memory dection on the OLPC */
  2297. +#define GLIU0_P2D_RO0 0x10000029
  2298. +
  2299. /* Display controller registers */
  2300. #define DC_UNLOCK 0x00
  2301. Index: linux-2.6.23.17/drivers/video/geode/geodefb.h
  2302. ===================================================================
  2303. --- linux-2.6.23.17.orig/drivers/video/geode/geodefb.h
  2304. +++ linux-2.6.23.17/drivers/video/geode/geodefb.h
  2305. @@ -12,6 +12,10 @@
  2306. #ifndef __GEODEFB_H__
  2307. #define __GEODEFB_H__
  2308. +#define FB_POWER_STATE_OFF 0
  2309. +#define FB_POWER_STATE_SUSPEND 1
  2310. +#define FB_POWER_STATE_ON 2
  2311. +
  2312. struct geodefb_info;
  2313. struct geode_dc_ops {
  2314. @@ -21,18 +25,24 @@ struct geode_dc_ops {
  2315. struct geode_vid_ops {
  2316. void (*set_dclk)(struct fb_info *);
  2317. + unsigned int (*get_dclk)(struct fb_info *);
  2318. void (*configure_display)(struct fb_info *);
  2319. int (*blank_display)(struct fb_info *, int blank_mode);
  2320. };
  2321. struct geodefb_par {
  2322. int enable_crt;
  2323. + int fbactive; /* True if the current console is in KD_GRAPHICS mode */
  2324. int panel_x; /* dimensions of an attached flat panel, non-zero => enable panel */
  2325. int panel_y;
  2326. + unsigned int curdclk; /* Used by GX to avoid unnessesary clock switching */
  2327. void __iomem *dc_regs;
  2328. void __iomem *vid_regs;
  2329. + void __iomem *gp_regs;
  2330. struct geode_dc_ops *dc_ops;
  2331. struct geode_vid_ops *vid_ops;
  2332. +
  2333. + int state;
  2334. };
  2335. #endif /* !__GEODEFB_H__ */
  2336. Index: linux-2.6.23.17/drivers/video/geode/gxfb_core.c
  2337. ===================================================================
  2338. --- linux-2.6.23.17.orig/drivers/video/geode/gxfb_core.c
  2339. +++ linux-2.6.23.17/drivers/video/geode/gxfb_core.c
  2340. @@ -30,12 +30,31 @@
  2341. #include <linux/fb.h>
  2342. #include <linux/init.h>
  2343. #include <linux/pci.h>
  2344. +#include <linux/notifier.h>
  2345. +#include <linux/vt_kern.h>
  2346. +#include <linux/console.h>
  2347. +#include <asm/uaccess.h>
  2348. +#include <asm/olpc.h>
  2349. #include "geodefb.h"
  2350. #include "display_gx.h"
  2351. #include "video_gx.h"
  2352. +#define FBIOSGAMMA _IOW('F', 0x20, void *)
  2353. +#define FBIOGGAMMA _IOW('F', 0x21, void *)
  2354. +
  2355. +#ifdef DEBUG
  2356. +
  2357. +#define FBIODUMPGP _IOW('F', 0x22, void *)
  2358. +#define FBIODUMPDC _IOW('F', 0x23, void *)
  2359. +#define FBIODUMPVP _IOW('F', 0x24, void *)
  2360. +#define FBIODUMPFP _IOW('F', 0x25, void *)
  2361. +
  2362. +#endif
  2363. +
  2364. static char *mode_option;
  2365. +static int noclear;
  2366. +struct fb_info *gxfb_info;
  2367. /* Modes relevant to the GX (taken from modedb.c) */
  2368. static const struct fb_videomode gx_modedb[] __initdata = {
  2369. @@ -103,8 +122,20 @@ static const struct fb_videomode gx_mode
  2370. { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
  2371. FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2372. FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  2373. + /* 1200x900-75 - CRT timings for the OLPC mode */
  2374. + { NULL, 75, 1200, 900, 8049, 104, 240, 29, 54, 136, 3,
  2375. + 0, FB_VMODE_NONINTERLACED, 0 }
  2376. };
  2377. +#ifdef CONFIG_OLPC
  2378. +static const struct fb_videomode gx_dcon_modedb[] __initdata = {
  2379. + /* The only mode the DCON has is 1200x900 */
  2380. + { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
  2381. + 0, FB_VMODE_NONINTERLACED, 0 }
  2382. +};
  2383. +#endif
  2384. +
  2385. +
  2386. static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
  2387. {
  2388. if (var->xres > 1600 || var->yres > 1200)
  2389. @@ -137,7 +168,7 @@ static int gxfb_check_var(struct fb_var_
  2390. return 0;
  2391. }
  2392. -static int gxfb_set_par(struct fb_info *info)
  2393. +int gxfb_set_par(struct fb_info *info)
  2394. {
  2395. struct geodefb_par *par = info->par;
  2396. @@ -204,16 +235,26 @@ static int gxfb_blank(int blank_mode, st
  2397. return par->vid_ops->blank_display(info, blank_mode);
  2398. }
  2399. +static int fbsize;
  2400. +
  2401. static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
  2402. {
  2403. struct geodefb_par *par = info->par;
  2404. - int fb_len;
  2405. int ret;
  2406. ret = pci_enable_device(dev);
  2407. if (ret < 0)
  2408. return ret;
  2409. + ret = pci_request_region(dev, 1, "gxfb (graphics processor)");
  2410. + if (ret < 0)
  2411. + return ret;
  2412. +
  2413. + par->gp_regs = ioremap(pci_resource_start(dev, 1),
  2414. + pci_resource_len(dev, 1));
  2415. + if (!par->gp_regs)
  2416. + return -ENOMEM;
  2417. +
  2418. ret = pci_request_region(dev, 3, "gxfb (video processor)");
  2419. if (ret < 0)
  2420. return ret;
  2421. @@ -232,36 +273,118 @@ static int __init gxfb_map_video_memory(
  2422. ret = pci_request_region(dev, 0, "gxfb (framebuffer)");
  2423. if (ret < 0)
  2424. return ret;
  2425. - if ((fb_len = gx_frame_buffer_size()) < 0)
  2426. - return -ENOMEM;
  2427. +
  2428. + /* If the fbsize wasn't specified then try to probe it */
  2429. +
  2430. + if (!fbsize) {
  2431. + fbsize = gx_frame_buffer_size();
  2432. + if (fbsize == 0)
  2433. + return -ENOMEM;
  2434. + }
  2435. +
  2436. info->fix.smem_start = pci_resource_start(dev, 0);
  2437. - info->fix.smem_len = fb_len;
  2438. + info->fix.smem_len = fbsize;
  2439. info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
  2440. if (!info->screen_base)
  2441. return -ENOMEM;
  2442. - /* Set the 16MB aligned base address of the graphics memory region
  2443. + /* Set the 16MiB aligned base address of the graphics memory region
  2444. * in the display controller */
  2445. writel(info->fix.smem_start & 0xFF000000,
  2446. par->dc_regs + DC_GLIU0_MEM_OFFSET);
  2447. - dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n",
  2448. + dev_info(&dev->dev, "%d KiB of video memory at 0x%lx\n",
  2449. info->fix.smem_len / 1024, info->fix.smem_start);
  2450. return 0;
  2451. }
  2452. +static int gxfb_ioctl( struct fb_info *info, unsigned int cmd,
  2453. + unsigned long arg)
  2454. +{
  2455. + unsigned int gamma[GXFB_GAMMA_DWORDS];
  2456. + int ret = -EINVAL;
  2457. + struct geodefb_par *par = info->par;
  2458. + int i;
  2459. +
  2460. + switch(cmd) {
  2461. + case FBIOSGAMMA:
  2462. + /* Read the gamma information from the user - 256 dwords */
  2463. +
  2464. + if (copy_from_user(gamma, (void * __user) arg, GXFB_GAMMA_SIZE))
  2465. + return -EFAULT;
  2466. +
  2467. + writel(0, par->vid_regs + GX_GAR);
  2468. +
  2469. + /* Sequential writes to the data register will increment the
  2470. + address automatically */
  2471. +
  2472. + for(i = 0; i < GXFB_GAMMA_DWORDS; i++)
  2473. + writel(gamma[i] & 0xFFFFFF, par->vid_regs + GX_GDR);
  2474. +
  2475. + writel(readl(par->vid_regs + GX_MISC) & ~GX_MISC_GAM_EN,
  2476. + par->vid_regs + GX_MISC);
  2477. +
  2478. + ret = 0;
  2479. + break;
  2480. +
  2481. + case FBIOGGAMMA:
  2482. + if (readl(par->vid_regs + GX_MISC) & GX_MISC_GAM_EN)
  2483. + return -EINVAL;
  2484. +
  2485. + memset(gamma, 0, GXFB_GAMMA_SIZE);
  2486. + writel(0, par->vid_regs + GX_GAR);
  2487. +
  2488. + for(i = 0; i < GXFB_GAMMA_DWORDS;i++)
  2489. + gamma[i] = readl(par->vid_regs + GX_GDR);
  2490. +
  2491. + if (copy_to_user((void * __user) arg, gamma, GXFB_GAMMA_SIZE))
  2492. + ret = -EFAULT;
  2493. + else
  2494. + ret = 0;
  2495. +
  2496. + break;
  2497. +
  2498. +#ifdef DEBUG
  2499. + case FBIODUMPGP:
  2500. + ret = 0;
  2501. + dump_regs(info, 0);
  2502. + break;
  2503. +
  2504. + case FBIODUMPDC:
  2505. + ret = 0;
  2506. + dump_regs(info, 1);
  2507. + break;
  2508. +
  2509. + case FBIODUMPVP:
  2510. + ret = 0;
  2511. + dump_regs(info, 2);
  2512. + break;
  2513. +
  2514. + case FBIODUMPFP:
  2515. + ret = 0;
  2516. + dump_regs(info, 3);
  2517. + break;
  2518. +#endif
  2519. + }
  2520. +
  2521. + return ret;
  2522. +}
  2523. +
  2524. static struct fb_ops gxfb_ops = {
  2525. .owner = THIS_MODULE,
  2526. .fb_check_var = gxfb_check_var,
  2527. .fb_set_par = gxfb_set_par,
  2528. .fb_setcolreg = gxfb_setcolreg,
  2529. .fb_blank = gxfb_blank,
  2530. + .fb_ioctl = gxfb_ioctl,
  2531. /* No HW acceleration for now. */
  2532. .fb_fillrect = cfb_fillrect,
  2533. .fb_copyarea = cfb_copyarea,
  2534. .fb_imageblit = cfb_imageblit,
  2535. + .fb_powerdown = gxfb_powerdown,
  2536. + .fb_powerup = gxfb_powerup,
  2537. };
  2538. static struct fb_info * __init gxfb_init_fbinfo(struct device *dev)
  2539. @@ -303,23 +426,86 @@ static struct fb_info * __init gxfb_init
  2540. return info;
  2541. }
  2542. -static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
  2543. +static int gxfb_console_notify(struct notifier_block *self,
  2544. + unsigned long action, void *data)
  2545. +{
  2546. + if (gxfb_info != NULL) {
  2547. + struct geodefb_par *par = gxfb_info->par;
  2548. + par->fbactive = (action == CONSOLE_EVENT_SWITCH_TEXT) ? 0 : 1;
  2549. + }
  2550. +
  2551. + return NOTIFY_OK;
  2552. +}
  2553. +
  2554. +static struct notifier_block gxfb_console_notifier = {
  2555. + .notifier_call = gxfb_console_notify
  2556. +};
  2557. +
  2558. +#ifdef CONFIG_PM
  2559. +
  2560. +static int gxfb_suspend(struct pci_dev *pdev, pm_message_t state)
  2561. +{
  2562. + struct fb_info *info = pci_get_drvdata(pdev);
  2563. + struct geodefb_par *par = info->par;
  2564. +
  2565. + if (pdev->dev.power.power_state.event == state.event)
  2566. + return 0;
  2567. +
  2568. + if (state.event == PM_EVENT_SUSPEND) {
  2569. +
  2570. + acquire_console_sem();
  2571. + gxfb_powerdown(info);
  2572. +
  2573. + par->state = FB_POWER_STATE_OFF;
  2574. + fb_set_suspend(info, 1);
  2575. +
  2576. + release_console_sem();
  2577. + }
  2578. +
  2579. + pdev->dev.power.power_state = state;
  2580. + return 0;
  2581. +}
  2582. +
  2583. +static int gxfb_resume(struct pci_dev *pdev)
  2584. +{
  2585. + struct fb_info *info = pci_get_drvdata(pdev);
  2586. +
  2587. + acquire_console_sem();
  2588. +
  2589. + /* Turn the engine completely on */
  2590. +
  2591. + if (gxfb_powerup(info))
  2592. + printk(KERN_ERR "gxfb: Powerup failed\n");
  2593. +
  2594. + fb_set_suspend(info, 0);
  2595. + release_console_sem();
  2596. +
  2597. + pdev->dev.power.power_state = PMSG_ON;
  2598. + return 0;
  2599. +}
  2600. +#endif
  2601. +
  2602. +static int __init gxfb_probe(struct pci_dev *pdev,
  2603. + const struct pci_device_id *id)
  2604. {
  2605. struct geodefb_par *par;
  2606. - struct fb_info *info;
  2607. int ret;
  2608. unsigned long val;
  2609. - info = gxfb_init_fbinfo(&pdev->dev);
  2610. - if (!info)
  2611. + struct fb_videomode *modedb_ptr;
  2612. + int modedb_size;
  2613. +
  2614. + gxfb_info = gxfb_init_fbinfo(&pdev->dev);
  2615. + if (gxfb_info == NULL)
  2616. return -ENOMEM;
  2617. - par = info->par;
  2618. +
  2619. + par = gxfb_info->par;
  2620. /* GX display controller and GX video device. */
  2621. par->dc_ops = &gx_dc_ops;
  2622. par->vid_ops = &gx_vid_ops;
  2623. - if ((ret = gxfb_map_video_memory(info, pdev)) < 0) {
  2624. + if ((ret = gxfb_map_video_memory(gxfb_info, pdev)) < 0) {
  2625. dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n");
  2626. goto err;
  2627. }
  2628. @@ -333,32 +519,60 @@ static int __init gxfb_probe(struct pci_
  2629. else
  2630. par->enable_crt = 1;
  2631. - ret = fb_find_mode(&info->var, info, mode_option,
  2632. - gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16);
  2633. + /* Get the current dotclock */
  2634. +
  2635. + par->curdclk = (par->vid_ops->get_dclk) ? par->vid_ops->get_dclk(gxfb_info) : 0;
  2636. +
  2637. + /* We need to determine a display mode right now, so we will
  2638. + * check to see if the DCON was previously detected by the BIOS
  2639. + * and use that to make our mode database decision.
  2640. + */
  2641. +
  2642. + modedb_ptr = (struct fb_videomode *) gx_modedb;
  2643. + modedb_size = ARRAY_SIZE(gx_modedb);
  2644. +
  2645. +#ifdef CONFIG_OLPC
  2646. + if (olpc_has_dcon()) {
  2647. + modedb_ptr = (struct fb_videomode *) gx_dcon_modedb;
  2648. + modedb_size = ARRAY_SIZE(gx_dcon_modedb);
  2649. + }
  2650. +#endif
  2651. +
  2652. + ret = fb_find_mode(&gxfb_info->var, gxfb_info, mode_option,
  2653. + modedb_ptr, modedb_size, NULL, 16);
  2654. +
  2655. if (ret == 0 || ret == 4) {
  2656. dev_err(&pdev->dev, "could not find valid video mode\n");
  2657. ret = -EINVAL;
  2658. goto err;
  2659. }
  2660. + /* Clear the screen of garbage, unless noclear was specified,
  2661. + * in which case we assume the user knows what he is doing */
  2662. +
  2663. + if (!noclear)
  2664. + memset_io(gxfb_info->screen_base, 0, gxfb_info->fix.smem_len);
  2665. +
  2666. + gxfb_check_var(&gxfb_info->var, gxfb_info);
  2667. + gxfb_set_par(gxfb_info);
  2668. +
  2669. + /* We are powered up */
  2670. + par->state = FB_POWER_STATE_ON;
  2671. - /* Clear the frame buffer of garbage. */
  2672. - memset_io(info->screen_base, 0, info->fix.smem_len);
  2673. - gxfb_check_var(&info->var, info);
  2674. - gxfb_set_par(info);
  2675. + console_event_register(&gxfb_console_notifier);
  2676. - if (register_framebuffer(info) < 0) {
  2677. + if (register_framebuffer(gxfb_info) < 0) {
  2678. ret = -EINVAL;
  2679. goto err;
  2680. }
  2681. - pci_set_drvdata(pdev, info);
  2682. - printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
  2683. + pci_set_drvdata(pdev, gxfb_info);
  2684. + printk(KERN_INFO "fb%d: %s frame buffer device\n", gxfb_info->node, gxfb_info->fix.id);
  2685. return 0;
  2686. err:
  2687. - if (info->screen_base) {
  2688. - iounmap(info->screen_base);
  2689. + if (gxfb_info->screen_base) {
  2690. + iounmap(gxfb_info->screen_base);
  2691. pci_release_region(pdev, 0);
  2692. }
  2693. if (par->vid_regs) {
  2694. @@ -370,8 +584,9 @@ static int __init gxfb_probe(struct pci_
  2695. pci_release_region(pdev, 2);
  2696. }
  2697. - if (info)
  2698. - framebuffer_release(info);
  2699. + if (gxfb_info)
  2700. + framebuffer_release(gxfb_info);
  2701. +
  2702. return ret;
  2703. }
  2704. @@ -397,9 +612,7 @@ static void gxfb_remove(struct pci_dev *
  2705. }
  2706. static struct pci_device_id gxfb_id_table[] = {
  2707. - { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO,
  2708. - PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
  2709. - 0xff0000, 0 },
  2710. + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO) },
  2711. { 0, }
  2712. };
  2713. @@ -410,22 +623,30 @@ static struct pci_driver gxfb_driver = {
  2714. .id_table = gxfb_id_table,
  2715. .probe = gxfb_probe,
  2716. .remove = gxfb_remove,
  2717. +#ifdef CONFIG_PM
  2718. + .suspend = gxfb_suspend,
  2719. + .resume = gxfb_resume
  2720. +#endif
  2721. };
  2722. #ifndef MODULE
  2723. -static int __init gxfb_setup(char *options)
  2724. -{
  2725. +static int __init gxfb_setup(char *options) {
  2726. char *opt;
  2727. if (!options || !*options)
  2728. return 0;
  2729. - while ((opt = strsep(&options, ",")) != NULL) {
  2730. + while((opt = strsep(&options, ",")) != NULL) {
  2731. if (!*opt)
  2732. continue;
  2733. - mode_option = opt;
  2734. + if (!strncmp(opt, "fbsize:", 7))
  2735. + fbsize = simple_strtoul(opt+7, NULL, 0);
  2736. + else if (!strcmp(opt, "noclear"))
  2737. + noclear = 1;
  2738. + else
  2739. + mode_option = opt;
  2740. }
  2741. return 0;
  2742. @@ -444,7 +665,6 @@ static int __init gxfb_init(void)
  2743. #endif
  2744. return pci_register_driver(&gxfb_driver);
  2745. }
  2746. -
  2747. static void __exit gxfb_cleanup(void)
  2748. {
  2749. pci_unregister_driver(&gxfb_driver);
  2750. @@ -456,5 +676,8 @@ module_exit(gxfb_cleanup);
  2751. module_param(mode_option, charp, 0);
  2752. MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])");
  2753. +module_param(fbsize, int, 0);
  2754. +MODULE_PARM_DESC(fbsize, "video memory size");
  2755. +
  2756. MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX");
  2757. MODULE_LICENSE("GPL");
  2758. Index: linux-2.6.23.17/drivers/video/geode/lxfb.h
  2759. ===================================================================
  2760. --- linux-2.6.23.17.orig/drivers/video/geode/lxfb.h
  2761. +++ linux-2.6.23.17/drivers/video/geode/lxfb.h
  2762. @@ -25,10 +25,23 @@ void lx_set_mode(struct fb_info *);
  2763. void lx_get_gamma(struct fb_info *, unsigned int *, int);
  2764. void lx_set_gamma(struct fb_info *, unsigned int *, int);
  2765. unsigned int lx_framebuffer_size(void);
  2766. +int lx_shutdown(struct fb_info *);
  2767. +int lx_powerup(struct fb_info *);
  2768. int lx_blank_display(struct fb_info *, int);
  2769. void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int,
  2770. unsigned int, unsigned int);
  2771. +
  2772. +
  2773. +/* ioctl() defines */
  2774. +
  2775. +#define FBIOSGAMMA _IOW('F', 0x20, void *)
  2776. +#define FBIOGGAMMA _IOW('F', 0x21, void *)
  2777. +
  2778. +/* General definitions */
  2779. +#define LXFB_GAMMA_DWORDS 256 /* number of dwords in the gamma ram */
  2780. +#define LXFB_GAMMA_SIZE (LXFB_GAMMA_DWORDS * sizeof(unsigned int))
  2781. +
  2782. /* MSRS */
  2783. #define MSR_LX_GLD_CONFIG 0x48002001
  2784. Index: linux-2.6.23.17/drivers/video/geode/lxfb_core.c
  2785. ===================================================================
  2786. --- linux-2.6.23.17.orig/drivers/video/geode/lxfb_core.c
  2787. +++ linux-2.6.23.17/drivers/video/geode/lxfb_core.c
  2788. @@ -22,6 +22,7 @@
  2789. #include <linux/init.h>
  2790. #include <linux/pci.h>
  2791. #include <linux/uaccess.h>
  2792. +#include <asm/olpc.h>
  2793. #include "lxfb.h"
  2794. @@ -35,186 +36,84 @@ static int fbsize;
  2795. */
  2796. const struct fb_videomode geode_modedb[] __initdata = {
  2797. - /* 640x480-60 */
  2798. - { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2,
  2799. + /* 640x480-60 VESA */
  2800. + { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
  2801. + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  2802. + /* 640x480-75 VESA */
  2803. + { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
  2804. + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  2805. + /* 640x480-85 VESA */
  2806. + { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
  2807. + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  2808. + /* 800x600-60 VESA */
  2809. + { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
  2810. + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2811. + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  2812. + /* 800x600-75 VESA */
  2813. + { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
  2814. + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2815. + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  2816. + /* 800x600-85 VESA */
  2817. + { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
  2818. + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2819. + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  2820. + /* 1024x768-60 VESA */
  2821. + { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
  2822. + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  2823. + /* 1024x768-75 VESA */
  2824. + { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
  2825. + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2826. + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  2827. + /* 1024x768-85 VESA */
  2828. + { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
  2829. + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2830. + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  2831. + /* 1280x960-60 VESA */
  2832. + { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
  2833. + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2834. + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  2835. + /* 1280x960-85 VESA */
  2836. + { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
  2837. + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2838. + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  2839. + /* 1280x1024-60 VESA */
  2840. + { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
  2841. + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2842. + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  2843. + /* 1280x1024-75 VESA */
  2844. + { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
  2845. + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2846. + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  2847. + /* 1280x1024-85 VESA */
  2848. + { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
  2849. FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2850. - FB_VMODE_NONINTERLACED, 0 },
  2851. - /* 640x400-70 */
  2852. - { NULL, 70, 640, 400, 39770, 40, 8, 28, 5, 96, 2,
  2853. - FB_SYNC_HOR_HIGH_ACT,
  2854. - FB_VMODE_NONINTERLACED, 0 },
  2855. - /* 640x480-70 */
  2856. - { NULL, 70, 640, 480, 35014, 88, 24, 15, 2, 64, 3,
  2857. - 0, FB_VMODE_NONINTERLACED, 0 },
  2858. - /* 640x480-72 */
  2859. - { NULL, 72, 640, 480, 32102, 120, 16, 20, 1, 40, 3,
  2860. - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2861. - FB_VMODE_NONINTERLACED, 0 },
  2862. - /* 640x480-75 */
  2863. - { NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3,
  2864. - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2865. - FB_VMODE_NONINTERLACED, 0 },
  2866. - /* 640x480-85 */
  2867. - { NULL, 85, 640, 480, 27780, 80, 56, 25, 1, 56, 3,
  2868. - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2869. - FB_VMODE_NONINTERLACED, 0 },
  2870. - /* 640x480-90 */
  2871. - { NULL, 90, 640, 480, 26392, 96, 32, 22, 1, 64, 3,
  2872. - 0, FB_VMODE_NONINTERLACED, 0 },
  2873. - /* 640x480-100 */
  2874. - { NULL, 100, 640, 480, 23167, 104, 40, 25, 1, 64, 3,
  2875. - 0, FB_VMODE_NONINTERLACED, 0 },
  2876. - /* 640x480-60 */
  2877. - { NULL, 60, 640, 480, 39682, 48, 16, 25, 10, 88, 2,
  2878. - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2879. - FB_VMODE_NONINTERLACED, 0 },
  2880. - /* 800x600-56 */
  2881. - { NULL, 56, 800, 600, 27901, 128, 24, 22, 1, 72, 2,
  2882. - 0, FB_VMODE_NONINTERLACED, 0 },
  2883. - /* 800x600-60 */
  2884. - { NULL, 60, 800, 600, 25131, 72, 32, 23, 1, 136, 4,
  2885. - 0, FB_VMODE_NONINTERLACED, 0 },
  2886. - /* 800x600-70 */
  2887. - { NULL, 70, 800, 600, 21873, 120, 40, 21, 4, 80, 3,
  2888. - 0, FB_VMODE_NONINTERLACED, 0 },
  2889. - /* 800x600-72 */
  2890. - { NULL, 72, 800, 600, 20052, 64, 56, 23, 37, 120, 6,
  2891. - 0, FB_VMODE_NONINTERLACED, 0 },
  2892. - /* 800x600-75 */
  2893. - { NULL, 75, 800, 600, 20202, 160, 16, 21, 1, 80, 3,
  2894. - 0, FB_VMODE_NONINTERLACED, 0 },
  2895. - /* 800x600-85 */
  2896. - { NULL, 85, 800, 600, 17790, 152, 32, 27, 1, 64, 3,
  2897. - 0, FB_VMODE_NONINTERLACED, 0 },
  2898. - /* 800x600-90 */
  2899. - { NULL, 90, 800, 600, 16648, 128, 40, 28, 1, 88, 3,
  2900. - 0, FB_VMODE_NONINTERLACED, 0 },
  2901. - /* 800x600-100 */
  2902. - { NULL, 100, 800, 600, 14667, 136, 48, 27, 1, 88, 3,
  2903. - 0, FB_VMODE_NONINTERLACED, 0 },
  2904. - /* 800x600-60 */
  2905. - { NULL, 60, 800, 600, 25131, 88, 40, 23, 1, 128, 4,
  2906. - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2907. - FB_VMODE_NONINTERLACED, 0 },
  2908. - /* 1024x768-60 */
  2909. - { NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
  2910. - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2911. - FB_VMODE_NONINTERLACED, 0 },
  2912. - /* 1024x768-70 */
  2913. - { NULL, 70, 1024, 768, 13346, 144, 24, 29, 3, 136, 6,
  2914. - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2915. - FB_VMODE_NONINTERLACED, 0 },
  2916. - /* 1024x768-72 */
  2917. - { NULL, 72, 1024, 768, 12702, 168, 56, 29, 4, 112, 3,
  2918. - 0, FB_VMODE_NONINTERLACED, 0 },
  2919. - /* 1024x768-75 */
  2920. - { NULL, 75, 1024, 768, 12703, 176, 16, 28, 1, 96, 3,
  2921. - 0, FB_VMODE_NONINTERLACED, 0 },
  2922. - /* 1024x768-85 */
  2923. - { NULL, 85, 1024, 768, 10581, 208, 48, 36, 1, 96, 3,
  2924. - 0, FB_VMODE_NONINTERLACED, 0 },
  2925. - /* 1024x768-90 */
  2926. - { NULL, 90, 1024, 768, 9981, 176, 64, 37, 1, 112, 3,
  2927. - 0, FB_VMODE_NONINTERLACED, 0 },
  2928. - /* 1024x768-100 */
  2929. - { NULL, 100, 1024, 768, 8825, 184, 72, 42, 1, 112, 3,
  2930. - 0, FB_VMODE_NONINTERLACED, 0 },
  2931. - /* 1024x768-60 */
  2932. - { NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
  2933. - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2934. - FB_VMODE_NONINTERLACED, 0 },
  2935. - /* 1152x864-60 */
  2936. - { NULL, 60, 1152, 864, 12251, 184, 64, 27, 1, 120, 3,
  2937. - 0, FB_VMODE_NONINTERLACED, 0 },
  2938. - /* 1152x864-70 */
  2939. - { NULL, 70, 1152, 864, 10254, 192, 72, 32, 8, 120, 3,
  2940. - 0, FB_VMODE_NONINTERLACED, 0 },
  2941. - /* 1152x864-72 */
  2942. - { NULL, 72, 1152, 864, 9866, 200, 72, 33, 7, 128, 3,
  2943. - 0, FB_VMODE_NONINTERLACED, 0 },
  2944. - /* 1152x864-75 */
  2945. - { NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3,
  2946. - 0, FB_VMODE_NONINTERLACED, 0 },
  2947. - /* 1152x864-85 */
  2948. - { NULL, 85, 1152, 864, 8357, 200, 72, 37, 3, 128, 3,
  2949. - 0, FB_VMODE_NONINTERLACED, 0 },
  2950. - /* 1152x864-90 */
  2951. - { NULL, 90, 1152, 864, 7719, 208, 80, 42, 9, 128, 3,
  2952. - 0, FB_VMODE_NONINTERLACED, 0 },
  2953. - /* 1152x864-100 */
  2954. - { NULL, 100, 1152, 864, 6947, 208, 80, 48, 3, 128, 3,
  2955. - 0, FB_VMODE_NONINTERLACED, 0 },
  2956. - /* 1152x864-60 */
  2957. - { NULL, 60, 1152, 864, 12251, 184, 64, 27, 1, 120, 3,
  2958. - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2959. - FB_VMODE_NONINTERLACED, 0 },
  2960. - /* 1280x1024-60 */
  2961. - { NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3,
  2962. - 0, FB_VMODE_NONINTERLACED, 0 },
  2963. - /* 1280x1024-70 */
  2964. - { NULL, 70, 1280, 1024, 7719, 224, 88, 38, 6, 136, 3,
  2965. - 0, FB_VMODE_NONINTERLACED, 0 },
  2966. - /* 1280x1024-72 */
  2967. - { NULL, 72, 1280, 1024, 7490, 224, 88, 39, 7, 136, 3,
  2968. - 0, FB_VMODE_NONINTERLACED, 0 },
  2969. - /* 1280x1024-75 */
  2970. - { NULL, 75, 1280, 1024, 7409, 248, 16, 38, 1, 144, 3,
  2971. - 0, FB_VMODE_NONINTERLACED, 0 },
  2972. - /* 1280x1024-85 */
  2973. - { NULL, 85, 1280, 1024, 6351, 224, 64, 44, 1, 160, 3,
  2974. - 0, FB_VMODE_NONINTERLACED, 0 },
  2975. - /* 1280x1024-90 */
  2976. - { NULL, 90, 1280, 1024, 5791, 240, 96, 51, 12, 144, 3,
  2977. - 0, FB_VMODE_NONINTERLACED, 0 },
  2978. - /* 1280x1024-100 */
  2979. - { NULL, 100, 1280, 1024, 5212, 240, 96, 57, 6, 144, 3,
  2980. - 0, FB_VMODE_NONINTERLACED, 0 },
  2981. - /* 1280x1024-60 */
  2982. - { NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3,
  2983. - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2984. - FB_VMODE_NONINTERLACED, 0 },
  2985. - /* 1600x1200-60 */
  2986. + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  2987. + /* 1600x1200-60 VESA */
  2988. { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
  2989. - 0, FB_VMODE_NONINTERLACED, 0 },
  2990. - /* 1600x1200-70 */
  2991. - { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
  2992. - 0, FB_VMODE_NONINTERLACED, 0 },
  2993. - /* 1600x1200-72 */
  2994. - { NULL, 72, 1600, 1200, 5053, 288, 112, 47, 13, 176, 3,
  2995. - 0, FB_VMODE_NONINTERLACED, 0 },
  2996. - /* 1600x1200-75 */
  2997. + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  2998. + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  2999. + /* 1600x1200-75 VESA */
  3000. { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
  3001. - 0, FB_VMODE_NONINTERLACED, 0 },
  3002. - /* 1600x1200-85 */
  3003. + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  3004. + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  3005. + /* 1600x1200-85 VESA */
  3006. { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
  3007. - 0, FB_VMODE_NONINTERLACED, 0 },
  3008. - /* 1600x1200-90 */
  3009. - { NULL, 90, 1600, 1200, 3981, 304, 128, 60, 1, 176, 3,
  3010. - 0, FB_VMODE_NONINTERLACED, 0 },
  3011. - /* 1600x1200-100 */
  3012. - { NULL, 100, 1600, 1200, 3563, 304, 128, 67, 1, 176, 3,
  3013. - 0, FB_VMODE_NONINTERLACED, 0 },
  3014. - /* 1600x1200-60 */
  3015. - { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
  3016. FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  3017. - FB_VMODE_NONINTERLACED, 0 },
  3018. - /* 1920x1440-60 */
  3019. - { NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 208, 3,
  3020. - 0, FB_VMODE_NONINTERLACED, 0 },
  3021. - /* 1920x1440-70 */
  3022. - { NULL, 70, 1920, 1440, 3593, 360, 152, 55, 8, 208, 3,
  3023. - 0, FB_VMODE_NONINTERLACED, 0 },
  3024. - /* 1920x1440-72 */
  3025. - { NULL, 72, 1920, 1440, 3472, 360, 152, 68, 4, 208, 3,
  3026. - 0, FB_VMODE_NONINTERLACED, 0 },
  3027. - /* 1920x1440-75 */
  3028. - { NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
  3029. - 0, FB_VMODE_NONINTERLACED, 0 },
  3030. - /* 1920x1440-85 */
  3031. - { NULL, 85, 1920, 1440, 2929, 368, 152, 68, 1, 216, 3,
  3032. - 0, FB_VMODE_NONINTERLACED, 0 },
  3033. + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
  3034. + /* 1200x900-75 - CRT timings for the OLPC mode */
  3035. + { NULL, 75, 1200, 900, 8049, 104, 240, 29, 54, 136, 3,
  3036. + 0, FB_VMODE_NONINTERLACED, 0 }
  3037. };
  3038. +#ifdef CONFIG_OLPC
  3039. +const struct fb_videomode olpc_dcon_modedb[] __initdata = {
  3040. + /* The only mode the DCON has is 1200x900 */
  3041. + { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
  3042. + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  3043. + FB_VMODE_NONINTERLACED, 0 }
  3044. +};
  3045. +#endif
  3046. +
  3047. static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
  3048. {
  3049. if (var->xres > 1920 || var->yres > 1440)
  3050. @@ -379,16 +278,55 @@ static int __init lxfb_map_video_memory(
  3051. return 0;
  3052. }
  3053. +static int lxfb_set_gamma(struct fb_info *info, void * __user data)
  3054. +{
  3055. + unsigned int gamma[LXFB_GAMMA_DWORDS];
  3056. +
  3057. + if (copy_from_user(gamma, data, LXFB_GAMMA_SIZE))
  3058. + return -EFAULT;
  3059. +
  3060. + lx_set_gamma(info, gamma, LXFB_GAMMA_SIZE);
  3061. + return 0;
  3062. +}
  3063. +
  3064. +static int lxfb_get_gamma(struct fb_info *info, void * __user data)
  3065. +{
  3066. + unsigned int gamma[LXFB_GAMMA_DWORDS];
  3067. + memset(gamma, 0, sizeof(gamma));
  3068. +
  3069. + lx_get_gamma(info, gamma, LXFB_GAMMA_DWORDS);
  3070. +
  3071. + return copy_to_user(data, gamma, LXFB_GAMMA_SIZE) ?
  3072. + -EFAULT : 0;
  3073. +}
  3074. +
  3075. +static int lxfb_ioctl( struct fb_info *info, unsigned int cmd,
  3076. + unsigned long arg)
  3077. +{
  3078. + switch(cmd) {
  3079. + case FBIOSGAMMA:
  3080. + return lxfb_set_gamma(info, (void * __user) arg);
  3081. +
  3082. + case FBIOGGAMMA:
  3083. + return lxfb_get_gamma(info, (void * __user) arg);
  3084. + }
  3085. +
  3086. + return -ENOTTY;
  3087. +}
  3088. +
  3089. static struct fb_ops lxfb_ops = {
  3090. .owner = THIS_MODULE,
  3091. .fb_check_var = lxfb_check_var,
  3092. .fb_set_par = lxfb_set_par,
  3093. .fb_setcolreg = lxfb_setcolreg,
  3094. .fb_blank = lxfb_blank,
  3095. + .fb_ioctl = lxfb_ioctl,
  3096. /* No HW acceleration for now. */
  3097. .fb_fillrect = cfb_fillrect,
  3098. .fb_copyarea = cfb_copyarea,
  3099. .fb_imageblit = cfb_imageblit,
  3100. + .fb_powerdown = lx_shutdown,
  3101. + .fb_powerup = lx_powerup,
  3102. };
  3103. static struct fb_info * __init lxfb_init_fbinfo(struct device *dev)
  3104. @@ -431,6 +369,45 @@ static struct fb_info * __init lxfb_init
  3105. return info;
  3106. }
  3107. +#ifdef CONFIG_PM
  3108. +
  3109. +static int lxfb_suspend(struct pci_dev *pdev, pm_message_t state)
  3110. +{
  3111. + struct fb_info *info = pci_get_drvdata(pdev);
  3112. +
  3113. + if (pdev->dev.power.power_state.event == state.event)
  3114. + return 0;
  3115. +
  3116. + if (state.event == PM_EVENT_SUSPEND) {
  3117. +
  3118. + acquire_console_sem();
  3119. + lx_shutdown(info);
  3120. + fb_set_suspend(info, 1);
  3121. + release_console_sem();
  3122. + }
  3123. +
  3124. + pdev->dev.power.power_state = state;
  3125. + return 0;
  3126. +}
  3127. +
  3128. +static int lxfb_resume(struct pci_dev *pdev)
  3129. +{
  3130. + struct fb_info *info = pci_get_drvdata(pdev);
  3131. +
  3132. + acquire_console_sem();
  3133. +
  3134. + /* Turn the engine completely on */
  3135. +
  3136. + lx_powerup(info);
  3137. + fb_set_suspend(info, 0);
  3138. + release_console_sem();
  3139. +
  3140. + pdev->dev.power.power_state = PMSG_ON;
  3141. + return 0;
  3142. +}
  3143. +
  3144. +#endif
  3145. +
  3146. static int __init lxfb_probe(struct pci_dev *pdev,
  3147. const struct pci_device_id *id)
  3148. {
  3149. @@ -467,6 +444,13 @@ static int __init lxfb_probe(struct pci_
  3150. modedb_ptr = (struct fb_videomode *) geode_modedb;
  3151. modedb_size = ARRAY_SIZE(geode_modedb);
  3152. +#ifdef CONFIG_OLPC
  3153. + if (olpc_has_dcon()) {
  3154. + modedb_ptr = (struct fb_videomode *) olpc_dcon_modedb;
  3155. + modedb_size = ARRAY_SIZE(olpc_dcon_modedb);
  3156. + }
  3157. +#endif
  3158. +
  3159. ret = fb_find_mode(&info->var, info, mode_option,
  3160. modedb_ptr, modedb_size, NULL, 16);
  3161. @@ -556,6 +540,10 @@ static struct pci_driver lxfb_driver = {
  3162. .id_table = lxfb_id_table,
  3163. .probe = lxfb_probe,
  3164. .remove = lxfb_remove,
  3165. +#ifdef CONFIG_PM
  3166. + .suspend = lxfb_suspend,
  3167. + .resume = lxfb_resume
  3168. +#endif
  3169. };
  3170. #ifndef MODULE
  3171. Index: linux-2.6.23.17/drivers/video/geode/lxfb_ops.c
  3172. ===================================================================
  3173. --- linux-2.6.23.17.orig/drivers/video/geode/lxfb_ops.c
  3174. +++ linux-2.6.23.17/drivers/video/geode/lxfb_ops.c
  3175. @@ -13,9 +13,13 @@
  3176. #include <linux/fb.h>
  3177. #include <linux/uaccess.h>
  3178. #include <linux/delay.h>
  3179. +#include <asm/olpc.h>
  3180. #include "lxfb.h"
  3181. +#define _GEODELX_
  3182. +#include "geode_regs.h"
  3183. +
  3184. /* TODO
  3185. * Support panel scaling
  3186. * Add acceleration
  3187. @@ -290,6 +294,19 @@ unsigned int lx_framebuffer_size(void)
  3188. {
  3189. unsigned int val;
  3190. +#ifdef CONFIG_OLPC
  3191. + if (machine_is_olpc() && !olpc_has_vsa()) {
  3192. + u32 hi,lo;
  3193. + rdmsr(MSR_LX_GLIU0_P2D_RO0, lo, hi);
  3194. +
  3195. + /* Top page number */
  3196. + val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20);
  3197. + val -= (lo & 0x000fffff); /* Subtract bottom page number */
  3198. + val += 1; /* Adjust page count */
  3199. + return (val << 12);
  3200. + }
  3201. +#endif
  3202. +
  3203. /* The frame buffer size is reported by a VSM in VSA II */
  3204. /* Virtual Register Class = 0x02 */
  3205. /* VG_MEM_SIZE (1MB units) = 0x00 */
  3206. @@ -301,6 +318,34 @@ unsigned int lx_framebuffer_size(void)
  3207. return (val << 20);
  3208. }
  3209. +void lx_set_gamma(struct fb_info *info, unsigned int *gamma, int len)
  3210. +{
  3211. + int i;
  3212. + struct lxfb_par *par = info->par;
  3213. +
  3214. + writel(0, par->df_regs + DF_PAR);
  3215. +
  3216. + /* Sequential writes to the data register will increment the
  3217. + address automatically */
  3218. +
  3219. + for(i = 0; i < len; i++)
  3220. + writel(gamma[i] & 0xFFFFFF, par->df_regs + DF_PDR);
  3221. +
  3222. + writel(readl(par->df_regs + DF_MISC) & ~DF_MISC_GAM_BYPASS,
  3223. + par->df_regs + DF_MISC);
  3224. +}
  3225. +
  3226. +void lx_get_gamma(struct fb_info *info, unsigned int *gamma, int len)
  3227. +{
  3228. + int i;
  3229. + struct lxfb_par *par = info->par;
  3230. +
  3231. + writel(0, par->df_regs + DF_PAR);
  3232. +
  3233. + for(i = 0; i < len;i++)
  3234. + gamma[i] = readl(par->df_regs + DF_PDR);
  3235. +}
  3236. +
  3237. void lx_set_mode(struct fb_info *info)
  3238. {
  3239. struct lxfb_par *par = info->par;
  3240. @@ -313,6 +358,7 @@ void lx_set_mode(struct fb_info *info)
  3241. int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
  3242. /* Unlock the DC registers */
  3243. + readl(par->dc_regs + DC_UNLOCK);
  3244. writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
  3245. lx_graphics_disable(info);
  3246. @@ -534,3 +580,285 @@ int lx_blank_display(struct fb_info *inf
  3247. return 0;
  3248. }
  3249. +
  3250. +static struct geoderegs saved_regs;
  3251. +
  3252. +static void lx_save_regs(struct fb_info *info, struct geoderegs *regs)
  3253. +{
  3254. + struct lxfb_par *par = info->par;
  3255. + int i;
  3256. +
  3257. + /* Wait for the command buffer to empty */
  3258. + while(!(readl(par->gp_regs + 0x44) & (1 << 4)));
  3259. +
  3260. + rdmsrl(MSR_LX_DF_PADSEL, regs->msr.padsel);
  3261. + rdmsrl(MSR_LX_GLCP_DOTPLL, regs->msr.dotpll);
  3262. + rdmsrl(MSR_LX_DF_GLCONFIG, regs->msr.dfglcfg);
  3263. + rdmsrl(MSR_LX_DC_SPARE, regs->msr.dcspare);
  3264. +
  3265. + writel(0x4758, par->dc_regs + 0x00);
  3266. +
  3267. + memcpy(regs->gp.b, par->gp_regs, GP_REG_SIZE);
  3268. + memcpy(regs->dc.b, par->dc_regs, DC_REG_SIZE);
  3269. + memcpy(regs->vp.b, par->df_regs, VP_REG_SIZE);
  3270. + memcpy(regs->fp.b, par->df_regs + VP_FP_START, FP_REG_SIZE);
  3271. +
  3272. + /* Save the palettes */
  3273. + writel(0, par->dc_regs + 0x70);
  3274. +
  3275. + for(i = 0; i < DC_PAL_SIZE; i++)
  3276. + regs->pal[i] = readl(par->dc_regs + 0x74);
  3277. +
  3278. + writel(0, par->df_regs + 0x38);
  3279. +
  3280. + for(i = 0; i <= 0xFF; i++)
  3281. + regs->gamma[i] = readl(par->df_regs + 0x40);
  3282. +}
  3283. +
  3284. +static void lx_restore_regs(struct fb_info *info, struct geoderegs *regs)
  3285. +{
  3286. + struct lxfb_par *par = info->par;
  3287. + u32 val, i;
  3288. +
  3289. + /* == DOTPLL == */
  3290. +
  3291. + lx_set_dotpll((u32) (regs->msr.dotpll >> 32));
  3292. +
  3293. + /* MSRs */
  3294. +
  3295. + wrmsrl(MSR_LX_DF_GLCONFIG, regs->msr.dfglcfg);
  3296. +
  3297. + /* == GP == */
  3298. +
  3299. + writel(regs->gp.r.dst_offset, par->gp_regs + 0x00);
  3300. + writel(regs->gp.r.src_offset, par->gp_regs + 0x04);
  3301. + writel(regs->gp.r.stride, par->gp_regs + 0x08);
  3302. + writel(regs->gp.r.wid_height, par->gp_regs + 0x0C);
  3303. + writel(regs->gp.r.src_color_fg, par->gp_regs + 0x10);
  3304. + writel(regs->gp.r.src_color_bg, par->gp_regs + 0x14);
  3305. + writel(regs->gp.r.pat_color_0, par->gp_regs + 0x18);
  3306. + writel(regs->gp.r.pat_color_1, par->gp_regs + 0x1C);
  3307. + writel(regs->gp.r.pat_color_2, par->gp_regs + 0x20);
  3308. + writel(regs->gp.r.pat_color_3, par->gp_regs + 0x24);
  3309. + writel(regs->gp.r.pat_color_4, par->gp_regs + 0x28);
  3310. + writel(regs->gp.r.pat_color_5, par->gp_regs + 0x2C);
  3311. + writel(regs->gp.r.pat_data_0, par->gp_regs + 0x30);
  3312. + writel(regs->gp.r.pat_data_1, par->gp_regs + 0x34);
  3313. +
  3314. + /* Writing to these registers would cause a blt to happen */
  3315. + /* 0x38, 0x3c, 0x40 */
  3316. +
  3317. + /* Status register (0x44) is read only */
  3318. +
  3319. + writel(regs->gp.r.hst_src, par->gp_regs + 0x48);
  3320. + writel(regs->gp.r.base_offset, par->gp_regs + 0x4c);
  3321. + writel(regs->gp.r.cmd_top, par->gp_regs + 0x50);
  3322. + writel(regs->gp.r.cmd_bot, par->gp_regs + 0x54);
  3323. + writel(regs->gp.r.cmd_read, par->gp_regs + 0x58);
  3324. + writel(regs->gp.r.cmd_write, par->gp_regs + 0x5C);
  3325. + writel(regs->gp.r.ch3_offset, par->gp_regs + 0x60);
  3326. + writel(regs->gp.r.ch3_mode_str, par->gp_regs + 0x64);
  3327. + writel(regs->gp.r.ch3_width, par->gp_regs + 0x6C);
  3328. + writel(regs->gp.r.ch3_hsrc, par->gp_regs + 0x70);
  3329. +
  3330. + /* FIXME: Restore the LUT data here */
  3331. +
  3332. + writel(regs->gp.r.int_cntrl, par->gp_regs + 0x70);
  3333. +
  3334. + /* == DC == */
  3335. +
  3336. + /* Write the unlock value */
  3337. + writel(0x4758, par->dc_regs + 0x00);
  3338. +
  3339. + /* Write the palette data first */
  3340. +
  3341. + writel(0, par->dc_regs + 0x70);
  3342. +
  3343. + for(i = 0; i < DC_PAL_SIZE; i++)
  3344. + writel(regs->pal[i], par->dc_regs + 0x74);
  3345. +
  3346. + /* MSRs */
  3347. + wrmsrl(MSR_LX_DC_SPARE, regs->msr.dcspare);
  3348. +
  3349. + /* Write the gcfg register without the enables */
  3350. + writel(regs->dc.r.gcfg & ~0x0F, par->dc_regs + 0x04);
  3351. +
  3352. + /* Write the vcfg register without the enables */
  3353. + writel(regs->dc.r.dcfg & ~0x19, par->dc_regs + 0x08);
  3354. +
  3355. + /* Write the rest of the active registers */
  3356. + writel(regs->dc.r.arb, par->dc_regs + 0x0C);
  3357. + writel(regs->dc.r.fb_st_offset, par->dc_regs + 0x10);
  3358. + writel(regs->dc.r.cb_st_offset, par->dc_regs + 0x14);
  3359. + writel(regs->dc.r.curs_st_offset, par->dc_regs + 0x18);
  3360. + writel(regs->dc.r.icon_st_offset, par->dc_regs + 0x1C);
  3361. + writel(regs->dc.r.vid_y_st_offset, par->dc_regs + 0x20);
  3362. + writel(regs->dc.r.vid_u_st_offset, par->dc_regs + 0x24);
  3363. + writel(regs->dc.r.vid_v_st_offset, par->dc_regs + 0x28);
  3364. + writel(regs->dc.r.dctop, par->dc_regs + 0x2c);
  3365. + writel(regs->dc.r.line_size, par->dc_regs + 0x30);
  3366. + writel(regs->dc.r.gfx_pitch, par->dc_regs + 0x34);
  3367. + writel(regs->dc.r.vid_yuv_pitch, par->dc_regs + 0x38);
  3368. + writel(regs->dc.r.h_active_timing, par->dc_regs + 0x40);
  3369. + writel(regs->dc.r.h_blank_timing, par->dc_regs + 0x44);
  3370. + writel(regs->dc.r.h_sync_timing, par->dc_regs + 0x48);
  3371. + writel(regs->dc.r.v_active_timing, par->dc_regs + 0x50);
  3372. + writel(regs->dc.r.v_blank_timing, par->dc_regs + 0x54);
  3373. + writel(regs->dc.r.v_sync_timing, par->dc_regs + 0x58);
  3374. + writel(regs->dc.r.fbactive, par->dc_regs + 0x5c);
  3375. + writel(regs->dc.r.dc_cursor_x, par->dc_regs + 0x60);
  3376. + writel(regs->dc.r.dc_cursor_y, par->dc_regs + 0x64);
  3377. + writel(regs->dc.r.dc_icon_x, par->dc_regs + 0x68);
  3378. +
  3379. + /* Skip register 0x6C (line_cnt), 0x70/0x74 (palette),
  3380. + 0x78 (diagnostic), and 0x7c (diagnostic)
  3381. + */
  3382. +
  3383. + writel(regs->dc.r.dc_vid_ds_delta, par->dc_regs + 0x80);
  3384. + writel(regs->dc.r.gliu0_mem_offset, par->dc_regs + 0x84);
  3385. + writel(regs->dc.r.dv_ctl, par->dc_regs + 0x88);
  3386. + writel(regs->dc.r.dv_acc, par->dc_regs + 0x8C);
  3387. +
  3388. + writel(regs->dc.r.gfx_scale, par->dc_regs + 0x90);
  3389. + writel(regs->dc.r.irq_filt_ctl, par->dc_regs + 0x94);
  3390. + writel(regs->dc.r.filt_coeff1, par->dc_regs + 0x98);
  3391. + writel(regs->dc.r.filt_coeff2, par->dc_regs + 0x9C);
  3392. + writel(regs->dc.r.vbi_event_ctl, par->dc_regs + 0xA0);
  3393. +
  3394. + writel(regs->dc.r.vbi_odd_ctl, par->dc_regs + 0xA4);
  3395. + writel(regs->dc.r.vbi_hor, par->dc_regs + 0xA8);
  3396. + writel(regs->dc.r.vbi_ln_odd, par->dc_regs + 0xAC);
  3397. + writel(regs->dc.r.vbi_ln_event, par->dc_regs + 0xB0);
  3398. + writel(regs->dc.r.vbi_pitch, par->dc_regs + 0xB4);
  3399. + writel(regs->dc.r.clr_key, par->dc_regs + 0xB8);
  3400. + writel(regs->dc.r.clr_key_mask, par->dc_regs + 0xBC);
  3401. +
  3402. + writel(regs->dc.r.clr_key_x, par->dc_regs + 0xC0);
  3403. + writel(regs->dc.r.clr_key_y, par->dc_regs + 0xC4);
  3404. + writel(regs->dc.r.irq, par->dc_regs + 0xC8);
  3405. + writel(regs->dc.r.genlk_ctrl, par->dc_regs + 0xD4);
  3406. +
  3407. + writel(regs->dc.r.vid_even_y_st_offset, par->dc_regs + 0xD8);
  3408. + writel(regs->dc.r.vid_even_u_st_offset, par->dc_regs + 0xDC);
  3409. + writel(regs->dc.r.vid_even_v_st_offset, par->dc_regs + 0xE0);
  3410. +
  3411. + writel(regs->dc.r.v_active_even_timing, par->dc_regs + 0xE4);
  3412. + writel(regs->dc.r.v_blank_even_timing, par->dc_regs + 0xE8);
  3413. + writel(regs->dc.r.v_sync_even_timing, par->dc_regs + 0xEC);
  3414. +
  3415. + /* == VP == */
  3416. +
  3417. + /* MSR */
  3418. + wrmsrl(MSR_LX_DF_PADSEL, regs->msr.padsel);
  3419. +
  3420. + /* Write gamma information first */
  3421. +
  3422. + writel(0, par->df_regs + 0x38);
  3423. +
  3424. + for(i = 0; i <= 0xFF; i++)
  3425. + writel((u32) regs->gamma[i], par->df_regs + 0x40);
  3426. +
  3427. + /* Don't enable video yet */
  3428. + writel((u32) regs->vp.r.vcfg & ~0x01, par->df_regs + 0x00);
  3429. +
  3430. + /* Don't enable the CRT yet */
  3431. + writel((u32) regs->vp.r.dcfg & ~0x0F, par->df_regs + 0x08);
  3432. +
  3433. + /* Write the rest of the VP registers */
  3434. +
  3435. + writel((u32) regs->vp.r.vx, par->df_regs + 0x10);
  3436. + writel((u32) regs->vp.r.vy, par->df_regs + 0x18);
  3437. + writel((u32) regs->vp.r.vs, par->df_regs + 0x20);
  3438. + writel((u32) regs->vp.r.vck, par->df_regs + 0x28);
  3439. + writel((u32) regs->vp.r.vcm, par->df_regs + 0x30);
  3440. + writel((u32) regs->vp.r.misc, par->df_regs + 0x50);
  3441. + writel((u32) regs->vp.r.ccs, par->df_regs + 0x58);
  3442. + writel((u32) regs->vp.r.vdc, par->df_regs + 0x78);
  3443. + writel((u32) regs->vp.r.vco, par->df_regs + 0x80);
  3444. + writel((u32) regs->vp.r.crc, par->df_regs + 0x88);
  3445. + writel((u32) regs->vp.r.vde, par->df_regs + 0x98);
  3446. + writel((u32) regs->vp.r.cck, par->df_regs + 0xA0);
  3447. + writel((u32) regs->vp.r.ccm, par->df_regs + 0xA8);
  3448. + writel((u32) regs->vp.r.cc1, par->df_regs + 0xB0);
  3449. + writel((u32) regs->vp.r.cc2, par->df_regs + 0xB8);
  3450. + writel((u32) regs->vp.r.a1x, par->df_regs + 0xC0);
  3451. + writel((u32) regs->vp.r.a1y, par->df_regs + 0xC8);
  3452. + writel((u32) regs->vp.r.a1c, par->df_regs + 0xD0);
  3453. + writel((u32) regs->vp.r.a1t, par->df_regs + 0xD8);
  3454. + writel((u32) regs->vp.r.a2x, par->df_regs + 0xE0);
  3455. + writel((u32) regs->vp.r.a2y, par->df_regs + 0xE8);
  3456. + writel((u32) regs->vp.r.a2c, par->df_regs + 0xF0);
  3457. + writel((u32) regs->vp.r.a2t, par->df_regs + 0xF8);
  3458. + writel((u32) regs->vp.r.a3x, par->df_regs + 0x100);
  3459. + writel((u32) regs->vp.r.a3y, par->df_regs + 0x108);
  3460. + writel((u32) regs->vp.r.a3c, par->df_regs + 0x110);
  3461. + writel((u32) regs->vp.r.a3t, par->df_regs + 0x118);
  3462. + writel((u32) regs->vp.r.vrr, par->df_regs + 0x120);
  3463. +
  3464. + writel((u32) regs->vp.r.vye, par->df_regs + 0x138);
  3465. + writel((u32) regs->vp.r.a1ye, par->df_regs + 0x140);
  3466. + writel((u32) regs->vp.r.a2ye, par->df_regs + 0x148);
  3467. + writel((u32) regs->vp.r.a3ye, par->df_regs + 0x150);
  3468. +
  3469. + /* == FP == */
  3470. +
  3471. + writel((u32) regs->fp.r.pt1, par->df_regs + 0x400);
  3472. + writel((u32) regs->fp.r.pt2, par->df_regs + 0x408);
  3473. + writel((u32) regs->fp.r.dfc, par->df_regs + 0x418);
  3474. + writel(regs->fp.r.dca, par->df_regs + 0x448);
  3475. + writel(regs->fp.r.dmd, par->df_regs + 0x450);
  3476. + writel(regs->fp.r.crc, par->df_regs + 0x458);
  3477. +
  3478. + /* Final enables */
  3479. +
  3480. + val = readl(par->df_regs + 0x410);
  3481. +
  3482. + /* Control the panel */
  3483. + if (regs->fp.r.pm & (1 << 24)) {
  3484. +
  3485. + if (!(val & 0x09))
  3486. + writel(regs->fp.r.pm, par->df_regs + 0x410);
  3487. + }
  3488. + else {
  3489. + if (!(val & 0x05))
  3490. + writel(regs->fp.r.pm, par->df_regs + 0x410);
  3491. + }
  3492. +
  3493. + /* Turn everything on */
  3494. +
  3495. + writel(regs->dc.r.gcfg, par->dc_regs + 0x04);
  3496. + writel((u32) regs->vp.r.vcfg, par->df_regs + 0x00);
  3497. + writel((u32) regs->vp.r.dcfg, par->df_regs + 0x08);
  3498. + writel(regs->dc.r.dcfg, par->dc_regs + 0x08);
  3499. +}
  3500. +
  3501. +static int lx_power_on = 1;
  3502. +
  3503. +int lx_shutdown(struct fb_info *info)
  3504. +{
  3505. + struct lxfb_par *par = info->par;
  3506. +
  3507. + if (lx_power_on == 0)
  3508. + return 0;
  3509. +
  3510. + writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
  3511. + lx_save_regs(info, &saved_regs);
  3512. + lx_graphics_disable(info);
  3513. +
  3514. + lx_power_on = 0;
  3515. + return 0;
  3516. +}
  3517. +
  3518. +int lx_powerup(struct fb_info *info)
  3519. +{
  3520. + struct lxfb_par *par = info->par;
  3521. +
  3522. + if (lx_power_on == 1)
  3523. + return 0;
  3524. +
  3525. + lx_restore_regs(info, &saved_regs);
  3526. + writel(0, par->dc_regs + DC_UNLOCK);
  3527. +
  3528. + lx_power_on = 1;
  3529. + return 0;
  3530. +}
  3531. Index: linux-2.6.23.17/drivers/video/geode/video_gx.c
  3532. ===================================================================
  3533. --- linux-2.6.23.17.orig/drivers/video/geode/video_gx.c
  3534. +++ linux-2.6.23.17/drivers/video/geode/video_gx.c
  3535. @@ -16,10 +16,14 @@
  3536. #include <asm/io.h>
  3537. #include <asm/delay.h>
  3538. #include <asm/msr.h>
  3539. +#include <asm/olpc.h>
  3540. #include "geodefb.h"
  3541. #include "video_gx.h"
  3542. +#include "display_gx.h"
  3543. +/* This structure is used to store the saved registers during suspend */
  3544. +static struct geoderegs gx_saved_regs;
  3545. /*
  3546. * Tables of register settings for various DOTCLKs.
  3547. @@ -58,7 +62,7 @@ static const struct gx_pll_entry gx_pll_
  3548. { 13888, POSTDIV3, 0x000007E1 }, /* 72.0000 */
  3549. { 13426, PREMULT2, 0x00000F4A }, /* 74.4810 */
  3550. { 13333, 0, 0x00000052 }, /* 75.0000 */
  3551. - { 12698, 0, 0x00000056 }, /* 78.7500 */
  3552. + { 12698, 0, 0x00000056 }, /* 78.7500 */
  3553. { 12500, POSTDIV3|PREMULT2, 0x00000709 }, /* 80.0000 */
  3554. { 11135, PREMULT2, 0x00000262 }, /* 89.8000 */
  3555. { 10582, 0, 0x000002D2 }, /* 94.5000 */
  3556. @@ -117,8 +121,9 @@ static const struct gx_pll_entry gx_pll_
  3557. { 4357, 0, 0x0000057D }, /* 229.5000 */
  3558. };
  3559. -static void gx_set_dclk_frequency(struct fb_info *info)
  3560. +void gx_set_dclk_frequency(struct fb_info *info)
  3561. {
  3562. + struct geodefb_par *par = info->par;
  3563. const struct gx_pll_entry *pll_table;
  3564. int pll_table_len;
  3565. int i, best_i;
  3566. @@ -173,115 +178,169 @@ static void gx_set_dclk_frequency(struct
  3567. do {
  3568. rdmsrl(MSR_GLCP_DOTPLL, dotpll);
  3569. } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK));
  3570. +
  3571. + par->curdclk = pll_table[best_i].dotpll_value;
  3572. }
  3573. -static void
  3574. -gx_configure_tft(struct fb_info *info)
  3575. +/* Find out the current clock - we will use this information to avoid
  3576. + re-programming it if we don't need to */
  3577. +
  3578. +unsigned int gx_get_dclk(struct fb_info *info)
  3579. {
  3580. - struct geodefb_par *par = info->par;
  3581. - unsigned long val;
  3582. - unsigned long fp;
  3583. + const struct gx_pll_entry *pll_table;
  3584. + int pll_table_len;
  3585. + u64 dotpll;
  3586. + int i;
  3587. - /* Set up the DF pad select MSR */
  3588. + if (cpu_data->x86_mask == 1) {
  3589. + pll_table = gx_pll_table_14MHz;
  3590. + pll_table_len = ARRAY_SIZE(gx_pll_table_14MHz);
  3591. + } else {
  3592. + pll_table = gx_pll_table_48MHz;
  3593. + pll_table_len = ARRAY_SIZE(gx_pll_table_48MHz);
  3594. + }
  3595. - rdmsrl(GX_VP_MSR_PAD_SELECT, val);
  3596. - val &= ~GX_VP_PAD_SELECT_MASK;
  3597. - val |= GX_VP_PAD_SELECT_TFT;
  3598. - wrmsrl(GX_VP_MSR_PAD_SELECT, val);
  3599. + rdmsrl(MSR_GLCP_DOTPLL, dotpll);
  3600. - /* Turn off the panel */
  3601. + for(i = 0; i < pll_table_len; i++) {
  3602. + if (pll_table[i].dotpll_value == (u32) (dotpll >> 32))
  3603. + break;
  3604. + }
  3605. +
  3606. + return (i == pll_table_len) ? 0 : pll_table[i].pixclock;
  3607. +}
  3608. - fp = readl(par->vid_regs + GX_FP_PM);
  3609. - fp &= ~GX_FP_PM_P;
  3610. - writel(fp, par->vid_regs + GX_FP_PM);
  3611. - /* Set timing 1 */
  3612. +#define CMP(val, mask, res) (((val) & (mask)) == (res))
  3613. - fp = readl(par->vid_regs + GX_FP_PT1);
  3614. - fp &= GX_FP_PT1_VSIZE_MASK;
  3615. - fp |= info->var.yres << GX_FP_PT1_VSIZE_SHIFT;
  3616. - writel(fp, par->vid_regs + GX_FP_PT1);
  3617. +static void
  3618. +gx_configure_tft(struct fb_info *info) {
  3619. - /* Timing 2 */
  3620. - /* Set bits that are always on for TFT */
  3621. + struct geodefb_par *par = info->par;
  3622. + u32 val, fp = 0, fp1, fp2, sync = 0;
  3623. - fp = 0x0F100000;
  3624. + /* Set up the DF pad select MSR */
  3625. - /* Add sync polarity */
  3626. + rdmsrl(GX_VP_MSR_PAD_SELECT, val);
  3627. +
  3628. + if ((val & GX_VP_PAD_SELECT_MASK) != GX_VP_PAD_SELECT_TFT) {
  3629. + val &= ~GX_VP_PAD_SELECT_MASK;
  3630. + val |= GX_VP_PAD_SELECT_TFT;
  3631. + wrmsrl(GX_VP_MSR_PAD_SELECT, val);
  3632. + }
  3633. if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
  3634. - fp |= GX_FP_PT2_VSP;
  3635. + sync |= GX_FP_PT2_VSP;
  3636. if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
  3637. - fp |= GX_FP_PT2_HSP;
  3638. + sync |= GX_FP_PT2_HSP;
  3639. - writel(fp, par->vid_regs + GX_FP_PT2);
  3640. + /* We only need to turn off the panel if something changed */
  3641. - /* Set the dither control */
  3642. - writel(0x70, par->vid_regs + GX_FP_DFC);
  3643. + fp1 = readl(par->vid_regs + GX_FP_PT1);
  3644. + fp2 = readl(par->vid_regs + GX_FP_PT2);
  3645. +
  3646. + if (!CMP(fp1, GX_FP_PT1_VSIZE_MASK, info->var.yres << GX_FP_PT1_VSIZE_SHIFT) ||
  3647. + (fp2 != (0x0F100000 | sync))) {
  3648. +
  3649. + /* Turn off the panel */
  3650. +
  3651. +#ifdef NOTUSED
  3652. + /* Do we really need to turn off the panel? */
  3653. + /* Possibly - we have a glitch somewhere */
  3654. - /* Enable the FP data and power (in case the BIOS didn't) */
  3655. + fp = readl(par->vid_regs + GX_FP_PM);
  3656. + fp &= ~GX_FP_PM_P;
  3657. + writel(fp, par->vid_regs + GX_FP_PM);
  3658. +#endif
  3659. - fp = readl(par->vid_regs + GX_DCFG);
  3660. - fp |= GX_DCFG_FP_PWR_EN | GX_DCFG_FP_DATA_EN;
  3661. - writel(fp, par->vid_regs + GX_DCFG);
  3662. + /* Timing 1 */
  3663. + fp1 &= GX_FP_PT1_VSIZE_MASK;
  3664. + fp1 |= info->var.yres << GX_FP_PT1_VSIZE_SHIFT;
  3665. + writel(fp, par->vid_regs + GX_FP_PT1);
  3666. - /* Unblank the panel */
  3667. + /* Timing 2 */
  3668. + writel(0x0F100000 | sync, par->vid_regs + GX_FP_PT2);
  3669. + }
  3670. +
  3671. + /* Set the dither control */
  3672. + if (readl(par->vid_regs + GX_FP_DFC) != 0x70) {
  3673. + writel(0x70, par->vid_regs + GX_FP_DFC);
  3674. + }
  3675. +
  3676. + /* Turn on the panel */
  3677. fp = readl(par->vid_regs + GX_FP_PM);
  3678. - fp |= GX_FP_PM_P;
  3679. - writel(fp, par->vid_regs + GX_FP_PM);
  3680. +
  3681. + if (!(fp & 0x09))
  3682. + writel(fp | GX_FP_PM_P, par->vid_regs + GX_FP_PM);
  3683. }
  3684. +#define DCFG_DEFAULT_VAL GX_DCFG_CRT_SYNC_SKW_DFLT | GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN | \
  3685. +GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN
  3686. +
  3687. static void gx_configure_display(struct fb_info *info)
  3688. {
  3689. struct geodefb_par *par = info->par;
  3690. - u32 dcfg, misc;
  3691. + u32 dcfg, misc, sync = 0;
  3692. /* Set up the MISC register */
  3693. -
  3694. misc = readl(par->vid_regs + GX_MISC);
  3695. - /* Power up the DAC */
  3696. - misc &= ~(GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN);
  3697. + /* We leave gamma enabled if it was already enabled.
  3698. + Although the hardware enables it without setting
  3699. + up the gamma table, the BIOS or bootloader ought
  3700. + to have either disabled it or loaded a table by now */
  3701. - /* Disable gamma correction */
  3702. - misc |= GX_MISC_GAM_EN;
  3703. - writel(misc, par->vid_regs + GX_MISC);
  3704. - /* Write the display configuration */
  3705. - dcfg = readl(par->vid_regs + GX_DCFG);
  3706. + if (par->enable_crt) {
  3707. + /* Power up the CRT DACs */
  3708. + if (misc & ( GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN)) {
  3709. + misc &= ~(GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN);
  3710. + writel(misc, par->vid_regs + GX_MISC);
  3711. + }
  3712. - /* Disable hsync and vsync */
  3713. - dcfg &= ~(GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
  3714. - writel(dcfg, par->vid_regs + GX_DCFG);
  3715. + if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
  3716. + sync |= GX_DCFG_CRT_HSYNC_POL;
  3717. - /* Clear bits from existing mode. */
  3718. - dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK
  3719. - | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL
  3720. - | GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
  3721. + if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
  3722. + sync |= GX_DCFG_CRT_VSYNC_POL;
  3723. + }
  3724. + else {
  3725. + /* Turn off the CRT DACs in FP mode - we don't need them */
  3726. + if ((misc & (GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN))) {
  3727. + misc |= (GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN);
  3728. + writel(misc, par->vid_regs + GX_MISC);
  3729. + }
  3730. + }
  3731. - /* Set default sync skew. */
  3732. - dcfg |= GX_DCFG_CRT_SYNC_SKW_DFLT;
  3733. + /* Write the display configuration */
  3734. + dcfg = readl(par->vid_regs + GX_DCFG);
  3735. - /* Enable hsync and vsync. */
  3736. - dcfg |= GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN;
  3737. + if (!CMP(dcfg, DCFG_DEFAULT_VAL | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL,
  3738. + DCFG_DEFAULT_VAL | sync)) {
  3739. - /* Sync polarities. */
  3740. - if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
  3741. - dcfg |= GX_DCFG_CRT_HSYNC_POL;
  3742. - if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
  3743. - dcfg |= GX_DCFG_CRT_VSYNC_POL;
  3744. + /* Disable hsync and vsync */
  3745. + dcfg &= ~(GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
  3746. + writel(dcfg, par->vid_regs + GX_DCFG);
  3747. - /* Enable the display logic */
  3748. - /* Set up the DACS to blank normally */
  3749. + /* Clear bits from existing mode. */
  3750. + dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK
  3751. + | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL
  3752. + | GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
  3753. - dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN;
  3754. + /* Set default sync skew. */
  3755. + dcfg |= GX_DCFG_CRT_SYNC_SKW_DFLT;
  3756. - /* Enable the external DAC VREF? */
  3757. + /* Enable hsync and vsync. */
  3758. + dcfg |= GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN;
  3759. - writel(dcfg, par->vid_regs + GX_DCFG);
  3760. + /* Enable the display logic */
  3761. + dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN;
  3762. +
  3763. + writel(dcfg, par->vid_regs + GX_DCFG);
  3764. + }
  3765. /* Set up the flat panel (if it is enabled) */
  3766. @@ -289,6 +348,100 @@ static void gx_configure_display(struct
  3767. gx_configure_tft(info);
  3768. }
  3769. +int gxfb_powerdown(struct fb_info *info)
  3770. +{
  3771. + struct geodefb_par *par = info->par;
  3772. +
  3773. + /* We're already suspended */
  3774. +
  3775. + if (par->state != FB_POWER_STATE_ON)
  3776. + return 0;
  3777. +
  3778. + /* Save the registers */
  3779. + gx_save_regs(info, &gx_saved_regs);
  3780. +
  3781. + /* Shut down the engine */
  3782. +
  3783. + writel(gx_saved_regs.vp.r.vcfg & ~0x01, par->vid_regs + GX_VCFG);
  3784. + writel(gx_saved_regs.vp.r.dcfg & ~0x0F, par->vid_regs + GX_DCFG);
  3785. +
  3786. + /* Turn off the flat panel unless we are attached to a DCON */
  3787. + if (!olpc_has_dcon())
  3788. + writel(gx_saved_regs.fp.r.pm & ~GX_FP_PM_P, par->vid_regs + GX_FP_PM);
  3789. +
  3790. + writel(0x4758, par->dc_regs + DC_UNLOCK);
  3791. +
  3792. + writel(gx_saved_regs.dc.r.gcfg & ~0x0F,
  3793. + par->dc_regs + DC_GENERAL_CFG);
  3794. +
  3795. + writel(gx_saved_regs.dc.r.dcfg & ~0x19,
  3796. + par->dc_regs + DC_DISPLAY_CFG);
  3797. +
  3798. + par->state = FB_POWER_STATE_SUSPEND;
  3799. +
  3800. + return 0;
  3801. +}
  3802. +
  3803. +int gxfb_powerup(struct fb_info *info)
  3804. +{
  3805. + struct geodefb_par *par = info->par;
  3806. + u32 val;
  3807. +
  3808. + if (par->state == FB_POWER_STATE_SUSPEND) {
  3809. +
  3810. + writel(gx_saved_regs.dc.r.dcfg,
  3811. + par->dc_regs + DC_DISPLAY_CFG);
  3812. +
  3813. + writel(gx_saved_regs.vp.r.vcfg, par->vid_regs + GX_VCFG);
  3814. + writel(gx_saved_regs.vp.r.dcfg, par->vid_regs + GX_DCFG);
  3815. +
  3816. + val = readl(par->vid_regs + GX_FP_PM);
  3817. +
  3818. + /* power up the panel if it needs it; we don't always power it down */
  3819. + if (!(val & 0x09)) {
  3820. + writel(gx_saved_regs.fp.r.pm, par->vid_regs + GX_FP_PM);
  3821. + mdelay(64);
  3822. + }
  3823. + }
  3824. +
  3825. + /* If the panel is currently on its way up, then wait up to 100ms
  3826. + for it */
  3827. +
  3828. + if (readl(par->vid_regs + GX_FP_PM) & 0x08) {
  3829. + int i;
  3830. +
  3831. + for(i = 0; i < 10; i++) {
  3832. + if (readl(par->vid_regs + GX_FP_PM) & 0x01)
  3833. + break;
  3834. +
  3835. + mdelay(10);
  3836. + }
  3837. +
  3838. + if (i == 10)
  3839. + printk(KERN_ERR "gxfb: Panel power up timed out\n");
  3840. + }
  3841. +
  3842. + if (par->state == FB_POWER_STATE_ON)
  3843. + return 0;
  3844. +
  3845. + switch(par->state) {
  3846. + case FB_POWER_STATE_OFF:
  3847. + gx_restore_regs(info, &gx_saved_regs);
  3848. + break;
  3849. +
  3850. + case FB_POWER_STATE_SUSPEND:
  3851. + /* Do this because it will turn on the FIFO which will
  3852. + start the line count */
  3853. + writel(gx_saved_regs.dc.r.gcfg,
  3854. + par->dc_regs + DC_GENERAL_CFG);
  3855. + writel(0x0, par->dc_regs + DC_UNLOCK);
  3856. + break;
  3857. + }
  3858. +
  3859. + par->state = FB_POWER_STATE_ON;
  3860. + return 0;
  3861. +}
  3862. +
  3863. static int gx_blank_display(struct fb_info *info, int blank_mode)
  3864. {
  3865. struct geodefb_par *par = info->par;
  3866. @@ -315,6 +468,7 @@ static int gx_blank_display(struct fb_in
  3867. default:
  3868. return -EINVAL;
  3869. }
  3870. +
  3871. dcfg = readl(par->vid_regs + GX_DCFG);
  3872. dcfg &= ~(GX_DCFG_DAC_BL_EN
  3873. | GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN);
  3874. @@ -326,7 +480,7 @@ static int gx_blank_display(struct fb_in
  3875. dcfg |= GX_DCFG_VSYNC_EN;
  3876. writel(dcfg, par->vid_regs + GX_DCFG);
  3877. - /* Power on/off flat panel. */
  3878. + /* Power on/off flat panel */
  3879. if (par->enable_crt == 0) {
  3880. fp_pm = readl(par->vid_regs + GX_FP_PM);
  3881. @@ -340,8 +494,37 @@ static int gx_blank_display(struct fb_in
  3882. return 0;
  3883. }
  3884. +extern struct fb_info *gxfb_info;
  3885. +
  3886. +/* This function controls the flatpanel power sequencing - this is used
  3887. + by the OLPC power management engine to enable the FP sequencing much
  3888. + earlier in the resume process
  3889. +*/
  3890. +
  3891. +void gxfb_flatpanel_control(int state)
  3892. +{
  3893. + struct geodefb_par *par = gxfb_info->par;
  3894. + u32 val, fp = readl(par->vid_regs + GX_FP_PM);
  3895. + val = fp;
  3896. +
  3897. + /* Turn on the panel if it isn't aleady */
  3898. +
  3899. + if (state) {
  3900. + if (!(val & 0x01))
  3901. + val |= GX_FP_PM_P;
  3902. + }
  3903. + else {
  3904. + if (!(val & 0x02))
  3905. + val &= ~GX_FP_PM_P;
  3906. + }
  3907. +
  3908. + if (val != fp)
  3909. + writel(val, par->vid_regs + GX_FP_PM);
  3910. +}
  3911. +
  3912. struct geode_vid_ops gx_vid_ops = {
  3913. .set_dclk = gx_set_dclk_frequency,
  3914. + .get_dclk = gx_get_dclk,
  3915. .configure_display = gx_configure_display,
  3916. .blank_display = gx_blank_display,
  3917. };
  3918. Index: linux-2.6.23.17/drivers/video/geode/video_gx.h
  3919. ===================================================================
  3920. --- linux-2.6.23.17.orig/drivers/video/geode/video_gx.h
  3921. +++ linux-2.6.23.17/drivers/video/geode/video_gx.h
  3922. @@ -11,6 +11,8 @@
  3923. #ifndef __VIDEO_GX_H__
  3924. #define __VIDEO_GX_H__
  3925. +#include "geode_regs.h"
  3926. +
  3927. extern struct geode_vid_ops gx_vid_ops;
  3928. /* GX Flatpanel control MSR */
  3929. @@ -20,6 +22,8 @@ extern struct geode_vid_ops gx_vid_ops;
  3930. /* Geode GX video processor registers */
  3931. +#define GX_VCFG 0x0000
  3932. +
  3933. #define GX_DCFG 0x0008
  3934. # define GX_DCFG_CRT_EN 0x00000001
  3935. # define GX_DCFG_HSYNC_EN 0x00000002
  3936. @@ -42,6 +46,14 @@ extern struct geode_vid_ops gx_vid_ops;
  3937. #define GX_MISC_DAC_PWRDN 0x00000400
  3938. #define GX_MISC_A_PWRDN 0x00000800
  3939. +/* Gamma correction RAM - address and data registers */
  3940. +
  3941. +#define GX_GAR 0x038
  3942. +#define GX_GDR 0x040
  3943. +
  3944. +#define GXFB_GAMMA_DWORDS 256 /* number of dwords in the gamma ram */
  3945. +#define GXFB_GAMMA_SIZE (GXFB_GAMMA_DWORDS * sizeof(unsigned int))
  3946. +
  3947. /* Geode GX flat panel display control registers */
  3948. #define GX_FP_PT1 0x0400
  3949. @@ -69,4 +81,13 @@ extern struct geode_vid_ops gx_vid_ops;
  3950. # define MSR_GLCP_DOTPLL_BYPASS (0x0000000000008000ull)
  3951. # define MSR_GLCP_DOTPLL_LOCK (0x0000000002000000ull)
  3952. +int gxfb_powerdown(struct fb_info *info);
  3953. +int gxfb_powerup(struct fb_info *info);
  3954. +
  3955. +void gx_set_dclk_frequency(struct fb_info *info);
  3956. +unsigned int gx_get_dclk(struct fb_info *info);
  3957. +
  3958. +void gx_save_regs(struct fb_info *info, struct geoderegs *regs);
  3959. +void gx_restore_regs(struct fb_info *info, struct geoderegs *regs);
  3960. +
  3961. #endif /* !__VIDEO_GX_H__ */
  3962. Index: linux-2.6.23.17/drivers/video/modedb.c
  3963. ===================================================================
  3964. --- linux-2.6.23.17.orig/drivers/video/modedb.c
  3965. +++ linux-2.6.23.17/drivers/video/modedb.c
  3966. @@ -33,6 +33,8 @@ const char *global_mode_option;
  3967. * Standard video mode definitions (taken from XFree86)
  3968. */
  3969. +#define DEFAULT_MODEDB_INDEX 0
  3970. +
  3971. static const struct fb_videomode modedb[] = {
  3972. {
  3973. /* 640x400 @ 70 Hz, 31.5 kHz hsync */
  3974. @@ -504,7 +506,8 @@ int fb_find_mode(struct fb_var_screeninf
  3975. }
  3976. if (!default_mode)
  3977. - default_mode = &db[0];
  3978. + default_mode = (db == modedb) ?
  3979. + &modedb[DEFAULT_MODEDB_INDEX] : &db[0];
  3980. if (!default_bpp)
  3981. default_bpp = 8;
  3982. Index: linux-2.6.23.17/fs/Kconfig
  3983. ===================================================================
  3984. --- linux-2.6.23.17.orig/fs/Kconfig
  3985. +++ linux-2.6.23.17/fs/Kconfig
  3986. @@ -1003,6 +1003,23 @@ config HUGETLBFS
  3987. config HUGETLB_PAGE
  3988. def_bool HUGETLBFS
  3989. +config PROMFS_FS
  3990. + tristate "PromFS IEEE 1275 file system support"
  3991. + depends on SPARC || PPC || OLPC
  3992. + help
  3993. + PromFS is a file system interface to various IEEE-1275 compatible
  3994. + firmwares. If you have such a firmware (Sparc64, PowerPC, and
  3995. + some other architectures and embedded systems have such firmwares,
  3996. + with names like "OpenBoot (tm)" and "OpenFirmware"), say Y here
  3997. + to be able to access the firmware's device-tree from Linux.
  3998. +
  3999. + The firmware device-tree is available as a virtual file system,
  4000. + can be mounted under /prom with the command "mount -t promfs
  4001. + none /prom".
  4002. +
  4003. + To compile PromFS support as a module, choose M here; the module
  4004. + will be called promfs. If unsure, choose M.
  4005. +
  4006. config RAMFS
  4007. bool
  4008. default y
  4009. @@ -1229,6 +1246,14 @@ config JFFS2_FS_WRITEBUFFER
  4010. - NOR flash with transparent ECC
  4011. - DataFlash
  4012. +config JFFS2_FS_WBUF_VERIFY
  4013. + bool "Verify JFFS2 write-buffer reads"
  4014. + depends on JFFS2_FS_WRITEBUFFER
  4015. + default n
  4016. + help
  4017. + This causes JFFS2 to read back every page written through the
  4018. + write-buffer, and check for errors.
  4019. +
  4020. config JFFS2_SUMMARY
  4021. bool "JFFS2 summary support (EXPERIMENTAL)"
  4022. depends on JFFS2_FS && EXPERIMENTAL
  4023. @@ -1299,52 +1324,52 @@ config JFFS2_ZLIB
  4024. select ZLIB_DEFLATE
  4025. depends on JFFS2_FS
  4026. default y
  4027. - help
  4028. - Zlib is designed to be a free, general-purpose, legally unencumbered,
  4029. - lossless data-compression library for use on virtually any computer
  4030. - hardware and operating system. See <http://www.gzip.org/zlib/> for
  4031. - further information.
  4032. + help
  4033. + Zlib is designed to be a free, general-purpose, legally unencumbered,
  4034. + lossless data-compression library for use on virtually any computer
  4035. + hardware and operating system. See <http://www.gzip.org/zlib/> for
  4036. + further information.
  4037. - Say 'Y' if unsure.
  4038. + Say 'Y' if unsure.
  4039. config JFFS2_RTIME
  4040. bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS
  4041. depends on JFFS2_FS
  4042. default y
  4043. - help
  4044. - Rtime does manage to recompress already-compressed data. Say 'Y' if unsure.
  4045. + help
  4046. + Rtime does manage to recompress already-compressed data. Say 'Y' if unsure.
  4047. config JFFS2_RUBIN
  4048. bool "JFFS2 RUBIN compression support" if JFFS2_COMPRESSION_OPTIONS
  4049. depends on JFFS2_FS
  4050. default n
  4051. - help
  4052. - RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
  4053. + help
  4054. + RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
  4055. choice
  4056. - prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS
  4057. - default JFFS2_CMODE_PRIORITY
  4058. - depends on JFFS2_FS
  4059. - help
  4060. - You can set here the default compression mode of JFFS2 from
  4061. - the available compression modes. Don't touch if unsure.
  4062. + prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS
  4063. + default JFFS2_CMODE_PRIORITY
  4064. + depends on JFFS2_FS
  4065. + help
  4066. + You can set here the default compression mode of JFFS2 from
  4067. + the available compression modes. Don't touch if unsure.
  4068. config JFFS2_CMODE_NONE
  4069. - bool "no compression"
  4070. - help
  4071. - Uses no compression.
  4072. + bool "no compression"
  4073. + help
  4074. + Uses no compression.
  4075. config JFFS2_CMODE_PRIORITY
  4076. - bool "priority"
  4077. - help
  4078. - Tries the compressors in a predefined order and chooses the first
  4079. - successful one.
  4080. + bool "priority"
  4081. + help
  4082. + Tries the compressors in a predefined order and chooses the first
  4083. + successful one.
  4084. config JFFS2_CMODE_SIZE
  4085. - bool "size (EXPERIMENTAL)"
  4086. - help
  4087. - Tries all compressors and chooses the one which has the smallest
  4088. - result.
  4089. + bool "size (EXPERIMENTAL)"
  4090. + help
  4091. + Tries all compressors and chooses the one which has the smallest
  4092. + result.
  4093. endchoice
  4094. Index: linux-2.6.23.17/fs/Makefile
  4095. ===================================================================
  4096. --- linux-2.6.23.17.orig/fs/Makefile
  4097. +++ linux-2.6.23.17/fs/Makefile
  4098. @@ -110,6 +110,7 @@ obj-$(CONFIG_ADFS_FS) += adfs/
  4099. obj-$(CONFIG_FUSE_FS) += fuse/
  4100. obj-$(CONFIG_UDF_FS) += udf/
  4101. obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/
  4102. +obj-$(CONFIG_PROMFS_FS) += promfs/
  4103. obj-$(CONFIG_JFS_FS) += jfs/
  4104. obj-$(CONFIG_XFS_FS) += xfs/
  4105. obj-$(CONFIG_9P_FS) += 9p/
  4106. Index: linux-2.6.23.17/fs/jffs2/background.c
  4107. ===================================================================
  4108. --- linux-2.6.23.17.orig/fs/jffs2/background.c
  4109. +++ linux-2.6.23.17/fs/jffs2/background.c
  4110. @@ -23,8 +23,8 @@ static int jffs2_garbage_collect_thread(
  4111. void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
  4112. {
  4113. spin_lock(&c->erase_completion_lock);
  4114. - if (c->gc_task && jffs2_thread_should_wake(c))
  4115. - send_sig(SIGHUP, c->gc_task, 1);
  4116. + if (c->gc_task && jffs2_thread_should_wake(c))
  4117. + send_sig(SIGHUP, c->gc_task, 1);
  4118. spin_unlock(&c->erase_completion_lock);
  4119. }
  4120. Index: linux-2.6.23.17/fs/jffs2/compr.c
  4121. ===================================================================
  4122. --- linux-2.6.23.17.orig/fs/jffs2/compr.c
  4123. +++ linux-2.6.23.17/fs/jffs2/compr.c
  4124. @@ -5,7 +5,7 @@
  4125. * Created by Arjan van de Ven <[email protected]>
  4126. *
  4127. * Copyright © 2004 Ferenc Havasi <[email protected]>,
  4128. - * University of Szeged, Hungary
  4129. + * University of Szeged, Hungary
  4130. *
  4131. * For licensing information, see the file 'LICENCE' in this directory.
  4132. *
  4133. @@ -43,121 +43,122 @@ static uint32_t none_stat_compr_blocks=0
  4134. * *datalen accordingly to show the amount of data which were compressed.
  4135. */
  4136. uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
  4137. - unsigned char *data_in, unsigned char **cpage_out,
  4138. - uint32_t *datalen, uint32_t *cdatalen)
  4139. + unsigned char *data_in, unsigned char **cpage_out,
  4140. + uint32_t *datalen, uint32_t *cdatalen)
  4141. {
  4142. int ret = JFFS2_COMPR_NONE;
  4143. - int compr_ret;
  4144. - struct jffs2_compressor *this, *best=NULL;
  4145. - unsigned char *output_buf = NULL, *tmp_buf;
  4146. - uint32_t orig_slen, orig_dlen;
  4147. - uint32_t best_slen=0, best_dlen=0;
  4148. -
  4149. - switch (jffs2_compression_mode) {
  4150. - case JFFS2_COMPR_MODE_NONE:
  4151. - break;
  4152. - case JFFS2_COMPR_MODE_PRIORITY:
  4153. - output_buf = kmalloc(*cdatalen,GFP_KERNEL);
  4154. - if (!output_buf) {
  4155. - printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
  4156. - goto out;
  4157. - }
  4158. - orig_slen = *datalen;
  4159. - orig_dlen = *cdatalen;
  4160. - spin_lock(&jffs2_compressor_list_lock);
  4161. - list_for_each_entry(this, &jffs2_compressor_list, list) {
  4162. - /* Skip decompress-only backwards-compatibility and disabled modules */
  4163. - if ((!this->compress)||(this->disabled))
  4164. - continue;
  4165. -
  4166. - this->usecount++;
  4167. - spin_unlock(&jffs2_compressor_list_lock);
  4168. - *datalen = orig_slen;
  4169. - *cdatalen = orig_dlen;
  4170. - compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL);
  4171. - spin_lock(&jffs2_compressor_list_lock);
  4172. - this->usecount--;
  4173. - if (!compr_ret) {
  4174. - ret = this->compr;
  4175. - this->stat_compr_blocks++;
  4176. - this->stat_compr_orig_size += *datalen;
  4177. - this->stat_compr_new_size += *cdatalen;
  4178. - break;
  4179. - }
  4180. - }
  4181. - spin_unlock(&jffs2_compressor_list_lock);
  4182. - if (ret == JFFS2_COMPR_NONE) kfree(output_buf);
  4183. - break;
  4184. - case JFFS2_COMPR_MODE_SIZE:
  4185. - orig_slen = *datalen;
  4186. - orig_dlen = *cdatalen;
  4187. - spin_lock(&jffs2_compressor_list_lock);
  4188. - list_for_each_entry(this, &jffs2_compressor_list, list) {
  4189. - /* Skip decompress-only backwards-compatibility and disabled modules */
  4190. - if ((!this->compress)||(this->disabled))
  4191. - continue;
  4192. - /* Allocating memory for output buffer if necessary */
  4193. - if ((this->compr_buf_size<orig_dlen)&&(this->compr_buf)) {
  4194. - spin_unlock(&jffs2_compressor_list_lock);
  4195. - kfree(this->compr_buf);
  4196. - spin_lock(&jffs2_compressor_list_lock);
  4197. - this->compr_buf_size=0;
  4198. - this->compr_buf=NULL;
  4199. - }
  4200. - if (!this->compr_buf) {
  4201. - spin_unlock(&jffs2_compressor_list_lock);
  4202. - tmp_buf = kmalloc(orig_dlen,GFP_KERNEL);
  4203. - spin_lock(&jffs2_compressor_list_lock);
  4204. - if (!tmp_buf) {
  4205. - printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen);
  4206. - continue;
  4207. - }
  4208. - else {
  4209. - this->compr_buf = tmp_buf;
  4210. - this->compr_buf_size = orig_dlen;
  4211. - }
  4212. - }
  4213. - this->usecount++;
  4214. - spin_unlock(&jffs2_compressor_list_lock);
  4215. - *datalen = orig_slen;
  4216. - *cdatalen = orig_dlen;
  4217. - compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL);
  4218. - spin_lock(&jffs2_compressor_list_lock);
  4219. - this->usecount--;
  4220. - if (!compr_ret) {
  4221. - if ((!best_dlen)||(best_dlen>*cdatalen)) {
  4222. - best_dlen = *cdatalen;
  4223. - best_slen = *datalen;
  4224. - best = this;
  4225. - }
  4226. - }
  4227. - }
  4228. - if (best_dlen) {
  4229. - *cdatalen = best_dlen;
  4230. - *datalen = best_slen;
  4231. - output_buf = best->compr_buf;
  4232. - best->compr_buf = NULL;
  4233. - best->compr_buf_size = 0;
  4234. - best->stat_compr_blocks++;
  4235. - best->stat_compr_orig_size += best_slen;
  4236. - best->stat_compr_new_size += best_dlen;
  4237. - ret = best->compr;
  4238. - }
  4239. - spin_unlock(&jffs2_compressor_list_lock);
  4240. - break;
  4241. - default:
  4242. - printk(KERN_ERR "JFFS2: unknow compression mode.\n");
  4243. - }
  4244. + int compr_ret;
  4245. + struct jffs2_compressor *this, *best=NULL;
  4246. + unsigned char *output_buf = NULL, *tmp_buf;
  4247. + uint32_t orig_slen, orig_dlen;
  4248. + uint32_t best_slen=0, best_dlen=0;
  4249. +
  4250. + switch (jffs2_compression_mode) {
  4251. + case JFFS2_COMPR_MODE_NONE:
  4252. + break;
  4253. + case JFFS2_COMPR_MODE_PRIORITY:
  4254. + output_buf = kmalloc(*cdatalen,GFP_KERNEL);
  4255. + if (!output_buf) {
  4256. + printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
  4257. + goto out;
  4258. + }
  4259. + orig_slen = *datalen;
  4260. + orig_dlen = *cdatalen;
  4261. + spin_lock(&jffs2_compressor_list_lock);
  4262. + list_for_each_entry(this, &jffs2_compressor_list, list) {
  4263. + /* Skip decompress-only backwards-compatibility and disabled modules */
  4264. + if ((!this->compress)||(this->disabled))
  4265. + continue;
  4266. +
  4267. + this->usecount++;
  4268. + spin_unlock(&jffs2_compressor_list_lock);
  4269. + *datalen = orig_slen;
  4270. + *cdatalen = orig_dlen;
  4271. + compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL);
  4272. + spin_lock(&jffs2_compressor_list_lock);
  4273. + this->usecount--;
  4274. + if (!compr_ret) {
  4275. + ret = this->compr;
  4276. + this->stat_compr_blocks++;
  4277. + this->stat_compr_orig_size += *datalen;
  4278. + this->stat_compr_new_size += *cdatalen;
  4279. + break;
  4280. + }
  4281. + }
  4282. + spin_unlock(&jffs2_compressor_list_lock);
  4283. + if (ret == JFFS2_COMPR_NONE)
  4284. + kfree(output_buf);
  4285. + break;
  4286. + case JFFS2_COMPR_MODE_SIZE:
  4287. + orig_slen = *datalen;
  4288. + orig_dlen = *cdatalen;
  4289. + spin_lock(&jffs2_compressor_list_lock);
  4290. + list_for_each_entry(this, &jffs2_compressor_list, list) {
  4291. + /* Skip decompress-only backwards-compatibility and disabled modules */
  4292. + if ((!this->compress)||(this->disabled))
  4293. + continue;
  4294. + /* Allocating memory for output buffer if necessary */
  4295. + if ((this->compr_buf_size<orig_dlen)&&(this->compr_buf)) {
  4296. + spin_unlock(&jffs2_compressor_list_lock);
  4297. + kfree(this->compr_buf);
  4298. + spin_lock(&jffs2_compressor_list_lock);
  4299. + this->compr_buf_size=0;
  4300. + this->compr_buf=NULL;
  4301. + }
  4302. + if (!this->compr_buf) {
  4303. + spin_unlock(&jffs2_compressor_list_lock);
  4304. + tmp_buf = kmalloc(orig_dlen,GFP_KERNEL);
  4305. + spin_lock(&jffs2_compressor_list_lock);
  4306. + if (!tmp_buf) {
  4307. + printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen);
  4308. + continue;
  4309. + }
  4310. + else {
  4311. + this->compr_buf = tmp_buf;
  4312. + this->compr_buf_size = orig_dlen;
  4313. + }
  4314. + }
  4315. + this->usecount++;
  4316. + spin_unlock(&jffs2_compressor_list_lock);
  4317. + *datalen = orig_slen;
  4318. + *cdatalen = orig_dlen;
  4319. + compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL);
  4320. + spin_lock(&jffs2_compressor_list_lock);
  4321. + this->usecount--;
  4322. + if (!compr_ret) {
  4323. + if ((!best_dlen)||(best_dlen>*cdatalen)) {
  4324. + best_dlen = *cdatalen;
  4325. + best_slen = *datalen;
  4326. + best = this;
  4327. + }
  4328. + }
  4329. + }
  4330. + if (best_dlen) {
  4331. + *cdatalen = best_dlen;
  4332. + *datalen = best_slen;
  4333. + output_buf = best->compr_buf;
  4334. + best->compr_buf = NULL;
  4335. + best->compr_buf_size = 0;
  4336. + best->stat_compr_blocks++;
  4337. + best->stat_compr_orig_size += best_slen;
  4338. + best->stat_compr_new_size += best_dlen;
  4339. + ret = best->compr;
  4340. + }
  4341. + spin_unlock(&jffs2_compressor_list_lock);
  4342. + break;
  4343. + default:
  4344. + printk(KERN_ERR "JFFS2: unknow compression mode.\n");
  4345. + }
  4346. out:
  4347. - if (ret == JFFS2_COMPR_NONE) {
  4348. - *cpage_out = data_in;
  4349. - *datalen = *cdatalen;
  4350. - none_stat_compr_blocks++;
  4351. - none_stat_compr_size += *datalen;
  4352. - }
  4353. - else {
  4354. - *cpage_out = output_buf;
  4355. - }
  4356. + if (ret == JFFS2_COMPR_NONE) {
  4357. + *cpage_out = data_in;
  4358. + *datalen = *cdatalen;
  4359. + none_stat_compr_blocks++;
  4360. + none_stat_compr_size += *datalen;
  4361. + }
  4362. + else {
  4363. + *cpage_out = output_buf;
  4364. + }
  4365. return ret;
  4366. }
  4367. @@ -165,8 +166,8 @@ int jffs2_decompress(struct jffs2_sb_inf
  4368. uint16_t comprtype, unsigned char *cdata_in,
  4369. unsigned char *data_out, uint32_t cdatalen, uint32_t datalen)
  4370. {
  4371. - struct jffs2_compressor *this;
  4372. - int ret;
  4373. + struct jffs2_compressor *this;
  4374. + int ret;
  4375. /* Older code had a bug where it would write non-zero 'usercompr'
  4376. fields. Deal with it. */
  4377. @@ -177,32 +178,32 @@ int jffs2_decompress(struct jffs2_sb_inf
  4378. case JFFS2_COMPR_NONE:
  4379. /* This should be special-cased elsewhere, but we might as well deal with it */
  4380. memcpy(data_out, cdata_in, datalen);
  4381. - none_stat_decompr_blocks++;
  4382. + none_stat_decompr_blocks++;
  4383. break;
  4384. case JFFS2_COMPR_ZERO:
  4385. memset(data_out, 0, datalen);
  4386. break;
  4387. default:
  4388. - spin_lock(&jffs2_compressor_list_lock);
  4389. - list_for_each_entry(this, &jffs2_compressor_list, list) {
  4390. - if (comprtype == this->compr) {
  4391. - this->usecount++;
  4392. - spin_unlock(&jffs2_compressor_list_lock);
  4393. - ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL);
  4394. - spin_lock(&jffs2_compressor_list_lock);
  4395. - if (ret) {
  4396. - printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret);
  4397. - }
  4398. - else {
  4399. - this->stat_decompr_blocks++;
  4400. - }
  4401. - this->usecount--;
  4402. - spin_unlock(&jffs2_compressor_list_lock);
  4403. - return ret;
  4404. - }
  4405. - }
  4406. + spin_lock(&jffs2_compressor_list_lock);
  4407. + list_for_each_entry(this, &jffs2_compressor_list, list) {
  4408. + if (comprtype == this->compr) {
  4409. + this->usecount++;
  4410. + spin_unlock(&jffs2_compressor_list_lock);
  4411. + ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL);
  4412. + spin_lock(&jffs2_compressor_list_lock);
  4413. + if (ret) {
  4414. + printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret);
  4415. + }
  4416. + else {
  4417. + this->stat_decompr_blocks++;
  4418. + }
  4419. + this->usecount--;
  4420. + spin_unlock(&jffs2_compressor_list_lock);
  4421. + return ret;
  4422. + }
  4423. + }
  4424. printk(KERN_WARNING "JFFS2 compression type 0x%02x not available.\n", comprtype);
  4425. - spin_unlock(&jffs2_compressor_list_lock);
  4426. + spin_unlock(&jffs2_compressor_list_lock);
  4427. return -EIO;
  4428. }
  4429. return 0;
  4430. @@ -210,108 +211,108 @@ int jffs2_decompress(struct jffs2_sb_inf
  4431. int jffs2_register_compressor(struct jffs2_compressor *comp)
  4432. {
  4433. - struct jffs2_compressor *this;
  4434. + struct jffs2_compressor *this;
  4435. - if (!comp->name) {
  4436. - printk(KERN_WARNING "NULL compressor name at registering JFFS2 compressor. Failed.\n");
  4437. - return -1;
  4438. - }
  4439. - comp->compr_buf_size=0;
  4440. - comp->compr_buf=NULL;
  4441. - comp->usecount=0;
  4442. - comp->stat_compr_orig_size=0;
  4443. - comp->stat_compr_new_size=0;
  4444. - comp->stat_compr_blocks=0;
  4445. - comp->stat_decompr_blocks=0;
  4446. - D1(printk(KERN_DEBUG "Registering JFFS2 compressor \"%s\"\n", comp->name));
  4447. -
  4448. - spin_lock(&jffs2_compressor_list_lock);
  4449. -
  4450. - list_for_each_entry(this, &jffs2_compressor_list, list) {
  4451. - if (this->priority < comp->priority) {
  4452. - list_add(&comp->list, this->list.prev);
  4453. - goto out;
  4454. - }
  4455. - }
  4456. - list_add_tail(&comp->list, &jffs2_compressor_list);
  4457. + if (!comp->name) {
  4458. + printk(KERN_WARNING "NULL compressor name at registering JFFS2 compressor. Failed.\n");
  4459. + return -1;
  4460. + }
  4461. + comp->compr_buf_size=0;
  4462. + comp->compr_buf=NULL;
  4463. + comp->usecount=0;
  4464. + comp->stat_compr_orig_size=0;
  4465. + comp->stat_compr_new_size=0;
  4466. + comp->stat_compr_blocks=0;
  4467. + comp->stat_decompr_blocks=0;
  4468. + D1(printk(KERN_DEBUG "Registering JFFS2 compressor \"%s\"\n", comp->name));
  4469. +
  4470. + spin_lock(&jffs2_compressor_list_lock);
  4471. +
  4472. + list_for_each_entry(this, &jffs2_compressor_list, list) {
  4473. + if (this->priority < comp->priority) {
  4474. + list_add(&comp->list, this->list.prev);
  4475. + goto out;
  4476. + }
  4477. + }
  4478. + list_add_tail(&comp->list, &jffs2_compressor_list);
  4479. out:
  4480. - D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
  4481. - printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
  4482. - })
  4483. + D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
  4484. + printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
  4485. + })
  4486. - spin_unlock(&jffs2_compressor_list_lock);
  4487. + spin_unlock(&jffs2_compressor_list_lock);
  4488. - return 0;
  4489. + return 0;
  4490. }
  4491. int jffs2_unregister_compressor(struct jffs2_compressor *comp)
  4492. {
  4493. - D2(struct jffs2_compressor *this;)
  4494. + D2(struct jffs2_compressor *this;)
  4495. +
  4496. + D1(printk(KERN_DEBUG "Unregistering JFFS2 compressor \"%s\"\n", comp->name));
  4497. - D1(printk(KERN_DEBUG "Unregistering JFFS2 compressor \"%s\"\n", comp->name));
  4498. + spin_lock(&jffs2_compressor_list_lock);
  4499. - spin_lock(&jffs2_compressor_list_lock);
  4500. + if (comp->usecount) {
  4501. + spin_unlock(&jffs2_compressor_list_lock);
  4502. + printk(KERN_WARNING "JFFS2: Compressor modul is in use. Unregister failed.\n");
  4503. + return -1;
  4504. + }
  4505. + list_del(&comp->list);
  4506. - if (comp->usecount) {
  4507. - spin_unlock(&jffs2_compressor_list_lock);
  4508. - printk(KERN_WARNING "JFFS2: Compressor modul is in use. Unregister failed.\n");
  4509. - return -1;
  4510. - }
  4511. - list_del(&comp->list);
  4512. -
  4513. - D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
  4514. - printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
  4515. - })
  4516. - spin_unlock(&jffs2_compressor_list_lock);
  4517. - return 0;
  4518. + D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
  4519. + printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
  4520. + })
  4521. + spin_unlock(&jffs2_compressor_list_lock);
  4522. + return 0;
  4523. }
  4524. void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
  4525. {
  4526. - if (orig != comprbuf)
  4527. - kfree(comprbuf);
  4528. + if (orig != comprbuf)
  4529. + kfree(comprbuf);
  4530. }
  4531. int __init jffs2_compressors_init(void)
  4532. {
  4533. /* Registering compressors */
  4534. #ifdef CONFIG_JFFS2_ZLIB
  4535. - jffs2_zlib_init();
  4536. + jffs2_zlib_init();
  4537. #endif
  4538. #ifdef CONFIG_JFFS2_RTIME
  4539. - jffs2_rtime_init();
  4540. + jffs2_rtime_init();
  4541. #endif
  4542. #ifdef CONFIG_JFFS2_RUBIN
  4543. - jffs2_rubinmips_init();
  4544. - jffs2_dynrubin_init();
  4545. + jffs2_rubinmips_init();
  4546. + jffs2_dynrubin_init();
  4547. #endif
  4548. /* Setting default compression mode */
  4549. #ifdef CONFIG_JFFS2_CMODE_NONE
  4550. - jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
  4551. - D1(printk(KERN_INFO "JFFS2: default compression mode: none\n");)
  4552. + jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
  4553. + D1(printk(KERN_INFO "JFFS2: default compression mode: none\n");)
  4554. #else
  4555. #ifdef CONFIG_JFFS2_CMODE_SIZE
  4556. - jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
  4557. - D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");)
  4558. + jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
  4559. + D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");)
  4560. #else
  4561. - D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");)
  4562. + D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");)
  4563. #endif
  4564. #endif
  4565. - return 0;
  4566. + return 0;
  4567. }
  4568. int jffs2_compressors_exit(void)
  4569. {
  4570. /* Unregistering compressors */
  4571. #ifdef CONFIG_JFFS2_RUBIN
  4572. - jffs2_dynrubin_exit();
  4573. - jffs2_rubinmips_exit();
  4574. + jffs2_dynrubin_exit();
  4575. + jffs2_rubinmips_exit();
  4576. #endif
  4577. #ifdef CONFIG_JFFS2_RTIME
  4578. - jffs2_rtime_exit();
  4579. + jffs2_rtime_exit();
  4580. #endif
  4581. #ifdef CONFIG_JFFS2_ZLIB
  4582. - jffs2_zlib_exit();
  4583. + jffs2_zlib_exit();
  4584. #endif
  4585. - return 0;
  4586. + return 0;
  4587. }
  4588. Index: linux-2.6.23.17/fs/jffs2/compr.h
  4589. ===================================================================
  4590. --- linux-2.6.23.17.orig/fs/jffs2/compr.h
  4591. +++ linux-2.6.23.17/fs/jffs2/compr.h
  4592. @@ -2,7 +2,7 @@
  4593. * JFFS2 -- Journalling Flash File System, Version 2.
  4594. *
  4595. * Copyright © 2004 Ferenc Havasi <[email protected]>,
  4596. - * University of Szeged, Hungary
  4597. + * University of Szeged, Hungary
  4598. *
  4599. * For licensing information, see the file 'LICENCE' in this directory.
  4600. *
  4601. @@ -32,29 +32,29 @@
  4602. #define JFFS2_ZLIB_PRIORITY 60
  4603. #define JFFS2_RUBINMIPS_DISABLED /* RUBINs will be used only */
  4604. -#define JFFS2_DYNRUBIN_DISABLED /* for decompression */
  4605. +#define JFFS2_DYNRUBIN_DISABLED /* for decompression */
  4606. #define JFFS2_COMPR_MODE_NONE 0
  4607. #define JFFS2_COMPR_MODE_PRIORITY 1
  4608. #define JFFS2_COMPR_MODE_SIZE 2
  4609. struct jffs2_compressor {
  4610. - struct list_head list;
  4611. - int priority; /* used by prirority comr. mode */
  4612. - char *name;
  4613. - char compr; /* JFFS2_COMPR_XXX */
  4614. - int (*compress)(unsigned char *data_in, unsigned char *cpage_out,
  4615. - uint32_t *srclen, uint32_t *destlen, void *model);
  4616. - int (*decompress)(unsigned char *cdata_in, unsigned char *data_out,
  4617. - uint32_t cdatalen, uint32_t datalen, void *model);
  4618. - int usecount;
  4619. - int disabled; /* if seted the compressor won't compress */
  4620. - unsigned char *compr_buf; /* used by size compr. mode */
  4621. - uint32_t compr_buf_size; /* used by size compr. mode */
  4622. - uint32_t stat_compr_orig_size;
  4623. - uint32_t stat_compr_new_size;
  4624. - uint32_t stat_compr_blocks;
  4625. - uint32_t stat_decompr_blocks;
  4626. + struct list_head list;
  4627. + int priority; /* used by prirority comr. mode */
  4628. + char *name;
  4629. + char compr; /* JFFS2_COMPR_XXX */
  4630. + int (*compress)(unsigned char *data_in, unsigned char *cpage_out,
  4631. + uint32_t *srclen, uint32_t *destlen, void *model);
  4632. + int (*decompress)(unsigned char *cdata_in, unsigned char *data_out,
  4633. + uint32_t cdatalen, uint32_t datalen, void *model);
  4634. + int usecount;
  4635. + int disabled; /* if set the compressor won't compress */
  4636. + unsigned char *compr_buf; /* used by size compr. mode */
  4637. + uint32_t compr_buf_size; /* used by size compr. mode */
  4638. + uint32_t stat_compr_orig_size;
  4639. + uint32_t stat_compr_new_size;
  4640. + uint32_t stat_compr_blocks;
  4641. + uint32_t stat_decompr_blocks;
  4642. };
  4643. int jffs2_register_compressor(struct jffs2_compressor *comp);
  4644. @@ -64,12 +64,12 @@ int jffs2_compressors_init(void);
  4645. int jffs2_compressors_exit(void);
  4646. uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
  4647. - unsigned char *data_in, unsigned char **cpage_out,
  4648. - uint32_t *datalen, uint32_t *cdatalen);
  4649. + unsigned char *data_in, unsigned char **cpage_out,
  4650. + uint32_t *datalen, uint32_t *cdatalen);
  4651. int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
  4652. - uint16_t comprtype, unsigned char *cdata_in,
  4653. - unsigned char *data_out, uint32_t cdatalen, uint32_t datalen);
  4654. + uint16_t comprtype, unsigned char *cdata_in,
  4655. + unsigned char *data_out, uint32_t cdatalen, uint32_t datalen);
  4656. void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig);
  4657. Index: linux-2.6.23.17/fs/jffs2/compr_rtime.c
  4658. ===================================================================
  4659. --- linux-2.6.23.17.orig/fs/jffs2/compr_rtime.c
  4660. +++ linux-2.6.23.17/fs/jffs2/compr_rtime.c
  4661. @@ -104,7 +104,7 @@ static int jffs2_rtime_decompress(unsign
  4662. }
  4663. }
  4664. }
  4665. - return 0;
  4666. + return 0;
  4667. }
  4668. static struct jffs2_compressor jffs2_rtime_comp = {
  4669. Index: linux-2.6.23.17/fs/jffs2/compr_rubin.c
  4670. ===================================================================
  4671. --- linux-2.6.23.17.orig/fs/jffs2/compr_rubin.c
  4672. +++ linux-2.6.23.17/fs/jffs2/compr_rubin.c
  4673. @@ -384,7 +384,7 @@ static int jffs2_rubinmips_decompress(un
  4674. void *model)
  4675. {
  4676. rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen);
  4677. - return 0;
  4678. + return 0;
  4679. }
  4680. static int jffs2_dynrubin_decompress(unsigned char *data_in,
  4681. @@ -399,7 +399,7 @@ static int jffs2_dynrubin_decompress(uns
  4682. bits[c] = data_in[c];
  4683. rubin_do_decompress(256, bits, data_in+8, cpage_out, sourcelen-8, dstlen);
  4684. - return 0;
  4685. + return 0;
  4686. }
  4687. static struct jffs2_compressor jffs2_rubinmips_comp = {
  4688. Index: linux-2.6.23.17/fs/jffs2/compr_zlib.c
  4689. ===================================================================
  4690. --- linux-2.6.23.17.orig/fs/jffs2/compr_zlib.c
  4691. +++ linux-2.6.23.17/fs/jffs2/compr_zlib.c
  4692. @@ -181,7 +181,7 @@ static int jffs2_zlib_decompress(unsigne
  4693. }
  4694. zlib_inflateEnd(&inf_strm);
  4695. mutex_unlock(&inflate_mutex);
  4696. - return 0;
  4697. + return 0;
  4698. }
  4699. static struct jffs2_compressor jffs2_zlib_comp = {
  4700. @@ -203,11 +203,11 @@ int __init jffs2_zlib_init(void)
  4701. ret = alloc_workspaces();
  4702. if (ret)
  4703. - return ret;
  4704. + return ret;
  4705. ret = jffs2_register_compressor(&jffs2_zlib_comp);
  4706. if (ret)
  4707. - free_workspaces();
  4708. + free_workspaces();
  4709. return ret;
  4710. }
  4711. Index: linux-2.6.23.17/fs/jffs2/dir.c
  4712. ===================================================================
  4713. --- linux-2.6.23.17.orig/fs/jffs2/dir.c
  4714. +++ linux-2.6.23.17/fs/jffs2/dir.c
  4715. @@ -32,7 +32,7 @@ static int jffs2_mkdir (struct inode *,s
  4716. static int jffs2_rmdir (struct inode *,struct dentry *);
  4717. static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t);
  4718. static int jffs2_rename (struct inode *, struct dentry *,
  4719. - struct inode *, struct dentry *);
  4720. + struct inode *, struct dentry *);
  4721. const struct file_operations jffs2_dir_operations =
  4722. {
  4723. @@ -770,7 +770,7 @@ static int jffs2_mknod (struct inode *di
  4724. }
  4725. static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
  4726. - struct inode *new_dir_i, struct dentry *new_dentry)
  4727. + struct inode *new_dir_i, struct dentry *new_dentry)
  4728. {
  4729. int ret;
  4730. struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
  4731. Index: linux-2.6.23.17/fs/jffs2/erase.c
  4732. ===================================================================
  4733. --- linux-2.6.23.17.orig/fs/jffs2/erase.c
  4734. +++ linux-2.6.23.17/fs/jffs2/erase.c
  4735. @@ -38,8 +38,8 @@ static void jffs2_erase_block(struct jff
  4736. #ifdef __ECOS
  4737. ret = jffs2_flash_erase(c, jeb);
  4738. if (!ret) {
  4739. - jffs2_erase_succeeded(c, jeb);
  4740. - return;
  4741. + jffs2_erase_succeeded(c, jeb);
  4742. + return;
  4743. }
  4744. bad_offset = jeb->offset;
  4745. #else /* Linux */
  4746. @@ -50,12 +50,14 @@ static void jffs2_erase_block(struct jff
  4747. instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL);
  4748. if (!instr) {
  4749. printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n");
  4750. + down(&c->erase_free_sem);
  4751. spin_lock(&c->erase_completion_lock);
  4752. list_move(&jeb->list, &c->erase_pending_list);
  4753. c->erasing_size -= c->sector_size;
  4754. c->dirty_size += c->sector_size;
  4755. jeb->dirty_size = c->sector_size;
  4756. spin_unlock(&c->erase_completion_lock);
  4757. + up(&c->erase_free_sem);
  4758. return;
  4759. }
  4760. @@ -82,12 +84,14 @@ static void jffs2_erase_block(struct jff
  4761. if (ret == -ENOMEM || ret == -EAGAIN) {
  4762. /* Erase failed immediately. Refile it on the list */
  4763. D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret));
  4764. + down(&c->erase_free_sem);
  4765. spin_lock(&c->erase_completion_lock);
  4766. list_move(&jeb->list, &c->erase_pending_list);
  4767. c->erasing_size -= c->sector_size;
  4768. c->dirty_size += c->sector_size;
  4769. jeb->dirty_size = c->sector_size;
  4770. spin_unlock(&c->erase_completion_lock);
  4771. + up(&c->erase_free_sem);
  4772. return;
  4773. }
  4774. @@ -114,6 +118,7 @@ void jffs2_erase_pending_blocks(struct j
  4775. jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list);
  4776. list_del(&jeb->list);
  4777. spin_unlock(&c->erase_completion_lock);
  4778. + up(&c->erase_free_sem);
  4779. jffs2_mark_erased_block(c, jeb);
  4780. if (!--count) {
  4781. @@ -134,6 +139,7 @@ void jffs2_erase_pending_blocks(struct j
  4782. jffs2_free_jeb_node_refs(c, jeb);
  4783. list_add(&jeb->list, &c->erasing_list);
  4784. spin_unlock(&c->erase_completion_lock);
  4785. + up(&c->erase_free_sem);
  4786. jffs2_erase_block(c, jeb);
  4787. @@ -142,23 +148,25 @@ void jffs2_erase_pending_blocks(struct j
  4788. }
  4789. /* Be nice */
  4790. - cond_resched();
  4791. + yield();
  4792. + down(&c->erase_free_sem);
  4793. spin_lock(&c->erase_completion_lock);
  4794. }
  4795. spin_unlock(&c->erase_completion_lock);
  4796. + up(&c->erase_free_sem);
  4797. done:
  4798. D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n"));
  4799. -
  4800. - up(&c->erase_free_sem);
  4801. }
  4802. static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
  4803. {
  4804. D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset));
  4805. + down(&c->erase_free_sem);
  4806. spin_lock(&c->erase_completion_lock);
  4807. list_move_tail(&jeb->list, &c->erase_complete_list);
  4808. spin_unlock(&c->erase_completion_lock);
  4809. + up(&c->erase_free_sem);
  4810. /* Ensure that kupdated calls us again to mark them clean */
  4811. jffs2_erase_pending_trigger(c);
  4812. }
  4813. @@ -172,22 +180,26 @@ static void jffs2_erase_failed(struct jf
  4814. failed too many times. */
  4815. if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) {
  4816. /* We'd like to give this block another try. */
  4817. + down(&c->erase_free_sem);
  4818. spin_lock(&c->erase_completion_lock);
  4819. list_move(&jeb->list, &c->erase_pending_list);
  4820. c->erasing_size -= c->sector_size;
  4821. c->dirty_size += c->sector_size;
  4822. jeb->dirty_size = c->sector_size;
  4823. spin_unlock(&c->erase_completion_lock);
  4824. + up(&c->erase_free_sem);
  4825. return;
  4826. }
  4827. }
  4828. + down(&c->erase_free_sem);
  4829. spin_lock(&c->erase_completion_lock);
  4830. c->erasing_size -= c->sector_size;
  4831. c->bad_size += c->sector_size;
  4832. list_move(&jeb->list, &c->bad_list);
  4833. c->nr_erasing_blocks--;
  4834. spin_unlock(&c->erase_completion_lock);
  4835. + up(&c->erase_free_sem);
  4836. wake_up(&c->erase_wait);
  4837. }
  4838. @@ -317,6 +329,33 @@ static int jffs2_block_check_erase(struc
  4839. size_t retlen;
  4840. int ret = -EIO;
  4841. + if (c->mtd->point) {
  4842. + unsigned long *wordebuf;
  4843. +
  4844. + ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size, &retlen, (unsigned char **)&ebuf);
  4845. + if (ret) {
  4846. + D1(printk(KERN_DEBUG "MTD point failed %d\n", ret));
  4847. + goto do_flash_read;
  4848. + }
  4849. + if (retlen < c->sector_size) {
  4850. + /* Don't muck about if it won't let us point to the whole erase sector */
  4851. + D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", retlen));
  4852. + c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size);
  4853. + goto do_flash_read;
  4854. + }
  4855. + wordebuf = ebuf-sizeof(*wordebuf);
  4856. + retlen /= sizeof(*wordebuf);
  4857. + do {
  4858. + if (*++wordebuf != ~0)
  4859. + break;
  4860. + } while(--retlen);
  4861. + c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size);
  4862. + if (retlen)
  4863. + printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08x\n",
  4864. + *wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf));
  4865. + return 0;
  4866. + }
  4867. + do_flash_read:
  4868. ebuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
  4869. if (!ebuf) {
  4870. printk(KERN_WARNING "Failed to allocate page buffer for verifying erase at 0x%08x. Refiling\n", jeb->offset);
  4871. @@ -417,6 +456,7 @@ static void jffs2_mark_erased_block(stru
  4872. jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
  4873. }
  4874. + down(&c->erase_free_sem);
  4875. spin_lock(&c->erase_completion_lock);
  4876. c->erasing_size -= c->sector_size;
  4877. c->free_size += jeb->free_size;
  4878. @@ -429,23 +469,28 @@ static void jffs2_mark_erased_block(stru
  4879. c->nr_erasing_blocks--;
  4880. c->nr_free_blocks++;
  4881. spin_unlock(&c->erase_completion_lock);
  4882. + up(&c->erase_free_sem);
  4883. wake_up(&c->erase_wait);
  4884. return;
  4885. filebad:
  4886. + down(&c->erase_free_sem);
  4887. spin_lock(&c->erase_completion_lock);
  4888. /* Stick it on a list (any list) so erase_failed can take it
  4889. right off again. Silly, but shouldn't happen often. */
  4890. list_add(&jeb->list, &c->erasing_list);
  4891. spin_unlock(&c->erase_completion_lock);
  4892. + up(&c->erase_free_sem);
  4893. jffs2_erase_failed(c, jeb, bad_offset);
  4894. return;
  4895. refile:
  4896. /* Stick it back on the list from whence it came and come back later */
  4897. jffs2_erase_pending_trigger(c);
  4898. + down(&c->erase_free_sem);
  4899. spin_lock(&c->erase_completion_lock);
  4900. list_add(&jeb->list, &c->erase_complete_list);
  4901. spin_unlock(&c->erase_completion_lock);
  4902. + up(&c->erase_free_sem);
  4903. return;
  4904. }
  4905. Index: linux-2.6.23.17/fs/jffs2/gc.c
  4906. ===================================================================
  4907. --- linux-2.6.23.17.orig/fs/jffs2/gc.c
  4908. +++ linux-2.6.23.17/fs/jffs2/gc.c
  4909. @@ -556,7 +556,7 @@ static int jffs2_garbage_collect_pristin
  4910. node = kmalloc(rawlen, GFP_KERNEL);
  4911. if (!node)
  4912. - return -ENOMEM;
  4913. + return -ENOMEM;
  4914. ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)node);
  4915. if (!ret && retlen != rawlen)
  4916. @@ -624,7 +624,7 @@ static int jffs2_garbage_collect_pristin
  4917. if (ret || (retlen != rawlen)) {
  4918. printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n",
  4919. - rawlen, phys_ofs, ret, retlen);
  4920. + rawlen, phys_ofs, ret, retlen);
  4921. if (retlen) {
  4922. jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL);
  4923. } else {
  4924. Index: linux-2.6.23.17/fs/jffs2/jffs2_fs_sb.h
  4925. ===================================================================
  4926. --- linux-2.6.23.17.orig/fs/jffs2/jffs2_fs_sb.h
  4927. +++ linux-2.6.23.17/fs/jffs2/jffs2_fs_sb.h
  4928. @@ -106,6 +106,9 @@ struct jffs2_sb_info {
  4929. uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
  4930. +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
  4931. + unsigned char *wbuf_verify; /* read-back buffer for verification */
  4932. +#endif
  4933. #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
  4934. unsigned char *wbuf; /* Write-behind buffer for NAND flash */
  4935. uint32_t wbuf_ofs;
  4936. Index: linux-2.6.23.17/fs/jffs2/nodelist.h
  4937. ===================================================================
  4938. --- linux-2.6.23.17.orig/fs/jffs2/nodelist.h
  4939. +++ linux-2.6.23.17/fs/jffs2/nodelist.h
  4940. @@ -127,7 +127,7 @@ static inline struct jffs2_inode_cache *
  4941. return ((struct jffs2_inode_cache *)raw);
  4942. }
  4943. - /* flash_offset & 3 always has to be zero, because nodes are
  4944. + /* flash_offset & 3 always has to be zero, because nodes are
  4945. always aligned at 4 bytes. So we have a couple of extra bits
  4946. to play with, which indicate the node's status; see below: */
  4947. #define REF_UNCHECKED 0 /* We haven't yet checked the CRC or built its inode */
  4948. @@ -197,7 +197,7 @@ struct jffs2_inode_cache {
  4949. #define RAWNODE_CLASS_XATTR_DATUM 1
  4950. #define RAWNODE_CLASS_XATTR_REF 2
  4951. -#define INOCACHE_HASHSIZE 128
  4952. +#define INOCACHE_HASHSIZE 1024
  4953. #define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size)
  4954. Index: linux-2.6.23.17/fs/jffs2/nodemgmt.c
  4955. ===================================================================
  4956. --- linux-2.6.23.17.orig/fs/jffs2/nodemgmt.c
  4957. +++ linux-2.6.23.17/fs/jffs2/nodemgmt.c
  4958. @@ -154,7 +154,7 @@ int jffs2_reserve_space_gc(struct jffs2_
  4959. while(ret == -EAGAIN) {
  4960. ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
  4961. if (ret) {
  4962. - D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret));
  4963. + D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret));
  4964. }
  4965. }
  4966. spin_unlock(&c->erase_completion_lock);
  4967. @@ -423,7 +423,12 @@ struct jffs2_raw_node_ref *jffs2_add_phy
  4968. even after refiling c->nextblock */
  4969. if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE))
  4970. && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) {
  4971. - printk(KERN_WARNING "argh. node added in wrong place\n");
  4972. + printk(KERN_WARNING "argh. node added in wrong place at 0x%08x(%d)\n", ofs & ~3, ofs & 3);
  4973. + if (c->nextblock)
  4974. + printk(KERN_WARNING "nextblock 0x%08x", c->nextblock->offset);
  4975. + else
  4976. + printk(KERN_WARNING "No nextblock");
  4977. + printk(", expected at %08x\n", jeb->offset + (c->sector_size - jeb->free_size));
  4978. return ERR_PTR(-EINVAL);
  4979. }
  4980. #endif
  4981. Index: linux-2.6.23.17/fs/jffs2/readinode.c
  4982. ===================================================================
  4983. --- linux-2.6.23.17.orig/fs/jffs2/readinode.c
  4984. +++ linux-2.6.23.17/fs/jffs2/readinode.c
  4985. @@ -211,7 +211,7 @@ static void jffs2_kill_tn(struct jffs2_s
  4986. * ordering.
  4987. *
  4988. * Returns 0 if the node was handled (including marking it obsolete)
  4989. - * < 0 an if error occurred
  4990. + * < 0 an if error occurred
  4991. */
  4992. static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
  4993. struct jffs2_readinode_info *rii,
  4994. @@ -862,8 +862,8 @@ static inline int read_unknown(struct jf
  4995. JFFS2_ERROR("REF_UNCHECKED but unknown node at %#08x\n",
  4996. ref_offset(ref));
  4997. JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n",
  4998. - je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
  4999. - je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc));
  5000. + je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
  5001. + je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc));
  5002. jffs2_mark_node_obsolete(c, ref);
  5003. return 0;
  5004. }
  5005. Index: linux-2.6.23.17/fs/jffs2/scan.c
  5006. ===================================================================
  5007. --- linux-2.6.23.17.orig/fs/jffs2/scan.c
  5008. +++ linux-2.6.23.17/fs/jffs2/scan.c
  5009. @@ -877,7 +877,7 @@ scan_more:
  5010. switch (je16_to_cpu(node->nodetype) & JFFS2_COMPAT_MASK) {
  5011. case JFFS2_FEATURE_ROCOMPAT:
  5012. printk(KERN_NOTICE "Read-only compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs);
  5013. - c->flags |= JFFS2_SB_FLAG_RO;
  5014. + c->flags |= JFFS2_SB_FLAG_RO;
  5015. if (!(jffs2_is_readonly(c)))
  5016. return -EROFS;
  5017. if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
  5018. Index: linux-2.6.23.17/fs/jffs2/security.c
  5019. ===================================================================
  5020. --- linux-2.6.23.17.orig/fs/jffs2/security.c
  5021. +++ linux-2.6.23.17/fs/jffs2/security.c
  5022. @@ -38,9 +38,9 @@ int jffs2_init_security(struct inode *in
  5023. }
  5024. rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0);
  5025. - kfree(name);
  5026. - kfree(value);
  5027. - return rc;
  5028. + kfree(name);
  5029. + kfree(value);
  5030. + return rc;
  5031. }
  5032. /* ---- XATTR Handler for "security.*" ----------------- */
  5033. Index: linux-2.6.23.17/fs/jffs2/summary.c
  5034. ===================================================================
  5035. --- linux-2.6.23.17.orig/fs/jffs2/summary.c
  5036. +++ linux-2.6.23.17/fs/jffs2/summary.c
  5037. @@ -2,10 +2,10 @@
  5038. * JFFS2 -- Journalling Flash File System, Version 2.
  5039. *
  5040. * Copyright © 2004 Ferenc Havasi <[email protected]>,
  5041. - * Zoltan Sogor <[email protected]>,
  5042. - * Patrik Kluba <[email protected]>,
  5043. - * University of Szeged, Hungary
  5044. - * 2006 KaiGai Kohei <[email protected]>
  5045. + * Zoltan Sogor <[email protected]>,
  5046. + * Patrik Kluba <[email protected]>,
  5047. + * University of Szeged, Hungary
  5048. + * 2006 KaiGai Kohei <[email protected]>
  5049. *
  5050. * For licensing information, see the file 'LICENCE' in this directory.
  5051. *
  5052. Index: linux-2.6.23.17/fs/jffs2/summary.h
  5053. ===================================================================
  5054. --- linux-2.6.23.17.orig/fs/jffs2/summary.h
  5055. +++ linux-2.6.23.17/fs/jffs2/summary.h
  5056. @@ -2,9 +2,9 @@
  5057. * JFFS2 -- Journalling Flash File System, Version 2.
  5058. *
  5059. * Copyright © 2004 Ferenc Havasi <[email protected]>,
  5060. - * Zoltan Sogor <[email protected]>,
  5061. - * Patrik Kluba <[email protected]>,
  5062. - * University of Szeged, Hungary
  5063. + * Zoltan Sogor <[email protected]>,
  5064. + * Patrik Kluba <[email protected]>,
  5065. + * University of Szeged, Hungary
  5066. *
  5067. * For licensing information, see the file 'LICENCE' in this directory.
  5068. *
  5069. Index: linux-2.6.23.17/fs/jffs2/wbuf.c
  5070. ===================================================================
  5071. --- linux-2.6.23.17.orig/fs/jffs2/wbuf.c
  5072. +++ linux-2.6.23.17/fs/jffs2/wbuf.c
  5073. @@ -220,6 +220,47 @@ static struct jffs2_raw_node_ref **jffs2
  5074. return NULL;
  5075. }
  5076. +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
  5077. +static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf,
  5078. + uint32_t ofs)
  5079. +{
  5080. + int ret;
  5081. + size_t retlen;
  5082. + char *eccstr;
  5083. +
  5084. + ret = c->mtd->read(c->mtd, ofs, c->wbuf_pagesize, &retlen, c->wbuf_verify);
  5085. + if (ret && ret != -EUCLEAN && ret != -EBADMSG) {
  5086. + printk(KERN_WARNING "jffs2_verify_write(): Read back of page at %08x failed: %d\n", c->wbuf_ofs, ret);
  5087. + return ret;
  5088. + } else if (retlen != c->wbuf_pagesize) {
  5089. + printk(KERN_WARNING "jffs2_verify_write(): Read back of page at %08x gave short read: %zd not %d.\n", ofs, retlen, c->wbuf_pagesize);
  5090. + return -EIO;
  5091. + }
  5092. + if (!memcmp(buf, c->wbuf_verify, c->wbuf_pagesize))
  5093. + return 0;
  5094. +
  5095. + if (ret == -EUCLEAN)
  5096. + eccstr = "corrected";
  5097. + else if (ret == -EBADMSG)
  5098. + eccstr = "correction failed";
  5099. + else
  5100. + eccstr = "OK or unused";
  5101. +
  5102. + printk(KERN_WARNING "Write verify error (ECC %s) at %08x. Wrote:\n",
  5103. + eccstr, c->wbuf_ofs);
  5104. + print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
  5105. + c->wbuf, c->wbuf_pagesize, 0);
  5106. +
  5107. + printk(KERN_WARNING "Read back:\n");
  5108. + print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
  5109. + c->wbuf_verify, c->wbuf_pagesize, 0);
  5110. +
  5111. + return -EIO;
  5112. +}
  5113. +#else
  5114. +#define jffs2_verify_write(c,b,o) (0)
  5115. +#endif
  5116. +
  5117. /* Recover from failure to write wbuf. Recover the nodes up to the
  5118. * wbuf, not the one which we were starting to try to write. */
  5119. @@ -380,7 +421,7 @@ static void jffs2_wbuf_recover(struct jf
  5120. ret = c->mtd->write(c->mtd, ofs, towrite, &retlen,
  5121. rewrite_buf);
  5122. - if (ret || retlen != towrite) {
  5123. + if (ret || retlen != towrite || jffs2_verify_write(c, rewrite_buf, ofs)) {
  5124. /* Argh. We tried. Really we did. */
  5125. printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n");
  5126. kfree(buf);
  5127. @@ -587,15 +628,16 @@ static int __jffs2_flush_wbuf(struct jff
  5128. ret = c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf);
  5129. - if (ret || retlen != c->wbuf_pagesize) {
  5130. - if (ret)
  5131. - printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n",ret);
  5132. - else {
  5133. - printk(KERN_WARNING "jffs2_flush_wbuf(): Write was short: %zd instead of %d\n",
  5134. - retlen, c->wbuf_pagesize);
  5135. - ret = -EIO;
  5136. - }
  5137. -
  5138. + if (ret) {
  5139. + printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n", ret);
  5140. + goto wfail;
  5141. + } else if (retlen != c->wbuf_pagesize) {
  5142. + printk(KERN_WARNING "jffs2_flush_wbuf(): Write was short: %zd instead of %d\n",
  5143. + retlen, c->wbuf_pagesize);
  5144. + ret = -EIO;
  5145. + goto wfail;
  5146. + } else if ((ret = jffs2_verify_write(c, c->wbuf, c->wbuf_ofs))) {
  5147. + wfail:
  5148. jffs2_wbuf_recover(c);
  5149. return ret;
  5150. @@ -966,8 +1008,8 @@ exit:
  5151. #define NR_OOB_SCAN_PAGES 4
  5152. -/* For historical reasons we use only 12 bytes for OOB clean marker */
  5153. -#define OOB_CM_SIZE 12
  5154. +/* For historical reasons we use only 8 bytes for OOB clean marker */
  5155. +#define OOB_CM_SIZE 8
  5156. static const struct jffs2_unknown_node oob_cleanmarker =
  5157. {
  5158. @@ -1021,8 +1063,8 @@ int jffs2_check_oob_empty(struct jffs2_s
  5159. /*
  5160. * Check for a valid cleanmarker.
  5161. * Returns: 0 if a valid cleanmarker was found
  5162. - * 1 if no cleanmarker was found
  5163. - * negative error code if an error occurred
  5164. + * 1 if no cleanmarker was found
  5165. + * negative error code if an error occurred
  5166. */
  5167. int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c,
  5168. struct jffs2_eraseblock *jeb)
  5169. @@ -1138,11 +1180,22 @@ int jffs2_nand_flash_setup(struct jffs2_
  5170. return -ENOMEM;
  5171. }
  5172. +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
  5173. + c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
  5174. + if (!c->wbuf_verify) {
  5175. + kfree(c->oobbuf);
  5176. + kfree(c->wbuf);
  5177. + return -ENOMEM;
  5178. + }
  5179. +#endif
  5180. return 0;
  5181. }
  5182. void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c)
  5183. {
  5184. +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
  5185. + kfree(c->wbuf_verify);
  5186. +#endif
  5187. kfree(c->wbuf);
  5188. kfree(c->oobbuf);
  5189. }
  5190. Index: linux-2.6.23.17/fs/jffs2/xattr.h
  5191. ===================================================================
  5192. --- linux-2.6.23.17.orig/fs/jffs2/xattr.h
  5193. +++ linux-2.6.23.17/fs/jffs2/xattr.h
  5194. @@ -75,7 +75,7 @@ extern void jffs2_build_xattr_subsystem(
  5195. extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c);
  5196. extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
  5197. - uint32_t xid, uint32_t version);
  5198. + uint32_t xid, uint32_t version);
  5199. extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
  5200. extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
  5201. Index: linux-2.6.23.17/fs/jffs2/xattr_user.c
  5202. ===================================================================
  5203. --- linux-2.6.23.17.orig/fs/jffs2/xattr_user.c
  5204. +++ linux-2.6.23.17/fs/jffs2/xattr_user.c
  5205. @@ -17,7 +17,7 @@
  5206. #include "nodelist.h"
  5207. static int jffs2_user_getxattr(struct inode *inode, const char *name,
  5208. - void *buffer, size_t size)
  5209. + void *buffer, size_t size)
  5210. {
  5211. if (!strcmp(name, ""))
  5212. return -EINVAL;
  5213. @@ -25,7 +25,7 @@ static int jffs2_user_getxattr(struct in
  5214. }
  5215. static int jffs2_user_setxattr(struct inode *inode, const char *name, const void *buffer,
  5216. - size_t size, int flags)
  5217. + size_t size, int flags)
  5218. {
  5219. if (!strcmp(name, ""))
  5220. return -EINVAL;
  5221. Index: linux-2.6.23.17/include/asm-i386/geode.h
  5222. ===================================================================
  5223. --- linux-2.6.23.17.orig/include/asm-i386/geode.h
  5224. +++ linux-2.6.23.17/include/asm-i386/geode.h
  5225. @@ -135,6 +135,55 @@ static inline void geode_gpio_event_pme(
  5226. geode_gpio_setup_event(gpio, pair, 1);
  5227. }
  5228. +/* MFGPT */
  5229. +
  5230. +#define MFGPT_TIMER_ANY -1
  5231. +
  5232. +#define MFGPT_DOMAIN_WORKING 1
  5233. +#define MFGPT_DOMAIN_STANDBY 2
  5234. +#define MFGPT_DOMAIN_ANY (MFGPT_DOMAIN_WORKING | MFGPT_DOMAIN_STANDBY)
  5235. +
  5236. +#define MFGPT_CMP1 0
  5237. +#define MFGPT_CMP2 1
  5238. +
  5239. +#define MFGPT_EVENT_IRQ 0
  5240. +#define MFGPT_EVENT_NMI 1
  5241. +#define MFGPT_EVENT_RESET 3
  5242. +
  5243. +#define MFGPT_REG_CMP1 0
  5244. +#define MFGPT_REG_CMP2 2
  5245. +#define MFGPT_REG_COUNTER 4
  5246. +#define MFGPT_REG_SETUP 6
  5247. +
  5248. +#define MFGPT_SETUP_CNTEN (1 << 15)
  5249. +#define MFGPT_SETUP_CMP2 (1 << 14)
  5250. +#define MFGPT_SETUP_CMP1 (1 << 13)
  5251. +#define MFGPT_SETUP_SETUP (1 << 12)
  5252. +#define MFGPT_SETUP_STOPEN (1 << 11)
  5253. +#define MFGPT_SETUP_EXTEN (1 << 10)
  5254. +#define MFGPT_SETUP_REVEN (1 << 5)
  5255. +#define MFGPT_SETUP_CLKSEL (1 << 4)
  5256. +
  5257. +static inline void geode_mfgpt_write(int timer, u16 reg, u16 value)
  5258. +{
  5259. + u32 base = geode_get_dev_base(GEODE_DEV_MFGPT);
  5260. + outw(value, base + reg + (timer * 8));
  5261. +}
  5262. +
  5263. +static inline u16 geode_mfgpt_read(int timer, u16 reg)
  5264. +{
  5265. + u32 base = geode_get_dev_base(GEODE_DEV_MFGPT);
  5266. + return inw(base + reg + (timer * 8));
  5267. +}
  5268. +
  5269. +extern int __init geode_mfgpt_detect(void);
  5270. +extern int geode_mfgpt_toggle_event(int timer, int cmp, int event, int enable);
  5271. +extern int geode_mfgpt_set_irq(int timer, int cmp, int irq, int enable);
  5272. +extern int geode_mfgpt_alloc_timer(int timer, int domain, struct module *owner);
  5273. +
  5274. +#define geode_mfgpt_setup_irq(t,c,i) geode_mfgpt_set_irq((t),(c),(i),1)
  5275. +#define geode_mfgpt_release_irq(t,c,i) geode_mfgpt_set_irq((t),(c),(i),0)
  5276. +
  5277. /* Specific geode tests */
  5278. static inline int is_geode_gx(void)
  5279. Index: linux-2.6.23.17/include/asm-i386/setup.h
  5280. ===================================================================
  5281. --- linux-2.6.23.17.orig/include/asm-i386/setup.h
  5282. +++ linux-2.6.23.17/include/asm-i386/setup.h
  5283. @@ -24,6 +24,7 @@
  5284. #define OLD_CL_BASE_ADDR 0x90000
  5285. #define OLD_CL_OFFSET 0x90022
  5286. #define NEW_CL_POINTER 0x228 /* Relative to real mode data */
  5287. +#define OFW_INFO_OFFSET 0xb0 /* Relative to real mode data */
  5288. #ifndef __ASSEMBLY__
  5289. Index: linux-2.6.23.17/include/linux/console.h
  5290. ===================================================================
  5291. --- linux-2.6.23.17.orig/include/linux/console.h
  5292. +++ linux-2.6.23.17/include/linux/console.h
  5293. @@ -121,14 +121,11 @@ extern void console_stop(struct console
  5294. extern void console_start(struct console *);
  5295. extern int is_console_locked(void);
  5296. -#ifndef CONFIG_DISABLE_CONSOLE_SUSPEND
  5297. +extern int serial_console_suspend_enabled;
  5298. +
  5299. /* Suspend and resume console messages over PM events */
  5300. extern void suspend_console(void);
  5301. extern void resume_console(void);
  5302. -#else
  5303. -static inline void suspend_console(void) {}
  5304. -static inline void resume_console(void) {}
  5305. -#endif /* CONFIG_DISABLE_CONSOLE_SUSPEND */
  5306. int mda_console_init(void);
  5307. void prom_con_init(void);
  5308. Index: linux-2.6.23.17/include/linux/fb.h
  5309. ===================================================================
  5310. --- linux-2.6.23.17.orig/include/linux/fb.h
  5311. +++ linux-2.6.23.17/include/linux/fb.h
  5312. @@ -664,6 +664,12 @@ struct fb_ops {
  5313. /* restore saved state */
  5314. void (*fb_restore_state)(struct fb_info *info);
  5315. + /* Shut down the graphics engine to save power */
  5316. + int (*fb_powerdown)(struct fb_info *info);
  5317. +
  5318. + /* Power it back up */
  5319. + int (*fb_powerup)(struct fb_info *info);
  5320. +
  5321. /* get capability given var */
  5322. void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,
  5323. struct fb_var_screeninfo *var);
  5324. @@ -943,6 +949,9 @@ extern int fb_get_color_depth(struct fb_
  5325. extern int fb_get_options(char *name, char **option);
  5326. extern int fb_new_modelist(struct fb_info *info);
  5327. +extern int fb_powerdown(struct fb_info *info);
  5328. +extern int fb_powerup(struct fb_info *info);
  5329. +
  5330. extern struct fb_info *registered_fb[FB_MAX];
  5331. extern int num_registered_fb;
  5332. extern struct class *fb_class;
  5333. Index: linux-2.6.23.17/include/linux/mtd/onenand.h
  5334. ===================================================================
  5335. --- linux-2.6.23.17.orig/include/linux/mtd/onenand.h
  5336. +++ linux-2.6.23.17/include/linux/mtd/onenand.h
  5337. @@ -60,6 +60,7 @@ struct onenand_bufferram {
  5338. * @erase_shift: [INTERN] number of address bits in a block
  5339. * @page_shift: [INTERN] number of address bits in a page
  5340. * @page_mask: [INTERN] a page per block mask
  5341. + * @writesize: [INTERN] a real page size
  5342. * @bufferram_index: [INTERN] BufferRAM index
  5343. * @bufferram: [INTERN] BufferRAM info
  5344. * @readw: [REPLACEABLE] hardware specific function for read short
  5345. @@ -100,6 +101,7 @@ struct onenand_chip {
  5346. unsigned int erase_shift;
  5347. unsigned int page_shift;
  5348. unsigned int page_mask;
  5349. + unsigned int writesize;
  5350. unsigned int bufferram_index;
  5351. struct onenand_bufferram bufferram[MAX_BUFFERRAM];
  5352. @@ -140,6 +142,8 @@ struct onenand_chip {
  5353. #define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1)
  5354. #define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1)
  5355. #define ONENAND_SET_PREV_BUFFERRAM(this) (this->bufferram_index ^= 1)
  5356. +#define ONENAND_SET_BUFFERRAM0(this) (this->bufferram_index = 0)
  5357. +#define ONENAND_SET_BUFFERRAM1(this) (this->bufferram_index = 1)
  5358. #define ONENAND_GET_SYS_CFG1(this) \
  5359. (this->read_word(this->base + ONENAND_REG_SYS_CFG1))
  5360. @@ -149,6 +153,13 @@ struct onenand_chip {
  5361. #define ONENAND_IS_DDP(this) \
  5362. (this->device_id & ONENAND_DEVICE_IS_DDP)
  5363. +#ifdef CONFIG_MTD_ONENAND_2X_PROGRAM
  5364. +#define ONENAND_IS_2PLANE(this) \
  5365. + (this->options & ONENAND_HAS_2PLANE)
  5366. +#else
  5367. +#define ONENAND_IS_2PLANE(this) (0)
  5368. +#endif
  5369. +
  5370. /* Check byte access in OneNAND */
  5371. #define ONENAND_CHECK_BYTE_ACCESS(addr) (addr & 0x1)
  5372. @@ -157,6 +168,7 @@ struct onenand_chip {
  5373. */
  5374. #define ONENAND_HAS_CONT_LOCK (0x0001)
  5375. #define ONENAND_HAS_UNLOCK_ALL (0x0002)
  5376. +#define ONENAND_HAS_2PLANE (0x0004)
  5377. #define ONENAND_PAGEBUF_ALLOC (0x1000)
  5378. #define ONENAND_OOBBUF_ALLOC (0x2000)
  5379. Index: linux-2.6.23.17/include/linux/mtd/onenand_regs.h
  5380. ===================================================================
  5381. --- linux-2.6.23.17.orig/include/linux/mtd/onenand_regs.h
  5382. +++ linux-2.6.23.17/include/linux/mtd/onenand_regs.h
  5383. @@ -74,6 +74,8 @@
  5384. #define ONENAND_DEVICE_DENSITY_512Mb (0x002)
  5385. #define ONENAND_DEVICE_DENSITY_1Gb (0x003)
  5386. +#define ONENAND_DEVICE_DENSITY_2Gb (0x004)
  5387. +#define ONENAND_DEVICE_DENSITY_4Gb (0x005)
  5388. /*
  5389. * Version ID Register F002h (R)
  5390. @@ -111,6 +113,8 @@
  5391. #define ONENAND_CMD_READOOB (0x13)
  5392. #define ONENAND_CMD_PROG (0x80)
  5393. #define ONENAND_CMD_PROGOOB (0x1A)
  5394. +#define ONENAND_CMD_2X_PROG (0x7D)
  5395. +#define ONENAND_CMD_2X_CACHE_PROG (0x7F)
  5396. #define ONENAND_CMD_UNLOCK (0x23)
  5397. #define ONENAND_CMD_LOCK (0x2A)
  5398. #define ONENAND_CMD_LOCK_TIGHT (0x2C)
  5399. Index: linux-2.6.23.17/include/linux/vt_kern.h
  5400. ===================================================================
  5401. --- linux-2.6.23.17.orig/include/linux/vt_kern.h
  5402. +++ linux-2.6.23.17/include/linux/vt_kern.h
  5403. @@ -95,4 +95,23 @@ struct vt_spawn_console {
  5404. };
  5405. extern struct vt_spawn_console vt_spawn_con;
  5406. +/* A notifier list for console events */
  5407. +extern struct raw_notifier_head console_notifier_list;
  5408. +
  5409. +/* Called when the FG console switches to KD_TEXT mode */
  5410. +#define CONSOLE_EVENT_SWITCH_TEXT 0x01
  5411. +
  5412. +/* Called when the FG console switches to KD_GRAPHICS mode */
  5413. +#define CONSOLE_EVENT_SWITCH_GRAPHICS 0x02
  5414. +
  5415. +static inline int console_event_register(struct notifier_block *n)
  5416. +{
  5417. + return raw_notifier_chain_register(&console_notifier_list, n);
  5418. +}
  5419. +
  5420. +static inline int console_event_unregister(struct notifier_block *n)
  5421. +{
  5422. + return raw_notifier_chain_unregister(&console_notifier_list, n);
  5423. +}
  5424. +
  5425. #endif /* _VT_KERN_H */
  5426. Index: linux-2.6.23.17/kernel/power/console.c
  5427. ===================================================================
  5428. --- linux-2.6.23.17.orig/kernel/power/console.c
  5429. +++ linux-2.6.23.17/kernel/power/console.c
  5430. @@ -9,7 +9,7 @@
  5431. #include <linux/console.h>
  5432. #include "power.h"
  5433. -#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE)
  5434. +#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) && !defined(CONFIG_DISABLE_SUSPEND_VT_SWITCH)
  5435. #define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1)
  5436. static int orig_fgconsole, orig_kmsg;