123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510245112451224513245142451524516245172451824519245202452124522245232452424525245262452724528245292453024531245322453324534245352453624537245382453924540245412454224543245442454524546245472454824549245502455124552245532455424555245562455724558245592456024561245622456324564245652456624567245682456924570245712457224573245742457524576245772457824579245802458124582245832458424585245862458724588245892459024591245922459324594245952459624597245982459924600246012460224603246042460524606246072460824609246102461124612246132461424615246162461724618246192462024621246222462324624246252462624627246282462924630246312463224633246342463524636246372463824639246402464124642246432464424645246462464724648246492465024651246522465324654246552465624657246582465924660246612466224663246642466524666246672466824669246702467124672246732467424675246762467724678246792468024681246822468324684246852468624687246882468924690246912469224693246942469524696246972469824699247002470124702247032470424705247062470724708247092471024711247122471324714247152471624717247182471924720247212472224723247242472524726247272472824729247302473124732247332473424735247362473724738247392474024741247422474324744247452474624747247482474924750247512475224753247542475524756247572475824759247602476124762247632476424765247662476724768247692477024771247722477324774247752477624777247782477924780247812478224783247842478524786247872478824789247902479124792247932479424795247962479724798247992480024801248022480324804248052480624807248082480924810248112481224813248142481524816248172481824819248202482124822248232482424825248262482724828248292483024831248322483324834248352483624837248382483924840248412484224843248442484524846248472484824849248502485124852248532485424855248562485724858248592486024861248622486324864248652486624867248682486924870248712487224873248742487524876248772487824879248802488124882248832488424885248862488724888248892489024891248922489324894248952489624897248982489924900249012490224903249042490524906249072490824909249102491124912249132491424915249162491724918249192492024921249222492324924249252492624927249282492924930249312493224933249342493524936249372493824939249402494124942249432494424945249462494724948249492495024951249522495324954249552495624957249582495924960249612496224963249642496524966249672496824969249702497124972249732497424975249762497724978249792498024981249822498324984249852498624987249882498924990249912499224993249942499524996249972499824999250002500125002250032500425005250062500725008250092501025011250122501325014250152501625017250182501925020250212502225023250242502525026250272502825029250302503125032250332503425035250362503725038250392504025041250422504325044250452504625047250482504925050250512505225053250542505525056250572505825059250602506125062250632506425065250662506725068250692507025071250722507325074250752507625077250782507925080250812508225083250842508525086250872508825089250902509125092250932509425095250962509725098250992510025101251022510325104251052510625107251082510925110251112511225113251142511525116251172511825119251202512125122251232512425125251262512725128251292513025131251322513325134251352513625137251382513925140251412514225143251442514525146251472514825149251502515125152251532515425155251562515725158251592516025161251622516325164251652516625167251682516925170251712517225173251742517525176251772517825179251802518125182251832518425185251862518725188251892519025191251922519325194251952519625197251982519925200252012520225203252042520525206252072520825209252102521125212252132521425215252162521725218252192522025221252222522325224252252522625227252282522925230252312523225233252342523525236252372523825239252402524125242252432524425245252462524725248252492525025251252522525325254252552525625257252582525925260252612526225263252642526525266252672526825269252702527125272252732527425275252762527725278252792528025281252822528325284252852528625287252882528925290252912529225293252942529525296252972529825299253002530125302253032530425305253062530725308253092531025311253122531325314253152531625317253182531925320253212532225323253242532525326253272532825329253302533125332253332533425335253362533725338253392534025341253422534325344253452534625347253482534925350253512535225353253542535525356253572535825359253602536125362253632536425365253662536725368253692537025371253722537325374253752537625377253782537925380253812538225383253842538525386253872538825389253902539125392253932539425395253962539725398253992540025401254022540325404254052540625407254082540925410254112541225413254142541525416254172541825419254202542125422254232542425425254262542725428254292543025431254322543325434254352543625437254382543925440254412544225443254442544525446254472544825449254502545125452254532545425455254562545725458254592546025461254622546325464254652546625467254682546925470254712547225473254742547525476254772547825479254802548125482254832548425485254862548725488254892549025491254922549325494254952549625497254982549925500255012550225503255042550525506255072550825509255102551125512255132551425515255162551725518255192552025521255222552325524255252552625527255282552925530255312553225533255342553525536255372553825539255402554125542255432554425545255462554725548255492555025551255522555325554255552555625557255582555925560255612556225563255642556525566255672556825569255702557125572255732557425575255762557725578255792558025581255822558325584255852558625587255882558925590255912559225593255942559525596255972559825599256002560125602256032560425605256062560725608256092561025611256122561325614256152561625617256182561925620256212562225623256242562525626256272562825629256302563125632256332563425635256362563725638256392564025641256422564325644256452564625647256482564925650256512565225653256542565525656256572565825659256602566125662256632566425665256662566725668256692567025671256722567325674256752567625677256782567925680256812568225683256842568525686256872568825689256902569125692256932569425695256962569725698256992570025701257022570325704257052570625707257082570925710257112571225713257142571525716257172571825719257202572125722257232572425725257262572725728257292573025731257322573325734257352573625737257382573925740257412574225743257442574525746257472574825749257502575125752257532575425755257562575725758257592576025761257622576325764257652576625767257682576925770257712577225773257742577525776257772577825779257802578125782257832578425785257862578725788257892579025791257922579325794257952579625797257982579925800258012580225803258042580525806258072580825809258102581125812258132581425815258162581725818258192582025821258222582325824258252582625827258282582925830258312583225833258342583525836258372583825839258402584125842258432584425845258462584725848258492585025851258522585325854258552585625857258582585925860258612586225863258642586525866258672586825869258702587125872258732587425875258762587725878258792588025881258822588325884258852588625887258882588925890258912589225893258942589525896258972589825899259002590125902259032590425905259062590725908259092591025911259122591325914259152591625917259182591925920259212592225923259242592525926259272592825929259302593125932259332593425935259362593725938259392594025941259422594325944259452594625947259482594925950259512595225953259542595525956259572595825959259602596125962259632596425965259662596725968259692597025971259722597325974259752597625977259782597925980259812598225983259842598525986259872598825989259902599125992259932599425995259962599725998259992600026001260022600326004260052600626007260082600926010260112601226013260142601526016260172601826019260202602126022260232602426025260262602726028260292603026031260322603326034260352603626037260382603926040260412604226043260442604526046260472604826049260502605126052260532605426055260562605726058260592606026061260622606326064260652606626067260682606926070260712607226073260742607526076260772607826079260802608126082260832608426085260862608726088260892609026091260922609326094260952609626097260982609926100261012610226103261042610526106261072610826109261102611126112261132611426115261162611726118261192612026121261222612326124261252612626127261282612926130261312613226133261342613526136261372613826139261402614126142261432614426145261462614726148261492615026151261522615326154261552615626157261582615926160261612616226163261642616526166261672616826169261702617126172261732617426175261762617726178261792618026181261822618326184261852618626187261882618926190261912619226193261942619526196261972619826199262002620126202262032620426205262062620726208262092621026211262122621326214262152621626217262182621926220262212622226223262242622526226262272622826229262302623126232262332623426235262362623726238262392624026241262422624326244262452624626247262482624926250262512625226253262542625526256262572625826259262602626126262262632626426265262662626726268262692627026271262722627326274262752627626277262782627926280262812628226283262842628526286262872628826289262902629126292262932629426295262962629726298262992630026301263022630326304263052630626307263082630926310263112631226313263142631526316263172631826319263202632126322263232632426325263262632726328263292633026331263322633326334263352633626337263382633926340263412634226343263442634526346263472634826349263502635126352263532635426355263562635726358263592636026361263622636326364263652636626367263682636926370263712637226373263742637526376263772637826379263802638126382263832638426385263862638726388263892639026391263922639326394263952639626397263982639926400264012640226403264042640526406264072640826409264102641126412264132641426415264162641726418264192642026421264222642326424264252642626427264282642926430264312643226433264342643526436264372643826439264402644126442264432644426445264462644726448264492645026451264522645326454264552645626457264582645926460264612646226463264642646526466264672646826469264702647126472264732647426475264762647726478264792648026481264822648326484264852648626487264882648926490264912649226493264942649526496264972649826499265002650126502265032650426505265062650726508265092651026511265122651326514265152651626517265182651926520265212652226523265242652526526265272652826529265302653126532265332653426535265362653726538265392654026541265422654326544265452654626547265482654926550265512655226553265542655526556265572655826559265602656126562265632656426565265662656726568265692657026571265722657326574265752657626577265782657926580265812658226583265842658526586265872658826589265902659126592265932659426595265962659726598265992660026601266022660326604266052660626607266082660926610266112661226613266142661526616266172661826619266202662126622266232662426625266262662726628266292663026631266322663326634266352663626637266382663926640266412664226643266442664526646266472664826649266502665126652266532665426655266562665726658266592666026661266622666326664266652666626667266682666926670266712667226673266742667526676266772667826679266802668126682266832668426685266862668726688266892669026691266922669326694266952669626697266982669926700267012670226703267042670526706267072670826709267102671126712267132671426715267162671726718267192672026721267222672326724267252672626727267282672926730267312673226733267342673526736267372673826739267402674126742267432674426745267462674726748267492675026751267522675326754267552675626757267582675926760267612676226763267642676526766267672676826769267702677126772267732677426775267762677726778267792678026781267822678326784267852678626787267882678926790267912679226793267942679526796267972679826799268002680126802268032680426805268062680726808268092681026811268122681326814268152681626817268182681926820268212682226823268242682526826268272682826829268302683126832268332683426835268362683726838268392684026841268422684326844268452684626847268482684926850268512685226853268542685526856268572685826859268602686126862268632686426865268662686726868268692687026871268722687326874268752687626877268782687926880268812688226883268842688526886268872688826889268902689126892268932689426895268962689726898268992690026901269022690326904269052690626907269082690926910269112691226913269142691526916269172691826919269202692126922269232692426925269262692726928269292693026931269322693326934269352693626937269382693926940269412694226943269442694526946269472694826949269502695126952269532695426955269562695726958269592696026961269622696326964269652696626967269682696926970269712697226973269742697526976269772697826979269802698126982269832698426985269862698726988269892699026991269922699326994269952699626997269982699927000270012700227003270042700527006270072700827009270102701127012270132701427015270162701727018270192702027021270222702327024270252702627027270282702927030270312703227033270342703527036270372703827039270402704127042270432704427045270462704727048270492705027051270522705327054270552705627057270582705927060270612706227063270642706527066270672706827069270702707127072270732707427075270762707727078270792708027081270822708327084270852708627087270882708927090270912709227093270942709527096270972709827099271002710127102271032710427105271062710727108271092711027111271122711327114271152711627117271182711927120271212712227123271242712527126271272712827129271302713127132271332713427135271362713727138271392714027141271422714327144271452714627147271482714927150271512715227153271542715527156271572715827159271602716127162271632716427165271662716727168271692717027171271722717327174271752717627177271782717927180271812718227183271842718527186271872718827189271902719127192271932719427195271962719727198271992720027201272022720327204272052720627207272082720927210272112721227213272142721527216272172721827219272202722127222272232722427225272262722727228272292723027231272322723327234272352723627237272382723927240272412724227243272442724527246272472724827249272502725127252272532725427255272562725727258272592726027261272622726327264272652726627267272682726927270272712727227273272742727527276272772727827279272802728127282272832728427285272862728727288272892729027291272922729327294272952729627297272982729927300273012730227303273042730527306273072730827309273102731127312273132731427315273162731727318273192732027321273222732327324273252732627327273282732927330273312733227333273342733527336273372733827339273402734127342273432734427345273462734727348273492735027351273522735327354273552735627357273582735927360273612736227363273642736527366273672736827369273702737127372273732737427375273762737727378273792738027381273822738327384273852738627387273882738927390273912739227393273942739527396273972739827399274002740127402274032740427405274062740727408274092741027411274122741327414274152741627417274182741927420274212742227423274242742527426274272742827429274302743127432274332743427435274362743727438274392744027441274422744327444274452744627447274482744927450274512745227453274542745527456274572745827459274602746127462274632746427465274662746727468274692747027471274722747327474274752747627477274782747927480274812748227483274842748527486274872748827489274902749127492274932749427495274962749727498274992750027501275022750327504275052750627507275082750927510275112751227513275142751527516275172751827519275202752127522275232752427525275262752727528275292753027531275322753327534275352753627537275382753927540275412754227543275442754527546275472754827549275502755127552275532755427555275562755727558275592756027561275622756327564275652756627567275682756927570275712757227573275742757527576275772757827579275802758127582275832758427585275862758727588275892759027591275922759327594275952759627597275982759927600276012760227603276042760527606276072760827609276102761127612276132761427615276162761727618276192762027621276222762327624276252762627627276282762927630276312763227633276342763527636276372763827639276402764127642276432764427645276462764727648276492765027651276522765327654276552765627657276582765927660276612766227663276642766527666276672766827669276702767127672276732767427675276762767727678276792768027681276822768327684276852768627687276882768927690276912769227693276942769527696276972769827699277002770127702277032770427705277062770727708277092771027711277122771327714277152771627717277182771927720277212772227723277242772527726277272772827729277302773127732277332773427735277362773727738277392774027741277422774327744277452774627747277482774927750277512775227753277542775527756277572775827759277602776127762277632776427765277662776727768277692777027771277722777327774277752777627777277782777927780277812778227783277842778527786277872778827789277902779127792277932779427795277962779727798277992780027801278022780327804278052780627807278082780927810278112781227813278142781527816278172781827819278202782127822278232782427825278262782727828278292783027831278322783327834278352783627837278382783927840278412784227843278442784527846278472784827849278502785127852278532785427855278562785727858278592786027861278622786327864278652786627867278682786927870278712787227873278742787527876278772787827879278802788127882278832788427885278862788727888278892789027891278922789327894278952789627897278982789927900279012790227903279042790527906279072790827909279102791127912279132791427915279162791727918279192792027921279222792327924279252792627927279282792927930279312793227933279342793527936279372793827939279402794127942279432794427945279462794727948279492795027951279522795327954279552795627957279582795927960279612796227963279642796527966279672796827969279702797127972279732797427975279762797727978279792798027981279822798327984279852798627987279882798927990279912799227993279942799527996279972799827999280002800128002280032800428005280062800728008280092801028011280122801328014280152801628017280182801928020280212802228023280242802528026280272802828029280302803128032280332803428035280362803728038280392804028041280422804328044280452804628047280482804928050280512805228053280542805528056280572805828059280602806128062280632806428065280662806728068280692807028071280722807328074280752807628077280782807928080280812808228083280842808528086280872808828089280902809128092280932809428095280962809728098280992810028101281022810328104281052810628107281082810928110281112811228113281142811528116281172811828119281202812128122281232812428125281262812728128281292813028131281322813328134281352813628137281382813928140281412814228143281442814528146281472814828149281502815128152281532815428155281562815728158281592816028161281622816328164281652816628167281682816928170281712817228173281742817528176281772817828179281802818128182281832818428185281862818728188281892819028191281922819328194281952819628197281982819928200282012820228203282042820528206282072820828209282102821128212282132821428215282162821728218282192822028221282222822328224282252822628227282282822928230282312823228233282342823528236282372823828239282402824128242282432824428245282462824728248282492825028251282522825328254282552825628257282582825928260282612826228263282642826528266282672826828269282702827128272282732827428275282762827728278282792828028281282822828328284282852828628287282882828928290282912829228293282942829528296282972829828299283002830128302283032830428305283062830728308283092831028311283122831328314283152831628317283182831928320283212832228323283242832528326283272832828329283302833128332283332833428335283362833728338283392834028341283422834328344283452834628347283482834928350283512835228353283542835528356283572835828359283602836128362283632836428365283662836728368283692837028371283722837328374283752837628377283782837928380283812838228383283842838528386283872838828389283902839128392283932839428395283962839728398283992840028401284022840328404284052840628407284082840928410284112841228413284142841528416284172841828419284202842128422284232842428425284262842728428284292843028431284322843328434284352843628437284382843928440284412844228443284442844528446284472844828449284502845128452284532845428455284562845728458284592846028461284622846328464284652846628467284682846928470284712847228473284742847528476284772847828479284802848128482284832848428485284862848728488284892849028491284922849328494284952849628497284982849928500285012850228503285042850528506285072850828509285102851128512285132851428515285162851728518285192852028521285222852328524285252852628527285282852928530285312853228533285342853528536285372853828539285402854128542285432854428545285462854728548285492855028551285522855328554285552855628557285582855928560285612856228563285642856528566285672856828569285702857128572285732857428575285762857728578285792858028581285822858328584285852858628587285882858928590285912859228593285942859528596285972859828599286002860128602286032860428605286062860728608286092861028611286122861328614286152861628617286182861928620286212862228623286242862528626286272862828629286302863128632286332863428635286362863728638286392864028641286422864328644286452864628647286482864928650286512865228653286542865528656286572865828659286602866128662286632866428665286662866728668286692867028671286722867328674286752867628677286782867928680286812868228683286842868528686286872868828689286902869128692286932869428695286962869728698286992870028701287022870328704287052870628707287082870928710287112871228713287142871528716287172871828719287202872128722287232872428725287262872728728287292873028731287322873328734287352873628737287382873928740287412874228743287442874528746287472874828749287502875128752287532875428755287562875728758287592876028761287622876328764287652876628767287682876928770287712877228773287742877528776287772877828779287802878128782287832878428785287862878728788287892879028791287922879328794287952879628797287982879928800288012880228803288042880528806288072880828809288102881128812288132881428815288162881728818288192882028821288222882328824288252882628827288282882928830288312883228833288342883528836288372883828839288402884128842288432884428845288462884728848288492885028851288522885328854288552885628857288582885928860288612886228863288642886528866288672886828869288702887128872288732887428875288762887728878288792888028881288822888328884288852888628887288882888928890288912889228893288942889528896288972889828899289002890128902289032890428905289062890728908289092891028911289122891328914289152891628917289182891928920289212892228923289242892528926289272892828929289302893128932289332893428935289362893728938289392894028941289422894328944289452894628947289482894928950289512895228953289542895528956289572895828959289602896128962289632896428965289662896728968289692897028971289722897328974289752897628977289782897928980289812898228983289842898528986289872898828989289902899128992289932899428995289962899728998289992900029001290022900329004290052900629007290082900929010290112901229013290142901529016290172901829019290202902129022290232902429025290262902729028290292903029031290322903329034290352903629037290382903929040290412904229043290442904529046290472904829049290502905129052290532905429055290562905729058290592906029061290622906329064290652906629067290682906929070290712907229073290742907529076290772907829079290802908129082290832908429085290862908729088290892909029091290922909329094290952909629097290982909929100291012910229103291042910529106291072910829109291102911129112291132911429115291162911729118291192912029121291222912329124291252912629127291282912929130291312913229133291342913529136291372913829139291402914129142291432914429145291462914729148291492915029151291522915329154291552915629157291582915929160291612916229163291642916529166291672916829169291702917129172291732917429175291762917729178291792918029181291822918329184291852918629187291882918929190291912919229193291942919529196291972919829199292002920129202292032920429205292062920729208292092921029211292122921329214292152921629217292182921929220292212922229223292242922529226292272922829229292302923129232292332923429235292362923729238292392924029241292422924329244292452924629247292482924929250292512925229253292542925529256292572925829259292602926129262292632926429265292662926729268292692927029271292722927329274292752927629277292782927929280292812928229283292842928529286292872928829289292902929129292292932929429295292962929729298292992930029301293022930329304293052930629307293082930929310293112931229313293142931529316293172931829319293202932129322293232932429325293262932729328293292933029331293322933329334293352933629337293382933929340293412934229343293442934529346293472934829349293502935129352293532935429355293562935729358293592936029361293622936329364293652936629367293682936929370293712937229373293742937529376293772937829379293802938129382293832938429385293862938729388293892939029391293922939329394293952939629397293982939929400294012940229403294042940529406294072940829409294102941129412294132941429415294162941729418294192942029421294222942329424294252942629427294282942929430294312943229433294342943529436294372943829439294402944129442294432944429445294462944729448294492945029451294522945329454294552945629457294582945929460294612946229463294642946529466294672946829469294702947129472294732947429475294762947729478294792948029481294822948329484294852948629487294882948929490294912949229493294942949529496294972949829499295002950129502295032950429505295062950729508295092951029511295122951329514295152951629517295182951929520295212952229523295242952529526295272952829529295302953129532295332953429535295362953729538295392954029541295422954329544295452954629547295482954929550295512955229553295542955529556295572955829559295602956129562295632956429565295662956729568295692957029571295722957329574295752957629577295782957929580295812958229583295842958529586295872958829589295902959129592295932959429595295962959729598295992960029601296022960329604296052960629607296082960929610296112961229613296142961529616296172961829619296202962129622296232962429625296262962729628296292963029631296322963329634296352963629637296382963929640296412964229643296442964529646296472964829649296502965129652296532965429655296562965729658296592966029661296622966329664296652966629667296682966929670296712967229673296742967529676296772967829679296802968129682296832968429685296862968729688296892969029691296922969329694296952969629697296982969929700297012970229703297042970529706297072970829709297102971129712297132971429715297162971729718297192972029721297222972329724297252972629727297282972929730297312973229733297342973529736297372973829739297402974129742297432974429745297462974729748297492975029751297522975329754297552975629757297582975929760297612976229763297642976529766297672976829769297702977129772297732977429775297762977729778297792978029781297822978329784297852978629787297882978929790297912979229793297942979529796297972979829799298002980129802298032980429805298062980729808298092981029811298122981329814298152981629817298182981929820298212982229823298242982529826298272982829829298302983129832298332983429835298362983729838298392984029841298422984329844298452984629847298482984929850298512985229853298542985529856298572985829859298602986129862298632986429865298662986729868298692987029871298722987329874298752987629877298782987929880298812988229883298842988529886298872988829889298902989129892298932989429895298962989729898298992990029901299022990329904299052990629907299082990929910299112991229913299142991529916299172991829919299202992129922299232992429925299262992729928299292993029931299322993329934299352993629937299382993929940299412994229943299442994529946299472994829949299502995129952299532995429955299562995729958299592996029961299622996329964299652996629967299682996929970299712997229973299742997529976299772997829979299802998129982299832998429985299862998729988299892999029991299922999329994299952999629997299982999930000300013000230003300043000530006300073000830009300103001130012300133001430015300163001730018300193002030021300223002330024300253002630027300283002930030300313003230033300343003530036300373003830039300403004130042300433004430045300463004730048300493005030051300523005330054300553005630057300583005930060300613006230063300643006530066300673006830069300703007130072300733007430075300763007730078300793008030081300823008330084300853008630087300883008930090300913009230093300943009530096300973009830099301003010130102301033010430105301063010730108301093011030111301123011330114301153011630117301183011930120301213012230123301243012530126301273012830129301303013130132301333013430135301363013730138301393014030141301423014330144301453014630147301483014930150301513015230153301543015530156301573015830159301603016130162301633016430165301663016730168301693017030171301723017330174301753017630177301783017930180301813018230183301843018530186301873018830189301903019130192301933019430195301963019730198301993020030201302023020330204302053020630207302083020930210302113021230213302143021530216302173021830219302203022130222302233022430225302263022730228302293023030231302323023330234302353023630237302383023930240302413024230243302443024530246302473024830249302503025130252302533025430255302563025730258302593026030261302623026330264302653026630267302683026930270302713027230273302743027530276302773027830279302803028130282302833028430285302863028730288302893029030291302923029330294302953029630297302983029930300303013030230303303043030530306303073030830309303103031130312303133031430315303163031730318303193032030321303223032330324303253032630327303283032930330303313033230333303343033530336303373033830339303403034130342303433034430345303463034730348303493035030351303523035330354303553035630357303583035930360303613036230363303643036530366303673036830369303703037130372303733037430375303763037730378303793038030381303823038330384303853038630387303883038930390303913039230393303943039530396303973039830399304003040130402304033040430405304063040730408304093041030411304123041330414304153041630417304183041930420304213042230423304243042530426304273042830429304303043130432304333043430435304363043730438304393044030441304423044330444304453044630447304483044930450304513045230453304543045530456304573045830459304603046130462304633046430465304663046730468304693047030471304723047330474304753047630477304783047930480304813048230483304843048530486304873048830489304903049130492304933049430495304963049730498304993050030501305023050330504305053050630507305083050930510305113051230513305143051530516305173051830519305203052130522305233052430525305263052730528305293053030531305323053330534305353053630537305383053930540305413054230543305443054530546305473054830549305503055130552305533055430555305563055730558305593056030561305623056330564305653056630567305683056930570305713057230573305743057530576305773057830579305803058130582305833058430585305863058730588305893059030591305923059330594305953059630597305983059930600306013060230603306043060530606306073060830609306103061130612306133061430615306163061730618306193062030621306223062330624306253062630627306283062930630306313063230633306343063530636306373063830639306403064130642306433064430645306463064730648306493065030651306523065330654306553065630657306583065930660306613066230663306643066530666306673066830669306703067130672306733067430675306763067730678306793068030681306823068330684306853068630687306883068930690306913069230693306943069530696306973069830699307003070130702307033070430705307063070730708307093071030711307123071330714307153071630717307183071930720307213072230723307243072530726307273072830729307303073130732307333073430735307363073730738307393074030741307423074330744307453074630747307483074930750307513075230753307543075530756307573075830759307603076130762307633076430765307663076730768307693077030771307723077330774307753077630777307783077930780307813078230783307843078530786307873078830789307903079130792307933079430795307963079730798307993080030801308023080330804308053080630807308083080930810308113081230813308143081530816308173081830819308203082130822308233082430825308263082730828308293083030831308323083330834308353083630837308383083930840308413084230843308443084530846308473084830849308503085130852308533085430855308563085730858308593086030861308623086330864308653086630867308683086930870308713087230873308743087530876308773087830879308803088130882308833088430885308863088730888308893089030891308923089330894308953089630897308983089930900309013090230903309043090530906309073090830909309103091130912309133091430915309163091730918309193092030921309223092330924309253092630927309283092930930309313093230933309343093530936309373093830939309403094130942309433094430945309463094730948309493095030951309523095330954309553095630957309583095930960309613096230963309643096530966309673096830969309703097130972309733097430975309763097730978309793098030981309823098330984309853098630987309883098930990309913099230993309943099530996309973099830999310003100131002310033100431005310063100731008310093101031011310123101331014310153101631017310183101931020310213102231023310243102531026310273102831029310303103131032310333103431035310363103731038310393104031041310423104331044310453104631047310483104931050310513105231053310543105531056310573105831059310603106131062310633106431065310663106731068310693107031071310723107331074310753107631077310783107931080310813108231083310843108531086310873108831089310903109131092310933109431095310963109731098310993110031101311023110331104311053110631107311083110931110311113111231113311143111531116311173111831119311203112131122311233112431125311263112731128311293113031131311323113331134311353113631137311383113931140311413114231143311443114531146311473114831149311503115131152311533115431155311563115731158311593116031161311623116331164311653116631167311683116931170311713117231173311743117531176311773117831179311803118131182311833118431185311863118731188311893119031191311923119331194311953119631197311983119931200312013120231203312043120531206312073120831209312103121131212312133121431215312163121731218312193122031221312223122331224312253122631227312283122931230312313123231233312343123531236312373123831239312403124131242312433124431245312463124731248312493125031251312523125331254312553125631257312583125931260312613126231263312643126531266312673126831269312703127131272312733127431275312763127731278312793128031281312823128331284312853128631287312883128931290312913129231293312943129531296312973129831299313003130131302313033130431305313063130731308313093131031311313123131331314313153131631317313183131931320313213132231323313243132531326313273132831329313303133131332313333133431335313363133731338313393134031341313423134331344313453134631347313483134931350313513135231353313543135531356313573135831359313603136131362313633136431365313663136731368313693137031371313723137331374313753137631377313783137931380313813138231383313843138531386313873138831389313903139131392313933139431395313963139731398313993140031401314023140331404314053140631407314083140931410314113141231413314143141531416314173141831419314203142131422314233142431425314263142731428314293143031431314323143331434314353143631437314383143931440314413144231443314443144531446314473144831449314503145131452314533145431455314563145731458314593146031461314623146331464314653146631467314683146931470314713147231473314743147531476314773147831479314803148131482314833148431485314863148731488314893149031491314923149331494314953149631497314983149931500315013150231503315043150531506315073150831509315103151131512315133151431515315163151731518315193152031521315223152331524315253152631527315283152931530315313153231533315343153531536315373153831539315403154131542315433154431545315463154731548315493155031551315523155331554315553155631557315583155931560315613156231563315643156531566315673156831569315703157131572315733157431575315763157731578315793158031581315823158331584315853158631587315883158931590315913159231593315943159531596315973159831599316003160131602316033160431605316063160731608316093161031611316123161331614316153161631617316183161931620316213162231623316243162531626316273162831629316303163131632316333163431635316363163731638316393164031641316423164331644316453164631647316483164931650316513165231653316543165531656316573165831659316603166131662316633166431665316663166731668316693167031671316723167331674316753167631677316783167931680316813168231683316843168531686316873168831689316903169131692316933169431695316963169731698316993170031701317023170331704317053170631707317083170931710317113171231713317143171531716317173171831719317203172131722317233172431725317263172731728317293173031731317323173331734317353173631737317383173931740317413174231743317443174531746317473174831749317503175131752317533175431755317563175731758317593176031761317623176331764317653176631767317683176931770317713177231773317743177531776317773177831779317803178131782317833178431785317863178731788317893179031791317923179331794317953179631797317983179931800318013180231803318043180531806318073180831809318103181131812318133181431815318163181731818318193182031821318223182331824318253182631827318283182931830318313183231833318343183531836318373183831839318403184131842318433184431845318463184731848318493185031851318523185331854318553185631857318583185931860318613186231863318643186531866318673186831869318703187131872318733187431875318763187731878318793188031881318823188331884318853188631887318883188931890318913189231893318943189531896318973189831899319003190131902319033190431905319063190731908319093191031911319123191331914319153191631917319183191931920319213192231923319243192531926319273192831929319303193131932319333193431935319363193731938319393194031941319423194331944319453194631947319483194931950319513195231953319543195531956319573195831959319603196131962319633196431965319663196731968319693197031971319723197331974319753197631977319783197931980319813198231983319843198531986319873198831989319903199131992319933199431995319963199731998319993200032001320023200332004320053200632007320083200932010320113201232013320143201532016320173201832019320203202132022320233202432025320263202732028320293203032031320323203332034320353203632037320383203932040320413204232043320443204532046320473204832049320503205132052320533205432055320563205732058320593206032061320623206332064320653206632067320683206932070320713207232073320743207532076320773207832079320803208132082320833208432085320863208732088320893209032091320923209332094320953209632097320983209932100321013210232103321043210532106321073210832109321103211132112321133211432115321163211732118321193212032121321223212332124321253212632127321283212932130321313213232133321343213532136321373213832139321403214132142321433214432145321463214732148321493215032151321523215332154321553215632157321583215932160321613216232163321643216532166321673216832169321703217132172321733217432175321763217732178321793218032181321823218332184321853218632187321883218932190321913219232193321943219532196321973219832199322003220132202322033220432205322063220732208322093221032211322123221332214322153221632217322183221932220322213222232223322243222532226322273222832229322303223132232322333223432235322363223732238322393224032241322423224332244322453224632247322483224932250322513225232253322543225532256322573225832259322603226132262322633226432265322663226732268322693227032271322723227332274322753227632277322783227932280322813228232283322843228532286322873228832289322903229132292322933229432295322963229732298322993230032301323023230332304323053230632307323083230932310323113231232313323143231532316323173231832319323203232132322323233232432325323263232732328323293233032331323323233332334323353233632337323383233932340323413234232343323443234532346323473234832349323503235132352323533235432355323563235732358323593236032361323623236332364323653236632367323683236932370323713237232373323743237532376323773237832379323803238132382323833238432385323863238732388323893239032391323923239332394323953239632397323983239932400324013240232403324043240532406324073240832409324103241132412324133241432415324163241732418324193242032421324223242332424324253242632427324283242932430324313243232433324343243532436324373243832439324403244132442324433244432445324463244732448324493245032451324523245332454324553245632457324583245932460324613246232463324643246532466324673246832469324703247132472324733247432475324763247732478324793248032481324823248332484324853248632487324883248932490324913249232493324943249532496324973249832499325003250132502325033250432505325063250732508325093251032511325123251332514325153251632517325183251932520325213252232523325243252532526325273252832529325303253132532325333253432535325363253732538325393254032541325423254332544325453254632547325483254932550325513255232553325543255532556325573255832559325603256132562325633256432565325663256732568325693257032571325723257332574325753257632577325783257932580325813258232583325843258532586325873258832589325903259132592325933259432595325963259732598325993260032601326023260332604326053260632607326083260932610326113261232613326143261532616326173261832619326203262132622326233262432625326263262732628326293263032631326323263332634326353263632637326383263932640326413264232643326443264532646326473264832649326503265132652326533265432655326563265732658326593266032661326623266332664326653266632667326683266932670326713267232673326743267532676326773267832679326803268132682326833268432685326863268732688326893269032691326923269332694326953269632697326983269932700327013270232703327043270532706327073270832709327103271132712327133271432715327163271732718327193272032721327223272332724327253272632727327283272932730327313273232733327343273532736327373273832739327403274132742327433274432745327463274732748327493275032751327523275332754327553275632757327583275932760327613276232763327643276532766327673276832769327703277132772327733277432775327763277732778327793278032781327823278332784327853278632787327883278932790327913279232793327943279532796327973279832799328003280132802328033280432805328063280732808328093281032811328123281332814328153281632817328183281932820328213282232823328243282532826328273282832829328303283132832328333283432835328363283732838328393284032841328423284332844328453284632847328483284932850328513285232853328543285532856328573285832859328603286132862328633286432865328663286732868328693287032871328723287332874328753287632877328783287932880328813288232883328843288532886328873288832889328903289132892328933289432895328963289732898328993290032901329023290332904329053290632907329083290932910329113291232913329143291532916329173291832919329203292132922329233292432925329263292732928329293293032931329323293332934329353293632937329383293932940329413294232943329443294532946329473294832949329503295132952329533295432955329563295732958329593296032961329623296332964329653296632967329683296932970329713297232973329743297532976329773297832979329803298132982329833298432985329863298732988329893299032991329923299332994329953299632997329983299933000330013300233003330043300533006330073300833009330103301133012330133301433015330163301733018330193302033021330223302333024330253302633027330283302933030330313303233033330343303533036330373303833039330403304133042330433304433045330463304733048330493305033051330523305333054330553305633057330583305933060330613306233063330643306533066330673306833069330703307133072330733307433075330763307733078330793308033081330823308333084330853308633087330883308933090330913309233093330943309533096330973309833099331003310133102331033310433105331063310733108331093311033111331123311333114331153311633117331183311933120331213312233123331243312533126331273312833129331303313133132331333313433135331363313733138331393314033141331423314333144331453314633147331483314933150331513315233153331543315533156331573315833159331603316133162331633316433165331663316733168331693317033171331723317333174331753317633177331783317933180331813318233183331843318533186331873318833189331903319133192331933319433195331963319733198331993320033201332023320333204332053320633207332083320933210332113321233213332143321533216332173321833219332203322133222332233322433225332263322733228332293323033231332323323333234332353323633237332383323933240332413324233243332443324533246332473324833249332503325133252332533325433255332563325733258332593326033261332623326333264332653326633267332683326933270332713327233273332743327533276332773327833279332803328133282332833328433285332863328733288332893329033291332923329333294332953329633297332983329933300333013330233303333043330533306333073330833309333103331133312333133331433315333163331733318333193332033321333223332333324333253332633327333283332933330333313333233333333343333533336333373333833339333403334133342333433334433345333463334733348333493335033351333523335333354333553335633357333583335933360333613336233363333643336533366333673336833369333703337133372333733337433375333763337733378333793338033381333823338333384333853338633387333883338933390333913339233393333943339533396333973339833399334003340133402334033340433405334063340733408334093341033411334123341333414334153341633417334183341933420334213342233423334243342533426334273342833429334303343133432334333343433435334363343733438334393344033441334423344333444334453344633447334483344933450334513345233453334543345533456334573345833459334603346133462334633346433465334663346733468334693347033471334723347333474334753347633477334783347933480334813348233483334843348533486334873348833489334903349133492334933349433495334963349733498334993350033501335023350333504335053350633507335083350933510335113351233513335143351533516335173351833519335203352133522335233352433525335263352733528335293353033531335323353333534335353353633537335383353933540335413354233543335443354533546335473354833549335503355133552335533355433555335563355733558335593356033561335623356333564335653356633567335683356933570335713357233573335743357533576335773357833579335803358133582335833358433585335863358733588335893359033591335923359333594335953359633597335983359933600336013360233603336043360533606336073360833609336103361133612336133361433615336163361733618336193362033621336223362333624336253362633627336283362933630336313363233633336343363533636336373363833639336403364133642336433364433645336463364733648336493365033651336523365333654336553365633657336583365933660336613366233663336643366533666336673366833669336703367133672336733367433675336763367733678336793368033681336823368333684336853368633687336883368933690336913369233693336943369533696336973369833699337003370133702337033370433705337063370733708337093371033711337123371333714337153371633717337183371933720337213372233723337243372533726337273372833729337303373133732337333373433735337363373733738337393374033741337423374333744337453374633747337483374933750337513375233753337543375533756337573375833759337603376133762337633376433765337663376733768337693377033771337723377333774337753377633777337783377933780337813378233783337843378533786337873378833789337903379133792337933379433795337963379733798337993380033801338023380333804338053380633807338083380933810338113381233813338143381533816338173381833819338203382133822338233382433825338263382733828338293383033831338323383333834338353383633837338383383933840338413384233843338443384533846338473384833849338503385133852338533385433855338563385733858338593386033861338623386333864338653386633867338683386933870338713387233873338743387533876338773387833879338803388133882338833388433885338863388733888338893389033891338923389333894338953389633897338983389933900339013390233903339043390533906339073390833909339103391133912339133391433915339163391733918339193392033921339223392333924339253392633927339283392933930339313393233933339343393533936339373393833939339403394133942339433394433945339463394733948339493395033951339523395333954339553395633957339583395933960339613396233963339643396533966339673396833969339703397133972339733397433975339763397733978339793398033981339823398333984339853398633987339883398933990339913399233993339943399533996339973399833999340003400134002340033400434005340063400734008340093401034011340123401334014340153401634017340183401934020340213402234023340243402534026340273402834029340303403134032340333403434035340363403734038340393404034041340423404334044340453404634047340483404934050340513405234053340543405534056340573405834059340603406134062340633406434065340663406734068340693407034071340723407334074340753407634077340783407934080340813408234083340843408534086340873408834089340903409134092340933409434095340963409734098340993410034101341023410334104341053410634107341083410934110341113411234113341143411534116341173411834119341203412134122341233412434125341263412734128341293413034131341323413334134341353413634137341383413934140341413414234143341443414534146341473414834149341503415134152341533415434155341563415734158341593416034161341623416334164341653416634167341683416934170341713417234173341743417534176341773417834179341803418134182341833418434185341863418734188341893419034191341923419334194341953419634197341983419934200342013420234203342043420534206342073420834209342103421134212342133421434215342163421734218342193422034221342223422334224342253422634227342283422934230342313423234233342343423534236342373423834239342403424134242342433424434245342463424734248342493425034251342523425334254342553425634257342583425934260342613426234263342643426534266342673426834269342703427134272342733427434275342763427734278342793428034281342823428334284342853428634287342883428934290342913429234293342943429534296342973429834299343003430134302343033430434305343063430734308343093431034311343123431334314343153431634317343183431934320343213432234323343243432534326343273432834329343303433134332343333433434335343363433734338343393434034341343423434334344343453434634347343483434934350343513435234353343543435534356343573435834359343603436134362343633436434365343663436734368343693437034371343723437334374343753437634377343783437934380343813438234383343843438534386343873438834389343903439134392343933439434395343963439734398343993440034401344023440334404344053440634407344083440934410344113441234413344143441534416344173441834419344203442134422344233442434425344263442734428344293443034431344323443334434344353443634437344383443934440344413444234443344443444534446344473444834449344503445134452344533445434455344563445734458344593446034461344623446334464344653446634467344683446934470344713447234473344743447534476344773447834479344803448134482344833448434485344863448734488344893449034491344923449334494344953449634497344983449934500345013450234503345043450534506345073450834509345103451134512345133451434515345163451734518345193452034521345223452334524345253452634527345283452934530345313453234533345343453534536345373453834539345403454134542345433454434545345463454734548345493455034551345523455334554345553455634557345583455934560345613456234563345643456534566345673456834569345703457134572345733457434575345763457734578345793458034581345823458334584345853458634587345883458934590345913459234593345943459534596345973459834599346003460134602346033460434605346063460734608346093461034611346123461334614346153461634617346183461934620346213462234623346243462534626346273462834629346303463134632346333463434635346363463734638346393464034641346423464334644346453464634647346483464934650346513465234653346543465534656346573465834659346603466134662346633466434665346663466734668346693467034671346723467334674346753467634677346783467934680346813468234683346843468534686346873468834689346903469134692346933469434695346963469734698346993470034701347023470334704347053470634707347083470934710347113471234713347143471534716347173471834719347203472134722347233472434725347263472734728347293473034731347323473334734347353473634737347383473934740347413474234743347443474534746347473474834749347503475134752347533475434755347563475734758347593476034761347623476334764347653476634767347683476934770347713477234773347743477534776347773477834779347803478134782347833478434785347863478734788347893479034791347923479334794347953479634797347983479934800348013480234803348043480534806348073480834809348103481134812348133481434815348163481734818348193482034821348223482334824348253482634827348283482934830348313483234833348343483534836348373483834839348403484134842348433484434845348463484734848348493485034851348523485334854348553485634857348583485934860348613486234863348643486534866348673486834869348703487134872348733487434875348763487734878348793488034881348823488334884348853488634887348883488934890348913489234893348943489534896348973489834899349003490134902349033490434905349063490734908349093491034911349123491334914349153491634917349183491934920349213492234923349243492534926349273492834929349303493134932349333493434935349363493734938349393494034941349423494334944349453494634947349483494934950349513495234953349543495534956349573495834959349603496134962349633496434965349663496734968349693497034971349723497334974349753497634977349783497934980349813498234983349843498534986349873498834989349903499134992349933499434995349963499734998349993500035001350023500335004350053500635007350083500935010350113501235013350143501535016350173501835019350203502135022350233502435025350263502735028350293503035031350323503335034350353503635037350383503935040350413504235043350443504535046350473504835049350503505135052350533505435055350563505735058350593506035061350623506335064350653506635067350683506935070350713507235073350743507535076350773507835079350803508135082350833508435085350863508735088350893509035091350923509335094350953509635097350983509935100351013510235103351043510535106351073510835109351103511135112351133511435115351163511735118351193512035121351223512335124351253512635127351283512935130351313513235133351343513535136351373513835139351403514135142351433514435145351463514735148351493515035151351523515335154351553515635157351583515935160351613516235163351643516535166351673516835169351703517135172351733517435175351763517735178351793518035181351823518335184351853518635187351883518935190351913519235193351943519535196351973519835199352003520135202352033520435205352063520735208352093521035211352123521335214352153521635217352183521935220352213522235223352243522535226352273522835229352303523135232352333523435235352363523735238352393524035241352423524335244352453524635247352483524935250352513525235253352543525535256352573525835259352603526135262352633526435265352663526735268352693527035271352723527335274352753527635277352783527935280352813528235283352843528535286352873528835289352903529135292352933529435295352963529735298352993530035301353023530335304353053530635307353083530935310353113531235313353143531535316353173531835319353203532135322353233532435325353263532735328353293533035331353323533335334353353533635337353383533935340353413534235343353443534535346353473534835349353503535135352353533535435355353563535735358353593536035361353623536335364353653536635367353683536935370353713537235373353743537535376353773537835379353803538135382353833538435385353863538735388353893539035391353923539335394353953539635397353983539935400354013540235403354043540535406354073540835409354103541135412354133541435415354163541735418354193542035421354223542335424354253542635427354283542935430354313543235433354343543535436354373543835439354403544135442354433544435445354463544735448354493545035451354523545335454354553545635457354583545935460354613546235463354643546535466354673546835469354703547135472354733547435475354763547735478354793548035481354823548335484354853548635487354883548935490354913549235493354943549535496354973549835499355003550135502355033550435505355063550735508355093551035511355123551335514355153551635517355183551935520355213552235523355243552535526355273552835529355303553135532355333553435535355363553735538355393554035541355423554335544355453554635547355483554935550355513555235553355543555535556355573555835559355603556135562355633556435565355663556735568355693557035571355723557335574355753557635577355783557935580355813558235583355843558535586355873558835589355903559135592355933559435595355963559735598355993560035601356023560335604356053560635607356083560935610356113561235613356143561535616356173561835619356203562135622356233562435625356263562735628356293563035631356323563335634356353563635637356383563935640356413564235643356443564535646356473564835649356503565135652356533565435655356563565735658356593566035661356623566335664356653566635667356683566935670356713567235673356743567535676356773567835679356803568135682356833568435685356863568735688356893569035691356923569335694356953569635697356983569935700357013570235703357043570535706357073570835709357103571135712357133571435715357163571735718357193572035721357223572335724357253572635727357283572935730357313573235733357343573535736357373573835739357403574135742357433574435745357463574735748357493575035751357523575335754357553575635757357583575935760357613576235763357643576535766357673576835769357703577135772357733577435775357763577735778357793578035781357823578335784357853578635787357883578935790357913579235793357943579535796357973579835799358003580135802358033580435805358063580735808358093581035811358123581335814358153581635817358183581935820358213582235823358243582535826358273582835829358303583135832358333583435835358363583735838358393584035841358423584335844358453584635847358483584935850358513585235853358543585535856358573585835859358603586135862358633586435865358663586735868358693587035871358723587335874358753587635877358783587935880358813588235883358843588535886358873588835889358903589135892358933589435895358963589735898358993590035901359023590335904359053590635907359083590935910359113591235913359143591535916359173591835919359203592135922359233592435925359263592735928359293593035931359323593335934359353593635937359383593935940359413594235943359443594535946359473594835949359503595135952359533595435955359563595735958359593596035961359623596335964359653596635967359683596935970359713597235973359743597535976359773597835979359803598135982359833598435985359863598735988359893599035991359923599335994359953599635997359983599936000360013600236003360043600536006360073600836009360103601136012360133601436015360163601736018360193602036021360223602336024360253602636027360283602936030360313603236033360343603536036360373603836039360403604136042360433604436045360463604736048360493605036051360523605336054360553605636057360583605936060360613606236063360643606536066360673606836069360703607136072360733607436075360763607736078360793608036081360823608336084360853608636087360883608936090360913609236093360943609536096360973609836099361003610136102361033610436105361063610736108361093611036111361123611336114361153611636117361183611936120361213612236123361243612536126361273612836129361303613136132361333613436135361363613736138361393614036141361423614336144361453614636147361483614936150361513615236153361543615536156361573615836159361603616136162361633616436165361663616736168361693617036171361723617336174361753617636177361783617936180361813618236183361843618536186361873618836189361903619136192361933619436195361963619736198361993620036201362023620336204362053620636207362083620936210362113621236213362143621536216362173621836219362203622136222362233622436225362263622736228362293623036231362323623336234362353623636237362383623936240362413624236243362443624536246362473624836249362503625136252362533625436255362563625736258362593626036261362623626336264362653626636267362683626936270362713627236273362743627536276362773627836279362803628136282362833628436285362863628736288362893629036291362923629336294362953629636297362983629936300363013630236303363043630536306363073630836309363103631136312363133631436315363163631736318363193632036321363223632336324363253632636327363283632936330363313633236333363343633536336363373633836339363403634136342363433634436345363463634736348363493635036351363523635336354363553635636357363583635936360363613636236363363643636536366363673636836369363703637136372363733637436375363763637736378363793638036381363823638336384363853638636387363883638936390363913639236393363943639536396363973639836399364003640136402364033640436405364063640736408364093641036411364123641336414364153641636417364183641936420364213642236423364243642536426364273642836429364303643136432364333643436435364363643736438364393644036441364423644336444364453644636447364483644936450364513645236453364543645536456364573645836459364603646136462364633646436465364663646736468364693647036471364723647336474364753647636477364783647936480364813648236483364843648536486364873648836489364903649136492364933649436495364963649736498364993650036501365023650336504365053650636507365083650936510365113651236513365143651536516365173651836519365203652136522365233652436525365263652736528365293653036531365323653336534365353653636537365383653936540365413654236543365443654536546365473654836549365503655136552365533655436555365563655736558365593656036561365623656336564365653656636567365683656936570365713657236573365743657536576365773657836579365803658136582365833658436585365863658736588365893659036591365923659336594365953659636597365983659936600366013660236603366043660536606366073660836609366103661136612366133661436615366163661736618366193662036621366223662336624366253662636627366283662936630366313663236633366343663536636366373663836639366403664136642366433664436645366463664736648366493665036651366523665336654366553665636657366583665936660366613666236663366643666536666366673666836669366703667136672366733667436675366763667736678366793668036681366823668336684366853668636687366883668936690366913669236693366943669536696366973669836699367003670136702367033670436705367063670736708367093671036711367123671336714367153671636717367183671936720367213672236723367243672536726367273672836729367303673136732367333673436735367363673736738367393674036741367423674336744367453674636747367483674936750367513675236753367543675536756367573675836759367603676136762367633676436765367663676736768367693677036771367723677336774367753677636777367783677936780367813678236783367843678536786367873678836789367903679136792367933679436795367963679736798367993680036801368023680336804368053680636807368083680936810368113681236813368143681536816368173681836819368203682136822368233682436825368263682736828368293683036831368323683336834368353683636837368383683936840368413684236843368443684536846368473684836849368503685136852368533685436855368563685736858368593686036861368623686336864368653686636867368683686936870368713687236873368743687536876368773687836879368803688136882368833688436885368863688736888368893689036891368923689336894368953689636897368983689936900369013690236903369043690536906369073690836909369103691136912369133691436915369163691736918369193692036921369223692336924369253692636927369283692936930369313693236933369343693536936369373693836939369403694136942369433694436945369463694736948369493695036951369523695336954369553695636957369583695936960369613696236963369643696536966369673696836969369703697136972369733697436975369763697736978369793698036981369823698336984369853698636987369883698936990369913699236993369943699536996369973699836999370003700137002370033700437005370063700737008370093701037011370123701337014370153701637017370183701937020370213702237023370243702537026370273702837029370303703137032370333703437035370363703737038370393704037041370423704337044370453704637047370483704937050370513705237053370543705537056370573705837059370603706137062370633706437065370663706737068370693707037071370723707337074370753707637077370783707937080370813708237083370843708537086370873708837089370903709137092370933709437095370963709737098370993710037101371023710337104371053710637107371083710937110371113711237113371143711537116371173711837119371203712137122371233712437125371263712737128371293713037131371323713337134371353713637137371383713937140371413714237143371443714537146371473714837149371503715137152371533715437155371563715737158371593716037161371623716337164371653716637167371683716937170371713717237173371743717537176371773717837179371803718137182371833718437185371863718737188371893719037191371923719337194371953719637197371983719937200372013720237203372043720537206372073720837209372103721137212372133721437215372163721737218372193722037221372223722337224372253722637227372283722937230372313723237233372343723537236372373723837239372403724137242372433724437245372463724737248372493725037251372523725337254372553725637257372583725937260372613726237263372643726537266372673726837269372703727137272372733727437275372763727737278372793728037281372823728337284372853728637287372883728937290372913729237293372943729537296372973729837299373003730137302373033730437305373063730737308373093731037311373123731337314373153731637317373183731937320373213732237323373243732537326373273732837329373303733137332373333733437335373363733737338373393734037341373423734337344373453734637347373483734937350373513735237353373543735537356373573735837359373603736137362373633736437365373663736737368373693737037371373723737337374373753737637377373783737937380373813738237383373843738537386373873738837389373903739137392373933739437395373963739737398373993740037401374023740337404374053740637407374083740937410374113741237413374143741537416374173741837419374203742137422374233742437425374263742737428374293743037431374323743337434374353743637437374383743937440374413744237443374443744537446374473744837449374503745137452374533745437455374563745737458374593746037461374623746337464374653746637467374683746937470374713747237473374743747537476374773747837479374803748137482374833748437485374863748737488374893749037491374923749337494374953749637497374983749937500375013750237503375043750537506375073750837509375103751137512375133751437515375163751737518375193752037521375223752337524375253752637527375283752937530375313753237533375343753537536375373753837539375403754137542375433754437545375463754737548375493755037551375523755337554375553755637557375583755937560375613756237563375643756537566375673756837569375703757137572375733757437575375763757737578375793758037581375823758337584375853758637587375883758937590375913759237593375943759537596375973759837599376003760137602376033760437605376063760737608376093761037611376123761337614376153761637617376183761937620376213762237623376243762537626376273762837629376303763137632376333763437635376363763737638376393764037641376423764337644376453764637647376483764937650376513765237653376543765537656376573765837659376603766137662376633766437665376663766737668376693767037671376723767337674376753767637677376783767937680376813768237683376843768537686376873768837689376903769137692376933769437695376963769737698376993770037701377023770337704377053770637707377083770937710377113771237713377143771537716377173771837719377203772137722377233772437725377263772737728377293773037731377323773337734377353773637737377383773937740377413774237743377443774537746377473774837749377503775137752377533775437755377563775737758377593776037761377623776337764377653776637767377683776937770377713777237773377743777537776377773777837779377803778137782377833778437785377863778737788377893779037791377923779337794377953779637797377983779937800378013780237803378043780537806378073780837809378103781137812378133781437815378163781737818378193782037821378223782337824378253782637827378283782937830378313783237833378343783537836378373783837839378403784137842378433784437845378463784737848378493785037851378523785337854378553785637857378583785937860378613786237863378643786537866378673786837869378703787137872378733787437875378763787737878378793788037881378823788337884378853788637887378883788937890378913789237893378943789537896378973789837899379003790137902379033790437905379063790737908379093791037911379123791337914379153791637917379183791937920379213792237923379243792537926379273792837929379303793137932379333793437935379363793737938379393794037941379423794337944379453794637947379483794937950379513795237953379543795537956379573795837959379603796137962379633796437965379663796737968379693797037971379723797337974379753797637977379783797937980379813798237983379843798537986379873798837989379903799137992379933799437995379963799737998379993800038001380023800338004380053800638007380083800938010380113801238013380143801538016380173801838019380203802138022380233802438025380263802738028380293803038031380323803338034380353803638037380383803938040380413804238043380443804538046380473804838049380503805138052380533805438055380563805738058380593806038061380623806338064380653806638067380683806938070380713807238073380743807538076380773807838079380803808138082380833808438085380863808738088380893809038091380923809338094380953809638097380983809938100381013810238103381043810538106381073810838109381103811138112381133811438115381163811738118381193812038121381223812338124381253812638127381283812938130381313813238133381343813538136381373813838139381403814138142381433814438145381463814738148381493815038151381523815338154381553815638157381583815938160381613816238163381643816538166381673816838169381703817138172381733817438175381763817738178381793818038181381823818338184381853818638187381883818938190381913819238193381943819538196381973819838199382003820138202382033820438205382063820738208382093821038211382123821338214382153821638217382183821938220382213822238223382243822538226382273822838229382303823138232382333823438235382363823738238382393824038241382423824338244382453824638247382483824938250382513825238253382543825538256382573825838259382603826138262382633826438265382663826738268382693827038271382723827338274382753827638277382783827938280382813828238283382843828538286382873828838289382903829138292382933829438295382963829738298382993830038301383023830338304383053830638307383083830938310383113831238313383143831538316383173831838319383203832138322383233832438325383263832738328383293833038331383323833338334383353833638337383383833938340383413834238343383443834538346383473834838349383503835138352383533835438355383563835738358383593836038361383623836338364383653836638367383683836938370383713837238373383743837538376383773837838379383803838138382383833838438385383863838738388383893839038391383923839338394383953839638397383983839938400384013840238403384043840538406384073840838409384103841138412384133841438415384163841738418384193842038421384223842338424384253842638427384283842938430384313843238433384343843538436384373843838439384403844138442384433844438445384463844738448384493845038451384523845338454384553845638457384583845938460384613846238463384643846538466384673846838469384703847138472384733847438475384763847738478384793848038481384823848338484384853848638487384883848938490384913849238493384943849538496384973849838499385003850138502385033850438505385063850738508385093851038511385123851338514385153851638517385183851938520385213852238523385243852538526385273852838529385303853138532385333853438535385363853738538385393854038541385423854338544385453854638547385483854938550385513855238553385543855538556385573855838559385603856138562385633856438565385663856738568385693857038571385723857338574385753857638577385783857938580385813858238583385843858538586385873858838589385903859138592385933859438595385963859738598385993860038601386023860338604386053860638607386083860938610386113861238613386143861538616386173861838619386203862138622386233862438625386263862738628386293863038631386323863338634386353863638637386383863938640386413864238643386443864538646386473864838649386503865138652386533865438655386563865738658386593866038661386623866338664386653866638667386683866938670386713867238673386743867538676386773867838679386803868138682386833868438685386863868738688386893869038691386923869338694386953869638697386983869938700387013870238703387043870538706387073870838709387103871138712387133871438715387163871738718387193872038721387223872338724387253872638727387283872938730387313873238733387343873538736387373873838739387403874138742387433874438745387463874738748387493875038751387523875338754387553875638757387583875938760387613876238763387643876538766387673876838769387703877138772387733877438775387763877738778387793878038781387823878338784387853878638787387883878938790387913879238793387943879538796387973879838799388003880138802388033880438805388063880738808388093881038811388123881338814388153881638817388183881938820388213882238823388243882538826388273882838829388303883138832388333883438835388363883738838388393884038841388423884338844388453884638847388483884938850388513885238853388543885538856388573885838859388603886138862388633886438865388663886738868388693887038871388723887338874388753887638877388783887938880388813888238883388843888538886388873888838889388903889138892388933889438895388963889738898388993890038901389023890338904389053890638907389083890938910389113891238913389143891538916389173891838919389203892138922389233892438925389263892738928389293893038931389323893338934389353893638937389383893938940389413894238943389443894538946389473894838949389503895138952389533895438955389563895738958389593896038961389623896338964389653896638967389683896938970389713897238973389743897538976389773897838979389803898138982389833898438985389863898738988389893899038991389923899338994389953899638997389983899939000390013900239003390043900539006390073900839009390103901139012390133901439015390163901739018390193902039021390223902339024390253902639027390283902939030390313903239033390343903539036390373903839039390403904139042390433904439045390463904739048390493905039051390523905339054390553905639057390583905939060390613906239063390643906539066390673906839069390703907139072390733907439075390763907739078390793908039081390823908339084390853908639087390883908939090390913909239093390943909539096390973909839099391003910139102391033910439105391063910739108391093911039111391123911339114391153911639117391183911939120391213912239123391243912539126391273912839129391303913139132391333913439135391363913739138391393914039141391423914339144391453914639147391483914939150391513915239153391543915539156391573915839159391603916139162391633916439165391663916739168391693917039171391723917339174391753917639177391783917939180391813918239183391843918539186391873918839189391903919139192391933919439195391963919739198391993920039201392023920339204392053920639207392083920939210392113921239213392143921539216392173921839219392203922139222392233922439225392263922739228392293923039231392323923339234392353923639237392383923939240392413924239243392443924539246392473924839249392503925139252392533925439255392563925739258392593926039261392623926339264392653926639267392683926939270392713927239273392743927539276392773927839279392803928139282392833928439285392863928739288392893929039291392923929339294392953929639297392983929939300393013930239303393043930539306393073930839309393103931139312393133931439315393163931739318393193932039321393223932339324393253932639327393283932939330393313933239333393343933539336393373933839339393403934139342393433934439345393463934739348393493935039351393523935339354393553935639357393583935939360393613936239363393643936539366393673936839369393703937139372393733937439375393763937739378393793938039381393823938339384393853938639387393883938939390393913939239393393943939539396393973939839399394003940139402394033940439405394063940739408394093941039411394123941339414394153941639417394183941939420394213942239423394243942539426394273942839429394303943139432394333943439435394363943739438394393944039441394423944339444394453944639447394483944939450394513945239453394543945539456394573945839459394603946139462394633946439465394663946739468394693947039471394723947339474394753947639477394783947939480394813948239483394843948539486394873948839489394903949139492394933949439495394963949739498394993950039501395023950339504395053950639507395083950939510395113951239513395143951539516395173951839519395203952139522395233952439525395263952739528395293953039531395323953339534395353953639537395383953939540395413954239543395443954539546395473954839549395503955139552395533955439555395563955739558395593956039561395623956339564395653956639567395683956939570395713957239573395743957539576395773957839579395803958139582395833958439585395863958739588395893959039591395923959339594395953959639597395983959939600396013960239603396043960539606396073960839609396103961139612396133961439615396163961739618396193962039621396223962339624396253962639627396283962939630396313963239633396343963539636396373963839639396403964139642396433964439645396463964739648396493965039651396523965339654396553965639657396583965939660396613966239663396643966539666396673966839669396703967139672396733967439675396763967739678396793968039681396823968339684396853968639687396883968939690396913969239693396943969539696396973969839699397003970139702397033970439705397063970739708397093971039711397123971339714397153971639717397183971939720397213972239723397243972539726397273972839729397303973139732397333973439735397363973739738397393974039741397423974339744397453974639747397483974939750397513975239753397543975539756397573975839759397603976139762397633976439765397663976739768397693977039771397723977339774397753977639777397783977939780397813978239783397843978539786397873978839789397903979139792397933979439795397963979739798397993980039801398023980339804398053980639807398083980939810398113981239813398143981539816398173981839819398203982139822398233982439825398263982739828398293983039831398323983339834398353983639837398383983939840398413984239843398443984539846398473984839849398503985139852398533985439855398563985739858398593986039861398623986339864398653986639867398683986939870398713987239873398743987539876398773987839879398803988139882398833988439885398863988739888398893989039891398923989339894398953989639897398983989939900399013990239903399043990539906399073990839909399103991139912399133991439915399163991739918399193992039921399223992339924399253992639927399283992939930399313993239933399343993539936399373993839939399403994139942399433994439945399463994739948399493995039951399523995339954399553995639957399583995939960399613996239963399643996539966399673996839969399703997139972399733997439975399763997739978399793998039981399823998339984399853998639987399883998939990399913999239993399943999539996399973999839999400004000140002400034000440005400064000740008400094001040011400124001340014400154001640017400184001940020400214002240023400244002540026400274002840029400304003140032400334003440035400364003740038400394004040041400424004340044400454004640047400484004940050400514005240053400544005540056400574005840059400604006140062400634006440065400664006740068400694007040071400724007340074400754007640077400784007940080400814008240083400844008540086400874008840089400904009140092400934009440095400964009740098400994010040101401024010340104401054010640107401084010940110401114011240113401144011540116401174011840119401204012140122401234012440125401264012740128401294013040131401324013340134401354013640137401384013940140401414014240143401444014540146401474014840149401504015140152401534015440155401564015740158401594016040161401624016340164401654016640167401684016940170401714017240173401744017540176401774017840179401804018140182401834018440185401864018740188401894019040191401924019340194401954019640197401984019940200402014020240203402044020540206402074020840209402104021140212402134021440215402164021740218402194022040221402224022340224402254022640227402284022940230402314023240233402344023540236402374023840239402404024140242402434024440245402464024740248402494025040251402524025340254402554025640257402584025940260402614026240263402644026540266402674026840269402704027140272402734027440275402764027740278402794028040281402824028340284402854028640287402884028940290402914029240293402944029540296402974029840299403004030140302403034030440305403064030740308403094031040311403124031340314403154031640317403184031940320403214032240323403244032540326403274032840329403304033140332403334033440335403364033740338403394034040341403424034340344403454034640347403484034940350403514035240353403544035540356403574035840359403604036140362403634036440365403664036740368403694037040371403724037340374403754037640377403784037940380403814038240383403844038540386403874038840389403904039140392403934039440395403964039740398403994040040401404024040340404404054040640407404084040940410404114041240413404144041540416404174041840419404204042140422404234042440425404264042740428404294043040431404324043340434404354043640437404384043940440404414044240443404444044540446404474044840449404504045140452404534045440455404564045740458404594046040461404624046340464404654046640467404684046940470404714047240473404744047540476404774047840479404804048140482404834048440485404864048740488404894049040491404924049340494404954049640497404984049940500405014050240503405044050540506405074050840509405104051140512405134051440515405164051740518405194052040521405224052340524405254052640527405284052940530405314053240533405344053540536405374053840539405404054140542405434054440545405464054740548405494055040551405524055340554405554055640557405584055940560405614056240563405644056540566405674056840569405704057140572405734057440575405764057740578405794058040581405824058340584405854058640587405884058940590405914059240593405944059540596405974059840599406004060140602406034060440605406064060740608406094061040611406124061340614406154061640617406184061940620406214062240623406244062540626406274062840629406304063140632406334063440635406364063740638406394064040641406424064340644406454064640647406484064940650406514065240653406544065540656406574065840659406604066140662406634066440665406664066740668406694067040671406724067340674406754067640677406784067940680406814068240683406844068540686406874068840689406904069140692406934069440695406964069740698406994070040701407024070340704407054070640707407084070940710407114071240713407144071540716407174071840719407204072140722407234072440725407264072740728407294073040731407324073340734407354073640737407384073940740407414074240743407444074540746407474074840749407504075140752407534075440755407564075740758407594076040761407624076340764407654076640767407684076940770407714077240773407744077540776407774077840779407804078140782407834078440785407864078740788407894079040791407924079340794407954079640797407984079940800408014080240803408044080540806408074080840809408104081140812408134081440815408164081740818408194082040821408224082340824408254082640827408284082940830408314083240833408344083540836408374083840839408404084140842408434084440845408464084740848408494085040851408524085340854408554085640857408584085940860408614086240863408644086540866408674086840869408704087140872408734087440875408764087740878408794088040881408824088340884408854088640887408884088940890408914089240893408944089540896408974089840899409004090140902409034090440905409064090740908409094091040911409124091340914409154091640917409184091940920409214092240923409244092540926409274092840929409304093140932409334093440935409364093740938409394094040941409424094340944409454094640947409484094940950409514095240953409544095540956409574095840959409604096140962409634096440965409664096740968409694097040971409724097340974409754097640977409784097940980409814098240983409844098540986409874098840989409904099140992409934099440995409964099740998409994100041001410024100341004410054100641007410084100941010410114101241013410144101541016410174101841019410204102141022410234102441025410264102741028410294103041031410324103341034410354103641037410384103941040410414104241043410444104541046410474104841049410504105141052410534105441055410564105741058410594106041061410624106341064410654106641067410684106941070410714107241073410744107541076410774107841079410804108141082410834108441085410864108741088410894109041091410924109341094410954109641097410984109941100411014110241103411044110541106411074110841109411104111141112411134111441115411164111741118411194112041121411224112341124411254112641127411284112941130411314113241133411344113541136411374113841139411404114141142411434114441145411464114741148411494115041151411524115341154411554115641157411584115941160411614116241163411644116541166411674116841169411704117141172411734117441175411764117741178411794118041181411824118341184411854118641187411884118941190411914119241193411944119541196411974119841199412004120141202412034120441205412064120741208412094121041211412124121341214412154121641217412184121941220412214122241223412244122541226412274122841229412304123141232412334123441235412364123741238412394124041241412424124341244412454124641247412484124941250412514125241253412544125541256412574125841259412604126141262412634126441265412664126741268412694127041271412724127341274412754127641277412784127941280412814128241283412844128541286412874128841289412904129141292412934129441295412964129741298412994130041301413024130341304413054130641307413084130941310413114131241313413144131541316413174131841319413204132141322413234132441325413264132741328413294133041331413324133341334413354133641337413384133941340413414134241343413444134541346413474134841349413504135141352413534135441355413564135741358413594136041361413624136341364413654136641367413684136941370413714137241373413744137541376413774137841379413804138141382413834138441385413864138741388413894139041391413924139341394413954139641397413984139941400414014140241403414044140541406414074140841409414104141141412414134141441415414164141741418414194142041421414224142341424414254142641427414284142941430414314143241433414344143541436414374143841439414404144141442414434144441445414464144741448414494145041451414524145341454414554145641457414584145941460414614146241463414644146541466414674146841469414704147141472414734147441475414764147741478414794148041481414824148341484414854148641487414884148941490414914149241493414944149541496414974149841499415004150141502415034150441505415064150741508415094151041511415124151341514415154151641517415184151941520415214152241523415244152541526415274152841529415304153141532415334153441535415364153741538415394154041541415424154341544415454154641547415484154941550415514155241553415544155541556415574155841559415604156141562415634156441565415664156741568415694157041571415724157341574415754157641577415784157941580415814158241583415844158541586415874158841589415904159141592415934159441595415964159741598415994160041601416024160341604416054160641607416084160941610416114161241613416144161541616416174161841619416204162141622416234162441625416264162741628416294163041631416324163341634416354163641637416384163941640416414164241643416444164541646416474164841649416504165141652416534165441655416564165741658416594166041661416624166341664416654166641667416684166941670416714167241673416744167541676416774167841679416804168141682416834168441685416864168741688416894169041691416924169341694416954169641697416984169941700417014170241703417044170541706417074170841709417104171141712417134171441715417164171741718417194172041721417224172341724417254172641727417284172941730417314173241733417344173541736417374173841739417404174141742417434174441745417464174741748417494175041751417524175341754417554175641757417584175941760417614176241763417644176541766417674176841769417704177141772417734177441775417764177741778417794178041781417824178341784417854178641787417884178941790417914179241793417944179541796417974179841799418004180141802418034180441805418064180741808418094181041811418124181341814418154181641817418184181941820418214182241823418244182541826418274182841829418304183141832418334183441835418364183741838418394184041841418424184341844418454184641847418484184941850418514185241853418544185541856418574185841859418604186141862418634186441865418664186741868418694187041871418724187341874418754187641877418784187941880418814188241883418844188541886418874188841889418904189141892418934189441895418964189741898418994190041901419024190341904419054190641907419084190941910419114191241913419144191541916419174191841919419204192141922419234192441925419264192741928419294193041931419324193341934419354193641937419384193941940419414194241943419444194541946419474194841949419504195141952419534195441955419564195741958419594196041961419624196341964419654196641967419684196941970419714197241973419744197541976419774197841979419804198141982419834198441985419864198741988419894199041991419924199341994419954199641997419984199942000420014200242003420044200542006420074200842009420104201142012420134201442015420164201742018420194202042021420224202342024420254202642027420284202942030420314203242033420344203542036420374203842039420404204142042420434204442045420464204742048420494205042051420524205342054420554205642057420584205942060420614206242063420644206542066420674206842069420704207142072420734207442075420764207742078420794208042081420824208342084420854208642087420884208942090420914209242093420944209542096420974209842099421004210142102421034210442105421064210742108421094211042111421124211342114421154211642117421184211942120421214212242123421244212542126421274212842129421304213142132421334213442135421364213742138421394214042141421424214342144421454214642147421484214942150421514215242153421544215542156421574215842159421604216142162421634216442165421664216742168421694217042171421724217342174421754217642177421784217942180421814218242183421844218542186421874218842189421904219142192421934219442195421964219742198421994220042201422024220342204422054220642207422084220942210422114221242213422144221542216422174221842219422204222142222422234222442225422264222742228422294223042231422324223342234422354223642237422384223942240422414224242243422444224542246422474224842249422504225142252422534225442255422564225742258422594226042261422624226342264422654226642267422684226942270422714227242273422744227542276422774227842279422804228142282422834228442285422864228742288422894229042291422924229342294422954229642297422984229942300423014230242303423044230542306423074230842309423104231142312423134231442315423164231742318423194232042321423224232342324423254232642327423284232942330423314233242333423344233542336423374233842339423404234142342423434234442345423464234742348423494235042351423524235342354423554235642357423584235942360423614236242363423644236542366423674236842369423704237142372423734237442375423764237742378423794238042381423824238342384423854238642387423884238942390423914239242393423944239542396423974239842399424004240142402424034240442405424064240742408424094241042411424124241342414424154241642417424184241942420424214242242423424244242542426424274242842429424304243142432424334243442435424364243742438424394244042441424424244342444424454244642447424484244942450424514245242453424544245542456424574245842459424604246142462424634246442465424664246742468424694247042471424724247342474424754247642477424784247942480424814248242483424844248542486424874248842489424904249142492424934249442495424964249742498424994250042501425024250342504425054250642507425084250942510425114251242513425144251542516425174251842519425204252142522425234252442525425264252742528425294253042531425324253342534425354253642537425384253942540425414254242543425444254542546425474254842549425504255142552425534255442555425564255742558425594256042561425624256342564425654256642567425684256942570425714257242573425744257542576425774257842579425804258142582425834258442585425864258742588425894259042591425924259342594425954259642597425984259942600426014260242603426044260542606426074260842609426104261142612426134261442615426164261742618426194262042621426224262342624426254262642627426284262942630426314263242633426344263542636426374263842639426404264142642426434264442645426464264742648426494265042651426524265342654426554265642657426584265942660426614266242663426644266542666426674266842669426704267142672426734267442675426764267742678426794268042681426824268342684426854268642687426884268942690426914269242693426944269542696426974269842699427004270142702427034270442705427064270742708427094271042711427124271342714427154271642717427184271942720427214272242723427244272542726427274272842729427304273142732427334273442735427364273742738427394274042741427424274342744427454274642747427484274942750427514275242753427544275542756427574275842759427604276142762427634276442765427664276742768427694277042771427724277342774427754277642777427784277942780427814278242783427844278542786427874278842789427904279142792427934279442795427964279742798427994280042801428024280342804428054280642807428084280942810428114281242813428144281542816428174281842819428204282142822428234282442825428264282742828428294283042831428324283342834428354283642837428384283942840428414284242843428444284542846428474284842849428504285142852428534285442855428564285742858428594286042861428624286342864428654286642867428684286942870428714287242873428744287542876428774287842879428804288142882428834288442885428864288742888428894289042891428924289342894428954289642897428984289942900429014290242903429044290542906429074290842909429104291142912429134291442915429164291742918429194292042921429224292342924429254292642927429284292942930429314293242933429344293542936429374293842939429404294142942429434294442945429464294742948429494295042951429524295342954429554295642957429584295942960429614296242963429644296542966429674296842969429704297142972429734297442975429764297742978429794298042981429824298342984429854298642987429884298942990429914299242993429944299542996429974299842999430004300143002430034300443005430064300743008430094301043011430124301343014430154301643017430184301943020430214302243023430244302543026430274302843029430304303143032430334303443035430364303743038430394304043041430424304343044430454304643047430484304943050430514305243053430544305543056430574305843059430604306143062430634306443065430664306743068430694307043071430724307343074430754307643077430784307943080430814308243083430844308543086430874308843089430904309143092430934309443095430964309743098430994310043101431024310343104431054310643107431084310943110431114311243113431144311543116431174311843119431204312143122431234312443125431264312743128431294313043131431324313343134431354313643137431384313943140431414314243143431444314543146431474314843149431504315143152431534315443155431564315743158431594316043161431624316343164431654316643167431684316943170431714317243173431744317543176431774317843179431804318143182431834318443185431864318743188431894319043191431924319343194431954319643197431984319943200432014320243203432044320543206432074320843209432104321143212432134321443215432164321743218432194322043221432224322343224432254322643227432284322943230432314323243233432344323543236432374323843239432404324143242432434324443245432464324743248432494325043251432524325343254432554325643257432584325943260432614326243263432644326543266432674326843269432704327143272432734327443275432764327743278432794328043281432824328343284432854328643287432884328943290432914329243293432944329543296432974329843299433004330143302433034330443305433064330743308433094331043311433124331343314433154331643317433184331943320433214332243323433244332543326433274332843329433304333143332433334333443335433364333743338433394334043341433424334343344433454334643347433484334943350433514335243353433544335543356433574335843359433604336143362433634336443365433664336743368433694337043371433724337343374433754337643377433784337943380433814338243383433844338543386433874338843389433904339143392433934339443395433964339743398433994340043401434024340343404434054340643407434084340943410434114341243413434144341543416434174341843419434204342143422434234342443425434264342743428434294343043431434324343343434434354343643437434384343943440434414344243443434444344543446434474344843449434504345143452434534345443455434564345743458434594346043461434624346343464434654346643467434684346943470434714347243473434744347543476434774347843479434804348143482434834348443485434864348743488434894349043491434924349343494434954349643497434984349943500435014350243503435044350543506435074350843509435104351143512435134351443515435164351743518435194352043521435224352343524435254352643527435284352943530435314353243533435344353543536435374353843539435404354143542435434354443545435464354743548435494355043551435524355343554435554355643557435584355943560435614356243563435644356543566435674356843569435704357143572435734357443575435764357743578435794358043581435824358343584435854358643587435884358943590435914359243593435944359543596435974359843599436004360143602436034360443605436064360743608436094361043611436124361343614436154361643617436184361943620436214362243623436244362543626436274362843629436304363143632436334363443635436364363743638436394364043641436424364343644436454364643647436484364943650436514365243653436544365543656436574365843659436604366143662436634366443665436664366743668436694367043671436724367343674436754367643677436784367943680436814368243683436844368543686436874368843689436904369143692436934369443695436964369743698436994370043701437024370343704437054370643707437084370943710437114371243713437144371543716437174371843719437204372143722437234372443725437264372743728437294373043731437324373343734437354373643737437384373943740437414374243743437444374543746437474374843749437504375143752437534375443755437564375743758437594376043761437624376343764437654376643767437684376943770437714377243773437744377543776437774377843779437804378143782437834378443785437864378743788437894379043791437924379343794437954379643797437984379943800438014380243803438044380543806438074380843809438104381143812438134381443815438164381743818438194382043821438224382343824438254382643827438284382943830438314383243833438344383543836438374383843839438404384143842438434384443845438464384743848438494385043851438524385343854438554385643857438584385943860438614386243863438644386543866438674386843869438704387143872438734387443875438764387743878438794388043881438824388343884438854388643887438884388943890438914389243893438944389543896438974389843899439004390143902439034390443905439064390743908439094391043911439124391343914439154391643917439184391943920439214392243923439244392543926439274392843929439304393143932439334393443935439364393743938439394394043941439424394343944439454394643947439484394943950439514395243953439544395543956439574395843959439604396143962439634396443965439664396743968439694397043971439724397343974439754397643977439784397943980439814398243983439844398543986439874398843989439904399143992439934399443995439964399743998439994400044001440024400344004440054400644007440084400944010440114401244013440144401544016440174401844019440204402144022440234402444025440264402744028440294403044031440324403344034440354403644037440384403944040440414404244043440444404544046440474404844049440504405144052440534405444055440564405744058440594406044061440624406344064440654406644067440684406944070440714407244073440744407544076440774407844079440804408144082440834408444085440864408744088440894409044091440924409344094440954409644097440984409944100441014410244103441044410544106441074410844109441104411144112441134411444115441164411744118441194412044121441224412344124441254412644127441284412944130441314413244133441344413544136441374413844139441404414144142441434414444145441464414744148441494415044151441524415344154441554415644157441584415944160441614416244163441644416544166441674416844169441704417144172441734417444175441764417744178441794418044181441824418344184441854418644187441884418944190441914419244193441944419544196441974419844199442004420144202442034420444205442064420744208442094421044211442124421344214442154421644217442184421944220442214422244223442244422544226442274422844229442304423144232442334423444235442364423744238442394424044241442424424344244442454424644247442484424944250442514425244253442544425544256442574425844259442604426144262442634426444265442664426744268442694427044271442724427344274442754427644277442784427944280442814428244283442844428544286442874428844289442904429144292442934429444295442964429744298442994430044301443024430344304443054430644307443084430944310443114431244313443144431544316443174431844319443204432144322443234432444325443264432744328443294433044331443324433344334443354433644337443384433944340443414434244343443444434544346443474434844349443504435144352443534435444355443564435744358443594436044361443624436344364443654436644367443684436944370443714437244373443744437544376443774437844379443804438144382443834438444385443864438744388443894439044391443924439344394443954439644397443984439944400444014440244403444044440544406444074440844409444104441144412444134441444415444164441744418444194442044421444224442344424444254442644427444284442944430444314443244433444344443544436444374443844439444404444144442444434444444445444464444744448444494445044451444524445344454444554445644457444584445944460444614446244463444644446544466444674446844469444704447144472444734447444475444764447744478444794448044481444824448344484444854448644487444884448944490444914449244493444944449544496444974449844499445004450144502445034450444505445064450744508445094451044511445124451344514445154451644517445184451944520445214452244523445244452544526445274452844529445304453144532445334453444535445364453744538445394454044541445424454344544445454454644547445484454944550445514455244553445544455544556445574455844559445604456144562445634456444565445664456744568445694457044571445724457344574445754457644577445784457944580445814458244583445844458544586445874458844589445904459144592445934459444595445964459744598445994460044601446024460344604446054460644607446084460944610446114461244613446144461544616446174461844619446204462144622446234462444625446264462744628446294463044631446324463344634446354463644637446384463944640446414464244643446444464544646446474464844649446504465144652446534465444655446564465744658446594466044661446624466344664446654466644667446684466944670446714467244673446744467544676446774467844679446804468144682446834468444685446864468744688446894469044691446924469344694446954469644697446984469944700447014470244703447044470544706447074470844709447104471144712447134471444715447164471744718447194472044721447224472344724447254472644727447284472944730447314473244733447344473544736447374473844739447404474144742447434474444745447464474744748447494475044751447524475344754447554475644757447584475944760447614476244763447644476544766447674476844769447704477144772447734477444775447764477744778447794478044781447824478344784447854478644787447884478944790447914479244793447944479544796447974479844799448004480144802448034480444805448064480744808448094481044811448124481344814448154481644817448184481944820448214482244823448244482544826448274482844829448304483144832448334483444835448364483744838448394484044841448424484344844448454484644847448484484944850448514485244853448544485544856448574485844859448604486144862448634486444865448664486744868448694487044871448724487344874448754487644877448784487944880448814488244883448844488544886448874488844889448904489144892448934489444895448964489744898448994490044901449024490344904449054490644907449084490944910449114491244913449144491544916449174491844919449204492144922449234492444925449264492744928449294493044931449324493344934449354493644937449384493944940449414494244943449444494544946449474494844949449504495144952449534495444955449564495744958449594496044961449624496344964449654496644967449684496944970449714497244973449744497544976449774497844979449804498144982449834498444985449864498744988449894499044991449924499344994449954499644997449984499945000450014500245003450044500545006450074500845009450104501145012450134501445015450164501745018450194502045021450224502345024450254502645027450284502945030450314503245033450344503545036450374503845039450404504145042450434504445045450464504745048450494505045051450524505345054450554505645057450584505945060450614506245063450644506545066450674506845069450704507145072450734507445075450764507745078450794508045081450824508345084450854508645087450884508945090450914509245093450944509545096450974509845099451004510145102451034510445105451064510745108451094511045111451124511345114451154511645117451184511945120451214512245123451244512545126451274512845129451304513145132451334513445135451364513745138451394514045141451424514345144451454514645147451484514945150451514515245153451544515545156451574515845159451604516145162451634516445165451664516745168451694517045171451724517345174451754517645177451784517945180451814518245183451844518545186451874518845189451904519145192451934519445195451964519745198451994520045201452024520345204452054520645207452084520945210452114521245213452144521545216452174521845219452204522145222452234522445225452264522745228452294523045231452324523345234452354523645237452384523945240452414524245243452444524545246452474524845249452504525145252452534525445255452564525745258452594526045261452624526345264452654526645267452684526945270452714527245273452744527545276452774527845279452804528145282452834528445285452864528745288452894529045291452924529345294452954529645297452984529945300453014530245303453044530545306453074530845309453104531145312453134531445315453164531745318453194532045321453224532345324453254532645327453284532945330453314533245333453344533545336453374533845339453404534145342453434534445345453464534745348453494535045351453524535345354453554535645357453584535945360453614536245363453644536545366453674536845369453704537145372453734537445375453764537745378453794538045381453824538345384453854538645387453884538945390453914539245393453944539545396453974539845399454004540145402454034540445405454064540745408454094541045411454124541345414454154541645417454184541945420454214542245423454244542545426454274542845429454304543145432454334543445435454364543745438454394544045441454424544345444454454544645447454484544945450454514545245453454544545545456454574545845459454604546145462454634546445465454664546745468454694547045471454724547345474454754547645477454784547945480454814548245483454844548545486454874548845489454904549145492454934549445495454964549745498454994550045501455024550345504455054550645507455084550945510455114551245513455144551545516455174551845519455204552145522455234552445525455264552745528455294553045531455324553345534455354553645537455384553945540455414554245543455444554545546455474554845549455504555145552455534555445555455564555745558455594556045561455624556345564455654556645567455684556945570455714557245573455744557545576455774557845579455804558145582455834558445585455864558745588455894559045591455924559345594455954559645597455984559945600456014560245603456044560545606456074560845609456104561145612456134561445615456164561745618456194562045621456224562345624456254562645627456284562945630456314563245633456344563545636456374563845639456404564145642456434564445645456464564745648456494565045651456524565345654456554565645657456584565945660456614566245663456644566545666456674566845669456704567145672456734567445675456764567745678456794568045681456824568345684456854568645687456884568945690456914569245693456944569545696456974569845699457004570145702457034570445705457064570745708457094571045711457124571345714457154571645717457184571945720457214572245723457244572545726457274572845729457304573145732457334573445735457364573745738457394574045741457424574345744457454574645747457484574945750457514575245753457544575545756457574575845759457604576145762457634576445765457664576745768457694577045771457724577345774457754577645777457784577945780457814578245783457844578545786457874578845789457904579145792457934579445795457964579745798457994580045801458024580345804458054580645807458084580945810458114581245813458144581545816458174581845819458204582145822458234582445825458264582745828458294583045831458324583345834458354583645837458384583945840458414584245843458444584545846458474584845849458504585145852458534585445855458564585745858458594586045861458624586345864458654586645867458684586945870458714587245873458744587545876458774587845879458804588145882458834588445885458864588745888458894589045891458924589345894458954589645897458984589945900459014590245903459044590545906459074590845909459104591145912459134591445915459164591745918459194592045921459224592345924459254592645927459284592945930459314593245933459344593545936459374593845939459404594145942459434594445945459464594745948459494595045951459524595345954459554595645957459584595945960459614596245963459644596545966459674596845969459704597145972459734597445975459764597745978459794598045981459824598345984459854598645987459884598945990459914599245993459944599545996459974599845999460004600146002460034600446005460064600746008460094601046011460124601346014460154601646017460184601946020460214602246023460244602546026460274602846029460304603146032460334603446035460364603746038460394604046041460424604346044460454604646047460484604946050460514605246053460544605546056460574605846059460604606146062460634606446065460664606746068460694607046071460724607346074460754607646077460784607946080460814608246083460844608546086460874608846089460904609146092460934609446095460964609746098460994610046101461024610346104461054610646107461084610946110461114611246113461144611546116461174611846119461204612146122461234612446125461264612746128461294613046131461324613346134461354613646137461384613946140461414614246143461444614546146461474614846149461504615146152461534615446155461564615746158461594616046161461624616346164461654616646167461684616946170461714617246173461744617546176461774617846179461804618146182461834618446185461864618746188461894619046191461924619346194461954619646197461984619946200462014620246203462044620546206462074620846209462104621146212462134621446215462164621746218462194622046221462224622346224462254622646227462284622946230462314623246233462344623546236462374623846239462404624146242462434624446245462464624746248462494625046251462524625346254462554625646257462584625946260462614626246263462644626546266462674626846269462704627146272462734627446275462764627746278462794628046281462824628346284462854628646287462884628946290462914629246293462944629546296462974629846299463004630146302463034630446305463064630746308463094631046311463124631346314463154631646317463184631946320463214632246323463244632546326463274632846329463304633146332463334633446335463364633746338463394634046341463424634346344463454634646347463484634946350463514635246353463544635546356463574635846359463604636146362463634636446365463664636746368463694637046371463724637346374463754637646377463784637946380463814638246383463844638546386463874638846389463904639146392463934639446395463964639746398463994640046401464024640346404464054640646407464084640946410464114641246413464144641546416464174641846419464204642146422464234642446425464264642746428464294643046431464324643346434464354643646437464384643946440464414644246443464444644546446464474644846449464504645146452464534645446455464564645746458464594646046461464624646346464464654646646467464684646946470464714647246473464744647546476464774647846479464804648146482464834648446485464864648746488464894649046491464924649346494464954649646497464984649946500465014650246503465044650546506465074650846509465104651146512465134651446515465164651746518465194652046521465224652346524465254652646527465284652946530465314653246533465344653546536465374653846539465404654146542465434654446545465464654746548465494655046551465524655346554465554655646557465584655946560465614656246563465644656546566465674656846569465704657146572465734657446575465764657746578465794658046581465824658346584465854658646587465884658946590465914659246593465944659546596465974659846599466004660146602466034660446605466064660746608466094661046611466124661346614466154661646617466184661946620466214662246623466244662546626466274662846629466304663146632466334663446635466364663746638466394664046641466424664346644466454664646647466484664946650466514665246653466544665546656466574665846659466604666146662466634666446665466664666746668466694667046671466724667346674466754667646677466784667946680466814668246683466844668546686466874668846689466904669146692466934669446695466964669746698466994670046701467024670346704467054670646707467084670946710467114671246713467144671546716467174671846719467204672146722467234672446725467264672746728467294673046731467324673346734467354673646737467384673946740467414674246743467444674546746467474674846749467504675146752467534675446755467564675746758467594676046761467624676346764467654676646767467684676946770467714677246773467744677546776467774677846779467804678146782467834678446785467864678746788467894679046791467924679346794467954679646797467984679946800468014680246803468044680546806468074680846809468104681146812468134681446815468164681746818468194682046821468224682346824468254682646827468284682946830468314683246833468344683546836468374683846839468404684146842468434684446845468464684746848468494685046851468524685346854468554685646857468584685946860468614686246863468644686546866468674686846869468704687146872468734687446875468764687746878468794688046881468824688346884468854688646887468884688946890468914689246893468944689546896468974689846899469004690146902469034690446905469064690746908469094691046911469124691346914469154691646917469184691946920469214692246923469244692546926469274692846929469304693146932469334693446935469364693746938469394694046941469424694346944469454694646947469484694946950469514695246953469544695546956469574695846959469604696146962469634696446965469664696746968469694697046971469724697346974469754697646977469784697946980469814698246983469844698546986469874698846989469904699146992469934699446995469964699746998469994700047001470024700347004470054700647007470084700947010470114701247013470144701547016470174701847019470204702147022470234702447025470264702747028470294703047031470324703347034470354703647037470384703947040470414704247043470444704547046470474704847049470504705147052470534705447055470564705747058470594706047061470624706347064470654706647067470684706947070470714707247073470744707547076470774707847079470804708147082470834708447085470864708747088470894709047091470924709347094470954709647097470984709947100471014710247103471044710547106471074710847109471104711147112471134711447115471164711747118471194712047121471224712347124471254712647127471284712947130471314713247133471344713547136471374713847139471404714147142471434714447145471464714747148471494715047151471524715347154471554715647157471584715947160471614716247163471644716547166471674716847169471704717147172471734717447175471764717747178471794718047181471824718347184471854718647187471884718947190471914719247193471944719547196471974719847199472004720147202472034720447205472064720747208472094721047211472124721347214472154721647217472184721947220472214722247223472244722547226472274722847229472304723147232472334723447235472364723747238472394724047241472424724347244472454724647247472484724947250472514725247253472544725547256472574725847259472604726147262472634726447265472664726747268472694727047271472724727347274472754727647277472784727947280472814728247283472844728547286472874728847289472904729147292472934729447295472964729747298472994730047301473024730347304473054730647307473084730947310473114731247313473144731547316473174731847319473204732147322473234732447325473264732747328473294733047331473324733347334473354733647337473384733947340473414734247343473444734547346473474734847349473504735147352473534735447355473564735747358473594736047361473624736347364473654736647367473684736947370473714737247373473744737547376473774737847379473804738147382473834738447385473864738747388473894739047391473924739347394473954739647397473984739947400474014740247403474044740547406474074740847409474104741147412474134741447415474164741747418474194742047421474224742347424474254742647427474284742947430474314743247433474344743547436474374743847439474404744147442474434744447445474464744747448474494745047451474524745347454474554745647457474584745947460474614746247463474644746547466474674746847469474704747147472474734747447475474764747747478474794748047481474824748347484474854748647487474884748947490474914749247493474944749547496474974749847499475004750147502475034750447505475064750747508475094751047511475124751347514475154751647517475184751947520475214752247523475244752547526475274752847529475304753147532475334753447535475364753747538475394754047541475424754347544475454754647547475484754947550475514755247553475544755547556475574755847559475604756147562475634756447565475664756747568475694757047571475724757347574475754757647577475784757947580475814758247583475844758547586475874758847589475904759147592475934759447595475964759747598475994760047601476024760347604476054760647607476084760947610476114761247613476144761547616476174761847619476204762147622476234762447625476264762747628476294763047631476324763347634476354763647637476384763947640476414764247643476444764547646476474764847649476504765147652476534765447655476564765747658476594766047661476624766347664476654766647667476684766947670476714767247673476744767547676476774767847679476804768147682476834768447685476864768747688476894769047691476924769347694476954769647697476984769947700477014770247703477044770547706477074770847709477104771147712477134771447715477164771747718477194772047721477224772347724477254772647727477284772947730477314773247733477344773547736477374773847739477404774147742477434774447745477464774747748477494775047751477524775347754477554775647757477584775947760477614776247763477644776547766477674776847769477704777147772477734777447775477764777747778477794778047781477824778347784477854778647787477884778947790477914779247793477944779547796477974779847799478004780147802478034780447805478064780747808478094781047811478124781347814478154781647817478184781947820478214782247823478244782547826478274782847829478304783147832478334783447835478364783747838478394784047841478424784347844478454784647847478484784947850478514785247853478544785547856478574785847859478604786147862478634786447865478664786747868478694787047871478724787347874478754787647877478784787947880478814788247883478844788547886478874788847889478904789147892478934789447895478964789747898478994790047901479024790347904479054790647907479084790947910479114791247913479144791547916479174791847919479204792147922479234792447925479264792747928479294793047931479324793347934479354793647937479384793947940479414794247943479444794547946479474794847949479504795147952479534795447955479564795747958479594796047961479624796347964479654796647967479684796947970479714797247973479744797547976479774797847979479804798147982479834798447985479864798747988479894799047991479924799347994479954799647997479984799948000480014800248003480044800548006480074800848009480104801148012480134801448015480164801748018480194802048021480224802348024480254802648027480284802948030480314803248033480344803548036480374803848039480404804148042480434804448045480464804748048480494805048051480524805348054480554805648057480584805948060480614806248063480644806548066480674806848069480704807148072480734807448075480764807748078480794808048081480824808348084480854808648087480884808948090480914809248093480944809548096480974809848099481004810148102481034810448105481064810748108481094811048111481124811348114481154811648117481184811948120481214812248123481244812548126481274812848129481304813148132481334813448135481364813748138481394814048141481424814348144481454814648147481484814948150481514815248153481544815548156481574815848159481604816148162481634816448165481664816748168481694817048171481724817348174481754817648177481784817948180481814818248183481844818548186481874818848189481904819148192481934819448195481964819748198481994820048201482024820348204482054820648207482084820948210482114821248213482144821548216482174821848219482204822148222482234822448225482264822748228482294823048231482324823348234482354823648237482384823948240482414824248243482444824548246482474824848249482504825148252482534825448255482564825748258482594826048261482624826348264482654826648267482684826948270482714827248273482744827548276482774827848279482804828148282482834828448285482864828748288482894829048291482924829348294482954829648297482984829948300483014830248303483044830548306483074830848309483104831148312483134831448315483164831748318483194832048321483224832348324483254832648327483284832948330483314833248333483344833548336483374833848339483404834148342483434834448345483464834748348483494835048351483524835348354483554835648357483584835948360483614836248363483644836548366483674836848369483704837148372483734837448375483764837748378483794838048381483824838348384483854838648387483884838948390483914839248393483944839548396483974839848399484004840148402484034840448405484064840748408484094841048411484124841348414484154841648417484184841948420484214842248423484244842548426484274842848429484304843148432484334843448435484364843748438484394844048441484424844348444484454844648447484484844948450484514845248453484544845548456484574845848459484604846148462484634846448465484664846748468484694847048471484724847348474484754847648477484784847948480484814848248483484844848548486484874848848489484904849148492484934849448495484964849748498484994850048501485024850348504485054850648507485084850948510485114851248513485144851548516485174851848519485204852148522485234852448525485264852748528485294853048531485324853348534485354853648537485384853948540485414854248543485444854548546485474854848549485504855148552485534855448555485564855748558485594856048561485624856348564485654856648567485684856948570485714857248573485744857548576485774857848579485804858148582485834858448585485864858748588485894859048591485924859348594485954859648597485984859948600486014860248603486044860548606486074860848609486104861148612486134861448615486164861748618486194862048621486224862348624486254862648627486284862948630486314863248633486344863548636486374863848639486404864148642486434864448645486464864748648486494865048651486524865348654486554865648657486584865948660486614866248663486644866548666486674866848669486704867148672486734867448675486764867748678486794868048681486824868348684486854868648687486884868948690486914869248693486944869548696486974869848699487004870148702487034870448705487064870748708487094871048711487124871348714487154871648717487184871948720487214872248723487244872548726487274872848729487304873148732487334873448735487364873748738487394874048741487424874348744487454874648747487484874948750487514875248753487544875548756487574875848759487604876148762487634876448765487664876748768487694877048771487724877348774487754877648777487784877948780487814878248783487844878548786487874878848789487904879148792487934879448795487964879748798487994880048801488024880348804488054880648807488084880948810488114881248813488144881548816488174881848819488204882148822488234882448825488264882748828488294883048831488324883348834488354883648837488384883948840488414884248843488444884548846488474884848849488504885148852488534885448855488564885748858488594886048861488624886348864488654886648867488684886948870488714887248873488744887548876488774887848879488804888148882488834888448885488864888748888488894889048891488924889348894488954889648897488984889948900489014890248903489044890548906489074890848909489104891148912489134891448915489164891748918489194892048921489224892348924489254892648927489284892948930489314893248933489344893548936489374893848939489404894148942489434894448945489464894748948489494895048951489524895348954489554895648957489584895948960489614896248963489644896548966489674896848969489704897148972489734897448975489764897748978489794898048981489824898348984489854898648987489884898948990489914899248993489944899548996489974899848999490004900149002490034900449005490064900749008490094901049011490124901349014490154901649017490184901949020490214902249023490244902549026490274902849029490304903149032490334903449035490364903749038490394904049041490424904349044490454904649047490484904949050490514905249053490544905549056490574905849059490604906149062490634906449065490664906749068490694907049071490724907349074490754907649077490784907949080490814908249083490844908549086490874908849089490904909149092490934909449095490964909749098490994910049101491024910349104491054910649107491084910949110491114911249113491144911549116491174911849119491204912149122491234912449125491264912749128491294913049131491324913349134491354913649137491384913949140491414914249143491444914549146491474914849149491504915149152491534915449155491564915749158491594916049161491624916349164491654916649167491684916949170491714917249173491744917549176491774917849179491804918149182491834918449185491864918749188491894919049191491924919349194491954919649197491984919949200492014920249203492044920549206492074920849209492104921149212492134921449215492164921749218492194922049221492224922349224492254922649227492284922949230492314923249233492344923549236492374923849239492404924149242492434924449245492464924749248492494925049251492524925349254492554925649257492584925949260492614926249263492644926549266492674926849269492704927149272492734927449275492764927749278492794928049281492824928349284492854928649287492884928949290492914929249293492944929549296492974929849299493004930149302493034930449305493064930749308493094931049311493124931349314493154931649317493184931949320493214932249323493244932549326493274932849329493304933149332493334933449335493364933749338493394934049341493424934349344493454934649347493484934949350493514935249353493544935549356493574935849359493604936149362493634936449365493664936749368493694937049371493724937349374493754937649377493784937949380493814938249383493844938549386493874938849389493904939149392493934939449395493964939749398493994940049401494024940349404494054940649407494084940949410494114941249413494144941549416494174941849419494204942149422494234942449425494264942749428494294943049431494324943349434494354943649437494384943949440494414944249443494444944549446494474944849449494504945149452494534945449455494564945749458494594946049461494624946349464494654946649467494684946949470494714947249473494744947549476494774947849479494804948149482494834948449485494864948749488494894949049491494924949349494494954949649497494984949949500495014950249503495044950549506495074950849509495104951149512495134951449515495164951749518495194952049521495224952349524495254952649527495284952949530495314953249533495344953549536495374953849539495404954149542495434954449545495464954749548495494955049551495524955349554495554955649557495584955949560495614956249563495644956549566495674956849569495704957149572495734957449575495764957749578495794958049581495824958349584495854958649587495884958949590495914959249593495944959549596495974959849599496004960149602496034960449605496064960749608496094961049611496124961349614496154961649617496184961949620496214962249623496244962549626496274962849629496304963149632496334963449635496364963749638496394964049641496424964349644496454964649647496484964949650496514965249653496544965549656496574965849659496604966149662496634966449665496664966749668496694967049671496724967349674496754967649677496784967949680496814968249683496844968549686496874968849689496904969149692496934969449695496964969749698496994970049701497024970349704497054970649707497084970949710497114971249713497144971549716497174971849719497204972149722497234972449725497264972749728497294973049731497324973349734497354973649737497384973949740497414974249743497444974549746497474974849749497504975149752497534975449755497564975749758497594976049761497624976349764497654976649767497684976949770497714977249773497744977549776497774977849779497804978149782497834978449785497864978749788497894979049791497924979349794497954979649797497984979949800498014980249803498044980549806498074980849809498104981149812498134981449815498164981749818498194982049821498224982349824498254982649827498284982949830498314983249833498344983549836498374983849839498404984149842498434984449845498464984749848498494985049851498524985349854498554985649857498584985949860498614986249863498644986549866498674986849869498704987149872498734987449875498764987749878498794988049881498824988349884498854988649887498884988949890498914989249893498944989549896498974989849899499004990149902499034990449905499064990749908499094991049911499124991349914499154991649917499184991949920499214992249923499244992549926499274992849929499304993149932499334993449935499364993749938499394994049941499424994349944499454994649947499484994949950499514995249953499544995549956499574995849959499604996149962499634996449965499664996749968499694997049971499724997349974499754997649977499784997949980499814998249983499844998549986499874998849989499904999149992499934999449995499964999749998499995000050001500025000350004500055000650007500085000950010500115001250013500145001550016500175001850019500205002150022500235002450025500265002750028500295003050031500325003350034500355003650037500385003950040500415004250043500445004550046500475004850049500505005150052500535005450055500565005750058500595006050061500625006350064500655006650067500685006950070500715007250073500745007550076500775007850079500805008150082500835008450085500865008750088500895009050091500925009350094500955009650097500985009950100501015010250103501045010550106501075010850109501105011150112501135011450115501165011750118501195012050121501225012350124501255012650127501285012950130501315013250133501345013550136501375013850139501405014150142501435014450145501465014750148501495015050151501525015350154501555015650157501585015950160501615016250163501645016550166501675016850169501705017150172501735017450175501765017750178501795018050181501825018350184501855018650187501885018950190501915019250193501945019550196501975019850199502005020150202502035020450205502065020750208502095021050211502125021350214502155021650217502185021950220502215022250223502245022550226502275022850229502305023150232502335023450235502365023750238502395024050241502425024350244502455024650247502485024950250502515025250253502545025550256502575025850259502605026150262502635026450265502665026750268502695027050271502725027350274502755027650277502785027950280502815028250283502845028550286502875028850289502905029150292502935029450295502965029750298502995030050301503025030350304503055030650307503085030950310503115031250313503145031550316503175031850319503205032150322503235032450325503265032750328503295033050331503325033350334503355033650337503385033950340503415034250343503445034550346503475034850349503505035150352503535035450355503565035750358503595036050361503625036350364503655036650367503685036950370503715037250373503745037550376503775037850379503805038150382503835038450385503865038750388503895039050391503925039350394503955039650397503985039950400504015040250403504045040550406504075040850409504105041150412504135041450415504165041750418504195042050421504225042350424504255042650427504285042950430504315043250433504345043550436504375043850439504405044150442504435044450445504465044750448504495045050451504525045350454504555045650457504585045950460504615046250463504645046550466504675046850469504705047150472504735047450475504765047750478504795048050481504825048350484504855048650487504885048950490504915049250493504945049550496504975049850499505005050150502505035050450505505065050750508505095051050511505125051350514505155051650517505185051950520505215052250523505245052550526505275052850529505305053150532505335053450535505365053750538505395054050541505425054350544505455054650547505485054950550505515055250553505545055550556505575055850559505605056150562505635056450565505665056750568505695057050571505725057350574505755057650577505785057950580505815058250583505845058550586505875058850589505905059150592505935059450595505965059750598505995060050601506025060350604506055060650607506085060950610506115061250613506145061550616506175061850619506205062150622506235062450625506265062750628506295063050631506325063350634506355063650637506385063950640506415064250643506445064550646506475064850649506505065150652506535065450655506565065750658506595066050661506625066350664506655066650667506685066950670506715067250673506745067550676506775067850679506805068150682506835068450685506865068750688506895069050691506925069350694506955069650697506985069950700507015070250703507045070550706507075070850709507105071150712507135071450715507165071750718507195072050721507225072350724507255072650727507285072950730507315073250733507345073550736507375073850739507405074150742507435074450745507465074750748507495075050751507525075350754507555075650757507585075950760507615076250763507645076550766507675076850769507705077150772507735077450775507765077750778507795078050781507825078350784507855078650787507885078950790507915079250793507945079550796507975079850799508005080150802508035080450805508065080750808508095081050811508125081350814508155081650817508185081950820508215082250823508245082550826508275082850829508305083150832508335083450835508365083750838508395084050841508425084350844508455084650847508485084950850508515085250853508545085550856508575085850859508605086150862508635086450865508665086750868508695087050871508725087350874508755087650877508785087950880508815088250883508845088550886508875088850889508905089150892508935089450895508965089750898508995090050901509025090350904509055090650907509085090950910509115091250913509145091550916509175091850919509205092150922509235092450925509265092750928509295093050931509325093350934509355093650937509385093950940509415094250943509445094550946509475094850949509505095150952509535095450955509565095750958509595096050961509625096350964509655096650967509685096950970509715097250973509745097550976509775097850979509805098150982509835098450985509865098750988509895099050991509925099350994509955099650997509985099951000510015100251003510045100551006510075100851009510105101151012510135101451015510165101751018510195102051021510225102351024510255102651027510285102951030510315103251033510345103551036510375103851039510405104151042510435104451045510465104751048510495105051051510525105351054510555105651057510585105951060510615106251063510645106551066510675106851069510705107151072510735107451075510765107751078510795108051081510825108351084510855108651087510885108951090510915109251093510945109551096510975109851099511005110151102511035110451105511065110751108511095111051111511125111351114511155111651117511185111951120511215112251123511245112551126511275112851129511305113151132511335113451135511365113751138511395114051141511425114351144511455114651147511485114951150511515115251153511545115551156511575115851159511605116151162511635116451165511665116751168511695117051171511725117351174511755117651177511785117951180511815118251183511845118551186511875118851189511905119151192511935119451195511965119751198511995120051201512025120351204512055120651207512085120951210512115121251213512145121551216512175121851219512205122151222512235122451225512265122751228512295123051231512325123351234512355123651237512385123951240512415124251243512445124551246512475124851249512505125151252512535125451255512565125751258512595126051261512625126351264512655126651267512685126951270512715127251273512745127551276512775127851279512805128151282512835128451285512865128751288512895129051291512925129351294512955129651297512985129951300513015130251303513045130551306513075130851309513105131151312513135131451315513165131751318513195132051321513225132351324513255132651327513285132951330513315133251333513345133551336513375133851339513405134151342513435134451345513465134751348513495135051351513525135351354513555135651357513585135951360513615136251363513645136551366513675136851369513705137151372513735137451375513765137751378513795138051381513825138351384513855138651387513885138951390513915139251393513945139551396513975139851399514005140151402514035140451405514065140751408514095141051411514125141351414514155141651417514185141951420514215142251423514245142551426514275142851429514305143151432514335143451435514365143751438514395144051441514425144351444514455144651447514485144951450514515145251453514545145551456514575145851459514605146151462514635146451465514665146751468514695147051471514725147351474514755147651477514785147951480514815148251483514845148551486514875148851489514905149151492514935149451495514965149751498514995150051501515025150351504515055150651507515085150951510515115151251513515145151551516515175151851519515205152151522515235152451525515265152751528515295153051531515325153351534515355153651537515385153951540515415154251543515445154551546515475154851549515505155151552515535155451555515565155751558515595156051561515625156351564515655156651567515685156951570515715157251573515745157551576515775157851579515805158151582515835158451585515865158751588515895159051591515925159351594515955159651597515985159951600516015160251603516045160551606516075160851609516105161151612516135161451615516165161751618516195162051621516225162351624516255162651627516285162951630516315163251633516345163551636516375163851639516405164151642516435164451645516465164751648516495165051651516525165351654516555165651657516585165951660516615166251663516645166551666516675166851669516705167151672516735167451675516765167751678516795168051681516825168351684516855168651687516885168951690516915169251693516945169551696516975169851699517005170151702517035170451705517065170751708517095171051711517125171351714517155171651717517185171951720517215172251723517245172551726517275172851729517305173151732517335173451735517365173751738517395174051741517425174351744517455174651747517485174951750517515175251753517545175551756517575175851759517605176151762517635176451765517665176751768517695177051771517725177351774517755177651777517785177951780517815178251783517845178551786517875178851789517905179151792517935179451795517965179751798517995180051801518025180351804518055180651807518085180951810518115181251813518145181551816518175181851819518205182151822518235182451825518265182751828518295183051831518325183351834518355183651837518385183951840518415184251843518445184551846518475184851849518505185151852518535185451855518565185751858518595186051861518625186351864518655186651867518685186951870518715187251873518745187551876518775187851879518805188151882518835188451885518865188751888518895189051891518925189351894518955189651897518985189951900519015190251903519045190551906519075190851909519105191151912519135191451915519165191751918519195192051921519225192351924519255192651927519285192951930519315193251933519345193551936519375193851939519405194151942519435194451945519465194751948519495195051951519525195351954519555195651957519585195951960519615196251963519645196551966519675196851969519705197151972519735197451975519765197751978519795198051981519825198351984519855198651987519885198951990519915199251993519945199551996519975199851999520005200152002520035200452005520065200752008520095201052011520125201352014520155201652017520185201952020520215202252023520245202552026520275202852029520305203152032520335203452035520365203752038520395204052041520425204352044520455204652047520485204952050520515205252053520545205552056520575205852059520605206152062520635206452065520665206752068520695207052071520725207352074520755207652077520785207952080520815208252083520845208552086520875208852089520905209152092520935209452095520965209752098520995210052101521025210352104521055210652107521085210952110521115211252113521145211552116521175211852119521205212152122521235212452125521265212752128521295213052131521325213352134521355213652137521385213952140521415214252143521445214552146521475214852149521505215152152521535215452155521565215752158521595216052161521625216352164521655216652167521685216952170521715217252173521745217552176521775217852179521805218152182521835218452185521865218752188521895219052191521925219352194521955219652197521985219952200522015220252203522045220552206522075220852209522105221152212522135221452215522165221752218522195222052221522225222352224522255222652227522285222952230522315223252233522345223552236522375223852239522405224152242522435224452245522465224752248522495225052251522525225352254522555225652257522585225952260522615226252263522645226552266522675226852269522705227152272522735227452275522765227752278522795228052281522825228352284522855228652287522885228952290522915229252293522945229552296522975229852299523005230152302523035230452305523065230752308523095231052311523125231352314523155231652317523185231952320523215232252323523245232552326523275232852329523305233152332523335233452335523365233752338523395234052341523425234352344523455234652347523485234952350523515235252353523545235552356523575235852359523605236152362523635236452365523665236752368523695237052371523725237352374523755237652377523785237952380523815238252383523845238552386523875238852389523905239152392523935239452395523965239752398523995240052401524025240352404524055240652407524085240952410524115241252413524145241552416524175241852419524205242152422524235242452425524265242752428524295243052431524325243352434524355243652437524385243952440524415244252443524445244552446524475244852449524505245152452524535245452455524565245752458524595246052461524625246352464524655246652467524685246952470524715247252473524745247552476524775247852479524805248152482524835248452485524865248752488524895249052491524925249352494524955249652497524985249952500525015250252503525045250552506525075250852509525105251152512525135251452515525165251752518525195252052521525225252352524525255252652527525285252952530525315253252533525345253552536525375253852539525405254152542525435254452545525465254752548525495255052551525525255352554525555255652557525585255952560525615256252563525645256552566525675256852569525705257152572525735257452575525765257752578525795258052581525825258352584525855258652587525885258952590525915259252593525945259552596525975259852599526005260152602526035260452605526065260752608526095261052611526125261352614526155261652617526185261952620526215262252623526245262552626526275262852629526305263152632526335263452635526365263752638526395264052641526425264352644526455264652647526485264952650526515265252653526545265552656526575265852659526605266152662526635266452665526665266752668526695267052671526725267352674526755267652677526785267952680526815268252683526845268552686526875268852689526905269152692526935269452695526965269752698526995270052701527025270352704527055270652707527085270952710527115271252713527145271552716527175271852719527205272152722527235272452725527265272752728527295273052731527325273352734527355273652737527385273952740527415274252743527445274552746527475274852749527505275152752527535275452755527565275752758527595276052761527625276352764527655276652767527685276952770527715277252773527745277552776527775277852779527805278152782527835278452785527865278752788527895279052791527925279352794527955279652797527985279952800528015280252803528045280552806528075280852809528105281152812528135281452815528165281752818528195282052821528225282352824528255282652827528285282952830528315283252833528345283552836528375283852839528405284152842528435284452845528465284752848528495285052851528525285352854528555285652857528585285952860528615286252863528645286552866528675286852869528705287152872528735287452875528765287752878528795288052881528825288352884528855288652887528885288952890528915289252893528945289552896528975289852899529005290152902529035290452905529065290752908529095291052911529125291352914529155291652917529185291952920529215292252923529245292552926529275292852929529305293152932529335293452935529365293752938529395294052941529425294352944529455294652947529485294952950529515295252953529545295552956529575295852959529605296152962529635296452965529665296752968529695297052971529725297352974529755297652977529785297952980529815298252983529845298552986529875298852989529905299152992529935299452995529965299752998529995300053001530025300353004530055300653007530085300953010530115301253013530145301553016530175301853019530205302153022530235302453025530265302753028530295303053031530325303353034530355303653037530385303953040530415304253043530445304553046530475304853049530505305153052530535305453055530565305753058530595306053061530625306353064530655306653067530685306953070530715307253073530745307553076530775307853079530805308153082530835308453085530865308753088530895309053091530925309353094530955309653097530985309953100531015310253103531045310553106531075310853109531105311153112531135311453115531165311753118531195312053121531225312353124531255312653127531285312953130531315313253133531345313553136531375313853139531405314153142531435314453145531465314753148531495315053151531525315353154531555315653157531585315953160531615316253163531645316553166531675316853169531705317153172531735317453175531765317753178531795318053181531825318353184531855318653187531885318953190531915319253193531945319553196531975319853199532005320153202532035320453205532065320753208532095321053211532125321353214532155321653217532185321953220532215322253223532245322553226532275322853229532305323153232532335323453235532365323753238532395324053241532425324353244532455324653247532485324953250532515325253253532545325553256532575325853259532605326153262532635326453265532665326753268532695327053271532725327353274532755327653277532785327953280532815328253283532845328553286532875328853289532905329153292532935329453295532965329753298532995330053301533025330353304533055330653307533085330953310533115331253313533145331553316533175331853319533205332153322533235332453325533265332753328533295333053331533325333353334533355333653337533385333953340533415334253343533445334553346533475334853349533505335153352533535335453355533565335753358533595336053361533625336353364533655336653367533685336953370533715337253373533745337553376533775337853379533805338153382533835338453385533865338753388533895339053391533925339353394533955339653397533985339953400534015340253403534045340553406534075340853409534105341153412534135341453415534165341753418534195342053421534225342353424534255342653427534285342953430534315343253433534345343553436534375343853439534405344153442534435344453445534465344753448534495345053451534525345353454534555345653457534585345953460534615346253463534645346553466534675346853469534705347153472534735347453475534765347753478534795348053481534825348353484534855348653487534885348953490534915349253493534945349553496534975349853499535005350153502535035350453505535065350753508535095351053511535125351353514535155351653517535185351953520535215352253523535245352553526535275352853529535305353153532535335353453535535365353753538535395354053541535425354353544535455354653547535485354953550535515355253553535545355553556535575355853559535605356153562535635356453565535665356753568535695357053571535725357353574535755357653577535785357953580535815358253583535845358553586535875358853589535905359153592535935359453595535965359753598535995360053601536025360353604536055360653607536085360953610536115361253613536145361553616536175361853619536205362153622536235362453625536265362753628536295363053631536325363353634536355363653637536385363953640536415364253643536445364553646536475364853649536505365153652536535365453655536565365753658536595366053661536625366353664536655366653667536685366953670536715367253673536745367553676536775367853679536805368153682536835368453685536865368753688536895369053691536925369353694536955369653697536985369953700537015370253703537045370553706537075370853709537105371153712537135371453715537165371753718537195372053721537225372353724537255372653727537285372953730537315373253733537345373553736537375373853739537405374153742537435374453745537465374753748537495375053751537525375353754537555375653757537585375953760537615376253763537645376553766537675376853769537705377153772537735377453775537765377753778537795378053781537825378353784537855378653787537885378953790537915379253793537945379553796537975379853799538005380153802538035380453805538065380753808538095381053811538125381353814538155381653817538185381953820538215382253823538245382553826538275382853829538305383153832538335383453835538365383753838538395384053841538425384353844538455384653847538485384953850538515385253853538545385553856538575385853859538605386153862538635386453865538665386753868538695387053871538725387353874538755387653877538785387953880538815388253883538845388553886538875388853889538905389153892538935389453895538965389753898538995390053901539025390353904539055390653907539085390953910539115391253913539145391553916539175391853919539205392153922539235392453925539265392753928539295393053931539325393353934539355393653937539385393953940539415394253943539445394553946539475394853949539505395153952539535395453955539565395753958539595396053961539625396353964539655396653967539685396953970539715397253973539745397553976539775397853979539805398153982539835398453985539865398753988539895399053991539925399353994539955399653997539985399954000540015400254003540045400554006540075400854009540105401154012540135401454015540165401754018540195402054021540225402354024540255402654027540285402954030540315403254033540345403554036540375403854039540405404154042540435404454045540465404754048540495405054051540525405354054540555405654057540585405954060540615406254063540645406554066540675406854069540705407154072540735407454075540765407754078540795408054081540825408354084540855408654087540885408954090540915409254093540945409554096540975409854099541005410154102541035410454105541065410754108541095411054111541125411354114541155411654117541185411954120541215412254123541245412554126541275412854129541305413154132541335413454135541365413754138541395414054141541425414354144541455414654147541485414954150541515415254153541545415554156541575415854159541605416154162541635416454165541665416754168541695417054171541725417354174541755417654177541785417954180541815418254183541845418554186541875418854189541905419154192541935419454195541965419754198541995420054201542025420354204542055420654207542085420954210542115421254213542145421554216542175421854219542205422154222542235422454225542265422754228542295423054231542325423354234542355423654237542385423954240542415424254243542445424554246542475424854249542505425154252542535425454255542565425754258542595426054261542625426354264542655426654267542685426954270542715427254273542745427554276542775427854279542805428154282542835428454285542865428754288542895429054291542925429354294542955429654297542985429954300543015430254303543045430554306543075430854309543105431154312543135431454315543165431754318543195432054321543225432354324543255432654327543285432954330543315433254333543345433554336543375433854339543405434154342543435434454345543465434754348543495435054351543525435354354543555435654357543585435954360543615436254363543645436554366543675436854369543705437154372543735437454375543765437754378543795438054381543825438354384543855438654387543885438954390543915439254393543945439554396543975439854399544005440154402544035440454405544065440754408544095441054411544125441354414544155441654417544185441954420544215442254423544245442554426544275442854429544305443154432544335443454435544365443754438544395444054441544425444354444544455444654447544485444954450544515445254453544545445554456544575445854459544605446154462544635446454465544665446754468544695447054471544725447354474544755447654477544785447954480544815448254483544845448554486544875448854489544905449154492544935449454495544965449754498544995450054501545025450354504545055450654507545085450954510545115451254513545145451554516545175451854519545205452154522545235452454525545265452754528545295453054531545325453354534545355453654537545385453954540545415454254543545445454554546545475454854549545505455154552545535455454555545565455754558545595456054561545625456354564545655456654567545685456954570545715457254573545745457554576545775457854579545805458154582545835458454585545865458754588545895459054591545925459354594545955459654597545985459954600546015460254603546045460554606546075460854609546105461154612546135461454615546165461754618546195462054621546225462354624546255462654627546285462954630546315463254633546345463554636546375463854639546405464154642546435464454645546465464754648546495465054651546525465354654546555465654657546585465954660546615466254663546645466554666546675466854669546705467154672546735467454675546765467754678546795468054681546825468354684546855468654687546885468954690546915469254693546945469554696546975469854699547005470154702547035470454705547065470754708547095471054711547125471354714547155471654717547185471954720547215472254723547245472554726547275472854729547305473154732547335473454735547365473754738547395474054741547425474354744547455474654747547485474954750547515475254753547545475554756547575475854759547605476154762547635476454765547665476754768547695477054771547725477354774547755477654777547785477954780547815478254783547845478554786547875478854789547905479154792547935479454795547965479754798547995480054801548025480354804548055480654807548085480954810548115481254813548145481554816548175481854819548205482154822548235482454825548265482754828548295483054831548325483354834548355483654837548385483954840548415484254843548445484554846548475484854849548505485154852548535485454855548565485754858548595486054861548625486354864548655486654867548685486954870548715487254873548745487554876548775487854879548805488154882548835488454885548865488754888548895489054891548925489354894548955489654897548985489954900549015490254903549045490554906549075490854909549105491154912549135491454915549165491754918549195492054921549225492354924549255492654927549285492954930549315493254933549345493554936549375493854939549405494154942549435494454945549465494754948549495495054951549525495354954549555495654957549585495954960549615496254963549645496554966549675496854969549705497154972549735497454975549765497754978549795498054981549825498354984549855498654987549885498954990549915499254993549945499554996549975499854999550005500155002550035500455005550065500755008550095501055011550125501355014550155501655017550185501955020550215502255023550245502555026550275502855029550305503155032550335503455035550365503755038550395504055041550425504355044550455504655047550485504955050550515505255053550545505555056550575505855059550605506155062550635506455065550665506755068550695507055071550725507355074550755507655077550785507955080550815508255083550845508555086550875508855089550905509155092550935509455095550965509755098550995510055101551025510355104551055510655107551085510955110551115511255113551145511555116551175511855119551205512155122551235512455125551265512755128551295513055131551325513355134551355513655137551385513955140551415514255143551445514555146551475514855149551505515155152551535515455155551565515755158551595516055161551625516355164551655516655167551685516955170551715517255173551745517555176551775517855179551805518155182551835518455185551865518755188551895519055191551925519355194551955519655197551985519955200552015520255203552045520555206552075520855209552105521155212552135521455215552165521755218552195522055221552225522355224552255522655227552285522955230552315523255233552345523555236552375523855239552405524155242552435524455245552465524755248552495525055251552525525355254552555525655257552585525955260552615526255263552645526555266552675526855269552705527155272552735527455275552765527755278552795528055281552825528355284552855528655287552885528955290552915529255293552945529555296552975529855299553005530155302553035530455305553065530755308553095531055311553125531355314553155531655317553185531955320553215532255323553245532555326553275532855329553305533155332553335533455335553365533755338553395534055341553425534355344553455534655347553485534955350553515535255353553545535555356553575535855359553605536155362553635536455365553665536755368553695537055371553725537355374553755537655377553785537955380553815538255383553845538555386553875538855389553905539155392553935539455395553965539755398553995540055401554025540355404554055540655407554085540955410554115541255413554145541555416554175541855419554205542155422554235542455425554265542755428554295543055431554325543355434554355543655437554385543955440554415544255443554445544555446554475544855449554505545155452554535545455455554565545755458554595546055461554625546355464554655546655467554685546955470554715547255473554745547555476554775547855479554805548155482554835548455485554865548755488554895549055491554925549355494554955549655497554985549955500555015550255503555045550555506555075550855509555105551155512555135551455515555165551755518555195552055521555225552355524555255552655527555285552955530555315553255533555345553555536555375553855539555405554155542555435554455545555465554755548555495555055551555525555355554555555555655557555585555955560555615556255563555645556555566555675556855569555705557155572555735557455575555765557755578555795558055581555825558355584555855558655587555885558955590555915559255593555945559555596555975559855599556005560155602556035560455605556065560755608556095561055611556125561355614556155561655617556185561955620556215562255623556245562555626556275562855629556305563155632556335563455635556365563755638556395564055641556425564355644556455564655647556485564955650556515565255653556545565555656556575565855659556605566155662556635566455665556665566755668556695567055671556725567355674556755567655677556785567955680556815568255683556845568555686556875568855689556905569155692556935569455695556965569755698556995570055701557025570355704557055570655707557085570955710557115571255713557145571555716557175571855719557205572155722557235572455725557265572755728557295573055731557325573355734557355573655737557385573955740557415574255743557445574555746557475574855749557505575155752557535575455755557565575755758557595576055761557625576355764557655576655767557685576955770557715577255773557745577555776557775577855779557805578155782557835578455785557865578755788557895579055791557925579355794557955579655797557985579955800558015580255803558045580555806558075580855809558105581155812558135581455815558165581755818558195582055821558225582355824558255582655827558285582955830558315583255833558345583555836558375583855839558405584155842558435584455845558465584755848558495585055851558525585355854558555585655857558585585955860558615586255863558645586555866558675586855869558705587155872558735587455875558765587755878558795588055881558825588355884558855588655887558885588955890558915589255893558945589555896558975589855899559005590155902559035590455905559065590755908559095591055911559125591355914559155591655917559185591955920559215592255923559245592555926559275592855929559305593155932559335593455935559365593755938559395594055941559425594355944559455594655947559485594955950559515595255953559545595555956559575595855959559605596155962559635596455965559665596755968559695597055971559725597355974559755597655977559785597955980559815598255983559845598555986559875598855989559905599155992559935599455995559965599755998559995600056001560025600356004560055600656007560085600956010560115601256013560145601556016560175601856019560205602156022560235602456025560265602756028560295603056031560325603356034560355603656037560385603956040560415604256043560445604556046560475604856049560505605156052560535605456055560565605756058560595606056061560625606356064560655606656067560685606956070560715607256073560745607556076560775607856079560805608156082560835608456085560865608756088560895609056091560925609356094560955609656097560985609956100561015610256103561045610556106561075610856109561105611156112561135611456115561165611756118561195612056121561225612356124561255612656127561285612956130561315613256133561345613556136561375613856139561405614156142561435614456145561465614756148561495615056151561525615356154561555615656157561585615956160561615616256163561645616556166561675616856169561705617156172561735617456175561765617756178561795618056181561825618356184561855618656187561885618956190561915619256193561945619556196561975619856199562005620156202562035620456205562065620756208562095621056211562125621356214562155621656217562185621956220562215622256223562245622556226562275622856229562305623156232562335623456235562365623756238562395624056241562425624356244562455624656247562485624956250562515625256253562545625556256562575625856259562605626156262562635626456265562665626756268562695627056271562725627356274562755627656277562785627956280562815628256283562845628556286562875628856289562905629156292562935629456295562965629756298562995630056301563025630356304563055630656307563085630956310563115631256313563145631556316563175631856319563205632156322563235632456325563265632756328563295633056331563325633356334563355633656337563385633956340563415634256343563445634556346563475634856349563505635156352563535635456355563565635756358563595636056361563625636356364563655636656367563685636956370563715637256373563745637556376563775637856379563805638156382563835638456385563865638756388563895639056391563925639356394563955639656397563985639956400564015640256403564045640556406564075640856409564105641156412564135641456415564165641756418564195642056421564225642356424564255642656427564285642956430564315643256433564345643556436564375643856439564405644156442564435644456445564465644756448564495645056451564525645356454564555645656457564585645956460564615646256463564645646556466564675646856469564705647156472564735647456475564765647756478564795648056481564825648356484564855648656487564885648956490564915649256493564945649556496564975649856499565005650156502565035650456505565065650756508565095651056511565125651356514565155651656517565185651956520565215652256523565245652556526565275652856529565305653156532565335653456535565365653756538565395654056541565425654356544565455654656547565485654956550565515655256553565545655556556565575655856559565605656156562565635656456565565665656756568565695657056571565725657356574565755657656577565785657956580565815658256583565845658556586565875658856589565905659156592565935659456595565965659756598565995660056601566025660356604566055660656607566085660956610566115661256613566145661556616566175661856619566205662156622566235662456625566265662756628566295663056631566325663356634566355663656637566385663956640566415664256643566445664556646566475664856649566505665156652566535665456655566565665756658566595666056661566625666356664566655666656667566685666956670566715667256673566745667556676566775667856679566805668156682566835668456685566865668756688566895669056691566925669356694566955669656697566985669956700567015670256703567045670556706567075670856709567105671156712567135671456715567165671756718567195672056721567225672356724567255672656727567285672956730567315673256733567345673556736567375673856739567405674156742567435674456745567465674756748567495675056751567525675356754567555675656757567585675956760567615676256763567645676556766567675676856769567705677156772567735677456775567765677756778567795678056781567825678356784567855678656787567885678956790567915679256793567945679556796567975679856799568005680156802568035680456805568065680756808568095681056811568125681356814568155681656817568185681956820568215682256823568245682556826568275682856829568305683156832568335683456835568365683756838568395684056841568425684356844568455684656847568485684956850568515685256853568545685556856568575685856859568605686156862568635686456865568665686756868568695687056871568725687356874568755687656877568785687956880568815688256883568845688556886568875688856889568905689156892568935689456895568965689756898568995690056901569025690356904569055690656907569085690956910569115691256913569145691556916569175691856919569205692156922569235692456925569265692756928569295693056931569325693356934569355693656937569385693956940569415694256943569445694556946569475694856949569505695156952569535695456955569565695756958569595696056961569625696356964569655696656967569685696956970569715697256973569745697556976569775697856979569805698156982569835698456985569865698756988569895699056991569925699356994569955699656997569985699957000570015700257003570045700557006570075700857009570105701157012570135701457015570165701757018570195702057021570225702357024570255702657027570285702957030570315703257033570345703557036570375703857039570405704157042570435704457045570465704757048570495705057051570525705357054570555705657057570585705957060570615706257063570645706557066570675706857069570705707157072570735707457075570765707757078570795708057081570825708357084570855708657087570885708957090570915709257093570945709557096570975709857099571005710157102571035710457105571065710757108571095711057111571125711357114571155711657117571185711957120571215712257123571245712557126571275712857129571305713157132571335713457135571365713757138571395714057141571425714357144571455714657147571485714957150571515715257153571545715557156571575715857159571605716157162571635716457165571665716757168571695717057171571725717357174571755717657177571785717957180571815718257183571845718557186571875718857189571905719157192571935719457195571965719757198571995720057201572025720357204572055720657207572085720957210572115721257213572145721557216572175721857219572205722157222572235722457225572265722757228572295723057231572325723357234572355723657237572385723957240572415724257243572445724557246572475724857249572505725157252572535725457255572565725757258572595726057261572625726357264572655726657267572685726957270572715727257273572745727557276572775727857279572805728157282572835728457285572865728757288572895729057291572925729357294572955729657297572985729957300573015730257303573045730557306573075730857309573105731157312573135731457315573165731757318573195732057321573225732357324573255732657327573285732957330573315733257333573345733557336573375733857339573405734157342573435734457345573465734757348573495735057351573525735357354573555735657357573585735957360573615736257363573645736557366573675736857369573705737157372573735737457375573765737757378573795738057381573825738357384573855738657387573885738957390573915739257393573945739557396573975739857399574005740157402574035740457405574065740757408574095741057411574125741357414574155741657417574185741957420574215742257423574245742557426574275742857429574305743157432574335743457435574365743757438574395744057441574425744357444574455744657447574485744957450574515745257453574545745557456574575745857459574605746157462574635746457465574665746757468574695747057471574725747357474574755747657477574785747957480574815748257483574845748557486574875748857489574905749157492574935749457495574965749757498574995750057501575025750357504575055750657507575085750957510575115751257513575145751557516575175751857519575205752157522575235752457525575265752757528575295753057531575325753357534575355753657537575385753957540575415754257543575445754557546575475754857549575505755157552575535755457555575565755757558575595756057561575625756357564575655756657567575685756957570575715757257573575745757557576575775757857579575805758157582575835758457585575865758757588575895759057591575925759357594575955759657597575985759957600576015760257603576045760557606576075760857609576105761157612576135761457615576165761757618576195762057621576225762357624576255762657627576285762957630576315763257633576345763557636576375763857639576405764157642576435764457645576465764757648576495765057651576525765357654576555765657657576585765957660576615766257663576645766557666576675766857669576705767157672576735767457675576765767757678576795768057681576825768357684576855768657687576885768957690576915769257693576945769557696576975769857699577005770157702577035770457705577065770757708577095771057711577125771357714577155771657717577185771957720577215772257723577245772557726577275772857729577305773157732577335773457735577365773757738577395774057741577425774357744577455774657747577485774957750577515775257753577545775557756577575775857759577605776157762577635776457765577665776757768577695777057771577725777357774577755777657777577785777957780577815778257783577845778557786577875778857789577905779157792577935779457795577965779757798577995780057801578025780357804578055780657807578085780957810578115781257813578145781557816578175781857819578205782157822578235782457825578265782757828578295783057831578325783357834578355783657837578385783957840578415784257843578445784557846578475784857849578505785157852578535785457855578565785757858578595786057861578625786357864578655786657867578685786957870578715787257873578745787557876578775787857879578805788157882578835788457885578865788757888578895789057891578925789357894578955789657897578985789957900579015790257903579045790557906579075790857909579105791157912579135791457915579165791757918579195792057921579225792357924579255792657927579285792957930579315793257933579345793557936579375793857939579405794157942579435794457945579465794757948579495795057951579525795357954579555795657957579585795957960579615796257963579645796557966579675796857969579705797157972579735797457975579765797757978579795798057981579825798357984579855798657987579885798957990579915799257993579945799557996579975799857999580005800158002580035800458005580065800758008580095801058011580125801358014580155801658017580185801958020580215802258023580245802558026580275802858029580305803158032580335803458035580365803758038580395804058041580425804358044580455804658047580485804958050580515805258053580545805558056580575805858059580605806158062580635806458065580665806758068580695807058071580725807358074580755807658077580785807958080580815808258083580845808558086580875808858089580905809158092580935809458095580965809758098580995810058101581025810358104581055810658107581085810958110581115811258113581145811558116581175811858119581205812158122581235812458125581265812758128581295813058131581325813358134581355813658137581385813958140581415814258143581445814558146581475814858149581505815158152581535815458155581565815758158581595816058161581625816358164581655816658167581685816958170581715817258173581745817558176581775817858179581805818158182581835818458185581865818758188581895819058191581925819358194581955819658197581985819958200582015820258203582045820558206582075820858209582105821158212582135821458215582165821758218582195822058221582225822358224582255822658227582285822958230582315823258233582345823558236582375823858239582405824158242582435824458245582465824758248582495825058251582525825358254582555825658257582585825958260582615826258263582645826558266582675826858269582705827158272582735827458275582765827758278582795828058281582825828358284582855828658287582885828958290582915829258293582945829558296582975829858299583005830158302583035830458305583065830758308583095831058311583125831358314583155831658317583185831958320583215832258323583245832558326583275832858329583305833158332583335833458335583365833758338583395834058341583425834358344583455834658347583485834958350583515835258353583545835558356583575835858359583605836158362583635836458365583665836758368583695837058371583725837358374583755837658377583785837958380583815838258383583845838558386583875838858389583905839158392583935839458395583965839758398583995840058401584025840358404584055840658407584085840958410584115841258413584145841558416584175841858419584205842158422584235842458425584265842758428584295843058431584325843358434584355843658437584385843958440584415844258443584445844558446584475844858449584505845158452584535845458455584565845758458584595846058461584625846358464584655846658467584685846958470584715847258473584745847558476584775847858479584805848158482584835848458485584865848758488584895849058491584925849358494584955849658497584985849958500585015850258503585045850558506585075850858509585105851158512585135851458515585165851758518585195852058521585225852358524585255852658527585285852958530585315853258533585345853558536585375853858539585405854158542585435854458545585465854758548585495855058551585525855358554585555855658557585585855958560585615856258563585645856558566585675856858569585705857158572585735857458575585765857758578585795858058581585825858358584585855858658587585885858958590585915859258593585945859558596585975859858599586005860158602586035860458605586065860758608586095861058611586125861358614586155861658617586185861958620586215862258623586245862558626586275862858629586305863158632586335863458635586365863758638586395864058641586425864358644586455864658647586485864958650586515865258653586545865558656586575865858659586605866158662586635866458665586665866758668586695867058671586725867358674586755867658677586785867958680586815868258683586845868558686586875868858689586905869158692586935869458695586965869758698586995870058701587025870358704587055870658707587085870958710587115871258713587145871558716587175871858719587205872158722587235872458725587265872758728587295873058731587325873358734587355873658737587385873958740587415874258743587445874558746587475874858749587505875158752587535875458755587565875758758587595876058761587625876358764587655876658767587685876958770587715877258773587745877558776587775877858779587805878158782587835878458785587865878758788587895879058791587925879358794587955879658797587985879958800588015880258803588045880558806588075880858809588105881158812588135881458815588165881758818588195882058821588225882358824588255882658827588285882958830588315883258833588345883558836588375883858839588405884158842588435884458845588465884758848588495885058851588525885358854588555885658857588585885958860588615886258863588645886558866588675886858869588705887158872588735887458875588765887758878588795888058881588825888358884588855888658887588885888958890588915889258893588945889558896588975889858899589005890158902589035890458905589065890758908589095891058911589125891358914589155891658917589185891958920589215892258923589245892558926589275892858929589305893158932589335893458935589365893758938589395894058941589425894358944589455894658947589485894958950589515895258953589545895558956589575895858959589605896158962589635896458965589665896758968589695897058971589725897358974589755897658977589785897958980589815898258983589845898558986589875898858989589905899158992589935899458995589965899758998589995900059001590025900359004590055900659007590085900959010590115901259013590145901559016590175901859019590205902159022590235902459025590265902759028590295903059031590325903359034590355903659037590385903959040590415904259043590445904559046590475904859049590505905159052590535905459055590565905759058590595906059061590625906359064590655906659067590685906959070590715907259073590745907559076590775907859079590805908159082590835908459085590865908759088590895909059091590925909359094590955909659097590985909959100591015910259103591045910559106591075910859109591105911159112591135911459115591165911759118591195912059121591225912359124591255912659127591285912959130591315913259133591345913559136591375913859139591405914159142591435914459145591465914759148591495915059151591525915359154591555915659157591585915959160591615916259163591645916559166591675916859169591705917159172591735917459175591765917759178591795918059181591825918359184591855918659187591885918959190591915919259193591945919559196591975919859199592005920159202592035920459205592065920759208592095921059211592125921359214592155921659217592185921959220592215922259223592245922559226592275922859229592305923159232592335923459235592365923759238592395924059241592425924359244592455924659247592485924959250592515925259253592545925559256592575925859259592605926159262592635926459265592665926759268592695927059271592725927359274592755927659277592785927959280592815928259283592845928559286592875928859289592905929159292592935929459295592965929759298592995930059301593025930359304593055930659307593085930959310593115931259313593145931559316593175931859319593205932159322593235932459325593265932759328593295933059331593325933359334593355933659337593385933959340593415934259343593445934559346593475934859349593505935159352593535935459355593565935759358593595936059361593625936359364593655936659367593685936959370593715937259373593745937559376593775937859379593805938159382593835938459385593865938759388593895939059391593925939359394593955939659397593985939959400594015940259403594045940559406594075940859409594105941159412594135941459415594165941759418594195942059421594225942359424594255942659427594285942959430594315943259433594345943559436594375943859439594405944159442594435944459445594465944759448594495945059451594525945359454594555945659457594585945959460594615946259463594645946559466594675946859469594705947159472594735947459475594765947759478594795948059481594825948359484594855948659487594885948959490594915949259493594945949559496594975949859499595005950159502595035950459505595065950759508595095951059511595125951359514595155951659517595185951959520595215952259523595245952559526595275952859529595305953159532595335953459535595365953759538595395954059541595425954359544595455954659547595485954959550595515955259553595545955559556595575955859559595605956159562595635956459565595665956759568595695957059571595725957359574595755957659577595785957959580595815958259583595845958559586595875958859589595905959159592595935959459595595965959759598595995960059601596025960359604596055960659607596085960959610596115961259613596145961559616596175961859619596205962159622596235962459625596265962759628596295963059631596325963359634596355963659637596385963959640596415964259643596445964559646596475964859649596505965159652596535965459655596565965759658596595966059661596625966359664596655966659667596685966959670596715967259673596745967559676596775967859679596805968159682596835968459685596865968759688596895969059691596925969359694596955969659697596985969959700597015970259703597045970559706597075970859709597105971159712597135971459715597165971759718597195972059721597225972359724597255972659727597285972959730597315973259733597345973559736597375973859739597405974159742597435974459745597465974759748597495975059751597525975359754597555975659757597585975959760597615976259763597645976559766597675976859769597705977159772597735977459775597765977759778597795978059781597825978359784597855978659787597885978959790597915979259793597945979559796597975979859799598005980159802598035980459805598065980759808598095981059811598125981359814598155981659817598185981959820598215982259823598245982559826598275982859829598305983159832598335983459835598365983759838598395984059841598425984359844598455984659847598485984959850598515985259853598545985559856598575985859859598605986159862598635986459865598665986759868598695987059871598725987359874598755987659877598785987959880598815988259883598845988559886598875988859889598905989159892598935989459895598965989759898598995990059901599025990359904599055990659907599085990959910599115991259913599145991559916599175991859919599205992159922599235992459925599265992759928599295993059931599325993359934599355993659937599385993959940599415994259943599445994559946599475994859949599505995159952599535995459955599565995759958599595996059961599625996359964599655996659967599685996959970599715997259973599745997559976599775997859979599805998159982599835998459985599865998759988599895999059991599925999359994599955999659997599985999960000600016000260003600046000560006600076000860009600106001160012600136001460015600166001760018600196002060021600226002360024600256002660027600286002960030600316003260033600346003560036600376003860039600406004160042600436004460045600466004760048600496005060051600526005360054600556005660057600586005960060600616006260063600646006560066600676006860069600706007160072600736007460075600766007760078600796008060081600826008360084600856008660087600886008960090600916009260093600946009560096600976009860099601006010160102601036010460105601066010760108601096011060111601126011360114601156011660117601186011960120601216012260123601246012560126601276012860129601306013160132601336013460135601366013760138601396014060141601426014360144601456014660147601486014960150601516015260153601546015560156601576015860159601606016160162601636016460165601666016760168601696017060171601726017360174601756017660177601786017960180601816018260183601846018560186601876018860189601906019160192601936019460195601966019760198601996020060201602026020360204602056020660207602086020960210602116021260213602146021560216602176021860219602206022160222602236022460225602266022760228602296023060231602326023360234602356023660237602386023960240602416024260243602446024560246602476024860249602506025160252602536025460255602566025760258602596026060261602626026360264602656026660267602686026960270602716027260273602746027560276602776027860279602806028160282602836028460285602866028760288602896029060291602926029360294602956029660297602986029960300603016030260303603046030560306603076030860309603106031160312603136031460315603166031760318603196032060321603226032360324603256032660327603286032960330603316033260333603346033560336603376033860339603406034160342603436034460345603466034760348603496035060351603526035360354603556035660357603586035960360603616036260363603646036560366603676036860369603706037160372603736037460375603766037760378603796038060381603826038360384603856038660387603886038960390603916039260393603946039560396603976039860399604006040160402604036040460405604066040760408604096041060411604126041360414604156041660417604186041960420604216042260423604246042560426604276042860429604306043160432604336043460435604366043760438604396044060441604426044360444604456044660447604486044960450604516045260453604546045560456604576045860459604606046160462604636046460465604666046760468604696047060471604726047360474604756047660477604786047960480604816048260483604846048560486604876048860489604906049160492604936049460495604966049760498604996050060501605026050360504605056050660507605086050960510605116051260513605146051560516605176051860519605206052160522605236052460525605266052760528605296053060531605326053360534605356053660537605386053960540605416054260543605446054560546605476054860549605506055160552605536055460555605566055760558605596056060561605626056360564605656056660567605686056960570605716057260573605746057560576605776057860579605806058160582605836058460585605866058760588605896059060591605926059360594605956059660597605986059960600606016060260603606046060560606606076060860609606106061160612606136061460615606166061760618606196062060621606226062360624606256062660627606286062960630606316063260633606346063560636606376063860639606406064160642606436064460645606466064760648606496065060651606526065360654606556065660657606586065960660606616066260663606646066560666606676066860669606706067160672606736067460675606766067760678606796068060681606826068360684606856068660687606886068960690606916069260693606946069560696606976069860699607006070160702607036070460705607066070760708607096071060711607126071360714607156071660717607186071960720607216072260723607246072560726607276072860729607306073160732607336073460735607366073760738607396074060741607426074360744607456074660747607486074960750607516075260753607546075560756607576075860759607606076160762607636076460765607666076760768607696077060771607726077360774607756077660777607786077960780607816078260783607846078560786607876078860789607906079160792607936079460795607966079760798607996080060801608026080360804608056080660807608086080960810608116081260813608146081560816608176081860819608206082160822608236082460825608266082760828608296083060831608326083360834608356083660837608386083960840608416084260843608446084560846608476084860849608506085160852608536085460855608566085760858608596086060861608626086360864608656086660867608686086960870608716087260873608746087560876608776087860879608806088160882608836088460885608866088760888608896089060891608926089360894608956089660897608986089960900609016090260903609046090560906609076090860909609106091160912609136091460915609166091760918609196092060921609226092360924609256092660927609286092960930609316093260933609346093560936609376093860939609406094160942609436094460945609466094760948609496095060951609526095360954609556095660957609586095960960609616096260963609646096560966609676096860969609706097160972609736097460975609766097760978609796098060981609826098360984609856098660987609886098960990609916099260993609946099560996609976099860999610006100161002610036100461005610066100761008610096101061011610126101361014610156101661017610186101961020610216102261023610246102561026610276102861029610306103161032610336103461035610366103761038610396104061041610426104361044610456104661047610486104961050610516105261053610546105561056610576105861059610606106161062610636106461065610666106761068610696107061071610726107361074610756107661077610786107961080610816108261083610846108561086610876108861089610906109161092610936109461095610966109761098610996110061101611026110361104611056110661107611086110961110611116111261113611146111561116611176111861119611206112161122611236112461125611266112761128611296113061131611326113361134611356113661137611386113961140611416114261143611446114561146611476114861149611506115161152611536115461155611566115761158611596116061161611626116361164611656116661167611686116961170611716117261173611746117561176611776117861179611806118161182611836118461185611866118761188611896119061191611926119361194611956119661197611986119961200612016120261203612046120561206612076120861209612106121161212612136121461215612166121761218612196122061221612226122361224612256122661227612286122961230612316123261233612346123561236612376123861239612406124161242612436124461245612466124761248612496125061251612526125361254612556125661257612586125961260612616126261263612646126561266612676126861269612706127161272612736127461275612766127761278612796128061281612826128361284612856128661287612886128961290612916129261293612946129561296612976129861299613006130161302613036130461305613066130761308613096131061311613126131361314613156131661317613186131961320613216132261323613246132561326613276132861329613306133161332613336133461335613366133761338613396134061341613426134361344613456134661347613486134961350613516135261353613546135561356613576135861359613606136161362613636136461365613666136761368613696137061371613726137361374613756137661377613786137961380613816138261383613846138561386613876138861389613906139161392613936139461395613966139761398613996140061401614026140361404614056140661407614086140961410614116141261413614146141561416614176141861419614206142161422614236142461425614266142761428614296143061431614326143361434614356143661437614386143961440614416144261443614446144561446614476144861449614506145161452614536145461455614566145761458614596146061461614626146361464614656146661467614686146961470614716147261473614746147561476614776147861479614806148161482614836148461485614866148761488614896149061491614926149361494614956149661497614986149961500615016150261503615046150561506615076150861509615106151161512615136151461515615166151761518615196152061521615226152361524615256152661527615286152961530615316153261533615346153561536615376153861539615406154161542615436154461545615466154761548615496155061551615526155361554615556155661557615586155961560615616156261563615646156561566615676156861569615706157161572615736157461575615766157761578615796158061581615826158361584615856158661587615886158961590615916159261593615946159561596615976159861599616006160161602616036160461605616066160761608616096161061611616126161361614616156161661617616186161961620616216162261623616246162561626616276162861629616306163161632616336163461635616366163761638616396164061641616426164361644616456164661647616486164961650616516165261653616546165561656616576165861659616606166161662616636166461665616666166761668616696167061671616726167361674616756167661677616786167961680616816168261683616846168561686616876168861689616906169161692616936169461695616966169761698616996170061701617026170361704617056170661707617086170961710617116171261713617146171561716617176171861719617206172161722617236172461725617266172761728617296173061731617326173361734617356173661737617386173961740617416174261743617446174561746617476174861749617506175161752617536175461755617566175761758617596176061761617626176361764617656176661767617686176961770617716177261773617746177561776617776177861779617806178161782617836178461785617866178761788617896179061791617926179361794617956179661797617986179961800618016180261803618046180561806618076180861809618106181161812618136181461815618166181761818618196182061821618226182361824618256182661827618286182961830618316183261833618346183561836618376183861839618406184161842618436184461845618466184761848618496185061851618526185361854618556185661857618586185961860618616186261863618646186561866618676186861869618706187161872618736187461875618766187761878618796188061881618826188361884618856188661887618886188961890618916189261893618946189561896618976189861899619006190161902619036190461905619066190761908619096191061911619126191361914619156191661917619186191961920619216192261923619246192561926619276192861929619306193161932619336193461935619366193761938619396194061941619426194361944619456194661947619486194961950619516195261953619546195561956619576195861959619606196161962619636196461965619666196761968619696197061971619726197361974619756197661977619786197961980619816198261983619846198561986619876198861989619906199161992619936199461995619966199761998619996200062001620026200362004620056200662007620086200962010620116201262013620146201562016620176201862019620206202162022620236202462025620266202762028620296203062031620326203362034620356203662037620386203962040620416204262043620446204562046620476204862049620506205162052620536205462055620566205762058620596206062061620626206362064620656206662067620686206962070620716207262073620746207562076620776207862079620806208162082620836208462085620866208762088620896209062091620926209362094620956209662097620986209962100621016210262103621046210562106621076210862109621106211162112621136211462115621166211762118621196212062121621226212362124621256212662127621286212962130621316213262133621346213562136621376213862139621406214162142621436214462145621466214762148621496215062151621526215362154621556215662157621586215962160621616216262163621646216562166621676216862169621706217162172621736217462175621766217762178621796218062181621826218362184621856218662187621886218962190621916219262193621946219562196621976219862199622006220162202622036220462205622066220762208622096221062211622126221362214622156221662217622186221962220622216222262223622246222562226622276222862229622306223162232622336223462235622366223762238622396224062241622426224362244622456224662247622486224962250622516225262253622546225562256622576225862259622606226162262622636226462265622666226762268622696227062271622726227362274622756227662277622786227962280622816228262283622846228562286622876228862289622906229162292622936229462295622966229762298622996230062301623026230362304623056230662307623086230962310623116231262313623146231562316623176231862319623206232162322623236232462325623266232762328623296233062331623326233362334623356233662337623386233962340623416234262343623446234562346623476234862349623506235162352623536235462355623566235762358623596236062361623626236362364623656236662367623686236962370623716237262373623746237562376623776237862379623806238162382623836238462385623866238762388623896239062391623926239362394623956239662397623986239962400624016240262403624046240562406624076240862409624106241162412624136241462415624166241762418624196242062421624226242362424624256242662427624286242962430624316243262433624346243562436624376243862439624406244162442624436244462445624466244762448624496245062451624526245362454624556245662457624586245962460624616246262463624646246562466624676246862469624706247162472624736247462475624766247762478624796248062481624826248362484624856248662487624886248962490624916249262493624946249562496624976249862499625006250162502625036250462505625066250762508625096251062511625126251362514625156251662517625186251962520625216252262523625246252562526625276252862529625306253162532625336253462535625366253762538625396254062541625426254362544625456254662547625486254962550625516255262553625546255562556625576255862559625606256162562625636256462565625666256762568625696257062571625726257362574625756257662577625786257962580625816258262583625846258562586625876258862589625906259162592625936259462595625966259762598625996260062601626026260362604626056260662607626086260962610626116261262613626146261562616626176261862619626206262162622626236262462625626266262762628626296263062631626326263362634626356263662637626386263962640626416264262643626446264562646626476264862649626506265162652626536265462655626566265762658626596266062661626626266362664626656266662667626686266962670626716267262673626746267562676626776267862679626806268162682626836268462685626866268762688626896269062691626926269362694626956269662697626986269962700627016270262703627046270562706627076270862709627106271162712627136271462715627166271762718627196272062721627226272362724627256272662727627286272962730627316273262733627346273562736627376273862739627406274162742627436274462745627466274762748627496275062751627526275362754627556275662757627586275962760627616276262763627646276562766627676276862769627706277162772627736277462775627766277762778627796278062781627826278362784627856278662787627886278962790627916279262793627946279562796627976279862799628006280162802628036280462805628066280762808628096281062811628126281362814628156281662817628186281962820628216282262823628246282562826628276282862829628306283162832628336283462835628366283762838628396284062841628426284362844628456284662847628486284962850628516285262853628546285562856628576285862859628606286162862628636286462865628666286762868628696287062871628726287362874628756287662877628786287962880628816288262883628846288562886628876288862889628906289162892628936289462895628966289762898628996290062901629026290362904629056290662907629086290962910629116291262913629146291562916629176291862919629206292162922629236292462925629266292762928629296293062931629326293362934629356293662937629386293962940629416294262943629446294562946629476294862949629506295162952629536295462955629566295762958629596296062961629626296362964629656296662967629686296962970629716297262973629746297562976629776297862979629806298162982629836298462985629866298762988629896299062991629926299362994629956299662997629986299963000630016300263003630046300563006630076300863009630106301163012630136301463015630166301763018630196302063021630226302363024630256302663027630286302963030630316303263033630346303563036630376303863039630406304163042630436304463045630466304763048630496305063051630526305363054630556305663057630586305963060630616306263063630646306563066630676306863069630706307163072630736307463075630766307763078630796308063081630826308363084630856308663087630886308963090630916309263093630946309563096630976309863099631006310163102631036310463105631066310763108631096311063111631126311363114631156311663117631186311963120631216312263123631246312563126631276312863129631306313163132631336313463135631366313763138631396314063141631426314363144631456314663147631486314963150631516315263153631546315563156631576315863159631606316163162631636316463165631666316763168631696317063171631726317363174631756317663177631786317963180631816318263183631846318563186631876318863189631906319163192631936319463195631966319763198631996320063201632026320363204632056320663207632086320963210632116321263213632146321563216632176321863219632206322163222632236322463225632266322763228632296323063231632326323363234632356323663237632386323963240632416324263243632446324563246632476324863249632506325163252632536325463255632566325763258632596326063261632626326363264632656326663267632686326963270632716327263273632746327563276632776327863279632806328163282632836328463285632866328763288632896329063291632926329363294632956329663297632986329963300633016330263303633046330563306633076330863309633106331163312633136331463315633166331763318633196332063321633226332363324633256332663327633286332963330633316333263333633346333563336633376333863339633406334163342633436334463345633466334763348633496335063351633526335363354633556335663357633586335963360633616336263363633646336563366633676336863369633706337163372633736337463375633766337763378633796338063381633826338363384633856338663387633886338963390633916339263393633946339563396633976339863399634006340163402634036340463405634066340763408634096341063411634126341363414634156341663417634186341963420634216342263423634246342563426634276342863429634306343163432634336343463435634366343763438634396344063441634426344363444634456344663447634486344963450634516345263453634546345563456634576345863459634606346163462634636346463465634666346763468634696347063471634726347363474634756347663477634786347963480634816348263483634846348563486634876348863489634906349163492634936349463495634966349763498634996350063501635026350363504635056350663507635086350963510635116351263513635146351563516635176351863519635206352163522635236352463525635266352763528635296353063531635326353363534635356353663537635386353963540635416354263543635446354563546635476354863549635506355163552635536355463555635566355763558635596356063561635626356363564635656356663567635686356963570635716357263573635746357563576635776357863579635806358163582635836358463585635866358763588635896359063591635926359363594635956359663597635986359963600636016360263603636046360563606636076360863609636106361163612636136361463615636166361763618636196362063621636226362363624636256362663627636286362963630636316363263633636346363563636636376363863639636406364163642636436364463645636466364763648636496365063651636526365363654636556365663657636586365963660636616366263663636646366563666636676366863669636706367163672636736367463675636766367763678636796368063681636826368363684636856368663687636886368963690636916369263693636946369563696636976369863699637006370163702637036370463705637066370763708637096371063711637126371363714637156371663717637186371963720637216372263723637246372563726637276372863729637306373163732637336373463735637366373763738637396374063741637426374363744637456374663747637486374963750637516375263753637546375563756637576375863759637606376163762637636376463765637666376763768637696377063771637726377363774637756377663777637786377963780637816378263783637846378563786637876378863789637906379163792637936379463795637966379763798637996380063801638026380363804638056380663807638086380963810638116381263813638146381563816638176381863819638206382163822638236382463825638266382763828638296383063831638326383363834638356383663837638386383963840638416384263843638446384563846638476384863849638506385163852638536385463855638566385763858638596386063861638626386363864638656386663867638686386963870638716387263873638746387563876638776387863879638806388163882638836388463885638866388763888638896389063891638926389363894638956389663897638986389963900639016390263903639046390563906639076390863909639106391163912639136391463915639166391763918639196392063921639226392363924639256392663927639286392963930639316393263933639346393563936639376393863939639406394163942639436394463945639466394763948639496395063951639526395363954639556395663957639586395963960639616396263963639646396563966639676396863969639706397163972639736397463975639766397763978639796398063981639826398363984639856398663987639886398963990639916399263993639946399563996639976399863999640006400164002640036400464005640066400764008640096401064011640126401364014640156401664017640186401964020640216402264023640246402564026640276402864029640306403164032640336403464035640366403764038640396404064041640426404364044640456404664047640486404964050640516405264053640546405564056640576405864059640606406164062640636406464065640666406764068640696407064071640726407364074640756407664077640786407964080640816408264083640846408564086640876408864089640906409164092640936409464095640966409764098640996410064101641026410364104641056410664107641086410964110641116411264113641146411564116641176411864119641206412164122641236412464125641266412764128641296413064131641326413364134641356413664137641386413964140641416414264143641446414564146641476414864149641506415164152641536415464155641566415764158641596416064161641626416364164641656416664167641686416964170641716417264173641746417564176641776417864179641806418164182641836418464185641866418764188641896419064191641926419364194641956419664197641986419964200642016420264203642046420564206642076420864209642106421164212642136421464215642166421764218642196422064221642226422364224642256422664227642286422964230642316423264233642346423564236642376423864239642406424164242642436424464245642466424764248642496425064251642526425364254642556425664257642586425964260642616426264263642646426564266642676426864269642706427164272642736427464275642766427764278642796428064281642826428364284642856428664287642886428964290642916429264293642946429564296642976429864299643006430164302643036430464305643066430764308643096431064311643126431364314643156431664317643186431964320643216432264323643246432564326643276432864329643306433164332643336433464335643366433764338643396434064341643426434364344643456434664347643486434964350643516435264353643546435564356643576435864359643606436164362643636436464365643666436764368643696437064371643726437364374643756437664377643786437964380643816438264383643846438564386643876438864389643906439164392643936439464395643966439764398643996440064401644026440364404644056440664407644086440964410644116441264413644146441564416644176441864419644206442164422644236442464425644266442764428644296443064431644326443364434644356443664437644386443964440644416444264443644446444564446644476444864449644506445164452644536445464455644566445764458644596446064461644626446364464644656446664467644686446964470644716447264473644746447564476644776447864479644806448164482644836448464485644866448764488644896449064491644926449364494644956449664497644986449964500645016450264503645046450564506645076450864509645106451164512645136451464515645166451764518645196452064521645226452364524645256452664527645286452964530645316453264533645346453564536645376453864539645406454164542645436454464545645466454764548645496455064551645526455364554645556455664557645586455964560645616456264563645646456564566645676456864569645706457164572645736457464575645766457764578645796458064581645826458364584645856458664587645886458964590645916459264593645946459564596645976459864599646006460164602646036460464605646066460764608646096461064611646126461364614646156461664617646186461964620646216462264623646246462564626646276462864629646306463164632646336463464635646366463764638646396464064641646426464364644646456464664647646486464964650646516465264653646546465564656646576465864659646606466164662646636466464665646666466764668646696467064671646726467364674646756467664677646786467964680646816468264683646846468564686646876468864689646906469164692646936469464695646966469764698646996470064701647026470364704647056470664707647086470964710647116471264713647146471564716647176471864719647206472164722647236472464725647266472764728647296473064731647326473364734647356473664737647386473964740647416474264743647446474564746647476474864749647506475164752647536475464755647566475764758647596476064761647626476364764647656476664767647686476964770647716477264773647746477564776647776477864779647806478164782647836478464785647866478764788647896479064791647926479364794647956479664797647986479964800648016480264803648046480564806648076480864809648106481164812648136481464815648166481764818648196482064821648226482364824648256482664827648286482964830648316483264833648346483564836648376483864839648406484164842648436484464845648466484764848648496485064851648526485364854648556485664857648586485964860648616486264863648646486564866648676486864869648706487164872648736487464875648766487764878648796488064881648826488364884648856488664887648886488964890648916489264893648946489564896648976489864899649006490164902649036490464905649066490764908649096491064911649126491364914649156491664917649186491964920649216492264923649246492564926649276492864929649306493164932649336493464935649366493764938649396494064941649426494364944649456494664947649486494964950649516495264953649546495564956649576495864959649606496164962649636496464965649666496764968649696497064971649726497364974649756497664977649786497964980649816498264983649846498564986649876498864989649906499164992649936499464995649966499764998649996500065001650026500365004650056500665007650086500965010650116501265013650146501565016650176501865019650206502165022650236502465025650266502765028650296503065031650326503365034650356503665037650386503965040650416504265043650446504565046650476504865049650506505165052650536505465055650566505765058650596506065061650626506365064650656506665067650686506965070650716507265073650746507565076650776507865079650806508165082650836508465085650866508765088650896509065091650926509365094650956509665097650986509965100651016510265103651046510565106651076510865109651106511165112651136511465115651166511765118651196512065121651226512365124651256512665127651286512965130651316513265133651346513565136651376513865139651406514165142651436514465145651466514765148651496515065151651526515365154651556515665157651586515965160651616516265163651646516565166651676516865169651706517165172651736517465175651766517765178651796518065181651826518365184651856518665187651886518965190651916519265193651946519565196651976519865199652006520165202652036520465205652066520765208652096521065211652126521365214652156521665217652186521965220652216522265223652246522565226652276522865229652306523165232652336523465235652366523765238652396524065241652426524365244652456524665247652486524965250652516525265253652546525565256652576525865259652606526165262652636526465265652666526765268652696527065271652726527365274652756527665277652786527965280652816528265283652846528565286652876528865289652906529165292652936529465295652966529765298652996530065301653026530365304653056530665307653086530965310653116531265313653146531565316653176531865319653206532165322653236532465325653266532765328653296533065331653326533365334653356533665337653386533965340653416534265343653446534565346653476534865349653506535165352653536535465355653566535765358653596536065361653626536365364653656536665367653686536965370653716537265373653746537565376653776537865379653806538165382653836538465385653866538765388653896539065391653926539365394653956539665397653986539965400654016540265403654046540565406654076540865409654106541165412654136541465415654166541765418654196542065421654226542365424654256542665427654286542965430654316543265433654346543565436654376543865439654406544165442654436544465445654466544765448654496545065451654526545365454654556545665457654586545965460654616546265463654646546565466654676546865469654706547165472654736547465475654766547765478654796548065481654826548365484654856548665487654886548965490654916549265493654946549565496654976549865499655006550165502655036550465505655066550765508655096551065511655126551365514655156551665517655186551965520655216552265523655246552565526655276552865529655306553165532655336553465535655366553765538655396554065541655426554365544655456554665547655486554965550655516555265553655546555565556655576555865559655606556165562655636556465565655666556765568655696557065571655726557365574655756557665577655786557965580655816558265583655846558565586655876558865589655906559165592655936559465595655966559765598655996560065601656026560365604656056560665607656086560965610656116561265613656146561565616656176561865619656206562165622656236562465625656266562765628656296563065631656326563365634656356563665637656386563965640656416564265643656446564565646656476564865649656506565165652656536565465655656566565765658656596566065661656626566365664656656566665667656686566965670656716567265673656746567565676656776567865679656806568165682656836568465685656866568765688656896569065691656926569365694656956569665697656986569965700657016570265703657046570565706657076570865709657106571165712657136571465715657166571765718657196572065721657226572365724657256572665727657286572965730657316573265733657346573565736657376573865739657406574165742657436574465745657466574765748657496575065751657526575365754657556575665757657586575965760657616576265763657646576565766657676576865769657706577165772657736577465775657766577765778657796578065781657826578365784657856578665787657886578965790657916579265793657946579565796657976579865799658006580165802658036580465805658066580765808658096581065811658126581365814658156581665817658186581965820658216582265823658246582565826658276582865829658306583165832658336583465835658366583765838658396584065841658426584365844658456584665847658486584965850658516585265853658546585565856658576585865859658606586165862658636586465865658666586765868658696587065871658726587365874658756587665877658786587965880658816588265883658846588565886658876588865889658906589165892658936589465895658966589765898658996590065901659026590365904659056590665907659086590965910659116591265913659146591565916659176591865919659206592165922659236592465925659266592765928659296593065931659326593365934659356593665937659386593965940659416594265943659446594565946659476594865949659506595165952659536595465955659566595765958659596596065961659626596365964659656596665967659686596965970659716597265973659746597565976659776597865979659806598165982659836598465985659866598765988659896599065991659926599365994659956599665997659986599966000660016600266003660046600566006660076600866009660106601166012660136601466015660166601766018660196602066021660226602366024660256602666027660286602966030660316603266033660346603566036660376603866039660406604166042660436604466045660466604766048660496605066051660526605366054660556605666057660586605966060660616606266063660646606566066660676606866069660706607166072660736607466075660766607766078660796608066081660826608366084660856608666087660886608966090660916609266093660946609566096660976609866099661006610166102661036610466105661066610766108661096611066111661126611366114661156611666117661186611966120661216612266123661246612566126661276612866129661306613166132661336613466135661366613766138661396614066141661426614366144661456614666147661486614966150661516615266153661546615566156661576615866159661606616166162661636616466165661666616766168661696617066171661726617366174661756617666177661786617966180661816618266183661846618566186661876618866189661906619166192661936619466195661966619766198661996620066201662026620366204662056620666207662086620966210662116621266213662146621566216662176621866219662206622166222662236622466225662266622766228662296623066231662326623366234662356623666237662386623966240662416624266243662446624566246662476624866249662506625166252662536625466255662566625766258662596626066261662626626366264662656626666267662686626966270662716627266273662746627566276662776627866279662806628166282662836628466285662866628766288662896629066291662926629366294662956629666297662986629966300663016630266303663046630566306663076630866309663106631166312663136631466315663166631766318663196632066321663226632366324663256632666327663286632966330663316633266333663346633566336663376633866339663406634166342663436634466345663466634766348663496635066351663526635366354663556635666357663586635966360663616636266363663646636566366663676636866369663706637166372663736637466375663766637766378663796638066381663826638366384663856638666387663886638966390663916639266393663946639566396663976639866399664006640166402664036640466405664066640766408664096641066411664126641366414664156641666417664186641966420664216642266423664246642566426664276642866429664306643166432664336643466435664366643766438664396644066441664426644366444664456644666447664486644966450664516645266453664546645566456664576645866459664606646166462664636646466465664666646766468664696647066471664726647366474664756647666477664786647966480664816648266483664846648566486664876648866489664906649166492664936649466495664966649766498664996650066501665026650366504665056650666507665086650966510665116651266513665146651566516665176651866519665206652166522665236652466525665266652766528665296653066531665326653366534665356653666537665386653966540665416654266543665446654566546665476654866549665506655166552665536655466555665566655766558665596656066561665626656366564665656656666567665686656966570665716657266573665746657566576665776657866579665806658166582665836658466585665866658766588665896659066591665926659366594665956659666597665986659966600666016660266603666046660566606666076660866609666106661166612666136661466615666166661766618666196662066621666226662366624666256662666627666286662966630666316663266633666346663566636666376663866639666406664166642666436664466645666466664766648666496665066651666526665366654666556665666657666586665966660666616666266663666646666566666666676666866669666706667166672666736667466675666766667766678666796668066681666826668366684666856668666687666886668966690666916669266693666946669566696666976669866699667006670166702667036670466705667066670766708667096671066711667126671366714667156671666717667186671966720667216672266723667246672566726667276672866729667306673166732667336673466735667366673766738667396674066741667426674366744667456674666747667486674966750667516675266753667546675566756667576675866759667606676166762667636676466765667666676766768667696677066771667726677366774667756677666777667786677966780667816678266783667846678566786667876678866789667906679166792667936679466795667966679766798667996680066801668026680366804668056680666807668086680966810668116681266813668146681566816668176681866819668206682166822668236682466825668266682766828668296683066831668326683366834668356683666837668386683966840668416684266843668446684566846668476684866849668506685166852668536685466855668566685766858668596686066861668626686366864668656686666867668686686966870668716687266873668746687566876668776687866879668806688166882668836688466885668866688766888668896689066891668926689366894668956689666897668986689966900669016690266903669046690566906669076690866909669106691166912669136691466915669166691766918669196692066921669226692366924669256692666927669286692966930669316693266933669346693566936669376693866939669406694166942669436694466945669466694766948669496695066951669526695366954669556695666957669586695966960669616696266963669646696566966669676696866969669706697166972669736697466975669766697766978669796698066981669826698366984669856698666987669886698966990669916699266993669946699566996669976699866999670006700167002670036700467005670066700767008670096701067011670126701367014670156701667017670186701967020670216702267023670246702567026670276702867029670306703167032670336703467035670366703767038670396704067041670426704367044670456704667047670486704967050670516705267053670546705567056670576705867059670606706167062670636706467065670666706767068670696707067071670726707367074670756707667077670786707967080670816708267083670846708567086670876708867089670906709167092670936709467095670966709767098670996710067101671026710367104671056710667107671086710967110671116711267113671146711567116671176711867119671206712167122671236712467125671266712767128671296713067131671326713367134671356713667137671386713967140671416714267143671446714567146671476714867149671506715167152671536715467155671566715767158671596716067161671626716367164671656716667167671686716967170671716717267173671746717567176671776717867179671806718167182671836718467185671866718767188671896719067191671926719367194671956719667197671986719967200672016720267203672046720567206672076720867209672106721167212672136721467215672166721767218672196722067221672226722367224672256722667227672286722967230672316723267233672346723567236672376723867239672406724167242672436724467245672466724767248672496725067251672526725367254672556725667257672586725967260672616726267263672646726567266672676726867269672706727167272672736727467275672766727767278672796728067281672826728367284672856728667287672886728967290672916729267293672946729567296672976729867299673006730167302673036730467305673066730767308673096731067311673126731367314673156731667317673186731967320673216732267323673246732567326673276732867329673306733167332673336733467335673366733767338673396734067341673426734367344673456734667347673486734967350673516735267353673546735567356673576735867359673606736167362673636736467365673666736767368673696737067371673726737367374673756737667377673786737967380673816738267383673846738567386673876738867389673906739167392673936739467395673966739767398673996740067401674026740367404674056740667407674086740967410674116741267413674146741567416674176741867419674206742167422674236742467425674266742767428674296743067431674326743367434674356743667437674386743967440674416744267443674446744567446674476744867449674506745167452674536745467455674566745767458674596746067461674626746367464674656746667467674686746967470674716747267473674746747567476674776747867479674806748167482674836748467485674866748767488674896749067491674926749367494674956749667497674986749967500675016750267503675046750567506675076750867509675106751167512675136751467515675166751767518675196752067521675226752367524675256752667527675286752967530675316753267533675346753567536675376753867539675406754167542675436754467545675466754767548675496755067551675526755367554675556755667557675586755967560675616756267563675646756567566675676756867569675706757167572675736757467575675766757767578675796758067581675826758367584675856758667587675886758967590675916759267593675946759567596675976759867599676006760167602676036760467605676066760767608676096761067611676126761367614676156761667617676186761967620676216762267623676246762567626676276762867629676306763167632676336763467635676366763767638676396764067641676426764367644676456764667647676486764967650676516765267653676546765567656676576765867659676606766167662676636766467665676666766767668676696767067671676726767367674676756767667677676786767967680676816768267683676846768567686676876768867689676906769167692676936769467695676966769767698676996770067701677026770367704677056770667707677086770967710677116771267713677146771567716677176771867719677206772167722677236772467725677266772767728677296773067731677326773367734677356773667737677386773967740677416774267743677446774567746677476774867749677506775167752677536775467755677566775767758677596776067761677626776367764677656776667767677686776967770677716777267773677746777567776677776777867779677806778167782677836778467785677866778767788677896779067791677926779367794677956779667797677986779967800678016780267803678046780567806678076780867809678106781167812678136781467815678166781767818678196782067821678226782367824678256782667827678286782967830678316783267833678346783567836678376783867839678406784167842678436784467845678466784767848678496785067851678526785367854678556785667857678586785967860678616786267863678646786567866678676786867869678706787167872678736787467875678766787767878678796788067881678826788367884678856788667887678886788967890678916789267893678946789567896678976789867899679006790167902679036790467905679066790767908679096791067911679126791367914679156791667917679186791967920679216792267923679246792567926679276792867929679306793167932679336793467935679366793767938679396794067941679426794367944679456794667947679486794967950679516795267953679546795567956679576795867959679606796167962679636796467965679666796767968679696797067971679726797367974679756797667977679786797967980679816798267983679846798567986679876798867989679906799167992679936799467995679966799767998679996800068001680026800368004680056800668007680086800968010680116801268013680146801568016680176801868019680206802168022680236802468025680266802768028680296803068031680326803368034680356803668037680386803968040680416804268043680446804568046680476804868049680506805168052680536805468055680566805768058680596806068061680626806368064680656806668067680686806968070680716807268073680746807568076680776807868079680806808168082680836808468085680866808768088680896809068091680926809368094680956809668097680986809968100681016810268103681046810568106681076810868109681106811168112681136811468115681166811768118681196812068121681226812368124681256812668127681286812968130681316813268133681346813568136681376813868139681406814168142681436814468145681466814768148681496815068151681526815368154681556815668157681586815968160681616816268163681646816568166681676816868169681706817168172681736817468175681766817768178681796818068181681826818368184681856818668187681886818968190681916819268193681946819568196681976819868199682006820168202682036820468205682066820768208682096821068211682126821368214682156821668217682186821968220682216822268223682246822568226682276822868229682306823168232682336823468235682366823768238682396824068241682426824368244682456824668247682486824968250682516825268253682546825568256682576825868259682606826168262682636826468265682666826768268682696827068271682726827368274682756827668277682786827968280682816828268283682846828568286682876828868289682906829168292682936829468295682966829768298682996830068301683026830368304683056830668307683086830968310683116831268313683146831568316683176831868319683206832168322683236832468325683266832768328683296833068331683326833368334683356833668337683386833968340683416834268343683446834568346683476834868349683506835168352683536835468355683566835768358683596836068361683626836368364683656836668367683686836968370683716837268373683746837568376683776837868379683806838168382683836838468385683866838768388683896839068391683926839368394683956839668397683986839968400684016840268403684046840568406684076840868409684106841168412684136841468415684166841768418684196842068421684226842368424684256842668427684286842968430684316843268433684346843568436684376843868439684406844168442684436844468445684466844768448684496845068451684526845368454684556845668457684586845968460684616846268463684646846568466684676846868469684706847168472684736847468475684766847768478684796848068481684826848368484684856848668487684886848968490684916849268493684946849568496684976849868499685006850168502685036850468505685066850768508685096851068511685126851368514685156851668517685186851968520685216852268523685246852568526685276852868529685306853168532685336853468535685366853768538685396854068541685426854368544685456854668547685486854968550685516855268553685546855568556685576855868559685606856168562685636856468565685666856768568685696857068571685726857368574685756857668577685786857968580685816858268583685846858568586685876858868589685906859168592685936859468595685966859768598685996860068601686026860368604686056860668607686086860968610686116861268613686146861568616686176861868619686206862168622686236862468625686266862768628686296863068631686326863368634686356863668637686386863968640686416864268643686446864568646686476864868649686506865168652686536865468655686566865768658686596866068661686626866368664686656866668667686686866968670686716867268673686746867568676686776867868679686806868168682686836868468685686866868768688686896869068691686926869368694686956869668697686986869968700687016870268703687046870568706687076870868709687106871168712687136871468715687166871768718687196872068721687226872368724687256872668727687286872968730687316873268733687346873568736687376873868739687406874168742687436874468745687466874768748687496875068751687526875368754687556875668757687586875968760687616876268763687646876568766687676876868769687706877168772687736877468775687766877768778687796878068781687826878368784687856878668787687886878968790687916879268793687946879568796687976879868799688006880168802688036880468805688066880768808688096881068811688126881368814688156881668817688186881968820688216882268823688246882568826688276882868829688306883168832688336883468835688366883768838688396884068841688426884368844688456884668847688486884968850688516885268853688546885568856688576885868859688606886168862688636886468865688666886768868688696887068871688726887368874688756887668877688786887968880688816888268883688846888568886688876888868889688906889168892688936889468895688966889768898688996890068901689026890368904689056890668907689086890968910689116891268913689146891568916689176891868919689206892168922689236892468925689266892768928689296893068931689326893368934689356893668937689386893968940689416894268943689446894568946689476894868949689506895168952689536895468955689566895768958689596896068961689626896368964689656896668967689686896968970689716897268973689746897568976689776897868979689806898168982689836898468985689866898768988689896899068991689926899368994689956899668997689986899969000690016900269003690046900569006690076900869009690106901169012690136901469015690166901769018690196902069021690226902369024690256902669027690286902969030690316903269033690346903569036690376903869039690406904169042690436904469045690466904769048690496905069051690526905369054690556905669057690586905969060690616906269063690646906569066690676906869069690706907169072690736907469075690766907769078690796908069081690826908369084690856908669087690886908969090690916909269093690946909569096690976909869099691006910169102691036910469105691066910769108691096911069111691126911369114691156911669117691186911969120691216912269123691246912569126691276912869129691306913169132691336913469135691366913769138691396914069141691426914369144691456914669147691486914969150691516915269153691546915569156691576915869159691606916169162691636916469165691666916769168691696917069171691726917369174691756917669177691786917969180691816918269183691846918569186691876918869189691906919169192691936919469195691966919769198691996920069201692026920369204692056920669207692086920969210692116921269213692146921569216692176921869219692206922169222692236922469225692266922769228692296923069231692326923369234692356923669237692386923969240692416924269243692446924569246692476924869249692506925169252692536925469255692566925769258692596926069261692626926369264692656926669267692686926969270692716927269273692746927569276692776927869279692806928169282692836928469285692866928769288692896929069291692926929369294692956929669297692986929969300693016930269303693046930569306693076930869309693106931169312693136931469315693166931769318693196932069321693226932369324693256932669327693286932969330693316933269333693346933569336693376933869339693406934169342693436934469345693466934769348693496935069351693526935369354693556935669357693586935969360693616936269363693646936569366693676936869369693706937169372693736937469375693766937769378693796938069381693826938369384693856938669387693886938969390693916939269393693946939569396693976939869399694006940169402694036940469405694066940769408694096941069411694126941369414694156941669417694186941969420694216942269423694246942569426694276942869429694306943169432694336943469435694366943769438694396944069441694426944369444694456944669447694486944969450694516945269453694546945569456694576945869459694606946169462694636946469465694666946769468694696947069471694726947369474694756947669477694786947969480694816948269483694846948569486694876948869489694906949169492694936949469495694966949769498694996950069501695026950369504695056950669507695086950969510695116951269513695146951569516695176951869519695206952169522695236952469525695266952769528695296953069531695326953369534695356953669537695386953969540695416954269543695446954569546695476954869549695506955169552695536955469555695566955769558695596956069561695626956369564695656956669567695686956969570695716957269573695746957569576695776957869579695806958169582695836958469585695866958769588695896959069591695926959369594695956959669597695986959969600696016960269603696046960569606696076960869609696106961169612696136961469615696166961769618696196962069621696226962369624696256962669627696286962969630696316963269633696346963569636696376963869639696406964169642696436964469645696466964769648696496965069651696526965369654696556965669657696586965969660696616966269663696646966569666696676966869669696706967169672696736967469675696766967769678696796968069681696826968369684696856968669687696886968969690696916969269693696946969569696696976969869699697006970169702697036970469705697066970769708697096971069711697126971369714697156971669717697186971969720697216972269723697246972569726697276972869729697306973169732697336973469735697366973769738697396974069741697426974369744697456974669747697486974969750697516975269753697546975569756697576975869759697606976169762697636976469765697666976769768697696977069771697726977369774697756977669777697786977969780697816978269783697846978569786697876978869789697906979169792697936979469795697966979769798697996980069801698026980369804698056980669807698086980969810698116981269813698146981569816698176981869819698206982169822698236982469825698266982769828698296983069831698326983369834698356983669837698386983969840698416984269843698446984569846698476984869849698506985169852698536985469855698566985769858698596986069861698626986369864698656986669867698686986969870698716987269873698746987569876698776987869879698806988169882698836988469885698866988769888698896989069891698926989369894698956989669897698986989969900699016990269903699046990569906699076990869909699106991169912699136991469915699166991769918699196992069921699226992369924699256992669927699286992969930699316993269933699346993569936699376993869939699406994169942699436994469945699466994769948699496995069951699526995369954699556995669957699586995969960699616996269963699646996569966699676996869969699706997169972699736997469975699766997769978699796998069981699826998369984699856998669987699886998969990699916999269993699946999569996699976999869999700007000170002700037000470005700067000770008700097001070011700127001370014700157001670017700187001970020700217002270023700247002570026700277002870029700307003170032700337003470035700367003770038700397004070041700427004370044700457004670047700487004970050700517005270053700547005570056700577005870059700607006170062700637006470065700667006770068700697007070071700727007370074700757007670077700787007970080700817008270083700847008570086700877008870089700907009170092700937009470095700967009770098700997010070101701027010370104701057010670107701087010970110701117011270113701147011570116701177011870119701207012170122701237012470125701267012770128701297013070131701327013370134701357013670137701387013970140701417014270143701447014570146701477014870149701507015170152701537015470155701567015770158701597016070161701627016370164701657016670167701687016970170701717017270173701747017570176701777017870179701807018170182701837018470185701867018770188701897019070191701927019370194701957019670197701987019970200702017020270203702047020570206702077020870209702107021170212702137021470215702167021770218702197022070221702227022370224702257022670227702287022970230702317023270233702347023570236702377023870239702407024170242702437024470245702467024770248702497025070251702527025370254702557025670257702587025970260702617026270263702647026570266702677026870269702707027170272702737027470275702767027770278702797028070281702827028370284702857028670287702887028970290702917029270293702947029570296702977029870299703007030170302703037030470305703067030770308703097031070311703127031370314703157031670317703187031970320703217032270323703247032570326703277032870329703307033170332703337033470335703367033770338703397034070341703427034370344703457034670347703487034970350703517035270353703547035570356703577035870359703607036170362703637036470365703667036770368703697037070371703727037370374703757037670377703787037970380703817038270383703847038570386703877038870389703907039170392703937039470395703967039770398703997040070401704027040370404704057040670407704087040970410704117041270413704147041570416704177041870419704207042170422704237042470425704267042770428704297043070431704327043370434704357043670437704387043970440704417044270443704447044570446704477044870449704507045170452704537045470455704567045770458704597046070461704627046370464704657046670467704687046970470704717047270473704747047570476704777047870479704807048170482704837048470485704867048770488704897049070491704927049370494704957049670497704987049970500705017050270503705047050570506705077050870509705107051170512705137051470515705167051770518705197052070521705227052370524705257052670527705287052970530705317053270533705347053570536705377053870539705407054170542705437054470545705467054770548705497055070551705527055370554705557055670557705587055970560705617056270563705647056570566705677056870569705707057170572705737057470575705767057770578705797058070581705827058370584705857058670587705887058970590705917059270593705947059570596705977059870599706007060170602706037060470605706067060770608706097061070611706127061370614706157061670617706187061970620706217062270623706247062570626706277062870629706307063170632706337063470635706367063770638706397064070641706427064370644706457064670647706487064970650706517065270653706547065570656706577065870659706607066170662706637066470665706667066770668706697067070671706727067370674706757067670677706787067970680706817068270683706847068570686706877068870689706907069170692706937069470695706967069770698706997070070701707027070370704707057070670707707087070970710707117071270713707147071570716707177071870719707207072170722707237072470725707267072770728707297073070731707327073370734707357073670737707387073970740707417074270743707447074570746707477074870749707507075170752707537075470755707567075770758707597076070761707627076370764707657076670767707687076970770707717077270773707747077570776707777077870779707807078170782707837078470785707867078770788707897079070791707927079370794707957079670797707987079970800708017080270803708047080570806708077080870809708107081170812708137081470815708167081770818708197082070821708227082370824708257082670827708287082970830708317083270833708347083570836708377083870839708407084170842708437084470845708467084770848708497085070851708527085370854708557085670857708587085970860708617086270863708647086570866708677086870869708707087170872708737087470875708767087770878708797088070881708827088370884708857088670887708887088970890708917089270893708947089570896708977089870899709007090170902709037090470905709067090770908709097091070911709127091370914709157091670917709187091970920709217092270923709247092570926709277092870929709307093170932709337093470935709367093770938709397094070941709427094370944709457094670947709487094970950709517095270953709547095570956709577095870959709607096170962709637096470965709667096770968709697097070971709727097370974709757097670977709787097970980709817098270983709847098570986709877098870989709907099170992709937099470995709967099770998709997100071001710027100371004710057100671007710087100971010710117101271013710147101571016710177101871019710207102171022710237102471025710267102771028710297103071031710327103371034710357103671037710387103971040710417104271043710447104571046710477104871049710507105171052710537105471055710567105771058710597106071061710627106371064710657106671067710687106971070710717107271073710747107571076710777107871079710807108171082710837108471085710867108771088710897109071091710927109371094710957109671097710987109971100711017110271103711047110571106711077110871109711107111171112711137111471115711167111771118711197112071121711227112371124711257112671127711287112971130711317113271133711347113571136711377113871139711407114171142711437114471145711467114771148711497115071151711527115371154711557115671157711587115971160711617116271163711647116571166711677116871169711707117171172711737117471175711767117771178711797118071181711827118371184711857118671187711887118971190711917119271193711947119571196711977119871199712007120171202712037120471205712067120771208712097121071211712127121371214712157121671217712187121971220712217122271223712247122571226712277122871229712307123171232712337123471235712367123771238712397124071241712427124371244712457124671247712487124971250712517125271253712547125571256712577125871259712607126171262712637126471265712667126771268712697127071271712727127371274712757127671277712787127971280712817128271283712847128571286712877128871289712907129171292712937129471295712967129771298712997130071301713027130371304713057130671307713087130971310713117131271313713147131571316713177131871319713207132171322713237132471325713267132771328713297133071331713327133371334713357133671337713387133971340713417134271343713447134571346713477134871349713507135171352713537135471355713567135771358713597136071361713627136371364713657136671367713687136971370713717137271373713747137571376713777137871379713807138171382713837138471385713867138771388713897139071391713927139371394713957139671397713987139971400714017140271403714047140571406714077140871409714107141171412714137141471415714167141771418714197142071421714227142371424714257142671427714287142971430714317143271433714347143571436714377143871439714407144171442714437144471445714467144771448714497145071451714527145371454714557145671457714587145971460714617146271463714647146571466714677146871469714707147171472714737147471475714767147771478714797148071481714827148371484714857148671487714887148971490714917149271493714947149571496714977149871499715007150171502715037150471505715067150771508715097151071511715127151371514715157151671517715187151971520715217152271523715247152571526715277152871529715307153171532715337153471535715367153771538715397154071541715427154371544715457154671547715487154971550715517155271553715547155571556715577155871559715607156171562715637156471565715667156771568715697157071571715727157371574715757157671577715787157971580715817158271583715847158571586715877158871589715907159171592715937159471595715967159771598715997160071601716027160371604716057160671607716087160971610716117161271613716147161571616716177161871619716207162171622716237162471625716267162771628716297163071631716327163371634716357163671637716387163971640716417164271643716447164571646716477164871649716507165171652716537165471655716567165771658716597166071661716627166371664716657166671667716687166971670716717167271673716747167571676716777167871679716807168171682716837168471685716867168771688716897169071691716927169371694716957169671697716987169971700717017170271703717047170571706717077170871709717107171171712717137171471715717167171771718717197172071721717227172371724717257172671727717287172971730717317173271733717347173571736717377173871739717407174171742717437174471745717467174771748717497175071751717527175371754717557175671757717587175971760717617176271763717647176571766717677176871769717707177171772717737177471775717767177771778717797178071781717827178371784717857178671787717887178971790717917179271793717947179571796717977179871799718007180171802718037180471805718067180771808718097181071811718127181371814718157181671817718187181971820718217182271823718247182571826718277182871829718307183171832718337183471835718367183771838718397184071841718427184371844718457184671847718487184971850718517185271853718547185571856718577185871859718607186171862718637186471865718667186771868718697187071871718727187371874718757187671877718787187971880718817188271883718847188571886718877188871889718907189171892718937189471895718967189771898718997190071901719027190371904719057190671907719087190971910719117191271913719147191571916719177191871919719207192171922719237192471925719267192771928719297193071931719327193371934719357193671937719387193971940719417194271943719447194571946719477194871949719507195171952719537195471955719567195771958719597196071961719627196371964719657196671967719687196971970719717197271973719747197571976719777197871979719807198171982719837198471985719867198771988719897199071991719927199371994719957199671997719987199972000720017200272003720047200572006720077200872009720107201172012720137201472015720167201772018720197202072021720227202372024720257202672027720287202972030720317203272033720347203572036720377203872039720407204172042720437204472045720467204772048720497205072051720527205372054720557205672057720587205972060720617206272063720647206572066720677206872069720707207172072720737207472075720767207772078720797208072081720827208372084720857208672087720887208972090720917209272093720947209572096720977209872099721007210172102721037210472105721067210772108721097211072111721127211372114721157211672117721187211972120721217212272123721247212572126721277212872129721307213172132 |
- diff -Nur linux-3.4.110.orig/arch/nds32/boot/install.sh linux-3.4.110/arch/nds32/boot/install.sh
- --- linux-3.4.110.orig/arch/nds32/boot/install.sh 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/boot/install.sh 2016-04-07 10:20:50.862077930 +0200
- @@ -0,0 +1,47 @@
- +#!/bin/sh
- +#
- +# arch/nds32/boot/install.sh
- +#
- +# This file is subject to the terms and conditions of the GNU General Public
- +# License. See the file "COPYING" in the main directory of this archive
- +# for more details.
- +#
- +# Copyright (C) 1995 by Linus Torvalds
- +# Copyright (C) 2009 Andes Technology Corporation
- +#
- +# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
- +# Adapted from code in arch/i386/boot/install.sh by Russell King
- +#
- +# "make install" script for arm architecture
- +#
- +# Arguments:
- +# $1 - kernel version
- +# $2 - kernel image file
- +# $3 - kernel map file
- +# $4 - default install path (blank if root directory)
- +#
- +
- +# User may have a custom install script
- +if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
- +if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
- +
- +# Normal install
- +echo "Installing normal kernel"
- +base=vmlinux
- +
- +if [ -f $4/$base-$1 ]; then
- + mv $4/$base-$1 $4/$base-$1.old
- +fi
- +cat $2 > $4/$base-$1
- +
- +# Install system map file
- +if [ -f $4/System.map-$1 ]; then
- + mv $4/System.map-$1 $4/System.map-$1.old
- +fi
- +cp $3 $4/System.map-$1
- +
- +if [ -x /sbin/loadmap ]; then
- + /sbin/loadmap
- +else
- + echo "You have to install it yourself"
- +fi
- diff -Nur linux-3.4.110.orig/arch/nds32/boot/Makefile linux-3.4.110/arch/nds32/boot/Makefile
- --- linux-3.4.110.orig/arch/nds32/boot/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/boot/Makefile 2016-04-07 10:20:50.862077930 +0200
- @@ -0,0 +1,22 @@
- +#
- +# arch/nds32/boot/Makefile
- +#
- +# This file is subject to the terms and conditions of the GNU General Public
- +# License. See the file "COPYING" in the main directory of this archive
- +# for more details.
- +#
- +# Copyright (C) 1995-2002 Russell King
- +# Copyright (C) 2009 Andes Technology Corporation
- +#
- +
- +targets := Image
- +
- +$(obj)/Image: vmlinux FORCE
- + $(call if_changed,objcopy)
- + @echo ' Kernel: $@ is ready'
- +
- +.PHONY: FORCE
- +install: $(obj)/Image
- + $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
- + $(obj)/Image System.map "$(INSTALL_PATH)"
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/common/dmabounce.c linux-3.4.110/arch/nds32/common/dmabounce.c
- --- linux-3.4.110.orig/arch/nds32/common/dmabounce.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/common/dmabounce.c 2016-04-07 10:20:50.882078703 +0200
- @@ -0,0 +1,672 @@
- +/*
- + * arch/nds32/common/dmabounce.c
- + *
- + * Special dma_{map/unmap/dma_sync}_* routines for systems that have
- + * limited DMA windows. These functions utilize bounce buffers to
- + * copy data to/from buffers located outside the DMA region. This
- + * only works for systems in which DMA memory is at the bottom of
- + * RAM and the remainder of memory is at the top an the DMA memory
- + * can be marked as ZONE_DMA. Anything beyond that such as discontigous
- + * DMA windows will require custom implementations that reserve memory
- + * areas at early bootup.
- + *
- + * Original version by Brad Parker (brad@heeltoe.com)
- + * Re-written by Christopher Hoover <ch@murgatroid.com>
- + * Made generic by Deepak Saxena <dsaxena@plexity.net>
- + *
- + * Copyright (C) 2002 Hewlett Packard Company.
- + * Copyright (C) 2004 MontaVista Software, Inc.
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU General Public License
- + * version 2 as published by the Free Software Foundation.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/init.h>
- +#include <linux/slab.h>
- +#include <linux/device.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/dmapool.h>
- +#include <linux/list.h>
- +
- +#undef DEBUG
- +
- +#undef STATS
- +#ifdef STATS
- +#define DO_STATS(X) do { X ; } while (0)
- +#else
- +#define DO_STATS(X) do { } while (0)
- +#endif
- +
- +/* ************************************************** */
- +
- +struct safe_buffer {
- + struct list_head node;
- +
- + /* original request */
- + void *ptr;
- + size_t size;
- + int direction;
- +
- + /* safe buffer info */
- + struct dma_pool *pool;
- + void *safe;
- + dma_addr_t safe_dma_addr;
- +};
- +
- +struct dmabounce_device_info {
- + struct list_head node;
- +
- + struct device *dev;
- + struct dma_pool *small_buffer_pool;
- + struct dma_pool *large_buffer_pool;
- + struct list_head safe_buffers;
- + unsigned long small_buffer_size, large_buffer_size;
- +#ifdef STATS
- + unsigned long sbp_allocs;
- + unsigned long lbp_allocs;
- + unsigned long total_allocs;
- + unsigned long map_op_count;
- + unsigned long bounce_count;
- +#endif
- +};
- +
- +static LIST_HEAD(dmabounce_devs);
- +
- +#ifdef STATS
- +static void print_alloc_stats(struct dmabounce_device_info *device_info)
- +{
- + printk(KERN_INFO
- + "%s: dmabounce: sbp: %lu, lbp: %lu, other: %lu, total: %lu\n",
- + device_info->dev->bus_id,
- + device_info->sbp_allocs, device_info->lbp_allocs,
- + device_info->total_allocs - device_info->sbp_allocs -
- + device_info->lbp_allocs, device_info->total_allocs);
- +}
- +#endif
- +
- +/* find the given device in the dmabounce device list */
- +static inline struct dmabounce_device_info *find_dmabounce_dev(struct device
- + *dev)
- +{
- + struct list_head *entry;
- +
- + list_for_each(entry, &dmabounce_devs) {
- + struct dmabounce_device_info *d =
- + list_entry(entry, struct dmabounce_device_info, node);
- +
- + if (d->dev == dev)
- + return d;
- + }
- + return NULL;
- +}
- +
- +/* allocate a 'safe' buffer and keep track of it */
- +static inline struct safe_buffer *alloc_safe_buffer(struct dmabounce_device_info
- + *device_info, void *ptr,
- + size_t size,
- + enum dma_data_direction dir)
- +{
- + struct safe_buffer *buf;
- + struct dma_pool *pool;
- + struct device *dev = device_info->dev;
- + void *safe;
- + dma_addr_t safe_dma_addr;
- +
- + dev_dbg(dev, "%s(ptr=%p, size=%d, dir=%d)\n", __func__, ptr, size, dir);
- +
- + DO_STATS(device_info->total_allocs++);
- +
- + buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC);
- + if (buf == NULL) {
- + dev_warn(dev, "%s: kmalloc failed\n", __func__);
- + return NULL;
- + }
- +
- + if (size <= device_info->small_buffer_size) {
- + pool = device_info->small_buffer_pool;
- + safe = dma_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr);
- +
- + DO_STATS(device_info->sbp_allocs++);
- + } else if (size <= device_info->large_buffer_size) {
- + pool = device_info->large_buffer_pool;
- + safe = dma_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr);
- +
- + DO_STATS(device_info->lbp_allocs++);
- + } else {
- + pool = NULL;
- + safe =
- + dma_alloc_coherent(dev, size, &safe_dma_addr, GFP_ATOMIC);
- + }
- +
- + if (safe == NULL) {
- + dev_warn(device_info->dev,
- + "%s: could not alloc dma memory (size=%d)\n",
- + __func__, size);
- + kfree(buf);
- + return NULL;
- + }
- +#ifdef STATS
- + if (device_info->total_allocs % 1000 == 0)
- + print_alloc_stats(device_info);
- +#endif
- +
- + buf->ptr = ptr;
- + buf->size = size;
- + buf->direction = dir;
- + buf->pool = pool;
- + buf->safe = safe;
- + buf->safe_dma_addr = safe_dma_addr;
- +
- + list_add(&buf->node, &device_info->safe_buffers);
- +
- + return buf;
- +}
- +
- +/* determine if a buffer is from our "safe" pool */
- +static inline struct safe_buffer *find_safe_buffer(struct dmabounce_device_info
- + *device_info,
- + dma_addr_t safe_dma_addr)
- +{
- + struct list_head *entry;
- +
- + list_for_each(entry, &device_info->safe_buffers) {
- + struct safe_buffer *b =
- + list_entry(entry, struct safe_buffer, node);
- +
- + if (b->safe_dma_addr == safe_dma_addr)
- + return b;
- + }
- +
- + return NULL;
- +}
- +
- +static inline void
- +free_safe_buffer(struct dmabounce_device_info *device_info,
- + struct safe_buffer *buf)
- +{
- + dev_dbg(device_info->dev, "%s(buf=%p)\n", __func__, buf);
- +
- + list_del(&buf->node);
- +
- + if (buf->pool)
- + dma_pool_free(buf->pool, buf->safe, buf->safe_dma_addr);
- + else
- + dma_free_coherent(device_info->dev, buf->size, buf->safe,
- + buf->safe_dma_addr);
- +
- + kfree(buf);
- +}
- +
- +/* ************************************************** */
- +
- +#ifdef STATS
- +
- +static void print_map_stats(struct dmabounce_device_info *device_info)
- +{
- + printk(KERN_INFO
- + "%s: dmabounce: map_op_count=%lu, bounce_count=%lu\n",
- + device_info->dev->bus_id,
- + device_info->map_op_count, device_info->bounce_count);
- +}
- +#endif
- +
- +static inline dma_addr_t
- +map_single(struct device *dev, void *ptr, size_t size,
- + enum dma_data_direction dir)
- +{
- + struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
- + dma_addr_t dma_addr;
- + int needs_bounce = 0;
- +
- + if (device_info)
- + DO_STATS(device_info->map_op_count++);
- +
- + dma_addr = virt_to_dma(dev, ptr);
- +
- + if (dev->dma_mask) {
- + unsigned long mask = *dev->dma_mask;
- + unsigned long limit;
- +
- + limit = (mask + 1) & ~mask;
- + if (limit && size > limit) {
- + dev_err(dev, "DMA mapping too big (requested %#x "
- + "mask %#Lx)\n", size, *dev->dma_mask);
- + return ~0;
- + }
- +
- + /*
- + * Figure out if we need to bounce from the DMA mask.
- + */
- + needs_bounce = (dma_addr | (dma_addr + size - 1)) & ~mask;
- + }
- +
- + if (device_info
- + && (needs_bounce || dma_needs_bounce(dev, dma_addr, size))) {
- + struct safe_buffer *buf;
- +
- + buf = alloc_safe_buffer(device_info, ptr, size, dir);
- + if (buf == 0) {
- + dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
- + __func__, ptr);
- + return 0;
- + }
- +
- + dev_dbg(dev,
- + "%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n",
- + __func__, buf->ptr, (void *)virt_to_dma(dev, buf->ptr),
- + buf->safe, (void *)buf->safe_dma_addr);
- +
- + if ((dir == DMA_TO_DEVICE) || (dir == DMA_BIDIRECTIONAL)) {
- + dev_dbg(dev, "%s: copy unsafe %p to safe %p, size %d\n",
- + __func__, ptr, buf->safe, size);
- + memcpy(buf->safe, ptr, size);
- + }
- + consistent_sync(buf->safe, size, dir);
- +
- + dma_addr = buf->safe_dma_addr;
- + } else {
- + consistent_sync(ptr, size, dir);
- + }
- +
- + return dma_addr;
- +}
- +
- +static inline void
- +unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
- + enum dma_data_direction dir)
- +{
- + struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
- + struct safe_buffer *buf = NULL;
- +
- + /*
- + * Trying to unmap an invalid mapping
- + */
- + if (dma_addr == ~0) {
- + dev_err(dev, "Trying to unmap invalid mapping\n");
- + return;
- + }
- +
- + if (device_info)
- + buf = find_safe_buffer(device_info, dma_addr);
- +
- + if (buf) {
- + BUG_ON(buf->size != size);
- +
- + dev_dbg(dev,
- + "%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n",
- + __func__, buf->ptr, (void *)virt_to_dma(dev, buf->ptr),
- + buf->safe, (void *)buf->safe_dma_addr);
- +
- + DO_STATS(device_info->bounce_count++);
- +
- + if ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)) {
- + dev_dbg(dev,
- + "%s: copy back safe %p to unsafe %p size %d\n",
- + __func__, buf->safe, buf->ptr, size);
- + memcpy(buf->ptr, buf->safe, size);
- + }
- + free_safe_buffer(device_info, buf);
- + }
- +}
- +
- +static inline void
- +sync_single(struct device *dev, dma_addr_t dma_addr, size_t size,
- + enum dma_data_direction dir)
- +{
- + struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
- + struct safe_buffer *buf = NULL;
- +
- + if (device_info)
- + buf = find_safe_buffer(device_info, dma_addr);
- +
- + if (buf) {
- + /*
- + * Both of these checks from original code need to be
- + * commented out b/c some drivers rely on the following:
- + *
- + * 1) Drivers may map a large chunk of memory into DMA space
- + * but only sync a small portion of it. Good example is
- + * allocating a large buffer, mapping it, and then
- + * breaking it up into small descriptors. No point
- + * in syncing the whole buffer if you only have to
- + * touch one descriptor.
- + *
- + * 2) Buffers that are mapped as DMA_BIDIRECTIONAL are
- + * usually only synced in one dir at a time.
- + *
- + * See drivers/net/eepro100.c for examples of both cases.
- + *
- + * -ds
- + *
- + * BUG_ON(buf->size != size);
- + * BUG_ON(buf->direction != dir);
- + */
- +
- + dev_dbg(dev,
- + "%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n",
- + __func__, buf->ptr, (void *)virt_to_dma(dev, buf->ptr),
- + buf->safe, (void *)buf->safe_dma_addr);
- +
- + DO_STATS(device_info->bounce_count++);
- +
- + switch (dir) {
- + case DMA_FROM_DEVICE:
- + dev_dbg(dev,
- + "%s: copy back safe %p to unsafe %p size %d\n",
- + __func__, buf->safe, buf->ptr, size);
- + memcpy(buf->ptr, buf->safe, size);
- + break;
- + case DMA_TO_DEVICE:
- + dev_dbg(dev,
- + "%s: copy out unsafe %p to safe %p, size %d\n",
- + __func__, buf->ptr, buf->safe, size);
- + memcpy(buf->safe, buf->ptr, size);
- + break;
- + case DMA_BIDIRECTIONAL:
- + BUG(); /* is this allowed? what does it mean? */
- + default:
- + BUG();
- + }
- + consistent_sync(buf->safe, size, dir);
- + } else {
- + consistent_sync(dma_to_virt(dev, dma_addr), size, dir);
- + }
- +}
- +
- +/* ************************************************** */
- +
- +/*
- + * see if a buffer address is in an 'unsafe' range. if it is
- + * allocate a 'safe' buffer and copy the unsafe buffer into it.
- + * substitute the safe buffer for the unsafe one.
- + * (basically move the buffer from an unsafe area to a safe one)
- + */
- +dma_addr_t
- +dma_map_single(struct device *dev, void *ptr, size_t size,
- + enum dma_data_direction dir)
- +{
- + unsigned long flags;
- + dma_addr_t dma_addr;
- +
- + dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", __func__, ptr, size, dir);
- +
- + BUG_ON(dir == DMA_NONE);
- +
- + local_irq_save(flags);
- +
- + dma_addr = map_single(dev, ptr, size, dir);
- +
- + local_irq_restore(flags);
- +
- + return dma_addr;
- +}
- +
- +/*
- + * see if a mapped address was really a "safe" buffer and if so, copy
- + * the data from the safe buffer back to the unsafe buffer and free up
- + * the safe buffer. (basically return things back to the way they
- + * should be)
- + */
- +
- +void
- +dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
- + enum dma_data_direction dir)
- +{
- + unsigned long flags;
- +
- + dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
- + __func__, (void *)dma_addr, size, dir);
- +
- + BUG_ON(dir == DMA_NONE);
- +
- + local_irq_save(flags);
- +
- + unmap_single(dev, dma_addr, size, dir);
- +
- + local_irq_restore(flags);
- +}
- +
- +int
- +dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
- + enum dma_data_direction dir)
- +{
- + unsigned long flags;
- + int i;
- +
- + dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", __func__, sg, nents, dir);
- +
- + BUG_ON(dir == DMA_NONE);
- +
- + local_irq_save(flags);
- +
- + for (i = 0; i < nents; i++, sg++) {
- + struct page *page = sg->page;
- + unsigned int offset = sg->offset;
- + unsigned int length = sg->length;
- + void *ptr = page_address(page) + offset;
- +
- + sg->dma_address = map_single(dev, ptr, length, dir);
- + }
- +
- + local_irq_restore(flags);
- +
- + return nents;
- +}
- +
- +void
- +dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
- + enum dma_data_direction dir)
- +{
- + unsigned long flags;
- + int i;
- +
- + dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", __func__, sg, nents, dir);
- +
- + BUG_ON(dir == DMA_NONE);
- +
- + local_irq_save(flags);
- +
- + for (i = 0; i < nents; i++, sg++) {
- + dma_addr_t dma_addr = sg->dma_address;
- + unsigned int length = sg->length;
- +
- + unmap_single(dev, dma_addr, length, dir);
- + }
- +
- + local_irq_restore(flags);
- +}
- +
- +void
- +dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_addr, size_t size,
- + enum dma_data_direction dir)
- +{
- + unsigned long flags;
- +
- + dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
- + __func__, (void *)dma_addr, size, dir);
- +
- + local_irq_save(flags);
- +
- + sync_single(dev, dma_addr, size, dir);
- +
- + local_irq_restore(flags);
- +}
- +
- +void
- +dma_sync_single_for_device(struct device *dev, dma_addr_t dma_addr, size_t size,
- + enum dma_data_direction dir)
- +{
- + unsigned long flags;
- +
- + dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
- + __func__, (void *)dma_addr, size, dir);
- +
- + local_irq_save(flags);
- +
- + sync_single(dev, dma_addr, size, dir);
- +
- + local_irq_restore(flags);
- +}
- +
- +void
- +dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
- + enum dma_data_direction dir)
- +{
- + unsigned long flags;
- + int i;
- +
- + dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", __func__, sg, nents, dir);
- +
- + BUG_ON(dir == DMA_NONE);
- +
- + local_irq_save(flags);
- +
- + for (i = 0; i < nents; i++, sg++) {
- + dma_addr_t dma_addr = sg->dma_address;
- + unsigned int length = sg->length;
- +
- + sync_single(dev, dma_addr, length, dir);
- + }
- +
- + local_irq_restore(flags);
- +}
- +
- +void
- +dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
- + enum dma_data_direction dir)
- +{
- + unsigned long flags;
- + int i;
- +
- + dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", __func__, sg, nents, dir);
- +
- + BUG_ON(dir == DMA_NONE);
- +
- + local_irq_save(flags);
- +
- + for (i = 0; i < nents; i++, sg++) {
- + dma_addr_t dma_addr = sg->dma_address;
- + unsigned int length = sg->length;
- +
- + sync_single(dev, dma_addr, length, dir);
- + }
- +
- + local_irq_restore(flags);
- +}
- +
- +int
- +dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
- + unsigned long large_buffer_size)
- +{
- + struct dmabounce_device_info *device_info;
- +
- + device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
- + if (!device_info) {
- + printk(KERN_ERR
- + "Could not allocated dmabounce_device_info for %s",
- + dev->bus_id);
- + return -ENOMEM;
- + }
- +
- + device_info->small_buffer_pool =
- + dma_pool_create("small_dmabounce_pool",
- + dev, small_buffer_size, 0 /* byte alignment */ ,
- + 0 /* no page-crossing issues */ );
- + if (!device_info->small_buffer_pool) {
- + printk(KERN_ERR
- + "dmabounce: could not allocate small DMA pool for %s\n",
- + dev->bus_id);
- + kfree(device_info);
- + return -ENOMEM;
- + }
- +
- + if (large_buffer_size) {
- + device_info->large_buffer_pool =
- + dma_pool_create("large_dmabounce_pool",
- + dev,
- + large_buffer_size, 0 /* byte alignment */ ,
- + 0 /* no page-crossing issues */ );
- + if (!device_info->large_buffer_pool) {
- + printk(KERN_ERR
- + "dmabounce: could not allocate large DMA pool for %s\n",
- + dev->bus_id);
- + dma_pool_destroy(device_info->small_buffer_pool);
- +
- + return -ENOMEM;
- + }
- + }
- +
- + device_info->dev = dev;
- + device_info->small_buffer_size = small_buffer_size;
- + device_info->large_buffer_size = large_buffer_size;
- + INIT_LIST_HEAD(&device_info->safe_buffers);
- +
- +#ifdef STATS
- + device_info->sbp_allocs = 0;
- + device_info->lbp_allocs = 0;
- + device_info->total_allocs = 0;
- + device_info->map_op_count = 0;
- + device_info->bounce_count = 0;
- +#endif
- +
- + list_add(&device_info->node, &dmabounce_devs);
- +
- + printk(KERN_INFO "dmabounce: registered device %s on %s bus\n",
- + dev->bus_id, dev->bus->name);
- +
- + return 0;
- +}
- +
- +void dmabounce_unregister_dev(struct device *dev)
- +{
- + struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
- +
- + if (!device_info) {
- + printk(KERN_WARNING
- + "%s: Never registered with dmabounce but attempting"
- + "to unregister!\n", dev->bus_id);
- + return;
- + }
- +
- + if (!list_empty(&device_info->safe_buffers)) {
- + printk(KERN_ERR
- + "%s: Removing from dmabounce with pending buffers!\n",
- + dev->bus_id);
- + BUG();
- + }
- +
- + if (device_info->small_buffer_pool)
- + dma_pool_destroy(device_info->small_buffer_pool);
- + if (device_info->large_buffer_pool)
- + dma_pool_destroy(device_info->large_buffer_pool);
- +
- +#ifdef STATS
- + print_alloc_stats(device_info);
- + print_map_stats(device_info);
- +#endif
- +
- + list_del(&device_info->node);
- +
- + kfree(device_info);
- +
- + printk(KERN_INFO "dmabounce: device %s on %s bus unregistered\n",
- + dev->bus_id, dev->bus->name);
- +}
- +
- +EXPORT_SYMBOL(dma_map_single);
- +EXPORT_SYMBOL(dma_unmap_single);
- +EXPORT_SYMBOL(dma_map_sg);
- +EXPORT_SYMBOL(dma_unmap_sg);
- +EXPORT_SYMBOL(dma_sync_single);
- +EXPORT_SYMBOL(dma_sync_sg);
- +EXPORT_SYMBOL(dmabounce_register_dev);
- +EXPORT_SYMBOL(dmabounce_unregister_dev);
- +
- +MODULE_AUTHOR
- + ("Christopher Hoover <ch@hpl.hp.com>, Deepak Saxena <dsaxena@plexity.net>");
- +MODULE_DESCRIPTION
- + ("Special dma_{map/unmap/dma_sync}_* routines for systems with limited DMA windows");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.4.110.orig/arch/nds32/common/Makefile linux-3.4.110/arch/nds32/common/Makefile
- --- linux-3.4.110.orig/arch/nds32/common/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/common/Makefile 2016-04-07 10:20:50.882078703 +0200
- @@ -0,0 +1,6 @@
- +#
- +# Makefile for the linux kernel.
- +#
- +
- +obj-y += rtctime.o
- +obj-$(CONFIG_DMABOUNCE) += dmabounce.o
- diff -Nur linux-3.4.110.orig/arch/nds32/common/rtctime.c linux-3.4.110/arch/nds32/common/rtctime.c
- --- linux-3.4.110.orig/arch/nds32/common/rtctime.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/common/rtctime.c 2016-04-07 10:20:50.882078703 +0200
- @@ -0,0 +1,441 @@
- +/*
- + * linux/arch/nds32/common/rtctime.c
- + *
- + * Copyright (C) 2003 Deep Blue Solutions Ltd.
- + * Based on sa1100-rtc.c, Nils Faerber, CIH, Nicolas Pitre.
- + * Based on rtc.c by Paul Gortmaker
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/time.h>
- +#include <linux/rtc.h>
- +#include <linux/poll.h>
- +#include <linux/proc_fs.h>
- +#include <linux/miscdevice.h>
- +#include <linux/spinlock.h>
- +#include <linux/capability.h>
- +#include <linux/device.h>
- +#include <linux/mutex.h>
- +#include <linux/rtc.h>
- +
- +#include <asm/rtc.h>
- +#include <asm/semaphore.h>
- +
- +static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
- +static struct fasync_struct *rtc_async_queue;
- +
- +/*
- + * rtc_lock protects rtc_irq_data
- + */
- +static DEFINE_SPINLOCK(rtc_lock);
- +static unsigned long rtc_irq_data;
- +
- +/*
- + * rtc_sem protects rtc_inuse and rtc_ops
- + */
- +static DEFINE_MUTEX(rtc_mutex);
- +static unsigned long rtc_inuse;
- +static struct rtc_ops *rtc_ops;
- +
- +#define rtc_epoch 1900UL
- +
- +/*
- + * Calculate the next alarm time given the requested alarm time mask
- + * and the current time.
- + */
- +void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
- + struct rtc_time *alrm)
- +{
- + unsigned long next_time;
- + unsigned long now_time;
- +
- + next->tm_year = now->tm_year;
- + next->tm_mon = now->tm_mon;
- + next->tm_mday = now->tm_mday;
- + next->tm_hour = alrm->tm_hour;
- + next->tm_min = alrm->tm_min;
- + next->tm_sec = alrm->tm_sec;
- +
- + rtc_tm_to_time(now, &now_time);
- + rtc_tm_to_time(next, &next_time);
- +
- + if (next_time < now_time) {
- + /* Advance one day */
- + next_time += 60 * 60 * 24;
- + rtc_time_to_tm(next_time, next);
- + }
- +}
- +
- +static inline int rtc_arm_read_time(struct rtc_ops *ops, struct rtc_time *tm)
- +{
- + memset(tm, 0, sizeof(struct rtc_time));
- + return ops->read_time(tm);
- +}
- +
- +static inline int rtc_arm_set_time(struct rtc_ops *ops, struct rtc_time *tm)
- +{
- + int ret;
- +
- + ret = rtc_valid_tm(tm);
- + if (ret == 0)
- + ret = ops->set_time(tm);
- +
- + return ret;
- +}
- +
- +static inline int rtc_arm_read_alarm(struct rtc_ops *ops,
- + struct rtc_wkalrm *alrm)
- +{
- + int ret = -EINVAL;
- + if (ops->read_alarm) {
- + memset(alrm, 0, sizeof(struct rtc_wkalrm));
- + ret = ops->read_alarm(alrm);
- + }
- + return ret;
- +}
- +
- +static inline int rtc_arm_set_alarm(struct rtc_ops *ops,
- + struct rtc_wkalrm *alrm)
- +{
- + int ret = -EINVAL;
- + if (ops->set_alarm)
- + ret = ops->set_alarm(alrm);
- + return ret;
- +}
- +
- +void rtc_update(unsigned long num, unsigned long events)
- +{
- + spin_lock(&rtc_lock);
- + rtc_irq_data = (rtc_irq_data + (num << 8)) | events;
- + spin_unlock(&rtc_lock);
- +
- + wake_up_interruptible(&rtc_wait);
- + kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
- +}
- +
- +EXPORT_SYMBOL(rtc_update);
- +
- +static ssize_t
- +rtc_read(struct file *file, char __user * buf, size_t count, loff_t * ppos)
- +{
- + DECLARE_WAITQUEUE(wait, current);
- + unsigned long data;
- + ssize_t ret;
- +
- + if (count < sizeof(unsigned long))
- + return -EINVAL;
- +
- + add_wait_queue(&rtc_wait, &wait);
- + do {
- + __set_current_state(TASK_INTERRUPTIBLE);
- +
- + spin_lock_irq(&rtc_lock);
- + data = rtc_irq_data;
- + rtc_irq_data = 0;
- + spin_unlock_irq(&rtc_lock);
- +
- + if (data != 0) {
- + ret = 0;
- + break;
- + }
- + if (file->f_flags & O_NONBLOCK) {
- + ret = -EAGAIN;
- + break;
- + }
- + if (signal_pending(current)) {
- + ret = -ERESTARTSYS;
- + break;
- + }
- + schedule();
- + } while (1);
- + set_current_state(TASK_RUNNING);
- + remove_wait_queue(&rtc_wait, &wait);
- +
- + if (ret == 0) {
- + ret = put_user(data, (unsigned long __user *)buf);
- + if (ret == 0)
- + ret = sizeof(unsigned long);
- + }
- + return ret;
- +}
- +
- +static unsigned int rtc_poll(struct file *file, poll_table * wait)
- +{
- + unsigned long data;
- +
- + poll_wait(file, &rtc_wait, wait);
- +
- + spin_lock_irq(&rtc_lock);
- + data = rtc_irq_data;
- + spin_unlock_irq(&rtc_lock);
- +
- + return data != 0 ? POLLIN | POLLRDNORM : 0;
- +}
- +
- +static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- + unsigned long arg)
- +{
- + struct rtc_ops *ops = file->private_data;
- + struct rtc_time tm;
- + struct rtc_wkalrm alrm;
- + void __user *uarg = (void __user *)arg;
- + int ret = -EINVAL;
- +
- + switch (cmd) {
- + case RTC_ALM_READ:
- + ret = rtc_arm_read_alarm(ops, &alrm);
- + if (ret)
- + break;
- + ret = copy_to_user(uarg, &alrm.time, sizeof(tm));
- + if (ret)
- + ret = -EFAULT;
- + break;
- +
- + case RTC_ALM_SET:
- + ret = copy_from_user(&alrm.time, uarg, sizeof(tm));
- + if (ret) {
- + ret = -EFAULT;
- + break;
- + }
- + alrm.enabled = 0;
- + alrm.pending = 0;
- + alrm.time.tm_mday = -1;
- + alrm.time.tm_mon = -1;
- + alrm.time.tm_year = -1;
- + alrm.time.tm_wday = -1;
- + alrm.time.tm_yday = -1;
- + alrm.time.tm_isdst = -1;
- + ret = rtc_arm_set_alarm(ops, &alrm);
- + break;
- +
- + case RTC_RD_TIME:
- + ret = rtc_arm_read_time(ops, &tm);
- + if (ret)
- + break;
- + ret = copy_to_user(uarg, &tm, sizeof(tm));
- + if (ret)
- + ret = -EFAULT;
- + break;
- +
- + case RTC_SET_TIME:
- + if (!capable(CAP_SYS_TIME)) {
- + ret = -EACCES;
- + break;
- + }
- + ret = copy_from_user(&tm, uarg, sizeof(tm));
- + if (ret) {
- + ret = -EFAULT;
- + break;
- + }
- + ret = rtc_arm_set_time(ops, &tm);
- + break;
- +
- + case RTC_EPOCH_SET:
- +#ifndef rtc_epoch
- + /*
- + * There were no RTC clocks before 1900.
- + */
- + if (arg < 1900) {
- + ret = -EINVAL;
- + break;
- + }
- + if (!capable(CAP_SYS_TIME)) {
- + ret = -EACCES;
- + break;
- + }
- + rtc_epoch = arg;
- + ret = 0;
- +#endif
- + break;
- +
- + case RTC_EPOCH_READ:
- + ret = put_user(rtc_epoch, (unsigned long __user *)uarg);
- + break;
- +
- + case RTC_WKALM_SET:
- + ret = copy_from_user(&alrm, uarg, sizeof(alrm));
- + if (ret) {
- + ret = -EFAULT;
- + break;
- + }
- + ret = rtc_arm_set_alarm(ops, &alrm);
- + break;
- +
- + case RTC_WKALM_RD:
- + ret = rtc_arm_read_alarm(ops, &alrm);
- + if (ret)
- + break;
- + ret = copy_to_user(uarg, &alrm, sizeof(alrm));
- + if (ret)
- + ret = -EFAULT;
- + break;
- +
- + default:
- + if (ops->ioctl)
- + ret = ops->ioctl(cmd, arg);
- + break;
- + }
- + return ret;
- +}
- +
- +static int rtc_open(struct inode *inode, struct file *file)
- +{
- + int ret;
- +
- + mutex_lock(&rtc_mutex);
- +
- + if (rtc_inuse) {
- + ret = -EBUSY;
- + } else if (!rtc_ops || !try_module_get(rtc_ops->owner)) {
- + ret = -ENODEV;
- + } else {
- + file->private_data = rtc_ops;
- +
- + ret = rtc_ops->open ? rtc_ops->open() : 0;
- + if (ret == 0) {
- + spin_lock_irq(&rtc_lock);
- + rtc_irq_data = 0;
- + spin_unlock_irq(&rtc_lock);
- +
- + rtc_inuse = 1;
- + }
- + }
- + mutex_unlock(&rtc_mutex);
- +
- + return ret;
- +}
- +
- +static int rtc_release(struct inode *inode, struct file *file)
- +{
- + struct rtc_ops *ops = file->private_data;
- +
- + if (ops->release)
- + ops->release();
- +
- + spin_lock_irq(&rtc_lock);
- + rtc_irq_data = 0;
- + spin_unlock_irq(&rtc_lock);
- +
- + module_put(rtc_ops->owner);
- + rtc_inuse = 0;
- +
- + return 0;
- +}
- +
- +static int rtc_fasync(int fd, struct file *file, int on)
- +{
- + return fasync_helper(fd, file, on, &rtc_async_queue);
- +}
- +
- +static struct file_operations rtc_fops = {
- + .owner = THIS_MODULE,
- + .llseek = no_llseek,
- + .read = rtc_read,
- + .poll = rtc_poll,
- + .ioctl = rtc_ioctl,
- + .open = rtc_open,
- + .release = rtc_release,
- + .fasync = rtc_fasync,
- +};
- +
- +static struct miscdevice rtc_miscdev = {
- + .minor = RTC_MINOR,
- + .name = "rtc",
- + .fops = &rtc_fops,
- +};
- +
- +static int rtc_read_proc(char *page, char **start, off_t off, int count,
- + int *eof, void *data)
- +{
- + struct rtc_ops *ops = data;
- + struct rtc_wkalrm alrm;
- + struct rtc_time tm;
- + char *p = page;
- +
- + if (rtc_arm_read_time(ops, &tm) == 0) {
- + p += sprintf(p,
- + "rtc_time\t: %02d:%02d:%02d\n"
- + "rtc_date\t: %04d-%02d-%02d\n"
- + "rtc_epoch\t: %04lu\n",
- + tm.tm_hour, tm.tm_min, tm.tm_sec,
- + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
- + rtc_epoch);
- + }
- +
- + if (rtc_arm_read_alarm(ops, &alrm) == 0) {
- + p += sprintf(p, "alrm_time\t: ");
- + if ((unsigned int)alrm.time.tm_hour <= 24)
- + p += sprintf(p, "%02d:", alrm.time.tm_hour);
- + else
- + p += sprintf(p, "**:");
- + if ((unsigned int)alrm.time.tm_min <= 59)
- + p += sprintf(p, "%02d:", alrm.time.tm_min);
- + else
- + p += sprintf(p, "**:");
- + if ((unsigned int)alrm.time.tm_sec <= 59)
- + p += sprintf(p, "%02d\n", alrm.time.tm_sec);
- + else
- + p += sprintf(p, "**\n");
- +
- + p += sprintf(p, "alrm_date\t: ");
- + if ((unsigned int)alrm.time.tm_year <= 200)
- + p += sprintf(p, "%04d-", alrm.time.tm_year + 1900);
- + else
- + p += sprintf(p, "****-");
- + if ((unsigned int)alrm.time.tm_mon <= 11)
- + p += sprintf(p, "%02d-", alrm.time.tm_mon + 1);
- + else
- + p += sprintf(p, "**-");
- + if ((unsigned int)alrm.time.tm_mday <= 31)
- + p += sprintf(p, "%02d\n", alrm.time.tm_mday);
- + else
- + p += sprintf(p, "**\n");
- + p += sprintf(p, "alrm_wakeup\t: %s\n",
- + alrm.enabled ? "yes" : "no");
- + p += sprintf(p, "alrm_pending\t: %s\n",
- + alrm.pending ? "yes" : "no");
- + }
- +
- + if (ops->proc)
- + p += ops->proc(p);
- +
- + return p - page;
- +}
- +
- +int register_rtc(struct rtc_ops *ops)
- +{
- + int ret = -EBUSY;
- +
- + mutex_lock(&rtc_mutex);
- + if (rtc_ops == NULL) {
- + rtc_ops = ops;
- +
- + ret = misc_register(&rtc_miscdev);
- + if (ret == 0)
- + create_proc_read_entry("driver/rtc", 0, NULL,
- + rtc_read_proc, ops);
- + }
- + mutex_unlock(&rtc_mutex);
- +
- + return ret;
- +}
- +
- +EXPORT_SYMBOL(register_rtc);
- +
- +void unregister_rtc(struct rtc_ops *rtc)
- +{
- + mutex_lock(&rtc_mutex);
- + if (rtc == rtc_ops) {
- + remove_proc_entry("driver/rtc", NULL);
- + misc_deregister(&rtc_miscdev);
- + rtc_ops = NULL;
- + }
- + mutex_unlock(&rtc_mutex);
- +}
- +
- +EXPORT_SYMBOL(unregister_rtc);
- diff -Nur linux-3.4.110.orig/arch/nds32/configs/orca_8k_defconfig linux-3.4.110/arch/nds32/configs/orca_8k_defconfig
- --- linux-3.4.110.orig/arch/nds32/configs/orca_8k_defconfig 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/configs/orca_8k_defconfig 2016-04-07 10:20:50.882078703 +0200
- @@ -0,0 +1,132 @@
- +CONFIG_EXPERIMENTAL=y
- +CONFIG_CROSS_COMPILE="nds32le-linux-"
- +# CONFIG_LOCALVERSION_AUTO is not set
- +CONFIG_SYSVIPC=y
- +CONFIG_POSIX_MQUEUE=y
- +CONFIG_BSD_PROCESS_ACCT=y
- +CONFIG_BSD_PROCESS_ACCT_V3=y
- +CONFIG_IKCONFIG=y
- +CONFIG_IKCONFIG_PROC=y
- +CONFIG_LOG_BUF_SHIFT=14
- +CONFIG_BLK_DEV_INITRD=y
- +CONFIG_CC_OPTIMIZE_FOR_SIZE=y
- +CONFIG_SYSCTL_SYSCALL=y
- +# CONFIG_HOTPLUG is not set
- +# CONFIG_SIGNALFD is not set
- +CONFIG_EMBEDDED=y
- +# CONFIG_VM_EVENT_COUNTERS is not set
- +CONFIG_PROFILING=y
- +CONFIG_OPROFILE=y
- +CONFIG_MODULES=y
- +CONFIG_MODULE_UNLOAD=y
- +# CONFIG_BLK_DEV_BSG is not set
- +CONFIG_PLATFORM_AHBDMA=y
- +CONFIG_PLATFORM_APBDMA=y
- +CONFIG_SYS_CLK=30000000
- +CONFIG_UART_CLK=14745600
- +CONFIG_SDRAM_SIZE=0x40000000
- +CONFIG_CPU_CACHE_NONALIASING=y
- +CONFIG_ANDES_PAGE_SIZE_8KB=y
- +CONFIG_HIGHMEM=y
- +CONFIG_HZ_100=y
- +CONFIG_CMDLINE="root=/dev/ram0 rw mem=1024M@0x0 initrd=0x1000000,8M earlyprintk=uart8250-32bit,0x99600000 console=ttyS0,38400n8 loglevel=7 rootfstype=ext2 init=/bin/busybox init -s user_debug=-1"
- +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
- +CONFIG_NET=y
- +CONFIG_PACKET=y
- +CONFIG_UNIX=y
- +CONFIG_NET_KEY=y
- +CONFIG_INET=y
- +CONFIG_IP_MULTICAST=y
- +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
- +# CONFIG_INET_XFRM_MODE_TUNNEL is not set
- +# CONFIG_INET_XFRM_MODE_BEET is not set
- +# CONFIG_INET_LRO is not set
- +# CONFIG_INET_DIAG is not set
- +# CONFIG_IPV6 is not set
- +CONFIG_BRIDGE=y
- +CONFIG_MTD=y
- +CONFIG_MTD_CMDLINE_PARTS=y
- +CONFIG_MTD_CHAR=y
- +CONFIG_MTD_BLOCK=y
- +CONFIG_MTD_CFI=y
- +CONFIG_MTD_CFI_INTELEXT=y
- +CONFIG_MTD_PHYSMAP=y
- +CONFIG_MTD_PHYSMAP_COMPAT=y
- +CONFIG_MTD_PHYSMAP_START=0x80400000
- +CONFIG_MTD_PHYSMAP_LEN=0x2000000
- +CONFIG_MTD_PHYSMAP_BANKWIDTH=4
- +CONFIG_BLK_DEV_LOOP=y
- +CONFIG_BLK_DEV_RAM=y
- +CONFIG_BLK_DEV_RAM_SIZE=8192
- +CONFIG_NETDEVICES=y
- +CONFIG_TUN=y
- +CONFIG_FTMAC100=y
- +# CONFIG_INPUT_MOUSEDEV is not set
- +CONFIG_INPUT_EVDEV=y
- +# CONFIG_INPUT_KEYBOARD is not set
- +# CONFIG_INPUT_MOUSE is not set
- +CONFIG_INPUT_TOUCHSCREEN=y
- +CONFIG_TOUCHSCREEN_CPE_TS=y
- +# CONFIG_SERIO is not set
- +CONFIG_SERIAL_8250=y
- +CONFIG_SERIAL_8250_CONSOLE=y
- +CONFIG_SERIAL_8250_NR_UARTS=3
- +CONFIG_SERIAL_8250_RUNTIME_UARTS=3
- +# CONFIG_HW_RANDOM is not set
- +CONFIG_GPIOLIB=y
- +CONFIG_GPIO_SYSFS=y
- +CONFIG_GPIO_FTGPIO010=y
- +# CONFIG_HWMON is not set
- +CONFIG_WATCHDOG=y
- +CONFIG_FTWDT010_WATCHDOG=y
- +CONFIG_FB=y
- +CONFIG_FB_FTLCDC100=y
- +# CONFIG_VGA_CONSOLE is not set
- +CONFIG_FRAMEBUFFER_CONSOLE=y
- +CONFIG_LOGO=y
- +CONFIG_SOUND=y
- +CONFIG_SND=y
- +CONFIG_SND_PCM_OSS=y
- +# CONFIG_SND_SUPPORT_OLD_API is not set
- +# CONFIG_SND_VERBOSE_PROCFS is not set
- +CONFIG_SND_FTSSP010=y
- +# CONFIG_HID_SUPPORT is not set
- +# CONFIG_USB_SUPPORT is not set
- +CONFIG_MMC=y
- +CONFIG_MMC_FTSDC010=y
- +CONFIG_RTC_CLASS=y
- +# CONFIG_RTC_HCTOSYS is not set
- +CONFIG_RTC_DRV_FTRTC010=y
- +CONFIG_EXT2_FS=y
- +CONFIG_FUSE_FS=y
- +CONFIG_MSDOS_FS=y
- +CONFIG_VFAT_FS=y
- +# CONFIG_PROC_PAGE_MONITOR is not set
- +CONFIG_TMPFS=y
- +CONFIG_JFFS2_FS=y
- +CONFIG_NFS_FS=y
- +CONFIG_NFS_V3=y
- +CONFIG_NFS_V3_ACL=y
- +CONFIG_NFS_V4=y
- +CONFIG_NFS_V4_1=y
- +CONFIG_NFS_USE_LEGACY_DNS=y
- +CONFIG_NLS_CODEPAGE_437=y
- +CONFIG_NLS_ISO8859_1=y
- +CONFIG_MAGIC_SYSRQ=y
- +CONFIG_DEBUG_FS=y
- +CONFIG_DEBUG_SHIRQ=y
- +CONFIG_SCHEDSTATS=y
- +CONFIG_TIMER_STATS=y
- +CONFIG_SLUB_DEBUG_ON=y
- +CONFIG_DEBUG_RT_MUTEXES=y
- +CONFIG_DEBUG_SPINLOCK=y
- +CONFIG_DEBUG_MUTEXES=y
- +CONFIG_DEBUG_INFO=y
- +CONFIG_DEBUG_MEMORY_INIT=y
- +CONFIG_DEBUG_LIST=y
- +CONFIG_DEBUG_SG=y
- +# CONFIG_FTRACE is not set
- +CONFIG_DEBUG_USER=y
- +CONFIG_DEBUG_ERRORS=y
- +# CONFIG_CRYPTO_ANSI_CPRNG is not set
- +# CONFIG_CRYPTO_HW is not set
- diff -Nur linux-3.4.110.orig/arch/nds32/configs/orca_defconfig linux-3.4.110/arch/nds32/configs/orca_defconfig
- --- linux-3.4.110.orig/arch/nds32/configs/orca_defconfig 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/configs/orca_defconfig 2016-04-07 10:20:50.882078703 +0200
- @@ -0,0 +1,125 @@
- +CONFIG_EXPERIMENTAL=y
- +CONFIG_CROSS_COMPILE="nds32le-linux-"
- +CONFIG_SYSVIPC=y
- +CONFIG_POSIX_MQUEUE=y
- +CONFIG_BSD_PROCESS_ACCT=y
- +CONFIG_BSD_PROCESS_ACCT_V3=y
- +CONFIG_IKCONFIG=y
- +CONFIG_IKCONFIG_PROC=y
- +CONFIG_LOG_BUF_SHIFT=14
- +CONFIG_NAMESPACES=y
- +CONFIG_SYSCTL_SYSCALL=y
- +CONFIG_KALLSYMS_ALL=y
- +# CONFIG_HOTPLUG is not set
- +CONFIG_EMBEDDED=y
- +# CONFIG_VM_EVENT_COUNTERS is not set
- +CONFIG_PROFILING=y
- +CONFIG_OPROFILE=y
- +CONFIG_MODULES=y
- +CONFIG_MODULE_UNLOAD=y
- +# CONFIG_BLK_DEV_BSG is not set
- +CONFIG_MEASURE_INTERRUPT_LATENCY=y
- +CONFIG_PLATFORM_AHBDMA=y
- +CONFIG_PLATFORM_APBDMA=y
- +CONFIG_SYS_CLK=30000000
- +CONFIG_UART_CLK=14745600
- +CONFIG_SDRAM_SIZE=0x40000000
- +CONFIG_MEMORY_START=0x0
- +# CONFIG_HWZOL is not set
- +CONFIG_IVIC=y
- +CONFIG_HIGH_RES_TIMERS=y
- +CONFIG_PREEMPT=y
- +CONFIG_HZ_100=y
- +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
- +CONFIG_NET=y
- +CONFIG_PACKET=y
- +CONFIG_UNIX=y
- +CONFIG_NET_KEY=y
- +CONFIG_INET=y
- +CONFIG_IP_MULTICAST=y
- +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
- +# CONFIG_INET_XFRM_MODE_TUNNEL is not set
- +# CONFIG_INET_XFRM_MODE_BEET is not set
- +# CONFIG_INET_LRO is not set
- +# CONFIG_INET_DIAG is not set
- +# CONFIG_IPV6 is not set
- +CONFIG_BRIDGE=y
- +CONFIG_MTD=y
- +CONFIG_MTD_CMDLINE_PARTS=y
- +CONFIG_MTD_CHAR=y
- +CONFIG_MTD_BLOCK=y
- +CONFIG_MTD_CFI=y
- +CONFIG_MTD_CFI_INTELEXT=y
- +CONFIG_MTD_PHYSMAP=y
- +CONFIG_MTD_PHYSMAP_COMPAT=y
- +CONFIG_MTD_PHYSMAP_START=0x80400000
- +CONFIG_MTD_PHYSMAP_LEN=0x2000000
- +CONFIG_MTD_PHYSMAP_BANKWIDTH=4
- +CONFIG_BLK_DEV_LOOP=y
- +CONFIG_BLK_DEV_RAM=y
- +CONFIG_BLK_DEV_RAM_SIZE=8192
- +CONFIG_NETDEVICES=y
- +CONFIG_TUN=y
- +CONFIG_FTMAC100=y
- +# CONFIG_INPUT_MOUSEDEV is not set
- +CONFIG_INPUT_EVDEV=y
- +# CONFIG_INPUT_KEYBOARD is not set
- +# CONFIG_INPUT_MOUSE is not set
- +CONFIG_INPUT_TOUCHSCREEN=y
- +CONFIG_TOUCHSCREEN_CPE_TS=m
- +# CONFIG_SERIO is not set
- +CONFIG_SERIAL_8250=y
- +CONFIG_SERIAL_8250_CONSOLE=y
- +CONFIG_SERIAL_8250_NR_UARTS=3
- +CONFIG_SERIAL_8250_RUNTIME_UARTS=3
- +# CONFIG_HW_RANDOM is not set
- +CONFIG_GPIOLIB=y
- +CONFIG_GPIO_SYSFS=y
- +CONFIG_GPIO_FTGPIO010=m
- +# CONFIG_HWMON is not set
- +CONFIG_WATCHDOG=y
- +CONFIG_FTWDT010_WATCHDOG=m
- +CONFIG_FB=y
- +CONFIG_FB_FTLCDC100=y
- +# CONFIG_VGA_CONSOLE is not set
- +CONFIG_FRAMEBUFFER_CONSOLE=y
- +CONFIG_LOGO=y
- +CONFIG_SOUND=y
- +CONFIG_SND=y
- +CONFIG_SND_PCM_OSS=y
- +# CONFIG_SND_SUPPORT_OLD_API is not set
- +# CONFIG_SND_VERBOSE_PROCFS is not set
- +CONFIG_SND_FTSSP010=m
- +# CONFIG_HID_SUPPORT is not set
- +# CONFIG_USB_SUPPORT is not set
- +CONFIG_MMC=y
- +CONFIG_MMC_FTSDC010=y
- +CONFIG_RTC_CLASS=y
- +# CONFIG_RTC_HCTOSYS is not set
- +CONFIG_RTC_DRV_FTRTC010=y
- +CONFIG_EXT2_FS=y
- +CONFIG_FUSE_FS=y
- +CONFIG_MSDOS_FS=y
- +CONFIG_VFAT_FS=y
- +CONFIG_TMPFS=y
- +CONFIG_TMPFS_POSIX_ACL=y
- +CONFIG_CONFIGFS_FS=y
- +CONFIG_JFFS2_FS=y
- +CONFIG_NFS_FS=y
- +CONFIG_NFS_V3=y
- +CONFIG_NFS_V3_ACL=y
- +CONFIG_NFS_V4=y
- +CONFIG_NFS_V4_1=y
- +CONFIG_NFS_USE_LEGACY_DNS=y
- +CONFIG_NLS_CODEPAGE_437=y
- +CONFIG_NLS_ISO8859_1=y
- +CONFIG_MAGIC_SYSRQ=y
- +CONFIG_HEADERS_CHECK=y
- +CONFIG_DEBUG_SECTION_MISMATCH=y
- +# CONFIG_SCHED_DEBUG is not set
- +CONFIG_DEBUG_INFO=y
- +# CONFIG_FTRACE is not set
- +CONFIG_DEBUG_USER=y
- +CONFIG_DEBUG_ERRORS=y
- +# CONFIG_CRYPTO_ANSI_CPRNG is not set
- +# CONFIG_CRYPTO_HW is not set
- diff -Nur linux-3.4.110.orig/arch/nds32/configs/qemu_defconfig linux-3.4.110/arch/nds32/configs/qemu_defconfig
- --- linux-3.4.110.orig/arch/nds32/configs/qemu_defconfig 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/configs/qemu_defconfig 2016-04-07 10:20:50.882078703 +0200
- @@ -0,0 +1,98 @@
- +CONFIG_EXPERIMENTAL=y
- +# CONFIG_LOCALVERSION_AUTO is not set
- +CONFIG_SYSVIPC=y
- +CONFIG_BSD_PROCESS_ACCT=y
- +CONFIG_BSD_PROCESS_ACCT_V3=y
- +CONFIG_LOG_BUF_SHIFT=14
- +CONFIG_BLK_DEV_INITRD=y
- +CONFIG_CC_OPTIMIZE_FOR_SIZE=y
- +CONFIG_SYSCTL_SYSCALL=y
- +# CONFIG_HOTPLUG is not set
- +# CONFIG_SIGNALFD is not set
- +CONFIG_EMBEDDED=y
- +# CONFIG_VM_EVENT_COUNTERS is not set
- +CONFIG_PROFILING=y
- +CONFIG_OPROFILE=y
- +CONFIG_MODULES=y
- +CONFIG_MODULE_UNLOAD=y
- +# CONFIG_BLK_DEV_BSG is not set
- +CONFIG_PLAT_QEMU=y
- +CONFIG_SYS_CLK=40000000
- +CONFIG_UART_CLK=14745600
- +CONFIG_SDRAM_SIZE=0x10000000
- +CONFIG_HZ_100=y
- +CONFIG_CMDLINE="root=/dev/ram0 rw mem=1024M@0x0 initrd=0x1000000,8M earlyprintk=uart8250-32bit,0x99600000 console=ttyS0,38400n8 loglevel=7 rootfstype=ext2 init=/bin/busybox init -s user_debug=-1"
- +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
- +CONFIG_NET=y
- +CONFIG_PACKET=y
- +CONFIG_UNIX=y
- +CONFIG_NET_KEY=y
- +CONFIG_INET=y
- +CONFIG_IP_MULTICAST=y
- +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
- +# CONFIG_INET_XFRM_MODE_TUNNEL is not set
- +# CONFIG_INET_XFRM_MODE_BEET is not set
- +# CONFIG_INET_LRO is not set
- +# CONFIG_INET_DIAG is not set
- +# CONFIG_IPV6 is not set
- +CONFIG_BLK_DEV_LOOP=y
- +CONFIG_BLK_DEV_RAM=y
- +CONFIG_BLK_DEV_RAM_SIZE=8192
- +CONFIG_FTSDC010=y
- +CONFIG_NETDEVICES=y
- +CONFIG_FTMAC100=y
- +# CONFIG_INPUT_MOUSEDEV is not set
- +CONFIG_INPUT_EVDEV=y
- +# CONFIG_INPUT_KEYBOARD is not set
- +# CONFIG_INPUT_MOUSE is not set
- +CONFIG_INPUT_TOUCHSCREEN=y
- +# CONFIG_SERIO is not set
- +CONFIG_SERIAL_8250=y
- +CONFIG_SERIAL_8250_CONSOLE=y
- +CONFIG_SERIAL_8250_NR_UARTS=3
- +CONFIG_SERIAL_8250_RUNTIME_UARTS=3
- +# CONFIG_HW_RANDOM is not set
- +# CONFIG_HWMON is not set
- +CONFIG_FB=y
- +# CONFIG_VGA_CONSOLE is not set
- +CONFIG_FRAMEBUFFER_CONSOLE=y
- +CONFIG_LOGO=y
- +# CONFIG_HID_SUPPORT is not set
- +# CONFIG_USB_SUPPORT is not set
- +CONFIG_EXT2_FS=y
- +CONFIG_EXT2_FS_XATTR=y
- +CONFIG_EXT2_FS_POSIX_ACL=y
- +CONFIG_EXT2_FS_SECURITY=y
- +CONFIG_EXT2_FS_XIP=y
- +CONFIG_EXT3_FS=y
- +CONFIG_EXT3_FS_POSIX_ACL=y
- +CONFIG_EXT3_FS_SECURITY=y
- +CONFIG_EXT4_FS=y
- +CONFIG_EXT4_FS_POSIX_ACL=y
- +CONFIG_EXT4_FS_SECURITY=y
- +CONFIG_EXT4_DEBUG=y
- +CONFIG_FUSE_FS=y
- +CONFIG_MSDOS_FS=y
- +CONFIG_VFAT_FS=y
- +# CONFIG_PROC_PAGE_MONITOR is not set
- +CONFIG_TMPFS=y
- +CONFIG_NFS_FS=y
- +CONFIG_NFS_V3=y
- +CONFIG_NLS_CODEPAGE_437=y
- +CONFIG_NLS_ISO8859_1=y
- +CONFIG_MAGIC_SYSRQ=y
- +CONFIG_DEBUG_FS=y
- +CONFIG_DEBUG_SHIRQ=y
- +CONFIG_DETECT_HUNG_TASK=y
- +CONFIG_SCHEDSTATS=y
- +CONFIG_TIMER_STATS=y
- +CONFIG_SLUB_DEBUG_ON=y
- +CONFIG_DEBUG_RT_MUTEXES=y
- +CONFIG_DEBUG_MUTEXES=y
- +CONFIG_DEBUG_INFO=y
- +CONFIG_DEBUG_LIST=y
- +CONFIG_DEBUG_SG=y
- +CONFIG_DEBUG_USER=y
- +CONFIG_DEBUG_ERRORS=y
- +# CONFIG_CRYPTO_ANSI_CPRNG is not set
- +# CONFIG_CRYPTO_HW is not set
- diff -Nur linux-3.4.110.orig/arch/nds32/configs/vep-be_defconfig linux-3.4.110/arch/nds32/configs/vep-be_defconfig
- --- linux-3.4.110.orig/arch/nds32/configs/vep-be_defconfig 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/configs/vep-be_defconfig 2016-04-07 10:20:50.882078703 +0200
- @@ -0,0 +1,777 @@
- +#
- +# Automatically generated make config: don't edit
- +# Linux kernel version: 2.6.29
- +# Mon Jul 13 11:42:57 2009
- +#
- +CONFIG_NDS32=y
- +CONFIG_NO_IOPORT=y
- +CONFIG_GENERIC_IOMAP=y
- +CONFIG_RWSEM_GENERIC_SPINLOCK=y
- +CONFIG_GENERIC_HWEIGHT=y
- +CONFIG_GENERIC_FIND_NEXT_BIT=y
- +CONFIG_GENERIC_CALIBRATE_DELAY=y
- +CONFIG_GENERIC_HARDIRQS=y
- +CONFIG_LOCKDEP_SUPPORT=y
- +CONFIG_STACKTRACE_SUPPORT=y
- +CONFIG_HAVE_LATENCYTOP_SUPPORT=y
- +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
- +
- +#
- +# General setup
- +#
- +CONFIG_EXPERIMENTAL=y
- +CONFIG_BROKEN_ON_SMP=y
- +CONFIG_INIT_ENV_ARG_LIMIT=32
- +CONFIG_LOCALVERSION=""
- +# CONFIG_LOCALVERSION_AUTO is not set
- +CONFIG_SWAP=y
- +CONFIG_SYSVIPC=y
- +CONFIG_SYSVIPC_SYSCTL=y
- +# CONFIG_POSIX_MQUEUE is not set
- +CONFIG_BSD_PROCESS_ACCT=y
- +CONFIG_BSD_PROCESS_ACCT_V3=y
- +# CONFIG_TASKSTATS is not set
- +# CONFIG_AUDIT is not set
- +
- +#
- +# RCU Subsystem
- +#
- +CONFIG_CLASSIC_RCU=y
- +# CONFIG_TREE_RCU is not set
- +# CONFIG_PREEMPT_RCU is not set
- +# CONFIG_TREE_RCU_TRACE is not set
- +# CONFIG_PREEMPT_RCU_TRACE is not set
- +# CONFIG_IKCONFIG is not set
- +CONFIG_LOG_BUF_SHIFT=14
- +# CONFIG_GROUP_SCHED is not set
- +# CONFIG_CGROUPS is not set
- +# CONFIG_SYSFS_DEPRECATED_V2 is not set
- +# CONFIG_RELAY is not set
- +# CONFIG_NAMESPACES is not set
- +CONFIG_BLK_DEV_INITRD=y
- +CONFIG_INITRAMFS_SOURCE=""
- +CONFIG_CC_OPTIMIZE_FOR_SIZE=y
- +CONFIG_SYSCTL=y
- +CONFIG_ANON_INODES=y
- +CONFIG_EMBEDDED=y
- +CONFIG_UID16=y
- +CONFIG_SYSCTL_SYSCALL=y
- +# CONFIG_KALLSYMS is not set
- +# CONFIG_HOTPLUG is not set
- +CONFIG_PRINTK=y
- +CONFIG_BUG=y
- +# CONFIG_ELF_CORE is not set
- +CONFIG_BASE_FULL=y
- +CONFIG_FUTEX=y
- +CONFIG_EPOLL=y
- +# CONFIG_SIGNALFD is not set
- +CONFIG_TIMERFD=y
- +CONFIG_EVENTFD=y
- +CONFIG_SHMEM=y
- +CONFIG_AIO=y
- +# CONFIG_VM_EVENT_COUNTERS is not set
- +CONFIG_SLUB_DEBUG=y
- +CONFIG_COMPAT_BRK=y
- +# CONFIG_SLAB is not set
- +CONFIG_SLUB=y
- +# CONFIG_SLOB is not set
- +CONFIG_PROFILING=y
- +CONFIG_TRACEPOINTS=y
- +# CONFIG_MARKERS is not set
- +CONFIG_OPROFILE=y
- +CONFIG_HAVE_OPROFILE=y
- +CONFIG_HAVE_KPROBES=y
- +CONFIG_HAVE_KRETPROBES=y
- +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
- +CONFIG_SLABINFO=y
- +CONFIG_RT_MUTEXES=y
- +CONFIG_BASE_SMALL=0
- +CONFIG_MODULES=y
- +# CONFIG_MODULE_FORCE_LOAD is not set
- +CONFIG_MODULE_UNLOAD=y
- +# CONFIG_MODULE_FORCE_UNLOAD is not set
- +# CONFIG_MODVERSIONS is not set
- +# CONFIG_MODULE_SRCVERSION_ALL is not set
- +CONFIG_BLOCK=y
- +# CONFIG_LBD is not set
- +# CONFIG_BLK_DEV_IO_TRACE is not set
- +# CONFIG_BLK_DEV_BSG is not set
- +# CONFIG_BLK_DEV_INTEGRITY is not set
- +
- +#
- +# IO Schedulers
- +#
- +CONFIG_IOSCHED_NOOP=y
- +# CONFIG_IOSCHED_AS is not set
- +# CONFIG_IOSCHED_DEADLINE is not set
- +# CONFIG_IOSCHED_CFQ is not set
- +# CONFIG_DEFAULT_AS is not set
- +# CONFIG_DEFAULT_DEADLINE is not set
- +# CONFIG_DEFAULT_CFQ is not set
- +CONFIG_DEFAULT_NOOP=y
- +CONFIG_DEFAULT_IOSCHED="noop"
- +# CONFIG_FREEZER is not set
- +
- +#
- +# System Type
- +#
- +# CONFIG_PLAT_FARADAY is not set
- +CONFIG_PLAT_VEP=y
- +# CONFIG_PLAT_AG101 is not set
- +# CONFIG_PLAT_AG102 is not set
- +# CONFIG_PLAT_AG101P is not set
- +# CONFIG_PLAT_QEMU is not set
- +CONFIG_PLATFORM_INTC=y
- +
- +#
- +# VEP Platform Options
- +#
- +# CONFIG_CACHE_L2 is not set
- +
- +#
- +# Common Platform Options
- +#
- +# CONFIG_PLATFORM_AHBDMA is not set
- +# CONFIG_PLATFORM_APBDMA is not set
- +CONFIG_SYS_CLK=67737600
- +CONFIG_UART_CLK=36864000
- +CONFIG_SDRAM_SIZE=0x10000000
- +
- +#
- +# Processor Features
- +#
- +CONFIG_CPU_CUSTOM=y
- +# CONFIG_FPU is not set
- +# CONFIG_AUDIO is not set
- +# CONFIG_EVIC is not set
- +CONFIG_CPU_CONTEXT_ID=y
- +CONFIG_ANDES_PAGE_SIZE_4KB=y
- +# CONFIG_ANDES_PAGE_SIZE_8KB is not set
- +# CONFIG_KERNEL_SPACE_LARGE_PAGE is not set
- +# CONFIG_CPU_ICACHE_DISABLE is not set
- +# CONFIG_CPU_DCACHE_DISABLE is not set
- +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
- +# CONFIG_ALIGNMENT_TRAP is not set
- +CONFIG_MMU=y
- +
- +#
- +# Kernel Features
- +#
- +CONFIG_PREEMPT_NONE=y
- +# CONFIG_PREEMPT_VOLUNTARY is not set
- +# CONFIG_PREEMPT is not set
- +CONFIG_SELECT_MEMORY_MODEL=y
- +CONFIG_FLATMEM_MANUAL=y
- +# CONFIG_DISCONTIGMEM_MANUAL is not set
- +# CONFIG_SPARSEMEM_MANUAL is not set
- +CONFIG_FLATMEM=y
- +CONFIG_FLAT_NODE_MEM_MAP=y
- +CONFIG_PAGEFLAGS_EXTENDED=y
- +CONFIG_SPLIT_PTLOCK_CPUS=4
- +# CONFIG_PHYS_ADDR_T_64BIT is not set
- +CONFIG_ZONE_DMA_FLAG=0
- +CONFIG_VIRT_TO_BUS=y
- +CONFIG_UNEVICTABLE_LRU=y
- +CONFIG_FORCE_MAX_ZONEORDER=11
- +CONFIG_HZ_100=y
- +# CONFIG_HZ_250 is not set
- +# CONFIG_HZ_300 is not set
- +# CONFIG_HZ_1000 is not set
- +CONFIG_HZ=100
- +# CONFIG_SCHED_HRTICK is not set
- +CONFIG_CMDLINE="root=/dev/ram0 rw mem=64M@0x0 initrd=0x1000000,8M console=ttyS0,38400n8 rootfstype=ext2 init=/bin/busybox init -s user_debug=-1"
- +
- +#
- +# Power management options
- +#
- +CONFIG_SYS_SUPPORTS_APM_EMULATION=y
- +CONFIG_ARCH_SUSPEND_POSSIBLE=y
- +# CONFIG_PM is not set
- +
- +#
- +# Bus options
- +#
- +# CONFIG_PCI is not set
- +# CONFIG_ARCH_SUPPORTS_MSI is not set
- +
- +#
- +# Executable file formats
- +#
- +CONFIG_BINFMT_ELF=y
- +# CONFIG_HAVE_AOUT is not set
- +# CONFIG_BINFMT_MISC is not set
- +CONFIG_NET=y
- +
- +#
- +# Networking options
- +#
- +CONFIG_COMPAT_NET_DEV_OPS=y
- +CONFIG_PACKET=y
- +# CONFIG_PACKET_MMAP is not set
- +CONFIG_UNIX=y
- +CONFIG_XFRM=y
- +# CONFIG_XFRM_USER is not set
- +# CONFIG_XFRM_SUB_POLICY is not set
- +# CONFIG_XFRM_MIGRATE is not set
- +# CONFIG_XFRM_STATISTICS is not set
- +CONFIG_NET_KEY=y
- +# CONFIG_NET_KEY_MIGRATE is not set
- +CONFIG_INET=y
- +CONFIG_IP_MULTICAST=y
- +# CONFIG_IP_ADVANCED_ROUTER is not set
- +CONFIG_IP_FIB_HASH=y
- +# CONFIG_IP_PNP is not set
- +# CONFIG_NET_IPIP is not set
- +# CONFIG_NET_IPGRE is not set
- +# CONFIG_IP_MROUTE is not set
- +# CONFIG_ARPD is not set
- +# CONFIG_SYN_COOKIES is not set
- +# CONFIG_INET_AH is not set
- +# CONFIG_INET_ESP is not set
- +# CONFIG_INET_IPCOMP is not set
- +# CONFIG_INET_XFRM_TUNNEL is not set
- +# CONFIG_INET_TUNNEL is not set
- +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
- +# CONFIG_INET_XFRM_MODE_TUNNEL is not set
- +# CONFIG_INET_XFRM_MODE_BEET is not set
- +# CONFIG_INET_LRO is not set
- +# CONFIG_INET_DIAG is not set
- +# CONFIG_TCP_CONG_ADVANCED is not set
- +CONFIG_TCP_CONG_CUBIC=y
- +CONFIG_DEFAULT_TCP_CONG="cubic"
- +# CONFIG_TCP_MD5SIG is not set
- +# CONFIG_IPV6 is not set
- +# CONFIG_NETWORK_SECMARK is not set
- +# CONFIG_NETFILTER is not set
- +# CONFIG_IP_DCCP is not set
- +# CONFIG_IP_SCTP is not set
- +# CONFIG_TIPC is not set
- +# CONFIG_ATM is not set
- +# CONFIG_BRIDGE is not set
- +# CONFIG_NET_DSA is not set
- +# CONFIG_VLAN_8021Q is not set
- +# CONFIG_DECNET is not set
- +# CONFIG_LLC2 is not set
- +# CONFIG_IPX is not set
- +# CONFIG_ATALK is not set
- +# CONFIG_X25 is not set
- +# CONFIG_LAPB is not set
- +# CONFIG_ECONET is not set
- +# CONFIG_WAN_ROUTER is not set
- +# CONFIG_NET_SCHED is not set
- +# CONFIG_DCB is not set
- +
- +#
- +# Network testing
- +#
- +# CONFIG_NET_PKTGEN is not set
- +# CONFIG_HAMRADIO is not set
- +# CONFIG_CAN is not set
- +# CONFIG_IRDA is not set
- +# CONFIG_BT is not set
- +# CONFIG_AF_RXRPC is not set
- +# CONFIG_PHONET is not set
- +CONFIG_WIRELESS=y
- +# CONFIG_CFG80211 is not set
- +CONFIG_WIRELESS_OLD_REGULATORY=y
- +# CONFIG_WIRELESS_EXT is not set
- +# CONFIG_LIB80211 is not set
- +# CONFIG_MAC80211 is not set
- +# CONFIG_WIMAX is not set
- +# CONFIG_RFKILL is not set
- +# CONFIG_NET_9P is not set
- +
- +#
- +# Device Drivers
- +#
- +
- +#
- +# Generic Driver Options
- +#
- +CONFIG_STANDALONE=y
- +CONFIG_PREVENT_FIRMWARE_BUILD=y
- +# CONFIG_SYS_HYPERVISOR is not set
- +# CONFIG_CONNECTOR is not set
- +# CONFIG_MTD is not set
- +# CONFIG_PARPORT is not set
- +CONFIG_BLK_DEV=y
- +# CONFIG_BLK_DEV_COW_COMMON is not set
- +CONFIG_BLK_DEV_LOOP=y
- +# CONFIG_BLK_DEV_CRYPTOLOOP is not set
- +# CONFIG_BLK_DEV_NBD is not set
- +CONFIG_BLK_DEV_RAM=y
- +CONFIG_BLK_DEV_RAM_COUNT=16
- +CONFIG_BLK_DEV_RAM_SIZE=8192
- +# CONFIG_BLK_DEV_XIP is not set
- +# CONFIG_CDROM_PKTCDVD is not set
- +# CONFIG_ATA_OVER_ETH is not set
- +# CONFIG_FTSDC010 is not set
- +# CONFIG_FTCFC010 is not set
- +# CONFIG_BLK_DEV_HD is not set
- +# CONFIG_MISC_DEVICES is not set
- +CONFIG_HAVE_IDE=y
- +# CONFIG_IDE is not set
- +
- +#
- +# SCSI device support
- +#
- +# CONFIG_RAID_ATTRS is not set
- +# CONFIG_SCSI is not set
- +# CONFIG_SCSI_DMA is not set
- +# CONFIG_SCSI_NETLINK is not set
- +# CONFIG_ATA is not set
- +# CONFIG_MD is not set
- +CONFIG_NETDEVICES=y
- +# CONFIG_DUMMY is not set
- +# CONFIG_BONDING is not set
- +# CONFIG_MACVLAN is not set
- +# CONFIG_EQUALIZER is not set
- +# CONFIG_TUN is not set
- +# CONFIG_VETH is not set
- +# CONFIG_PHYLIB is not set
- +CONFIG_NET_ETHERNET=y
- +# CONFIG_MII is not set
- +# CONFIG_SMC91X is not set
- +# CONFIG_DNET is not set
- +# CONFIG_IBM_NEW_EMAC_ZMII is not set
- +# CONFIG_IBM_NEW_EMAC_RGMII is not set
- +# CONFIG_IBM_NEW_EMAC_TAH is not set
- +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
- +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
- +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
- +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
- +# CONFIG_B44 is not set
- +CONFIG_FTMAC100=y
- +# CONFIG_NETDEV_1000 is not set
- +# CONFIG_NETDEV_10000 is not set
- +
- +#
- +# Wireless LAN
- +#
- +# CONFIG_WLAN_PRE80211 is not set
- +# CONFIG_WLAN_80211 is not set
- +# CONFIG_IWLWIFI_LEDS is not set
- +
- +#
- +# Enable WiMAX (Networking options) to see the WiMAX drivers
- +#
- +# CONFIG_WAN is not set
- +# CONFIG_PPP is not set
- +# CONFIG_SLIP is not set
- +# CONFIG_NETCONSOLE is not set
- +# CONFIG_NETPOLL is not set
- +# CONFIG_NET_POLL_CONTROLLER is not set
- +# CONFIG_ISDN is not set
- +# CONFIG_PHONE is not set
- +
- +#
- +# Input device support
- +#
- +CONFIG_INPUT=y
- +# CONFIG_INPUT_FF_MEMLESS is not set
- +# CONFIG_INPUT_POLLDEV is not set
- +
- +#
- +# Userland interfaces
- +#
- +# CONFIG_INPUT_MOUSEDEV is not set
- +# CONFIG_INPUT_JOYDEV is not set
- +# CONFIG_INPUT_EVDEV is not set
- +# CONFIG_INPUT_EVBUG is not set
- +
- +#
- +# Input Device Drivers
- +#
- +# CONFIG_INPUT_KEYBOARD is not set
- +# CONFIG_INPUT_MOUSE is not set
- +# CONFIG_INPUT_JOYSTICK is not set
- +# CONFIG_INPUT_TABLET is not set
- +# CONFIG_INPUT_TOUCHSCREEN is not set
- +# CONFIG_INPUT_MISC is not set
- +
- +#
- +# Hardware I/O ports
- +#
- +# CONFIG_SERIO is not set
- +# CONFIG_GAMEPORT is not set
- +
- +#
- +# Character devices
- +#
- +CONFIG_VT=y
- +CONFIG_CONSOLE_TRANSLATIONS=y
- +CONFIG_VT_CONSOLE=y
- +CONFIG_HW_CONSOLE=y
- +# CONFIG_VT_HW_CONSOLE_BINDING is not set
- +CONFIG_DEVKMEM=y
- +# CONFIG_SERIAL_NONSTANDARD is not set
- +
- +#
- +# Serial drivers
- +#
- +CONFIG_SERIAL_8250=y
- +CONFIG_SERIAL_8250_CONSOLE=y
- +CONFIG_SERIAL_8250_NR_UARTS=3
- +CONFIG_SERIAL_8250_RUNTIME_UARTS=3
- +# CONFIG_SERIAL_8250_EXTENDED is not set
- +
- +#
- +# Non-8250 serial port support
- +#
- +CONFIG_SERIAL_CORE=y
- +CONFIG_SERIAL_CORE_CONSOLE=y
- +CONFIG_UNIX98_PTYS=y
- +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
- +CONFIG_LEGACY_PTYS=y
- +CONFIG_LEGACY_PTY_COUNT=256
- +# CONFIG_IPMI_HANDLER is not set
- +# CONFIG_HW_RANDOM is not set
- +# CONFIG_R3964 is not set
- +# CONFIG_GPIO_FTGPIO010 is not set
- +# CONFIG_RAW_DRIVER is not set
- +# CONFIG_TCG_TPM is not set
- +# CONFIG_I2C is not set
- +# CONFIG_SPI is not set
- +# CONFIG_W1 is not set
- +# CONFIG_POWER_SUPPLY is not set
- +# CONFIG_HWMON is not set
- +# CONFIG_THERMAL is not set
- +# CONFIG_THERMAL_HWMON is not set
- +# CONFIG_WATCHDOG is not set
- +CONFIG_SSB_POSSIBLE=y
- +
- +#
- +# Sonics Silicon Backplane
- +#
- +# CONFIG_SSB is not set
- +
- +#
- +# Multifunction device drivers
- +#
- +# CONFIG_MFD_CORE is not set
- +# CONFIG_MFD_SM501 is not set
- +# CONFIG_HTC_PASIC3 is not set
- +# CONFIG_MFD_TMIO is not set
- +# CONFIG_REGULATOR is not set
- +
- +#
- +# Multimedia devices
- +#
- +
- +#
- +# Multimedia core support
- +#
- +# CONFIG_VIDEO_DEV is not set
- +# CONFIG_DVB_CORE is not set
- +# CONFIG_VIDEO_MEDIA is not set
- +
- +#
- +# Multimedia drivers
- +#
- +# CONFIG_DAB is not set
- +
- +#
- +# Graphics support
- +#
- +# CONFIG_VGASTATE is not set
- +# CONFIG_VIDEO_OUTPUT_CONTROL is not set
- +# CONFIG_FB is not set
- +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
- +
- +#
- +# Display device support
- +#
- +# CONFIG_DISPLAY_SUPPORT is not set
- +
- +#
- +# Console display driver support
- +#
- +# CONFIG_VGA_CONSOLE is not set
- +CONFIG_DUMMY_CONSOLE=y
- +# CONFIG_SOUND is not set
- +# CONFIG_HID_SUPPORT is not set
- +# CONFIG_USB_SUPPORT is not set
- +# CONFIG_MMC is not set
- +# CONFIG_MEMSTICK is not set
- +# CONFIG_NEW_LEDS is not set
- +# CONFIG_ACCESSIBILITY is not set
- +CONFIG_RTC_LIB=y
- +# CONFIG_RTC_CLASS is not set
- +# CONFIG_DMADEVICES is not set
- +# CONFIG_UIO is not set
- +# CONFIG_STAGING is not set
- +
- +#
- +# File systems
- +#
- +CONFIG_EXT2_FS=y
- +# CONFIG_EXT2_FS_XATTR is not set
- +# CONFIG_EXT2_FS_XIP is not set
- +# CONFIG_EXT3_FS is not set
- +# CONFIG_EXT4_FS is not set
- +# CONFIG_REISERFS_FS is not set
- +# CONFIG_JFS_FS is not set
- +# CONFIG_FS_POSIX_ACL is not set
- +CONFIG_FILE_LOCKING=y
- +# CONFIG_XFS_FS is not set
- +# CONFIG_OCFS2_FS is not set
- +# CONFIG_BTRFS_FS is not set
- +CONFIG_DNOTIFY=y
- +CONFIG_INOTIFY=y
- +CONFIG_INOTIFY_USER=y
- +# CONFIG_QUOTA is not set
- +# CONFIG_AUTOFS_FS is not set
- +# CONFIG_AUTOFS4_FS is not set
- +CONFIG_FUSE_FS=y
- +
- +#
- +# CD-ROM/DVD Filesystems
- +#
- +# CONFIG_ISO9660_FS is not set
- +# CONFIG_UDF_FS is not set
- +
- +#
- +# DOS/FAT/NT Filesystems
- +#
- +# CONFIG_MSDOS_FS is not set
- +# CONFIG_VFAT_FS is not set
- +# CONFIG_NTFS_FS is not set
- +
- +#
- +# Pseudo filesystems
- +#
- +CONFIG_PROC_FS=y
- +# CONFIG_PROC_KCORE is not set
- +CONFIG_PROC_SYSCTL=y
- +# CONFIG_PROC_PAGE_MONITOR is not set
- +CONFIG_SYSFS=y
- +CONFIG_TMPFS=y
- +# CONFIG_TMPFS_POSIX_ACL is not set
- +# CONFIG_HUGETLB_PAGE is not set
- +# CONFIG_CONFIGFS_FS is not set
- +CONFIG_MISC_FILESYSTEMS=y
- +# CONFIG_ADFS_FS is not set
- +# CONFIG_AFFS_FS is not set
- +# CONFIG_HFS_FS is not set
- +# CONFIG_HFSPLUS_FS is not set
- +# CONFIG_BEFS_FS is not set
- +# CONFIG_BFS_FS is not set
- +# CONFIG_EFS_FS is not set
- +# CONFIG_CRAMFS is not set
- +# CONFIG_SQUASHFS is not set
- +# CONFIG_VXFS_FS is not set
- +# CONFIG_MINIX_FS is not set
- +# CONFIG_OMFS_FS is not set
- +# CONFIG_HPFS_FS is not set
- +# CONFIG_QNX4FS_FS is not set
- +# CONFIG_ROMFS_FS is not set
- +# CONFIG_SYSV_FS is not set
- +# CONFIG_UFS_FS is not set
- +CONFIG_NETWORK_FILESYSTEMS=y
- +CONFIG_NFS_FS=y
- +CONFIG_NFS_V3=y
- +# CONFIG_NFS_V3_ACL is not set
- +# CONFIG_NFS_V4 is not set
- +# CONFIG_NFSD is not set
- +CONFIG_LOCKD=y
- +CONFIG_LOCKD_V4=y
- +CONFIG_NFS_COMMON=y
- +CONFIG_SUNRPC=y
- +# CONFIG_SUNRPC_REGISTER_V4 is not set
- +# CONFIG_RPCSEC_GSS_KRB5 is not set
- +# CONFIG_RPCSEC_GSS_SPKM3 is not set
- +# CONFIG_SMB_FS is not set
- +# CONFIG_CIFS is not set
- +# CONFIG_NCP_FS is not set
- +# CONFIG_CODA_FS is not set
- +# CONFIG_AFS_FS is not set
- +
- +#
- +# Partition Types
- +#
- +# CONFIG_PARTITION_ADVANCED is not set
- +CONFIG_MSDOS_PARTITION=y
- +CONFIG_NLS=y
- +CONFIG_NLS_DEFAULT="iso8859-1"
- +CONFIG_NLS_CODEPAGE_437=y
- +# CONFIG_NLS_CODEPAGE_737 is not set
- +# CONFIG_NLS_CODEPAGE_775 is not set
- +# CONFIG_NLS_CODEPAGE_850 is not set
- +# CONFIG_NLS_CODEPAGE_852 is not set
- +# CONFIG_NLS_CODEPAGE_855 is not set
- +# CONFIG_NLS_CODEPAGE_857 is not set
- +# CONFIG_NLS_CODEPAGE_860 is not set
- +# CONFIG_NLS_CODEPAGE_861 is not set
- +# CONFIG_NLS_CODEPAGE_862 is not set
- +# CONFIG_NLS_CODEPAGE_863 is not set
- +# CONFIG_NLS_CODEPAGE_864 is not set
- +# CONFIG_NLS_CODEPAGE_865 is not set
- +# CONFIG_NLS_CODEPAGE_866 is not set
- +# CONFIG_NLS_CODEPAGE_869 is not set
- +# CONFIG_NLS_CODEPAGE_936 is not set
- +# CONFIG_NLS_CODEPAGE_950 is not set
- +# CONFIG_NLS_CODEPAGE_932 is not set
- +# CONFIG_NLS_CODEPAGE_949 is not set
- +# CONFIG_NLS_CODEPAGE_874 is not set
- +# CONFIG_NLS_ISO8859_8 is not set
- +# CONFIG_NLS_CODEPAGE_1250 is not set
- +# CONFIG_NLS_CODEPAGE_1251 is not set
- +# CONFIG_NLS_ASCII is not set
- +CONFIG_NLS_ISO8859_1=y
- +# CONFIG_NLS_ISO8859_2 is not set
- +# CONFIG_NLS_ISO8859_3 is not set
- +# CONFIG_NLS_ISO8859_4 is not set
- +# CONFIG_NLS_ISO8859_5 is not set
- +# CONFIG_NLS_ISO8859_6 is not set
- +# CONFIG_NLS_ISO8859_7 is not set
- +# CONFIG_NLS_ISO8859_9 is not set
- +# CONFIG_NLS_ISO8859_13 is not set
- +# CONFIG_NLS_ISO8859_14 is not set
- +# CONFIG_NLS_ISO8859_15 is not set
- +# CONFIG_NLS_KOI8_R is not set
- +# CONFIG_NLS_KOI8_U is not set
- +# CONFIG_NLS_UTF8 is not set
- +# CONFIG_DLM is not set
- +
- +#
- +# Kernel hacking
- +#
- +CONFIG_TRACE_IRQFLAGS_SUPPORT=y
- +# CONFIG_PRINTK_TIME is not set
- +CONFIG_ENABLE_WARN_DEPRECATED=y
- +CONFIG_ENABLE_MUST_CHECK=y
- +CONFIG_FRAME_WARN=1024
- +# CONFIG_MAGIC_SYSRQ is not set
- +# CONFIG_UNUSED_SYMBOLS is not set
- +CONFIG_DEBUG_FS=y
- +# CONFIG_HEADERS_CHECK is not set
- +# CONFIG_DEBUG_KERNEL is not set
- +# CONFIG_SLUB_DEBUG_ON is not set
- +# CONFIG_SLUB_STATS is not set
- +CONFIG_STACKTRACE=y
- +# CONFIG_DEBUG_MEMORY_INIT is not set
- +CONFIG_FRAME_POINTER=y
- +# CONFIG_RCU_CPU_STALL_DETECTOR is not set
- +# CONFIG_LATENCYTOP is not set
- +CONFIG_SYSCTL_SYSCALL_CHECK=y
- +CONFIG_NOP_TRACER=y
- +CONFIG_RING_BUFFER=y
- +CONFIG_TRACING=y
- +
- +#
- +# Tracers
- +#
- +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
- +# CONFIG_SAMPLES is not set
- +CONFIG_HAVE_ARCH_KGDB=y
- +CONFIG_DEBUG_USER=y
- +# CONFIG_CCTL is not set
- +CONFIG_ELFCHK_DEFAULT_ENABLE=y
- +
- +#
- +# Security options
- +#
- +# CONFIG_KEYS is not set
- +# CONFIG_SECURITY is not set
- +# CONFIG_SECURITYFS is not set
- +# CONFIG_SECURITY_FILE_CAPABILITIES is not set
- +CONFIG_CRYPTO=y
- +
- +#
- +# Crypto core or helper
- +#
- +# CONFIG_CRYPTO_FIPS is not set
- +# CONFIG_CRYPTO_MANAGER is not set
- +# CONFIG_CRYPTO_MANAGER2 is not set
- +# CONFIG_CRYPTO_GF128MUL is not set
- +# CONFIG_CRYPTO_NULL is not set
- +# CONFIG_CRYPTO_CRYPTD is not set
- +# CONFIG_CRYPTO_AUTHENC is not set
- +# CONFIG_CRYPTO_TEST is not set
- +
- +#
- +# Authenticated Encryption with Associated Data
- +#
- +# CONFIG_CRYPTO_CCM is not set
- +# CONFIG_CRYPTO_GCM is not set
- +# CONFIG_CRYPTO_SEQIV is not set
- +
- +#
- +# Block modes
- +#
- +# CONFIG_CRYPTO_CBC is not set
- +# CONFIG_CRYPTO_CTR is not set
- +# CONFIG_CRYPTO_CTS is not set
- +# CONFIG_CRYPTO_ECB is not set
- +# CONFIG_CRYPTO_LRW is not set
- +# CONFIG_CRYPTO_PCBC is not set
- +# CONFIG_CRYPTO_XTS is not set
- +
- +#
- +# Hash modes
- +#
- +# CONFIG_CRYPTO_HMAC is not set
- +# CONFIG_CRYPTO_XCBC is not set
- +
- +#
- +# Digest
- +#
- +# CONFIG_CRYPTO_CRC32C is not set
- +# CONFIG_CRYPTO_MD4 is not set
- +# CONFIG_CRYPTO_MD5 is not set
- +# CONFIG_CRYPTO_MICHAEL_MIC is not set
- +# CONFIG_CRYPTO_RMD128 is not set
- +# CONFIG_CRYPTO_RMD160 is not set
- +# CONFIG_CRYPTO_RMD256 is not set
- +# CONFIG_CRYPTO_RMD320 is not set
- +# CONFIG_CRYPTO_SHA1 is not set
- +# CONFIG_CRYPTO_SHA256 is not set
- +# CONFIG_CRYPTO_SHA512 is not set
- +# CONFIG_CRYPTO_TGR192 is not set
- +# CONFIG_CRYPTO_WP512 is not set
- +
- +#
- +# Ciphers
- +#
- +# CONFIG_CRYPTO_AES is not set
- +# CONFIG_CRYPTO_ANUBIS is not set
- +# CONFIG_CRYPTO_ARC4 is not set
- +# CONFIG_CRYPTO_BLOWFISH is not set
- +# CONFIG_CRYPTO_CAMELLIA is not set
- +# CONFIG_CRYPTO_CAST5 is not set
- +# CONFIG_CRYPTO_CAST6 is not set
- +# CONFIG_CRYPTO_DES is not set
- +# CONFIG_CRYPTO_FCRYPT is not set
- +# CONFIG_CRYPTO_KHAZAD is not set
- +# CONFIG_CRYPTO_SALSA20 is not set
- +# CONFIG_CRYPTO_SEED is not set
- +# CONFIG_CRYPTO_SERPENT is not set
- +# CONFIG_CRYPTO_TEA is not set
- +# CONFIG_CRYPTO_TWOFISH is not set
- +
- +#
- +# Compression
- +#
- +# CONFIG_CRYPTO_DEFLATE is not set
- +# CONFIG_CRYPTO_LZO is not set
- +
- +#
- +# Random Number Generation
- +#
- +# CONFIG_CRYPTO_ANSI_CPRNG is not set
- +# CONFIG_CRYPTO_HW is not set
- +
- +#
- +# Library routines
- +#
- +CONFIG_GENERIC_FIND_LAST_BIT=y
- +# CONFIG_CRC_CCITT is not set
- +# CONFIG_CRC16 is not set
- +# CONFIG_CRC_T10DIF is not set
- +# CONFIG_CRC_ITU_T is not set
- +# CONFIG_CRC32 is not set
- +# CONFIG_CRC7 is not set
- +# CONFIG_LIBCRC32C is not set
- +CONFIG_PLIST=y
- +CONFIG_HAS_IOMEM=y
- +CONFIG_HAS_DMA=y
- diff -Nur linux-3.4.110.orig/arch/nds32/configs/vep-le_defconfig linux-3.4.110/arch/nds32/configs/vep-le_defconfig
- --- linux-3.4.110.orig/arch/nds32/configs/vep-le_defconfig 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/configs/vep-le_defconfig 2016-04-07 10:20:50.882078703 +0200
- @@ -0,0 +1,777 @@
- +#
- +# Automatically generated make config: don't edit
- +# Linux kernel version: 2.6.29
- +# Mon Jul 13 11:41:30 2009
- +#
- +CONFIG_NDS32=y
- +CONFIG_NO_IOPORT=y
- +CONFIG_GENERIC_IOMAP=y
- +CONFIG_RWSEM_GENERIC_SPINLOCK=y
- +CONFIG_GENERIC_HWEIGHT=y
- +CONFIG_GENERIC_FIND_NEXT_BIT=y
- +CONFIG_GENERIC_CALIBRATE_DELAY=y
- +CONFIG_GENERIC_HARDIRQS=y
- +CONFIG_LOCKDEP_SUPPORT=y
- +CONFIG_STACKTRACE_SUPPORT=y
- +CONFIG_HAVE_LATENCYTOP_SUPPORT=y
- +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
- +
- +#
- +# General setup
- +#
- +CONFIG_EXPERIMENTAL=y
- +CONFIG_BROKEN_ON_SMP=y
- +CONFIG_INIT_ENV_ARG_LIMIT=32
- +CONFIG_LOCALVERSION=""
- +# CONFIG_LOCALVERSION_AUTO is not set
- +CONFIG_SWAP=y
- +CONFIG_SYSVIPC=y
- +CONFIG_SYSVIPC_SYSCTL=y
- +# CONFIG_POSIX_MQUEUE is not set
- +CONFIG_BSD_PROCESS_ACCT=y
- +CONFIG_BSD_PROCESS_ACCT_V3=y
- +# CONFIG_TASKSTATS is not set
- +# CONFIG_AUDIT is not set
- +
- +#
- +# RCU Subsystem
- +#
- +CONFIG_CLASSIC_RCU=y
- +# CONFIG_TREE_RCU is not set
- +# CONFIG_PREEMPT_RCU is not set
- +# CONFIG_TREE_RCU_TRACE is not set
- +# CONFIG_PREEMPT_RCU_TRACE is not set
- +# CONFIG_IKCONFIG is not set
- +CONFIG_LOG_BUF_SHIFT=14
- +# CONFIG_GROUP_SCHED is not set
- +# CONFIG_CGROUPS is not set
- +# CONFIG_SYSFS_DEPRECATED_V2 is not set
- +# CONFIG_RELAY is not set
- +# CONFIG_NAMESPACES is not set
- +CONFIG_BLK_DEV_INITRD=y
- +CONFIG_INITRAMFS_SOURCE=""
- +CONFIG_CC_OPTIMIZE_FOR_SIZE=y
- +CONFIG_SYSCTL=y
- +CONFIG_ANON_INODES=y
- +CONFIG_EMBEDDED=y
- +CONFIG_UID16=y
- +CONFIG_SYSCTL_SYSCALL=y
- +# CONFIG_KALLSYMS is not set
- +# CONFIG_HOTPLUG is not set
- +CONFIG_PRINTK=y
- +CONFIG_BUG=y
- +# CONFIG_ELF_CORE is not set
- +CONFIG_BASE_FULL=y
- +CONFIG_FUTEX=y
- +CONFIG_EPOLL=y
- +# CONFIG_SIGNALFD is not set
- +CONFIG_TIMERFD=y
- +CONFIG_EVENTFD=y
- +CONFIG_SHMEM=y
- +CONFIG_AIO=y
- +# CONFIG_VM_EVENT_COUNTERS is not set
- +CONFIG_SLUB_DEBUG=y
- +CONFIG_COMPAT_BRK=y
- +# CONFIG_SLAB is not set
- +CONFIG_SLUB=y
- +# CONFIG_SLOB is not set
- +CONFIG_PROFILING=y
- +CONFIG_TRACEPOINTS=y
- +# CONFIG_MARKERS is not set
- +CONFIG_OPROFILE=y
- +CONFIG_HAVE_OPROFILE=y
- +CONFIG_HAVE_KPROBES=y
- +CONFIG_HAVE_KRETPROBES=y
- +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
- +CONFIG_SLABINFO=y
- +CONFIG_RT_MUTEXES=y
- +CONFIG_BASE_SMALL=0
- +CONFIG_MODULES=y
- +# CONFIG_MODULE_FORCE_LOAD is not set
- +CONFIG_MODULE_UNLOAD=y
- +# CONFIG_MODULE_FORCE_UNLOAD is not set
- +# CONFIG_MODVERSIONS is not set
- +# CONFIG_MODULE_SRCVERSION_ALL is not set
- +CONFIG_BLOCK=y
- +# CONFIG_LBD is not set
- +# CONFIG_BLK_DEV_IO_TRACE is not set
- +# CONFIG_BLK_DEV_BSG is not set
- +# CONFIG_BLK_DEV_INTEGRITY is not set
- +
- +#
- +# IO Schedulers
- +#
- +CONFIG_IOSCHED_NOOP=y
- +# CONFIG_IOSCHED_AS is not set
- +# CONFIG_IOSCHED_DEADLINE is not set
- +# CONFIG_IOSCHED_CFQ is not set
- +# CONFIG_DEFAULT_AS is not set
- +# CONFIG_DEFAULT_DEADLINE is not set
- +# CONFIG_DEFAULT_CFQ is not set
- +CONFIG_DEFAULT_NOOP=y
- +CONFIG_DEFAULT_IOSCHED="noop"
- +# CONFIG_FREEZER is not set
- +
- +#
- +# System Type
- +#
- +# CONFIG_PLAT_FARADAY is not set
- +CONFIG_PLAT_VEP=y
- +# CONFIG_PLAT_AG101 is not set
- +# CONFIG_PLAT_AG102 is not set
- +# CONFIG_PLAT_AG101P is not set
- +# CONFIG_PLAT_QEMU is not set
- +CONFIG_PLATFORM_INTC=y
- +
- +#
- +# VEP Platform Options
- +#
- +# CONFIG_CACHE_L2 is not set
- +
- +#
- +# Common Platform Options
- +#
- +# CONFIG_PLATFORM_AHBDMA is not set
- +# CONFIG_PLATFORM_APBDMA is not set
- +CONFIG_SYS_CLK=67737600
- +CONFIG_UART_CLK=36864000
- +CONFIG_SDRAM_SIZE=0x10000000
- +
- +#
- +# Processor Features
- +#
- +CONFIG_CPU_CUSTOM=y
- +# CONFIG_FPU is not set
- +# CONFIG_AUDIO is not set
- +# CONFIG_EVIC is not set
- +CONFIG_CPU_CONTEXT_ID=y
- +CONFIG_ANDES_PAGE_SIZE_4KB=y
- +# CONFIG_ANDES_PAGE_SIZE_8KB is not set
- +# CONFIG_KERNEL_SPACE_LARGE_PAGE is not set
- +# CONFIG_CPU_ICACHE_DISABLE is not set
- +# CONFIG_CPU_DCACHE_DISABLE is not set
- +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
- +# CONFIG_ALIGNMENT_TRAP is not set
- +CONFIG_MMU=y
- +
- +#
- +# Kernel Features
- +#
- +CONFIG_PREEMPT_NONE=y
- +# CONFIG_PREEMPT_VOLUNTARY is not set
- +# CONFIG_PREEMPT is not set
- +CONFIG_SELECT_MEMORY_MODEL=y
- +CONFIG_FLATMEM_MANUAL=y
- +# CONFIG_DISCONTIGMEM_MANUAL is not set
- +# CONFIG_SPARSEMEM_MANUAL is not set
- +CONFIG_FLATMEM=y
- +CONFIG_FLAT_NODE_MEM_MAP=y
- +CONFIG_PAGEFLAGS_EXTENDED=y
- +CONFIG_SPLIT_PTLOCK_CPUS=4
- +# CONFIG_PHYS_ADDR_T_64BIT is not set
- +CONFIG_ZONE_DMA_FLAG=0
- +CONFIG_VIRT_TO_BUS=y
- +CONFIG_UNEVICTABLE_LRU=y
- +CONFIG_FORCE_MAX_ZONEORDER=11
- +CONFIG_HZ_100=y
- +# CONFIG_HZ_250 is not set
- +# CONFIG_HZ_300 is not set
- +# CONFIG_HZ_1000 is not set
- +CONFIG_HZ=100
- +# CONFIG_SCHED_HRTICK is not set
- +CONFIG_CMDLINE="root=/dev/ram0 rw mem=64M@0x0 initrd=0x1000000,8M console=ttyS0,38400n8 rootfstype=ext2 init=/bin/busybox init -s user_debug=-1"
- +
- +#
- +# Power management options
- +#
- +CONFIG_SYS_SUPPORTS_APM_EMULATION=y
- +CONFIG_ARCH_SUSPEND_POSSIBLE=y
- +# CONFIG_PM is not set
- +
- +#
- +# Bus options
- +#
- +# CONFIG_PCI is not set
- +# CONFIG_ARCH_SUPPORTS_MSI is not set
- +
- +#
- +# Executable file formats
- +#
- +CONFIG_BINFMT_ELF=y
- +# CONFIG_HAVE_AOUT is not set
- +# CONFIG_BINFMT_MISC is not set
- +CONFIG_NET=y
- +
- +#
- +# Networking options
- +#
- +CONFIG_COMPAT_NET_DEV_OPS=y
- +CONFIG_PACKET=y
- +# CONFIG_PACKET_MMAP is not set
- +CONFIG_UNIX=y
- +CONFIG_XFRM=y
- +# CONFIG_XFRM_USER is not set
- +# CONFIG_XFRM_SUB_POLICY is not set
- +# CONFIG_XFRM_MIGRATE is not set
- +# CONFIG_XFRM_STATISTICS is not set
- +CONFIG_NET_KEY=y
- +# CONFIG_NET_KEY_MIGRATE is not set
- +CONFIG_INET=y
- +CONFIG_IP_MULTICAST=y
- +# CONFIG_IP_ADVANCED_ROUTER is not set
- +CONFIG_IP_FIB_HASH=y
- +# CONFIG_IP_PNP is not set
- +# CONFIG_NET_IPIP is not set
- +# CONFIG_NET_IPGRE is not set
- +# CONFIG_IP_MROUTE is not set
- +# CONFIG_ARPD is not set
- +# CONFIG_SYN_COOKIES is not set
- +# CONFIG_INET_AH is not set
- +# CONFIG_INET_ESP is not set
- +# CONFIG_INET_IPCOMP is not set
- +# CONFIG_INET_XFRM_TUNNEL is not set
- +# CONFIG_INET_TUNNEL is not set
- +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
- +# CONFIG_INET_XFRM_MODE_TUNNEL is not set
- +# CONFIG_INET_XFRM_MODE_BEET is not set
- +# CONFIG_INET_LRO is not set
- +# CONFIG_INET_DIAG is not set
- +# CONFIG_TCP_CONG_ADVANCED is not set
- +CONFIG_TCP_CONG_CUBIC=y
- +CONFIG_DEFAULT_TCP_CONG="cubic"
- +# CONFIG_TCP_MD5SIG is not set
- +# CONFIG_IPV6 is not set
- +# CONFIG_NETWORK_SECMARK is not set
- +# CONFIG_NETFILTER is not set
- +# CONFIG_IP_DCCP is not set
- +# CONFIG_IP_SCTP is not set
- +# CONFIG_TIPC is not set
- +# CONFIG_ATM is not set
- +# CONFIG_BRIDGE is not set
- +# CONFIG_NET_DSA is not set
- +# CONFIG_VLAN_8021Q is not set
- +# CONFIG_DECNET is not set
- +# CONFIG_LLC2 is not set
- +# CONFIG_IPX is not set
- +# CONFIG_ATALK is not set
- +# CONFIG_X25 is not set
- +# CONFIG_LAPB is not set
- +# CONFIG_ECONET is not set
- +# CONFIG_WAN_ROUTER is not set
- +# CONFIG_NET_SCHED is not set
- +# CONFIG_DCB is not set
- +
- +#
- +# Network testing
- +#
- +# CONFIG_NET_PKTGEN is not set
- +# CONFIG_HAMRADIO is not set
- +# CONFIG_CAN is not set
- +# CONFIG_IRDA is not set
- +# CONFIG_BT is not set
- +# CONFIG_AF_RXRPC is not set
- +# CONFIG_PHONET is not set
- +CONFIG_WIRELESS=y
- +# CONFIG_CFG80211 is not set
- +CONFIG_WIRELESS_OLD_REGULATORY=y
- +# CONFIG_WIRELESS_EXT is not set
- +# CONFIG_LIB80211 is not set
- +# CONFIG_MAC80211 is not set
- +# CONFIG_WIMAX is not set
- +# CONFIG_RFKILL is not set
- +# CONFIG_NET_9P is not set
- +
- +#
- +# Device Drivers
- +#
- +
- +#
- +# Generic Driver Options
- +#
- +CONFIG_STANDALONE=y
- +CONFIG_PREVENT_FIRMWARE_BUILD=y
- +# CONFIG_SYS_HYPERVISOR is not set
- +# CONFIG_CONNECTOR is not set
- +# CONFIG_MTD is not set
- +# CONFIG_PARPORT is not set
- +CONFIG_BLK_DEV=y
- +# CONFIG_BLK_DEV_COW_COMMON is not set
- +CONFIG_BLK_DEV_LOOP=y
- +# CONFIG_BLK_DEV_CRYPTOLOOP is not set
- +# CONFIG_BLK_DEV_NBD is not set
- +CONFIG_BLK_DEV_RAM=y
- +CONFIG_BLK_DEV_RAM_COUNT=16
- +CONFIG_BLK_DEV_RAM_SIZE=8192
- +# CONFIG_BLK_DEV_XIP is not set
- +# CONFIG_CDROM_PKTCDVD is not set
- +# CONFIG_ATA_OVER_ETH is not set
- +# CONFIG_FTSDC010 is not set
- +# CONFIG_FTCFC010 is not set
- +# CONFIG_BLK_DEV_HD is not set
- +# CONFIG_MISC_DEVICES is not set
- +CONFIG_HAVE_IDE=y
- +# CONFIG_IDE is not set
- +
- +#
- +# SCSI device support
- +#
- +# CONFIG_RAID_ATTRS is not set
- +# CONFIG_SCSI is not set
- +# CONFIG_SCSI_DMA is not set
- +# CONFIG_SCSI_NETLINK is not set
- +# CONFIG_ATA is not set
- +# CONFIG_MD is not set
- +CONFIG_NETDEVICES=y
- +# CONFIG_DUMMY is not set
- +# CONFIG_BONDING is not set
- +# CONFIG_MACVLAN is not set
- +# CONFIG_EQUALIZER is not set
- +# CONFIG_TUN is not set
- +# CONFIG_VETH is not set
- +# CONFIG_PHYLIB is not set
- +CONFIG_NET_ETHERNET=y
- +# CONFIG_MII is not set
- +# CONFIG_SMC91X is not set
- +# CONFIG_DNET is not set
- +# CONFIG_IBM_NEW_EMAC_ZMII is not set
- +# CONFIG_IBM_NEW_EMAC_RGMII is not set
- +# CONFIG_IBM_NEW_EMAC_TAH is not set
- +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
- +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
- +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
- +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
- +# CONFIG_B44 is not set
- +CONFIG_FTMAC100=y
- +# CONFIG_NETDEV_1000 is not set
- +# CONFIG_NETDEV_10000 is not set
- +
- +#
- +# Wireless LAN
- +#
- +# CONFIG_WLAN_PRE80211 is not set
- +# CONFIG_WLAN_80211 is not set
- +# CONFIG_IWLWIFI_LEDS is not set
- +
- +#
- +# Enable WiMAX (Networking options) to see the WiMAX drivers
- +#
- +# CONFIG_WAN is not set
- +# CONFIG_PPP is not set
- +# CONFIG_SLIP is not set
- +# CONFIG_NETCONSOLE is not set
- +# CONFIG_NETPOLL is not set
- +# CONFIG_NET_POLL_CONTROLLER is not set
- +# CONFIG_ISDN is not set
- +# CONFIG_PHONE is not set
- +
- +#
- +# Input device support
- +#
- +CONFIG_INPUT=y
- +# CONFIG_INPUT_FF_MEMLESS is not set
- +# CONFIG_INPUT_POLLDEV is not set
- +
- +#
- +# Userland interfaces
- +#
- +# CONFIG_INPUT_MOUSEDEV is not set
- +# CONFIG_INPUT_JOYDEV is not set
- +# CONFIG_INPUT_EVDEV is not set
- +# CONFIG_INPUT_EVBUG is not set
- +
- +#
- +# Input Device Drivers
- +#
- +# CONFIG_INPUT_KEYBOARD is not set
- +# CONFIG_INPUT_MOUSE is not set
- +# CONFIG_INPUT_JOYSTICK is not set
- +# CONFIG_INPUT_TABLET is not set
- +# CONFIG_INPUT_TOUCHSCREEN is not set
- +# CONFIG_INPUT_MISC is not set
- +
- +#
- +# Hardware I/O ports
- +#
- +# CONFIG_SERIO is not set
- +# CONFIG_GAMEPORT is not set
- +
- +#
- +# Character devices
- +#
- +CONFIG_VT=y
- +CONFIG_CONSOLE_TRANSLATIONS=y
- +CONFIG_VT_CONSOLE=y
- +CONFIG_HW_CONSOLE=y
- +# CONFIG_VT_HW_CONSOLE_BINDING is not set
- +CONFIG_DEVKMEM=y
- +# CONFIG_SERIAL_NONSTANDARD is not set
- +
- +#
- +# Serial drivers
- +#
- +CONFIG_SERIAL_8250=y
- +CONFIG_SERIAL_8250_CONSOLE=y
- +CONFIG_SERIAL_8250_NR_UARTS=3
- +CONFIG_SERIAL_8250_RUNTIME_UARTS=3
- +# CONFIG_SERIAL_8250_EXTENDED is not set
- +
- +#
- +# Non-8250 serial port support
- +#
- +CONFIG_SERIAL_CORE=y
- +CONFIG_SERIAL_CORE_CONSOLE=y
- +CONFIG_UNIX98_PTYS=y
- +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
- +CONFIG_LEGACY_PTYS=y
- +CONFIG_LEGACY_PTY_COUNT=256
- +# CONFIG_IPMI_HANDLER is not set
- +# CONFIG_HW_RANDOM is not set
- +# CONFIG_R3964 is not set
- +# CONFIG_GPIO_FTGPIO010 is not set
- +# CONFIG_RAW_DRIVER is not set
- +# CONFIG_TCG_TPM is not set
- +# CONFIG_I2C is not set
- +# CONFIG_SPI is not set
- +# CONFIG_W1 is not set
- +# CONFIG_POWER_SUPPLY is not set
- +# CONFIG_HWMON is not set
- +# CONFIG_THERMAL is not set
- +# CONFIG_THERMAL_HWMON is not set
- +# CONFIG_WATCHDOG is not set
- +CONFIG_SSB_POSSIBLE=y
- +
- +#
- +# Sonics Silicon Backplane
- +#
- +# CONFIG_SSB is not set
- +
- +#
- +# Multifunction device drivers
- +#
- +# CONFIG_MFD_CORE is not set
- +# CONFIG_MFD_SM501 is not set
- +# CONFIG_HTC_PASIC3 is not set
- +# CONFIG_MFD_TMIO is not set
- +# CONFIG_REGULATOR is not set
- +
- +#
- +# Multimedia devices
- +#
- +
- +#
- +# Multimedia core support
- +#
- +# CONFIG_VIDEO_DEV is not set
- +# CONFIG_DVB_CORE is not set
- +# CONFIG_VIDEO_MEDIA is not set
- +
- +#
- +# Multimedia drivers
- +#
- +# CONFIG_DAB is not set
- +
- +#
- +# Graphics support
- +#
- +# CONFIG_VGASTATE is not set
- +# CONFIG_VIDEO_OUTPUT_CONTROL is not set
- +# CONFIG_FB is not set
- +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
- +
- +#
- +# Display device support
- +#
- +# CONFIG_DISPLAY_SUPPORT is not set
- +
- +#
- +# Console display driver support
- +#
- +# CONFIG_VGA_CONSOLE is not set
- +CONFIG_DUMMY_CONSOLE=y
- +# CONFIG_SOUND is not set
- +# CONFIG_HID_SUPPORT is not set
- +# CONFIG_USB_SUPPORT is not set
- +# CONFIG_MMC is not set
- +# CONFIG_MEMSTICK is not set
- +# CONFIG_NEW_LEDS is not set
- +# CONFIG_ACCESSIBILITY is not set
- +CONFIG_RTC_LIB=y
- +# CONFIG_RTC_CLASS is not set
- +# CONFIG_DMADEVICES is not set
- +# CONFIG_UIO is not set
- +# CONFIG_STAGING is not set
- +
- +#
- +# File systems
- +#
- +CONFIG_EXT2_FS=y
- +# CONFIG_EXT2_FS_XATTR is not set
- +# CONFIG_EXT2_FS_XIP is not set
- +# CONFIG_EXT3_FS is not set
- +# CONFIG_EXT4_FS is not set
- +# CONFIG_REISERFS_FS is not set
- +# CONFIG_JFS_FS is not set
- +# CONFIG_FS_POSIX_ACL is not set
- +CONFIG_FILE_LOCKING=y
- +# CONFIG_XFS_FS is not set
- +# CONFIG_OCFS2_FS is not set
- +# CONFIG_BTRFS_FS is not set
- +CONFIG_DNOTIFY=y
- +CONFIG_INOTIFY=y
- +CONFIG_INOTIFY_USER=y
- +# CONFIG_QUOTA is not set
- +# CONFIG_AUTOFS_FS is not set
- +# CONFIG_AUTOFS4_FS is not set
- +CONFIG_FUSE_FS=y
- +
- +#
- +# CD-ROM/DVD Filesystems
- +#
- +# CONFIG_ISO9660_FS is not set
- +# CONFIG_UDF_FS is not set
- +
- +#
- +# DOS/FAT/NT Filesystems
- +#
- +# CONFIG_MSDOS_FS is not set
- +# CONFIG_VFAT_FS is not set
- +# CONFIG_NTFS_FS is not set
- +
- +#
- +# Pseudo filesystems
- +#
- +CONFIG_PROC_FS=y
- +# CONFIG_PROC_KCORE is not set
- +CONFIG_PROC_SYSCTL=y
- +# CONFIG_PROC_PAGE_MONITOR is not set
- +CONFIG_SYSFS=y
- +CONFIG_TMPFS=y
- +# CONFIG_TMPFS_POSIX_ACL is not set
- +# CONFIG_HUGETLB_PAGE is not set
- +# CONFIG_CONFIGFS_FS is not set
- +CONFIG_MISC_FILESYSTEMS=y
- +# CONFIG_ADFS_FS is not set
- +# CONFIG_AFFS_FS is not set
- +# CONFIG_HFS_FS is not set
- +# CONFIG_HFSPLUS_FS is not set
- +# CONFIG_BEFS_FS is not set
- +# CONFIG_BFS_FS is not set
- +# CONFIG_EFS_FS is not set
- +# CONFIG_CRAMFS is not set
- +# CONFIG_SQUASHFS is not set
- +# CONFIG_VXFS_FS is not set
- +# CONFIG_MINIX_FS is not set
- +# CONFIG_OMFS_FS is not set
- +# CONFIG_HPFS_FS is not set
- +# CONFIG_QNX4FS_FS is not set
- +# CONFIG_ROMFS_FS is not set
- +# CONFIG_SYSV_FS is not set
- +# CONFIG_UFS_FS is not set
- +CONFIG_NETWORK_FILESYSTEMS=y
- +CONFIG_NFS_FS=y
- +CONFIG_NFS_V3=y
- +# CONFIG_NFS_V3_ACL is not set
- +# CONFIG_NFS_V4 is not set
- +# CONFIG_NFSD is not set
- +CONFIG_LOCKD=y
- +CONFIG_LOCKD_V4=y
- +CONFIG_NFS_COMMON=y
- +CONFIG_SUNRPC=y
- +# CONFIG_SUNRPC_REGISTER_V4 is not set
- +# CONFIG_RPCSEC_GSS_KRB5 is not set
- +# CONFIG_RPCSEC_GSS_SPKM3 is not set
- +# CONFIG_SMB_FS is not set
- +# CONFIG_CIFS is not set
- +# CONFIG_NCP_FS is not set
- +# CONFIG_CODA_FS is not set
- +# CONFIG_AFS_FS is not set
- +
- +#
- +# Partition Types
- +#
- +# CONFIG_PARTITION_ADVANCED is not set
- +CONFIG_MSDOS_PARTITION=y
- +CONFIG_NLS=y
- +CONFIG_NLS_DEFAULT="iso8859-1"
- +CONFIG_NLS_CODEPAGE_437=y
- +# CONFIG_NLS_CODEPAGE_737 is not set
- +# CONFIG_NLS_CODEPAGE_775 is not set
- +# CONFIG_NLS_CODEPAGE_850 is not set
- +# CONFIG_NLS_CODEPAGE_852 is not set
- +# CONFIG_NLS_CODEPAGE_855 is not set
- +# CONFIG_NLS_CODEPAGE_857 is not set
- +# CONFIG_NLS_CODEPAGE_860 is not set
- +# CONFIG_NLS_CODEPAGE_861 is not set
- +# CONFIG_NLS_CODEPAGE_862 is not set
- +# CONFIG_NLS_CODEPAGE_863 is not set
- +# CONFIG_NLS_CODEPAGE_864 is not set
- +# CONFIG_NLS_CODEPAGE_865 is not set
- +# CONFIG_NLS_CODEPAGE_866 is not set
- +# CONFIG_NLS_CODEPAGE_869 is not set
- +# CONFIG_NLS_CODEPAGE_936 is not set
- +# CONFIG_NLS_CODEPAGE_950 is not set
- +# CONFIG_NLS_CODEPAGE_932 is not set
- +# CONFIG_NLS_CODEPAGE_949 is not set
- +# CONFIG_NLS_CODEPAGE_874 is not set
- +# CONFIG_NLS_ISO8859_8 is not set
- +# CONFIG_NLS_CODEPAGE_1250 is not set
- +# CONFIG_NLS_CODEPAGE_1251 is not set
- +# CONFIG_NLS_ASCII is not set
- +CONFIG_NLS_ISO8859_1=y
- +# CONFIG_NLS_ISO8859_2 is not set
- +# CONFIG_NLS_ISO8859_3 is not set
- +# CONFIG_NLS_ISO8859_4 is not set
- +# CONFIG_NLS_ISO8859_5 is not set
- +# CONFIG_NLS_ISO8859_6 is not set
- +# CONFIG_NLS_ISO8859_7 is not set
- +# CONFIG_NLS_ISO8859_9 is not set
- +# CONFIG_NLS_ISO8859_13 is not set
- +# CONFIG_NLS_ISO8859_14 is not set
- +# CONFIG_NLS_ISO8859_15 is not set
- +# CONFIG_NLS_KOI8_R is not set
- +# CONFIG_NLS_KOI8_U is not set
- +# CONFIG_NLS_UTF8 is not set
- +# CONFIG_DLM is not set
- +
- +#
- +# Kernel hacking
- +#
- +CONFIG_TRACE_IRQFLAGS_SUPPORT=y
- +# CONFIG_PRINTK_TIME is not set
- +CONFIG_ENABLE_WARN_DEPRECATED=y
- +CONFIG_ENABLE_MUST_CHECK=y
- +CONFIG_FRAME_WARN=1024
- +# CONFIG_MAGIC_SYSRQ is not set
- +# CONFIG_UNUSED_SYMBOLS is not set
- +CONFIG_DEBUG_FS=y
- +# CONFIG_HEADERS_CHECK is not set
- +# CONFIG_DEBUG_KERNEL is not set
- +# CONFIG_SLUB_DEBUG_ON is not set
- +# CONFIG_SLUB_STATS is not set
- +CONFIG_STACKTRACE=y
- +# CONFIG_DEBUG_MEMORY_INIT is not set
- +CONFIG_FRAME_POINTER=y
- +# CONFIG_RCU_CPU_STALL_DETECTOR is not set
- +# CONFIG_LATENCYTOP is not set
- +CONFIG_SYSCTL_SYSCALL_CHECK=y
- +CONFIG_NOP_TRACER=y
- +CONFIG_RING_BUFFER=y
- +CONFIG_TRACING=y
- +
- +#
- +# Tracers
- +#
- +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
- +# CONFIG_SAMPLES is not set
- +CONFIG_HAVE_ARCH_KGDB=y
- +CONFIG_DEBUG_USER=y
- +# CONFIG_CCTL is not set
- +CONFIG_ELFCHK_DEFAULT_ENABLE=y
- +
- +#
- +# Security options
- +#
- +# CONFIG_KEYS is not set
- +# CONFIG_SECURITY is not set
- +# CONFIG_SECURITYFS is not set
- +# CONFIG_SECURITY_FILE_CAPABILITIES is not set
- +CONFIG_CRYPTO=y
- +
- +#
- +# Crypto core or helper
- +#
- +# CONFIG_CRYPTO_FIPS is not set
- +# CONFIG_CRYPTO_MANAGER is not set
- +# CONFIG_CRYPTO_MANAGER2 is not set
- +# CONFIG_CRYPTO_GF128MUL is not set
- +# CONFIG_CRYPTO_NULL is not set
- +# CONFIG_CRYPTO_CRYPTD is not set
- +# CONFIG_CRYPTO_AUTHENC is not set
- +# CONFIG_CRYPTO_TEST is not set
- +
- +#
- +# Authenticated Encryption with Associated Data
- +#
- +# CONFIG_CRYPTO_CCM is not set
- +# CONFIG_CRYPTO_GCM is not set
- +# CONFIG_CRYPTO_SEQIV is not set
- +
- +#
- +# Block modes
- +#
- +# CONFIG_CRYPTO_CBC is not set
- +# CONFIG_CRYPTO_CTR is not set
- +# CONFIG_CRYPTO_CTS is not set
- +# CONFIG_CRYPTO_ECB is not set
- +# CONFIG_CRYPTO_LRW is not set
- +# CONFIG_CRYPTO_PCBC is not set
- +# CONFIG_CRYPTO_XTS is not set
- +
- +#
- +# Hash modes
- +#
- +# CONFIG_CRYPTO_HMAC is not set
- +# CONFIG_CRYPTO_XCBC is not set
- +
- +#
- +# Digest
- +#
- +# CONFIG_CRYPTO_CRC32C is not set
- +# CONFIG_CRYPTO_MD4 is not set
- +# CONFIG_CRYPTO_MD5 is not set
- +# CONFIG_CRYPTO_MICHAEL_MIC is not set
- +# CONFIG_CRYPTO_RMD128 is not set
- +# CONFIG_CRYPTO_RMD160 is not set
- +# CONFIG_CRYPTO_RMD256 is not set
- +# CONFIG_CRYPTO_RMD320 is not set
- +# CONFIG_CRYPTO_SHA1 is not set
- +# CONFIG_CRYPTO_SHA256 is not set
- +# CONFIG_CRYPTO_SHA512 is not set
- +# CONFIG_CRYPTO_TGR192 is not set
- +# CONFIG_CRYPTO_WP512 is not set
- +
- +#
- +# Ciphers
- +#
- +# CONFIG_CRYPTO_AES is not set
- +# CONFIG_CRYPTO_ANUBIS is not set
- +# CONFIG_CRYPTO_ARC4 is not set
- +# CONFIG_CRYPTO_BLOWFISH is not set
- +# CONFIG_CRYPTO_CAMELLIA is not set
- +# CONFIG_CRYPTO_CAST5 is not set
- +# CONFIG_CRYPTO_CAST6 is not set
- +# CONFIG_CRYPTO_DES is not set
- +# CONFIG_CRYPTO_FCRYPT is not set
- +# CONFIG_CRYPTO_KHAZAD is not set
- +# CONFIG_CRYPTO_SALSA20 is not set
- +# CONFIG_CRYPTO_SEED is not set
- +# CONFIG_CRYPTO_SERPENT is not set
- +# CONFIG_CRYPTO_TEA is not set
- +# CONFIG_CRYPTO_TWOFISH is not set
- +
- +#
- +# Compression
- +#
- +# CONFIG_CRYPTO_DEFLATE is not set
- +# CONFIG_CRYPTO_LZO is not set
- +
- +#
- +# Random Number Generation
- +#
- +# CONFIG_CRYPTO_ANSI_CPRNG is not set
- +# CONFIG_CRYPTO_HW is not set
- +
- +#
- +# Library routines
- +#
- +CONFIG_GENERIC_FIND_LAST_BIT=y
- +# CONFIG_CRC_CCITT is not set
- +# CONFIG_CRC16 is not set
- +# CONFIG_CRC_T10DIF is not set
- +# CONFIG_CRC_ITU_T is not set
- +# CONFIG_CRC32 is not set
- +# CONFIG_CRC7 is not set
- +# CONFIG_LIBCRC32C is not set
- +CONFIG_PLIST=y
- +CONFIG_HAS_IOMEM=y
- +CONFIG_HAS_DMA=y
- diff -Nur linux-3.4.110.orig/arch/nds32/configs/xc5_8k_defconfig linux-3.4.110/arch/nds32/configs/xc5_8k_defconfig
- --- linux-3.4.110.orig/arch/nds32/configs/xc5_8k_defconfig 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/configs/xc5_8k_defconfig 2016-04-07 10:20:50.882078703 +0200
- @@ -0,0 +1,1051 @@
- +#
- +# Automatically generated make config: don't edit
- +# Linux kernel version: 2.6.29
- +# Fri Oct 2 14:21:05 2009
- +#
- +CONFIG_NDS32=y
- +# CONFIG_GENERIC_GPIO is not set
- +CONFIG_NO_IOPORT=y
- +CONFIG_GENERIC_IOMAP=y
- +CONFIG_RWSEM_GENERIC_SPINLOCK=y
- +CONFIG_GENERIC_HWEIGHT=y
- +CONFIG_GENERIC_FIND_NEXT_BIT=y
- +CONFIG_GENERIC_CALIBRATE_DELAY=y
- +CONFIG_GENERIC_HARDIRQS=y
- +CONFIG_LOCKDEP_SUPPORT=y
- +CONFIG_STACKTRACE_SUPPORT=y
- +CONFIG_HAVE_LATENCYTOP_SUPPORT=y
- +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
- +
- +#
- +# General setup
- +#
- +CONFIG_EXPERIMENTAL=y
- +CONFIG_BROKEN_ON_SMP=y
- +CONFIG_INIT_ENV_ARG_LIMIT=32
- +CONFIG_LOCALVERSION=""
- +# CONFIG_LOCALVERSION_AUTO is not set
- +CONFIG_SWAP=y
- +CONFIG_SYSVIPC=y
- +CONFIG_SYSVIPC_SYSCTL=y
- +# CONFIG_POSIX_MQUEUE is not set
- +CONFIG_BSD_PROCESS_ACCT=y
- +CONFIG_BSD_PROCESS_ACCT_V3=y
- +# CONFIG_TASKSTATS is not set
- +# CONFIG_AUDIT is not set
- +
- +#
- +# RCU Subsystem
- +#
- +CONFIG_CLASSIC_RCU=y
- +# CONFIG_TREE_RCU is not set
- +# CONFIG_PREEMPT_RCU is not set
- +# CONFIG_TREE_RCU_TRACE is not set
- +# CONFIG_PREEMPT_RCU_TRACE is not set
- +# CONFIG_IKCONFIG is not set
- +CONFIG_LOG_BUF_SHIFT=14
- +# CONFIG_GROUP_SCHED is not set
- +# CONFIG_CGROUPS is not set
- +# CONFIG_SYSFS_DEPRECATED_V2 is not set
- +# CONFIG_RELAY is not set
- +# CONFIG_NAMESPACES is not set
- +CONFIG_BLK_DEV_INITRD=y
- +CONFIG_INITRAMFS_SOURCE=""
- +CONFIG_CC_OPTIMIZE_FOR_SIZE=y
- +CONFIG_SYSCTL=y
- +CONFIG_ANON_INODES=y
- +CONFIG_EMBEDDED=y
- +CONFIG_UID16=y
- +CONFIG_SYSCTL_SYSCALL=y
- +CONFIG_KALLSYMS=y
- +# CONFIG_KALLSYMS_ALL is not set
- +CONFIG_KALLSYMS_EXTRA_PASS=y
- +# CONFIG_HOTPLUG is not set
- +CONFIG_PRINTK=y
- +CONFIG_BUG=y
- +CONFIG_ELF_CORE=y
- +CONFIG_BASE_FULL=y
- +CONFIG_FUTEX=y
- +CONFIG_EPOLL=y
- +# CONFIG_SIGNALFD is not set
- +CONFIG_TIMERFD=y
- +CONFIG_EVENTFD=y
- +CONFIG_SHMEM=y
- +CONFIG_AIO=y
- +# CONFIG_VM_EVENT_COUNTERS is not set
- +CONFIG_SLUB_DEBUG=y
- +CONFIG_COMPAT_BRK=y
- +# CONFIG_SLAB is not set
- +CONFIG_SLUB=y
- +# CONFIG_SLOB is not set
- +CONFIG_PROFILING=y
- +CONFIG_TRACEPOINTS=y
- +# CONFIG_MARKERS is not set
- +CONFIG_OPROFILE=y
- +CONFIG_HAVE_OPROFILE=y
- +# CONFIG_KPROBES is not set
- +CONFIG_HAVE_KPROBES=y
- +CONFIG_HAVE_KRETPROBES=y
- +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
- +CONFIG_SLABINFO=y
- +CONFIG_RT_MUTEXES=y
- +CONFIG_BASE_SMALL=0
- +CONFIG_MODULES=y
- +# CONFIG_MODULE_FORCE_LOAD is not set
- +CONFIG_MODULE_UNLOAD=y
- +# CONFIG_MODULE_FORCE_UNLOAD is not set
- +# CONFIG_MODVERSIONS is not set
- +# CONFIG_MODULE_SRCVERSION_ALL is not set
- +CONFIG_BLOCK=y
- +# CONFIG_LBD is not set
- +# CONFIG_BLK_DEV_IO_TRACE is not set
- +# CONFIG_BLK_DEV_BSG is not set
- +# CONFIG_BLK_DEV_INTEGRITY is not set
- +
- +#
- +# IO Schedulers
- +#
- +CONFIG_IOSCHED_NOOP=y
- +CONFIG_IOSCHED_AS=y
- +CONFIG_IOSCHED_DEADLINE=y
- +CONFIG_IOSCHED_CFQ=y
- +# CONFIG_DEFAULT_AS is not set
- +# CONFIG_DEFAULT_DEADLINE is not set
- +CONFIG_DEFAULT_CFQ=y
- +# CONFIG_DEFAULT_NOOP is not set
- +CONFIG_DEFAULT_IOSCHED="cfq"
- +# CONFIG_FREEZER is not set
- +
- +#
- +# System Type
- +#
- +# CONFIG_PLAT_VEP is not set
- +# CONFIG_PLAT_AG101 is not set
- +# CONFIG_PLAT_AG102 is not set
- +CONFIG_PLAT_AG101P=y
- +# CONFIG_PLAT_QEMU is not set
- +CONFIG_PLATFORM_INTC=y
- +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
- +
- +#
- +# AG101P Platform Options
- +#
- +
- +#
- +# Common Platform Options
- +#
- +CONFIG_PLATFORM_AHBDMA=y
- +CONFIG_PLATFORM_APBDMA=y
- +CONFIG_SYS_CLK=40000000
- +CONFIG_UART_CLK=14745600
- +CONFIG_SDRAM_SIZE=0x10000000
- +
- +#
- +# Processor Features
- +#
- +CONFIG_CPU_CUSTOM=y
- +# CONFIG_FPU is not set
- +# CONFIG_AUDIO is not set
- +# CONFIG_EVIC is not set
- +CONFIG_CPU_CONTEXT_ID=y
- +# CONFIG_CPU_CACHE_NONALIASING is not set
- +# CONFIG_ANDES_PAGE_SIZE_4KB is not set
- +CONFIG_ANDES_PAGE_SIZE_8KB=y
- +CONFIG_KERNEL_SPACE_LARGE_PAGE=y
- +# CONFIG_CPU_ICACHE_DISABLE is not set
- +# CONFIG_CPU_DCACHE_DISABLE is not set
- +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
- +# CONFIG_ABI1 is not set
- +CONFIG_ALIGNMENT_TRAP=y
- +CONFIG_GENERIC_TIME=y
- +CONFIG_GENERIC_CLOCKEVENTS=y
- +CONFIG_MMU=y
- +
- +#
- +# Kernel Features
- +#
- +# CONFIG_NO_HZ is not set
- +# CONFIG_HIGH_RES_TIMERS is not set
- +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
- +CONFIG_PREEMPT_NONE=y
- +# CONFIG_PREEMPT_VOLUNTARY is not set
- +# CONFIG_PREEMPT is not set
- +CONFIG_SELECT_MEMORY_MODEL=y
- +CONFIG_FLATMEM_MANUAL=y
- +# CONFIG_DISCONTIGMEM_MANUAL is not set
- +# CONFIG_SPARSEMEM_MANUAL is not set
- +CONFIG_FLATMEM=y
- +CONFIG_FLAT_NODE_MEM_MAP=y
- +CONFIG_PAGEFLAGS_EXTENDED=y
- +CONFIG_SPLIT_PTLOCK_CPUS=4
- +# CONFIG_PHYS_ADDR_T_64BIT is not set
- +CONFIG_ZONE_DMA_FLAG=0
- +CONFIG_VIRT_TO_BUS=y
- +CONFIG_UNEVICTABLE_LRU=y
- +CONFIG_FORCE_MAX_ZONEORDER=11
- +CONFIG_HZ_100=y
- +# CONFIG_HZ_250 is not set
- +# CONFIG_HZ_300 is not set
- +# CONFIG_HZ_1000 is not set
- +CONFIG_HZ=100
- +# CONFIG_SCHED_HRTICK is not set
- +CONFIG_CMDLINE="root=/dev/ram0 rw mem=128M@0x0 initrd=0x1000000,8M console=ttyS0,38400n8 rootfstype=ext2 init=/bin/busybox init -s user_debug=-1"
- +
- +#
- +# Power management options
- +#
- +CONFIG_SYS_SUPPORTS_APM_EMULATION=y
- +CONFIG_ARCH_SUSPEND_POSSIBLE=y
- +# CONFIG_PM is not set
- +
- +#
- +# Bus options
- +#
- +# CONFIG_PCI is not set
- +# CONFIG_ARCH_SUPPORTS_MSI is not set
- +
- +#
- +# Executable file formats
- +#
- +CONFIG_BINFMT_ELF=y
- +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
- +# CONFIG_HAVE_AOUT is not set
- +# CONFIG_BINFMT_MISC is not set
- +CONFIG_NET=y
- +
- +#
- +# Networking options
- +#
- +CONFIG_COMPAT_NET_DEV_OPS=y
- +CONFIG_PACKET=y
- +# CONFIG_PACKET_MMAP is not set
- +CONFIG_UNIX=y
- +CONFIG_XFRM=y
- +# CONFIG_XFRM_USER is not set
- +# CONFIG_XFRM_SUB_POLICY is not set
- +# CONFIG_XFRM_MIGRATE is not set
- +# CONFIG_XFRM_STATISTICS is not set
- +CONFIG_NET_KEY=y
- +# CONFIG_NET_KEY_MIGRATE is not set
- +CONFIG_INET=y
- +CONFIG_IP_MULTICAST=y
- +# CONFIG_IP_ADVANCED_ROUTER is not set
- +CONFIG_IP_FIB_HASH=y
- +# CONFIG_IP_PNP is not set
- +# CONFIG_NET_IPIP is not set
- +# CONFIG_NET_IPGRE is not set
- +# CONFIG_IP_MROUTE is not set
- +# CONFIG_ARPD is not set
- +# CONFIG_SYN_COOKIES is not set
- +# CONFIG_INET_AH is not set
- +# CONFIG_INET_ESP is not set
- +# CONFIG_INET_IPCOMP is not set
- +# CONFIG_INET_XFRM_TUNNEL is not set
- +# CONFIG_INET_TUNNEL is not set
- +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
- +# CONFIG_INET_XFRM_MODE_TUNNEL is not set
- +# CONFIG_INET_XFRM_MODE_BEET is not set
- +# CONFIG_INET_LRO is not set
- +# CONFIG_INET_DIAG is not set
- +# CONFIG_TCP_CONG_ADVANCED is not set
- +CONFIG_TCP_CONG_CUBIC=y
- +CONFIG_DEFAULT_TCP_CONG="cubic"
- +# CONFIG_TCP_MD5SIG is not set
- +# CONFIG_IPV6 is not set
- +# CONFIG_NETWORK_SECMARK is not set
- +# CONFIG_NETFILTER is not set
- +# CONFIG_IP_DCCP is not set
- +# CONFIG_IP_SCTP is not set
- +# CONFIG_TIPC is not set
- +# CONFIG_ATM is not set
- +# CONFIG_BRIDGE is not set
- +# CONFIG_NET_DSA is not set
- +# CONFIG_VLAN_8021Q is not set
- +# CONFIG_DECNET is not set
- +# CONFIG_LLC2 is not set
- +# CONFIG_IPX is not set
- +# CONFIG_ATALK is not set
- +# CONFIG_X25 is not set
- +# CONFIG_LAPB is not set
- +# CONFIG_ECONET is not set
- +# CONFIG_WAN_ROUTER is not set
- +# CONFIG_NET_SCHED is not set
- +# CONFIG_DCB is not set
- +
- +#
- +# Network testing
- +#
- +# CONFIG_NET_PKTGEN is not set
- +# CONFIG_HAMRADIO is not set
- +# CONFIG_CAN is not set
- +# CONFIG_IRDA is not set
- +# CONFIG_BT is not set
- +# CONFIG_AF_RXRPC is not set
- +# CONFIG_PHONET is not set
- +CONFIG_WIRELESS=y
- +# CONFIG_CFG80211 is not set
- +CONFIG_WIRELESS_OLD_REGULATORY=y
- +# CONFIG_WIRELESS_EXT is not set
- +# CONFIG_LIB80211 is not set
- +# CONFIG_MAC80211 is not set
- +# CONFIG_WIMAX is not set
- +# CONFIG_RFKILL is not set
- +# CONFIG_NET_9P is not set
- +
- +#
- +# Device Drivers
- +#
- +
- +#
- +# Generic Driver Options
- +#
- +CONFIG_STANDALONE=y
- +CONFIG_PREVENT_FIRMWARE_BUILD=y
- +# CONFIG_DEBUG_DRIVER is not set
- +# CONFIG_DEBUG_DEVRES is not set
- +# CONFIG_SYS_HYPERVISOR is not set
- +# CONFIG_CONNECTOR is not set
- +CONFIG_MTD=y
- +# CONFIG_MTD_DEBUG is not set
- +# CONFIG_MTD_CONCAT is not set
- +CONFIG_MTD_PARTITIONS=y
- +# CONFIG_MTD_TESTS is not set
- +# CONFIG_MTD_REDBOOT_PARTS is not set
- +CONFIG_MTD_CMDLINE_PARTS=y
- +# CONFIG_MTD_AR7_PARTS is not set
- +
- +#
- +# User Modules And Translation Layers
- +#
- +CONFIG_MTD_CHAR=y
- +CONFIG_MTD_BLKDEVS=y
- +CONFIG_MTD_BLOCK=y
- +# CONFIG_FTL is not set
- +# CONFIG_NFTL is not set
- +# CONFIG_INFTL is not set
- +# CONFIG_RFD_FTL is not set
- +# CONFIG_SSFDC is not set
- +# CONFIG_MTD_OOPS is not set
- +
- +#
- +# RAM/ROM/Flash chip drivers
- +#
- +CONFIG_MTD_CFI=y
- +# CONFIG_MTD_JEDECPROBE is not set
- +CONFIG_MTD_GEN_PROBE=y
- +# CONFIG_MTD_CFI_ADV_OPTIONS is not set
- +CONFIG_MTD_MAP_BANK_WIDTH_1=y
- +CONFIG_MTD_MAP_BANK_WIDTH_2=y
- +CONFIG_MTD_MAP_BANK_WIDTH_4=y
- +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
- +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
- +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
- +CONFIG_MTD_CFI_I1=y
- +CONFIG_MTD_CFI_I2=y
- +# CONFIG_MTD_CFI_I4 is not set
- +# CONFIG_MTD_CFI_I8 is not set
- +CONFIG_MTD_CFI_INTELEXT=y
- +# CONFIG_MTD_CFI_AMDSTD is not set
- +# CONFIG_MTD_CFI_STAA is not set
- +CONFIG_MTD_CFI_UTIL=y
- +# CONFIG_MTD_RAM is not set
- +# CONFIG_MTD_ROM is not set
- +# CONFIG_MTD_ABSENT is not set
- +
- +#
- +# Mapping drivers for chip access
- +#
- +# CONFIG_MTD_COMPLEX_MAPPINGS is not set
- +CONFIG_MTD_PHYSMAP=y
- +CONFIG_MTD_PHYSMAP_COMPAT=y
- +CONFIG_MTD_PHYSMAP_START=0x80400000
- +CONFIG_MTD_PHYSMAP_LEN=0x2000000
- +CONFIG_MTD_PHYSMAP_BANKWIDTH=4
- +# CONFIG_MTD_PLATRAM is not set
- +
- +#
- +# Self-contained MTD device drivers
- +#
- +# CONFIG_MTD_SLRAM is not set
- +# CONFIG_MTD_PHRAM is not set
- +# CONFIG_MTD_MTDRAM is not set
- +# CONFIG_MTD_BLOCK2MTD is not set
- +
- +#
- +# Disk-On-Chip Device Drivers
- +#
- +# CONFIG_MTD_DOC2000 is not set
- +# CONFIG_MTD_DOC2001 is not set
- +# CONFIG_MTD_DOC2001PLUS is not set
- +# CONFIG_MTD_NAND is not set
- +# CONFIG_MTD_ONENAND is not set
- +
- +#
- +# LPDDR flash memory drivers
- +#
- +# CONFIG_MTD_LPDDR is not set
- +
- +#
- +# UBI - Unsorted block images
- +#
- +# CONFIG_MTD_UBI is not set
- +# CONFIG_PARPORT is not set
- +CONFIG_BLK_DEV=y
- +# CONFIG_BLK_DEV_COW_COMMON is not set
- +CONFIG_BLK_DEV_LOOP=y
- +# CONFIG_BLK_DEV_CRYPTOLOOP is not set
- +# CONFIG_BLK_DEV_NBD is not set
- +CONFIG_BLK_DEV_RAM=y
- +CONFIG_BLK_DEV_RAM_COUNT=16
- +CONFIG_BLK_DEV_RAM_SIZE=8192
- +# CONFIG_BLK_DEV_XIP is not set
- +# CONFIG_CDROM_PKTCDVD is not set
- +# CONFIG_ATA_OVER_ETH is not set
- +CONFIG_FTSDC010=y
- +# CONFIG_FTCFC010 is not set
- +# CONFIG_BLK_DEV_HD is not set
- +# CONFIG_MISC_DEVICES is not set
- +CONFIG_HAVE_IDE=y
- +# CONFIG_IDE is not set
- +
- +#
- +# SCSI device support
- +#
- +# CONFIG_RAID_ATTRS is not set
- +# CONFIG_SCSI is not set
- +# CONFIG_SCSI_DMA is not set
- +# CONFIG_SCSI_NETLINK is not set
- +# CONFIG_ATA is not set
- +# CONFIG_MD is not set
- +CONFIG_NETDEVICES=y
- +# CONFIG_DUMMY is not set
- +# CONFIG_BONDING is not set
- +# CONFIG_MACVLAN is not set
- +# CONFIG_EQUALIZER is not set
- +# CONFIG_TUN is not set
- +# CONFIG_VETH is not set
- +# CONFIG_PHYLIB is not set
- +CONFIG_NET_ETHERNET=y
- +# CONFIG_MII is not set
- +# CONFIG_SMC91X is not set
- +# CONFIG_DNET is not set
- +# CONFIG_IBM_NEW_EMAC_ZMII is not set
- +# CONFIG_IBM_NEW_EMAC_RGMII is not set
- +# CONFIG_IBM_NEW_EMAC_TAH is not set
- +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
- +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
- +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
- +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
- +# CONFIG_B44 is not set
- +CONFIG_FTMAC100=y
- +# CONFIG_NETDEV_1000 is not set
- +# CONFIG_NETDEV_10000 is not set
- +
- +#
- +# Wireless LAN
- +#
- +# CONFIG_WLAN_PRE80211 is not set
- +# CONFIG_WLAN_80211 is not set
- +# CONFIG_IWLWIFI_LEDS is not set
- +
- +#
- +# Enable WiMAX (Networking options) to see the WiMAX drivers
- +#
- +# CONFIG_WAN is not set
- +# CONFIG_PPP is not set
- +# CONFIG_SLIP is not set
- +# CONFIG_NETCONSOLE is not set
- +# CONFIG_NETPOLL is not set
- +# CONFIG_NET_POLL_CONTROLLER is not set
- +# CONFIG_ISDN is not set
- +# CONFIG_PHONE is not set
- +
- +#
- +# Input device support
- +#
- +CONFIG_INPUT=y
- +# CONFIG_INPUT_FF_MEMLESS is not set
- +# CONFIG_INPUT_POLLDEV is not set
- +
- +#
- +# Userland interfaces
- +#
- +# CONFIG_INPUT_MOUSEDEV is not set
- +# CONFIG_INPUT_JOYDEV is not set
- +CONFIG_INPUT_EVDEV=y
- +# CONFIG_INPUT_EVBUG is not set
- +
- +#
- +# Input Device Drivers
- +#
- +# CONFIG_INPUT_KEYBOARD is not set
- +# CONFIG_INPUT_MOUSE is not set
- +# CONFIG_INPUT_JOYSTICK is not set
- +# CONFIG_INPUT_TABLET is not set
- +CONFIG_INPUT_TOUCHSCREEN=y
- +CONFIG_TOUCHSCREEN_CPE_TS=y
- +CONFIG_TOUCHSCREEN_CPE_TS_DEJITTER=y
- +# CONFIG_TOUCHSCREEN_FUJITSU is not set
- +# CONFIG_TOUCHSCREEN_GUNZE is not set
- +# CONFIG_TOUCHSCREEN_ELO is not set
- +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
- +# CONFIG_TOUCHSCREEN_MTOUCH is not set
- +# CONFIG_TOUCHSCREEN_INEXIO is not set
- +# CONFIG_TOUCHSCREEN_MK712 is not set
- +# CONFIG_TOUCHSCREEN_PENMOUNT is not set
- +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
- +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
- +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
- +# CONFIG_INPUT_MISC is not set
- +
- +#
- +# Hardware I/O ports
- +#
- +# CONFIG_SERIO is not set
- +# CONFIG_GAMEPORT is not set
- +
- +#
- +# Character devices
- +#
- +CONFIG_VT=y
- +CONFIG_CONSOLE_TRANSLATIONS=y
- +CONFIG_VT_CONSOLE=y
- +CONFIG_HW_CONSOLE=y
- +# CONFIG_VT_HW_CONSOLE_BINDING is not set
- +CONFIG_DEVKMEM=y
- +# CONFIG_SERIAL_NONSTANDARD is not set
- +
- +#
- +# Serial drivers
- +#
- +CONFIG_SERIAL_8250=y
- +CONFIG_SERIAL_8250_CONSOLE=y
- +CONFIG_SERIAL_8250_NR_UARTS=3
- +CONFIG_SERIAL_8250_RUNTIME_UARTS=3
- +# CONFIG_SERIAL_8250_EXTENDED is not set
- +
- +#
- +# Non-8250 serial port support
- +#
- +CONFIG_SERIAL_CORE=y
- +CONFIG_SERIAL_CORE_CONSOLE=y
- +CONFIG_UNIX98_PTYS=y
- +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
- +CONFIG_LEGACY_PTYS=y
- +CONFIG_LEGACY_PTY_COUNT=256
- +# CONFIG_IPMI_HANDLER is not set
- +# CONFIG_HW_RANDOM is not set
- +# CONFIG_R3964 is not set
- +# CONFIG_GPIO_FTGPIO010_OLD is not set
- +# CONFIG_RAW_DRIVER is not set
- +# CONFIG_TCG_TPM is not set
- +# CONFIG_I2C is not set
- +# CONFIG_SPI is not set
- +# CONFIG_GPIOLIB is not set
- +# CONFIG_W1 is not set
- +# CONFIG_POWER_SUPPLY is not set
- +# CONFIG_HWMON is not set
- +# CONFIG_THERMAL is not set
- +# CONFIG_THERMAL_HWMON is not set
- +# CONFIG_WATCHDOG is not set
- +CONFIG_SSB_POSSIBLE=y
- +
- +#
- +# Sonics Silicon Backplane
- +#
- +# CONFIG_SSB is not set
- +
- +#
- +# Multifunction device drivers
- +#
- +# CONFIG_MFD_CORE is not set
- +# CONFIG_MFD_SM501 is not set
- +# CONFIG_HTC_PASIC3 is not set
- +# CONFIG_MFD_TMIO is not set
- +# CONFIG_REGULATOR is not set
- +
- +#
- +# Multimedia devices
- +#
- +
- +#
- +# Multimedia core support
- +#
- +# CONFIG_VIDEO_DEV is not set
- +# CONFIG_DVB_CORE is not set
- +# CONFIG_VIDEO_MEDIA is not set
- +
- +#
- +# Multimedia drivers
- +#
- +# CONFIG_DAB is not set
- +
- +#
- +# Graphics support
- +#
- +# CONFIG_VGASTATE is not set
- +# CONFIG_VIDEO_OUTPUT_CONTROL is not set
- +CONFIG_FB=y
- +# CONFIG_FIRMWARE_EDID is not set
- +# CONFIG_FB_DDC is not set
- +# CONFIG_FB_BOOT_VESA_SUPPORT is not set
- +CONFIG_FB_CFB_FILLRECT=y
- +CONFIG_FB_CFB_COPYAREA=y
- +CONFIG_FB_CFB_IMAGEBLIT=y
- +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
- +# CONFIG_FB_SYS_FILLRECT is not set
- +# CONFIG_FB_SYS_COPYAREA is not set
- +# CONFIG_FB_SYS_IMAGEBLIT is not set
- +# CONFIG_FB_FOREIGN_ENDIAN is not set
- +# CONFIG_FB_SYS_FOPS is not set
- +# CONFIG_FB_SVGALIB is not set
- +# CONFIG_FB_MACMODES is not set
- +# CONFIG_FB_BACKLIGHT is not set
- +# CONFIG_FB_MODE_HELPERS is not set
- +# CONFIG_FB_TILEBLITTING is not set
- +
- +#
- +# Frame buffer hardware drivers
- +#
- +# CONFIG_FB_S1D13XXX is not set
- +CONFIG_FB_FTLCDC100=y
- +CONFIG_PANEL_AUA036QN01=y
- +# CONFIG_PANEL_CH7013A is not set
- +# CONFIG_PANEL_AUA070VW04 is not set
- +# CONFIG_PANEL_LW500AC9601 is not set
- +CONFIG_FFB_MODE_RGB=y
- +# CONFIG_FFB_MODE_YUV422 is not set
- +# CONFIG_FFB_MODE_YUV420 is not set
- +# CONFIG_FFB_MODE_8BPP is not set
- +CONFIG_FFB_MODE_16BPP=y
- +# CONFIG_FFB_MODE_24BPP is not set
- +# CONFIG_FB_VIRTUAL is not set
- +# CONFIG_FB_METRONOME is not set
- +# CONFIG_FB_MB862XX is not set
- +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
- +
- +#
- +# Display device support
- +#
- +# CONFIG_DISPLAY_SUPPORT is not set
- +
- +#
- +# Console display driver support
- +#
- +# CONFIG_VGA_CONSOLE is not set
- +CONFIG_DUMMY_CONSOLE=y
- +CONFIG_FRAMEBUFFER_CONSOLE=y
- +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
- +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
- +# CONFIG_FONTS is not set
- +CONFIG_FONT_8x8=y
- +CONFIG_FONT_8x16=y
- +CONFIG_LOGO=y
- +CONFIG_LOGO_LINUX_MONO=y
- +CONFIG_LOGO_LINUX_VGA16=y
- +CONFIG_LOGO_LINUX_CLUT224=y
- +CONFIG_SOUND=y
- +CONFIG_SOUND_OSS_CORE=y
- +CONFIG_SND=y
- +CONFIG_SND_TIMER=y
- +CONFIG_SND_PCM=y
- +# CONFIG_SND_SEQUENCER is not set
- +CONFIG_SND_OSSEMUL=y
- +# CONFIG_SND_MIXER_OSS is not set
- +CONFIG_SND_PCM_OSS=y
- +CONFIG_SND_PCM_OSS_PLUGINS=y
- +# CONFIG_SND_DYNAMIC_MINORS is not set
- +# CONFIG_SND_SUPPORT_OLD_API is not set
- +# CONFIG_SND_VERBOSE_PROCFS is not set
- +# CONFIG_SND_VERBOSE_PRINTK is not set
- +# CONFIG_SND_DEBUG is not set
- +CONFIG_SND_DRIVERS=y
- +# CONFIG_SND_DUMMY is not set
- +# CONFIG_SND_MTPAV is not set
- +# CONFIG_SND_SERIAL_U16550 is not set
- +# CONFIG_SND_MPU401 is not set
- +
- +#
- +# ALSA NDS32 devices
- +#
- +CONFIG_SND_FTSSP010=y
- +CONFIG_SND_FTSSP010_AC97=y
- +# CONFIG_SND_FTSSP010_I2S is not set
- +# CONFIG_SND_SOC is not set
- +# CONFIG_SOUND_PRIME is not set
- +# CONFIG_HID_SUPPORT is not set
- +# CONFIG_USB_SUPPORT is not set
- +# CONFIG_MMC is not set
- +# CONFIG_MEMSTICK is not set
- +# CONFIG_NEW_LEDS is not set
- +# CONFIG_ACCESSIBILITY is not set
- +CONFIG_RTC_LIB=y
- +CONFIG_RTC_CLASS=y
- +# CONFIG_RTC_HCTOSYS is not set
- +# CONFIG_RTC_DEBUG is not set
- +
- +#
- +# RTC interfaces
- +#
- +CONFIG_RTC_INTF_SYSFS=y
- +CONFIG_RTC_INTF_PROC=y
- +CONFIG_RTC_INTF_DEV=y
- +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
- +# CONFIG_RTC_DRV_TEST is not set
- +
- +#
- +# SPI RTC drivers
- +#
- +
- +#
- +# Platform RTC drivers
- +#
- +# CONFIG_RTC_DRV_DS1286 is not set
- +# CONFIG_RTC_DRV_DS1511 is not set
- +# CONFIG_RTC_DRV_DS1553 is not set
- +# CONFIG_RTC_DRV_DS1742 is not set
- +# CONFIG_RTC_DRV_STK17TA8 is not set
- +# CONFIG_RTC_DRV_M48T86 is not set
- +# CONFIG_RTC_DRV_M48T35 is not set
- +# CONFIG_RTC_DRV_M48T59 is not set
- +# CONFIG_RTC_DRV_BQ4802 is not set
- +# CONFIG_RTC_DRV_V3020 is not set
- +
- +#
- +# on-CPU RTC drivers
- +#
- +CONFIG_RTC_DRV_FTRTC010=y
- +# CONFIG_DMADEVICES is not set
- +# CONFIG_UIO is not set
- +# CONFIG_STAGING is not set
- +
- +#
- +# File systems
- +#
- +CONFIG_EXT2_FS=y
- +# CONFIG_EXT2_FS_XATTR is not set
- +# CONFIG_EXT2_FS_XIP is not set
- +# CONFIG_EXT3_FS is not set
- +# CONFIG_EXT4_FS is not set
- +# CONFIG_REISERFS_FS is not set
- +# CONFIG_JFS_FS is not set
- +# CONFIG_FS_POSIX_ACL is not set
- +CONFIG_FILE_LOCKING=y
- +# CONFIG_XFS_FS is not set
- +# CONFIG_OCFS2_FS is not set
- +# CONFIG_BTRFS_FS is not set
- +CONFIG_DNOTIFY=y
- +CONFIG_INOTIFY=y
- +CONFIG_INOTIFY_USER=y
- +# CONFIG_QUOTA is not set
- +# CONFIG_AUTOFS_FS is not set
- +# CONFIG_AUTOFS4_FS is not set
- +CONFIG_FUSE_FS=y
- +
- +#
- +# CD-ROM/DVD Filesystems
- +#
- +# CONFIG_ISO9660_FS is not set
- +# CONFIG_UDF_FS is not set
- +
- +#
- +# DOS/FAT/NT Filesystems
- +#
- +CONFIG_FAT_FS=y
- +CONFIG_MSDOS_FS=y
- +CONFIG_VFAT_FS=y
- +CONFIG_FAT_DEFAULT_CODEPAGE=437
- +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
- +# CONFIG_NTFS_FS is not set
- +
- +#
- +# Pseudo filesystems
- +#
- +CONFIG_PROC_FS=y
- +# CONFIG_PROC_KCORE is not set
- +CONFIG_PROC_SYSCTL=y
- +# CONFIG_PROC_PAGE_MONITOR is not set
- +CONFIG_SYSFS=y
- +CONFIG_TMPFS=y
- +# CONFIG_TMPFS_POSIX_ACL is not set
- +# CONFIG_HUGETLB_PAGE is not set
- +# CONFIG_CONFIGFS_FS is not set
- +CONFIG_MISC_FILESYSTEMS=y
- +# CONFIG_ADFS_FS is not set
- +# CONFIG_AFFS_FS is not set
- +# CONFIG_HFS_FS is not set
- +# CONFIG_HFSPLUS_FS is not set
- +# CONFIG_BEFS_FS is not set
- +# CONFIG_BFS_FS is not set
- +# CONFIG_EFS_FS is not set
- +CONFIG_JFFS2_FS=y
- +CONFIG_JFFS2_FS_DEBUG=0
- +CONFIG_JFFS2_FS_WRITEBUFFER=y
- +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
- +# CONFIG_JFFS2_SUMMARY is not set
- +# CONFIG_JFFS2_FS_XATTR is not set
- +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
- +CONFIG_JFFS2_ZLIB=y
- +# CONFIG_JFFS2_LZO is not set
- +CONFIG_JFFS2_RTIME=y
- +# CONFIG_JFFS2_RUBIN is not set
- +# CONFIG_CRAMFS is not set
- +# CONFIG_SQUASHFS is not set
- +# CONFIG_VXFS_FS is not set
- +# CONFIG_MINIX_FS is not set
- +# CONFIG_OMFS_FS is not set
- +# CONFIG_HPFS_FS is not set
- +# CONFIG_QNX4FS_FS is not set
- +# CONFIG_ROMFS_FS is not set
- +# CONFIG_SYSV_FS is not set
- +# CONFIG_UFS_FS is not set
- +CONFIG_NETWORK_FILESYSTEMS=y
- +CONFIG_NFS_FS=y
- +CONFIG_NFS_V3=y
- +# CONFIG_NFS_V3_ACL is not set
- +# CONFIG_NFS_V4 is not set
- +# CONFIG_NFSD is not set
- +CONFIG_LOCKD=y
- +CONFIG_LOCKD_V4=y
- +CONFIG_NFS_COMMON=y
- +CONFIG_SUNRPC=y
- +# CONFIG_SUNRPC_REGISTER_V4 is not set
- +# CONFIG_RPCSEC_GSS_KRB5 is not set
- +# CONFIG_RPCSEC_GSS_SPKM3 is not set
- +# CONFIG_SMB_FS is not set
- +# CONFIG_CIFS is not set
- +# CONFIG_NCP_FS is not set
- +# CONFIG_CODA_FS is not set
- +# CONFIG_AFS_FS is not set
- +
- +#
- +# Partition Types
- +#
- +# CONFIG_PARTITION_ADVANCED is not set
- +CONFIG_MSDOS_PARTITION=y
- +CONFIG_NLS=y
- +CONFIG_NLS_DEFAULT="iso8859-1"
- +CONFIG_NLS_CODEPAGE_437=y
- +# CONFIG_NLS_CODEPAGE_737 is not set
- +# CONFIG_NLS_CODEPAGE_775 is not set
- +# CONFIG_NLS_CODEPAGE_850 is not set
- +# CONFIG_NLS_CODEPAGE_852 is not set
- +# CONFIG_NLS_CODEPAGE_855 is not set
- +# CONFIG_NLS_CODEPAGE_857 is not set
- +# CONFIG_NLS_CODEPAGE_860 is not set
- +# CONFIG_NLS_CODEPAGE_861 is not set
- +# CONFIG_NLS_CODEPAGE_862 is not set
- +# CONFIG_NLS_CODEPAGE_863 is not set
- +# CONFIG_NLS_CODEPAGE_864 is not set
- +# CONFIG_NLS_CODEPAGE_865 is not set
- +# CONFIG_NLS_CODEPAGE_866 is not set
- +# CONFIG_NLS_CODEPAGE_869 is not set
- +# CONFIG_NLS_CODEPAGE_936 is not set
- +# CONFIG_NLS_CODEPAGE_950 is not set
- +# CONFIG_NLS_CODEPAGE_932 is not set
- +# CONFIG_NLS_CODEPAGE_949 is not set
- +# CONFIG_NLS_CODEPAGE_874 is not set
- +# CONFIG_NLS_ISO8859_8 is not set
- +# CONFIG_NLS_CODEPAGE_1250 is not set
- +# CONFIG_NLS_CODEPAGE_1251 is not set
- +# CONFIG_NLS_ASCII is not set
- +CONFIG_NLS_ISO8859_1=y
- +# CONFIG_NLS_ISO8859_2 is not set
- +# CONFIG_NLS_ISO8859_3 is not set
- +# CONFIG_NLS_ISO8859_4 is not set
- +# CONFIG_NLS_ISO8859_5 is not set
- +# CONFIG_NLS_ISO8859_6 is not set
- +# CONFIG_NLS_ISO8859_7 is not set
- +# CONFIG_NLS_ISO8859_9 is not set
- +# CONFIG_NLS_ISO8859_13 is not set
- +# CONFIG_NLS_ISO8859_14 is not set
- +# CONFIG_NLS_ISO8859_15 is not set
- +# CONFIG_NLS_KOI8_R is not set
- +# CONFIG_NLS_KOI8_U is not set
- +# CONFIG_NLS_UTF8 is not set
- +# CONFIG_DLM is not set
- +
- +#
- +# Kernel hacking
- +#
- +CONFIG_TRACE_IRQFLAGS_SUPPORT=y
- +# CONFIG_PRINTK_TIME is not set
- +CONFIG_ENABLE_WARN_DEPRECATED=y
- +CONFIG_ENABLE_MUST_CHECK=y
- +CONFIG_FRAME_WARN=1024
- +CONFIG_MAGIC_SYSRQ=y
- +# CONFIG_UNUSED_SYMBOLS is not set
- +CONFIG_DEBUG_FS=y
- +# CONFIG_HEADERS_CHECK is not set
- +CONFIG_DEBUG_KERNEL=y
- +CONFIG_DEBUG_SHIRQ=y
- +CONFIG_DETECT_SOFTLOCKUP=y
- +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
- +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
- +CONFIG_SCHED_DEBUG=y
- +CONFIG_SCHEDSTATS=y
- +CONFIG_TIMER_STATS=y
- +# CONFIG_DEBUG_OBJECTS is not set
- +# CONFIG_SLUB_DEBUG_ON is not set
- +# CONFIG_SLUB_STATS is not set
- +CONFIG_DEBUG_RT_MUTEXES=y
- +CONFIG_DEBUG_PI_LIST=y
- +# CONFIG_RT_MUTEX_TESTER is not set
- +CONFIG_DEBUG_SPINLOCK=y
- +CONFIG_DEBUG_MUTEXES=y
- +# CONFIG_DEBUG_LOCK_ALLOC is not set
- +# CONFIG_PROVE_LOCKING is not set
- +# CONFIG_LOCK_STAT is not set
- +CONFIG_DEBUG_SPINLOCK_SLEEP=y
- +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
- +CONFIG_STACKTRACE=y
- +# CONFIG_DEBUG_KOBJECT is not set
- +CONFIG_DEBUG_INFO=y
- +# CONFIG_DEBUG_VM is not set
- +# CONFIG_DEBUG_WRITECOUNT is not set
- +# CONFIG_DEBUG_MEMORY_INIT is not set
- +CONFIG_DEBUG_LIST=y
- +CONFIG_DEBUG_SG=y
- +# CONFIG_DEBUG_NOTIFIERS is not set
- +CONFIG_FRAME_POINTER=y
- +# CONFIG_BOOT_PRINTK_DELAY is not set
- +# CONFIG_RCU_TORTURE_TEST is not set
- +# CONFIG_RCU_CPU_STALL_DETECTOR is not set
- +# CONFIG_BACKTRACE_SELF_TEST is not set
- +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
- +# CONFIG_FAULT_INJECTION is not set
- +# CONFIG_LATENCYTOP is not set
- +CONFIG_SYSCTL_SYSCALL_CHECK=y
- +CONFIG_NOP_TRACER=y
- +CONFIG_RING_BUFFER=y
- +CONFIG_TRACING=y
- +
- +#
- +# Tracers
- +#
- +# CONFIG_IRQSOFF_TRACER is not set
- +# CONFIG_SCHED_TRACER is not set
- +# CONFIG_CONTEXT_SWITCH_TRACER is not set
- +# CONFIG_BOOT_TRACER is not set
- +# CONFIG_TRACE_BRANCH_PROFILING is not set
- +# CONFIG_FTRACE_STARTUP_TEST is not set
- +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
- +# CONFIG_SAMPLES is not set
- +CONFIG_HAVE_ARCH_KGDB=y
- +# CONFIG_KGDB is not set
- +CONFIG_DEBUG_USER=y
- +CONFIG_DEBUG_ERRORS=y
- +# CONFIG_DEBUG_LL is not set
- +# CONFIG_CCTL is not set
- +# CONFIG_ELFCHK_DEFAULT_ENABLE is not set
- +
- +#
- +# Security options
- +#
- +# CONFIG_KEYS is not set
- +# CONFIG_SECURITY is not set
- +# CONFIG_SECURITYFS is not set
- +# CONFIG_SECURITY_FILE_CAPABILITIES is not set
- +CONFIG_CRYPTO=y
- +
- +#
- +# Crypto core or helper
- +#
- +# CONFIG_CRYPTO_FIPS is not set
- +# CONFIG_CRYPTO_MANAGER is not set
- +# CONFIG_CRYPTO_MANAGER2 is not set
- +# CONFIG_CRYPTO_GF128MUL is not set
- +# CONFIG_CRYPTO_NULL is not set
- +# CONFIG_CRYPTO_CRYPTD is not set
- +# CONFIG_CRYPTO_AUTHENC is not set
- +# CONFIG_CRYPTO_TEST is not set
- +
- +#
- +# Authenticated Encryption with Associated Data
- +#
- +# CONFIG_CRYPTO_CCM is not set
- +# CONFIG_CRYPTO_GCM is not set
- +# CONFIG_CRYPTO_SEQIV is not set
- +
- +#
- +# Block modes
- +#
- +# CONFIG_CRYPTO_CBC is not set
- +# CONFIG_CRYPTO_CTR is not set
- +# CONFIG_CRYPTO_CTS is not set
- +# CONFIG_CRYPTO_ECB is not set
- +# CONFIG_CRYPTO_LRW is not set
- +# CONFIG_CRYPTO_PCBC is not set
- +# CONFIG_CRYPTO_XTS is not set
- +
- +#
- +# Hash modes
- +#
- +# CONFIG_CRYPTO_HMAC is not set
- +# CONFIG_CRYPTO_XCBC is not set
- +
- +#
- +# Digest
- +#
- +# CONFIG_CRYPTO_CRC32C is not set
- +# CONFIG_CRYPTO_MD4 is not set
- +# CONFIG_CRYPTO_MD5 is not set
- +# CONFIG_CRYPTO_MICHAEL_MIC is not set
- +# CONFIG_CRYPTO_RMD128 is not set
- +# CONFIG_CRYPTO_RMD160 is not set
- +# CONFIG_CRYPTO_RMD256 is not set
- +# CONFIG_CRYPTO_RMD320 is not set
- +# CONFIG_CRYPTO_SHA1 is not set
- +# CONFIG_CRYPTO_SHA256 is not set
- +# CONFIG_CRYPTO_SHA512 is not set
- +# CONFIG_CRYPTO_TGR192 is not set
- +# CONFIG_CRYPTO_WP512 is not set
- +
- +#
- +# Ciphers
- +#
- +# CONFIG_CRYPTO_AES is not set
- +# CONFIG_CRYPTO_ANUBIS is not set
- +# CONFIG_CRYPTO_ARC4 is not set
- +# CONFIG_CRYPTO_BLOWFISH is not set
- +# CONFIG_CRYPTO_CAMELLIA is not set
- +# CONFIG_CRYPTO_CAST5 is not set
- +# CONFIG_CRYPTO_CAST6 is not set
- +# CONFIG_CRYPTO_DES is not set
- +# CONFIG_CRYPTO_FCRYPT is not set
- +# CONFIG_CRYPTO_KHAZAD is not set
- +# CONFIG_CRYPTO_SALSA20 is not set
- +# CONFIG_CRYPTO_SEED is not set
- +# CONFIG_CRYPTO_SERPENT is not set
- +# CONFIG_CRYPTO_TEA is not set
- +# CONFIG_CRYPTO_TWOFISH is not set
- +
- +#
- +# Compression
- +#
- +# CONFIG_CRYPTO_DEFLATE is not set
- +# CONFIG_CRYPTO_LZO is not set
- +
- +#
- +# Random Number Generation
- +#
- +# CONFIG_CRYPTO_ANSI_CPRNG is not set
- +# CONFIG_CRYPTO_HW is not set
- +
- +#
- +# Library routines
- +#
- +CONFIG_BITREVERSE=y
- +CONFIG_GENERIC_FIND_LAST_BIT=y
- +# CONFIG_CRC_CCITT is not set
- +# CONFIG_CRC16 is not set
- +# CONFIG_CRC_T10DIF is not set
- +# CONFIG_CRC_ITU_T is not set
- +CONFIG_CRC32=y
- +# CONFIG_CRC7 is not set
- +# CONFIG_LIBCRC32C is not set
- +CONFIG_ZLIB_INFLATE=y
- +CONFIG_ZLIB_DEFLATE=y
- +CONFIG_PLIST=y
- +CONFIG_HAS_IOMEM=y
- +CONFIG_HAS_DMA=y
- diff -Nur linux-3.4.110.orig/arch/nds32/configs/xc5_defconfig linux-3.4.110/arch/nds32/configs/xc5_defconfig
- --- linux-3.4.110.orig/arch/nds32/configs/xc5_defconfig 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/configs/xc5_defconfig 2016-04-07 10:20:50.882078703 +0200
- @@ -0,0 +1,117 @@
- +CONFIG_EXPERIMENTAL=y
- +CONFIG_CROSS_COMPILE="nds32le-linux-"
- +# CONFIG_LOCALVERSION_AUTO is not set
- +CONFIG_SYSVIPC=y
- +CONFIG_BSD_PROCESS_ACCT=y
- +CONFIG_BSD_PROCESS_ACCT_V3=y
- +CONFIG_IKCONFIG=y
- +CONFIG_IKCONFIG_PROC=y
- +CONFIG_LOG_BUF_SHIFT=14
- +CONFIG_BLK_DEV_INITRD=y
- +CONFIG_INITRAMFS_SOURCE="/home/users/greentime/os/ramdisk/disk-nds32le-linux-glibc-v3 /home/users/greentime/os/ramdisk/disk-nds32le-linux-glibc-v3/dev/initramfs.devnodes"
- +CONFIG_CC_OPTIMIZE_FOR_SIZE=y
- +CONFIG_SYSCTL_SYSCALL=y
- +# CONFIG_HOTPLUG is not set
- +# CONFIG_SIGNALFD is not set
- +CONFIG_EMBEDDED=y
- +# CONFIG_VM_EVENT_COUNTERS is not set
- +CONFIG_PROFILING=y
- +CONFIG_OPROFILE=y
- +CONFIG_MODULES=y
- +CONFIG_MODULE_UNLOAD=y
- +# CONFIG_BLK_DEV_BSG is not set
- +CONFIG_PLATFORM_AHBDMA=y
- +CONFIG_PLATFORM_APBDMA=y
- +CONFIG_SYS_CLK=30000000
- +CONFIG_UART_CLK=14745600
- +CONFIG_SDRAM_SIZE=0x8000000
- +CONFIG_HZ_100=y
- +CONFIG_CMDLINE="root=/dev/ram0 rw mem=128M@0x0 initrd=0x1000000,8M console=ttyS0,38400n8 earlyprintk=uart8250-32bit,0x99600000 rootfstype=ext2 init=/bin/busybox init -s user_debug=-1"
- +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
- +CONFIG_NET=y
- +CONFIG_PACKET=y
- +CONFIG_UNIX=y
- +CONFIG_NET_KEY=y
- +CONFIG_INET=y
- +CONFIG_IP_MULTICAST=y
- +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
- +# CONFIG_INET_XFRM_MODE_TUNNEL is not set
- +# CONFIG_INET_XFRM_MODE_BEET is not set
- +# CONFIG_INET_LRO is not set
- +# CONFIG_INET_DIAG is not set
- +# CONFIG_IPV6 is not set
- +CONFIG_BRIDGE=y
- +CONFIG_MTD=y
- +CONFIG_MTD_CMDLINE_PARTS=y
- +CONFIG_MTD_CHAR=y
- +CONFIG_MTD_BLOCK=y
- +CONFIG_MTD_CFI=y
- +CONFIG_MTD_CFI_INTELEXT=y
- +CONFIG_MTD_PHYSMAP=y
- +CONFIG_MTD_PHYSMAP_COMPAT=y
- +CONFIG_MTD_PHYSMAP_START=0x80400000
- +CONFIG_MTD_PHYSMAP_LEN=0x2000000
- +CONFIG_MTD_PHYSMAP_BANKWIDTH=4
- +CONFIG_BLK_DEV_LOOP=y
- +CONFIG_BLK_DEV_RAM=y
- +CONFIG_BLK_DEV_RAM_SIZE=8192
- +CONFIG_NETDEVICES=y
- +CONFIG_TUN=y
- +CONFIG_FTMAC100=y
- +# CONFIG_INPUT_MOUSEDEV is not set
- +CONFIG_INPUT_EVDEV=y
- +# CONFIG_INPUT_KEYBOARD is not set
- +# CONFIG_INPUT_MOUSE is not set
- +CONFIG_INPUT_TOUCHSCREEN=y
- +# CONFIG_SERIO is not set
- +CONFIG_SERIAL_8250=y
- +CONFIG_SERIAL_8250_CONSOLE=y
- +CONFIG_SERIAL_8250_NR_UARTS=3
- +CONFIG_SERIAL_8250_RUNTIME_UARTS=3
- +# CONFIG_HW_RANDOM is not set
- +# CONFIG_HWMON is not set
- +CONFIG_FB=y
- +# CONFIG_VGA_CONSOLE is not set
- +CONFIG_FRAMEBUFFER_CONSOLE=y
- +CONFIG_LOGO=y
- +CONFIG_SOUND=y
- +CONFIG_SND=y
- +CONFIG_SND_PCM_OSS=y
- +# CONFIG_SND_SUPPORT_OLD_API is not set
- +# CONFIG_SND_VERBOSE_PROCFS is not set
- +# CONFIG_HID_SUPPORT is not set
- +# CONFIG_USB_SUPPORT is not set
- +CONFIG_MMC=y
- +CONFIG_MMC_FTSDC010=y
- +# CONFIG_MEMSTICK is not set
- +# CONFIG_NEW_LEDS is not set
- +# CONFIG_ACCESSIBILITY is not set
- +CONFIG_RTC_LIB=y
- +CONFIG_RTC_CLASS=y
- +# CONFIG_RTC_HCTOSYS is not set
- +CONFIG_EXT2_FS=y
- +CONFIG_FUSE_FS=y
- +CONFIG_MSDOS_FS=y
- +CONFIG_VFAT_FS=y
- +# CONFIG_PROC_PAGE_MONITOR is not set
- +CONFIG_TMPFS=y
- +CONFIG_JFFS2_FS=y
- +CONFIG_NFS_FS=y
- +CONFIG_NFS_V3=y
- +CONFIG_NLS_CODEPAGE_437=y
- +CONFIG_NLS_ISO8859_1=y
- +CONFIG_MAGIC_SYSRQ=y
- +CONFIG_DEBUG_FS=y
- +CONFIG_DEBUG_SHIRQ=y
- +CONFIG_SCHEDSTATS=y
- +CONFIG_TIMER_STATS=y
- +CONFIG_DEBUG_RT_MUTEXES=y
- +CONFIG_DEBUG_SPINLOCK=y
- +CONFIG_DEBUG_MUTEXES=y
- +CONFIG_DEBUG_INFO=y
- +CONFIG_DEBUG_LIST=y
- +CONFIG_DEBUG_SG=y
- +CONFIG_DEBUG_USER=y
- +CONFIG_DEBUG_ERRORS=y
- +# CONFIG_CRYPTO_ANSI_CPRNG is not set
- +# CONFIG_CRYPTO_HW is not set
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/amic.h linux-3.4.110/arch/nds32/include/asm/amic.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/amic.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/amic.h 2016-04-07 10:20:50.882078703 +0200
- @@ -0,0 +1,60 @@
- +/*
- + * linux/arch/nds32/include/asm/amic.h
- + *
- + * Andes Multi-core Interrupt Controller Device Driver Interface
- + *
- + * Copyright (C) 2010 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + * ChangeLog
- + *
- + * Shawn Lin 09/02/2010 Created for Andes AG102 platform code.
- + */
- +
- +#ifndef __NDS32_AMIC_HEADER__
- +#define __NDS32_AMIC_HEADER__
- +
- +#define IRQ_BASE 0x0
- +#define IRQ_TOTAL 0x20
- +#define DEFAULT_MODE 0x000ecc00
- +#define DEFAULT_LEVEL 0xffffffff
- +#define AMIC_BASE AMIC_VA_BASE
- +#define CONFIG 0x00
- +#define CPUDC 0x04
- +#define CPUID0 0x08
- +#define CPUID1 0x0c
- +#define INTTRG 0x20
- +#define INTLVL 0x24
- +#define INTSRC 0x28
- +#define IPITRG 0x40
- +#define IPISTA 0x44
- +#define IPIPTR 0x48
- +#define IPIGST 0x4c
- +#define IPIGPT 0x50
- +#define INTEN 0x80
- +#define INTSTA 0x84
- +#define HW0STA 0x88
- +#define HW1STA 0x8c
- +#define HW2STA 0x90
- +#define HW3STA 0x94
- +#define HW4STA 0x98
- +#define HW5STA 0x9c
- +#define PRITY0 0xa0
- +#define PRITY1 0xa4
- +#define PRITY2 0xa8
- +#define PRITY3 0xac
- +
- +#endif /* __NDS32_AMIC_HEADER__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/asm-offsets.h linux-3.4.110/arch/nds32/include/asm/asm-offsets.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/asm-offsets.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/asm-offsets.h 2016-04-07 10:20:50.882078703 +0200
- @@ -0,0 +1 @@
- +#include <generated/asm-offsets.h>
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/assembler.h linux-3.4.110/arch/nds32/include/asm/assembler.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/assembler.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/assembler.h 2016-04-07 10:20:50.882078703 +0200
- @@ -0,0 +1,141 @@
- +/*
- + * linux/arch/nds32/include/asm/assembler.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_ASSEMBLER_H__
- +#define __NDS32_ASSEMBLER_H__
- +
- +/*
- + * Stack format
- + */
- +
- +#define S_PAD 0xac /* Padding for stack pointer 8-byte alignment. */
- +#define S_FUCOP_CTL 0xa8
- +#define S_LP 0xa4
- +#define S_GP 0xa0
- +#define S_FP 0x9c
- +#define S_R25 0x98
- +#define S_R24 0x94
- +#define S_R23 0x90
- +#define S_R22 0x8c
- +#define S_R21 0x88
- +#define S_R20 0x84
- +#define S_R19 0x80
- +#define S_R18 0x7c
- +#define S_R17 0x78
- +#define S_R16 0x74
- +#define S_R15 0x70
- +#define S_R14 0x6c
- +#define S_R13 0x68
- +#define S_R12 0x64
- +#define S_R11 0x60
- +#define S_R10 0x5c
- +#define S_R9 0x58
- +#define S_R8 0x54
- +#define S_R7 0x50
- +#define S_R6 0x4c
- +#define S_R5 0x48
- +#define S_R4 0x44
- +#define S_R3 0x40
- +#define S_R2 0x3c
- +#define S_R1 0x38
- +#define S_R0 0x34
- +#define S_D1LO 0x30
- +#define S_D1HI 0x2c
- +#define S_D0LO 0x28
- +#define S_D0HI 0x24
- +#define S_PP1 0x20
- +#define S_PP0 0x1c
- +#define S_PIPC 0x18
- +#define S_PIPSW 0x14
- +#define S_ORIG_R0 0x10
- +#define S_SP 0xc
- +#define S_IPC 0x8
- +#define S_IPSW 0x4
- +#define S_IR0 0x0
- +
- +#if !defined(CONFIG_ABI1)
- +#define S_OFF 0
- +#else
- +#define S_OFF 24
- +#endif
- +
- +#ifdef __ASSEMBLY__
- +.macro get_thread_info, rd
- + srli \rd, $sp, #13
- + slli \rd, \rd, #13
- +.endm
- +
- +.macro gie_disable
- + setgie.d
- +#ifdef CONFIG_CPU_N1213_43U1HA0
- + isb
- +#else
- + dsb
- +#endif
- +.endm
- +
- +.macro gie_enable
- + setgie.e
- +#ifdef CONFIG_CPU_N1213_43U1HA0
- + isb
- +#else
- + dsb
- +#endif
- +.endm
- +
- +.macro gie_save oldpsw
- + mfsr \oldpsw, $ir0
- + setgie.d
- +#ifdef CONFIG_CPU_N1213_43U1HA0
- + isb
- +#else
- + dsb
- +#endif
- +.endm
- +
- +.macro gie_restore oldpsw
- + andi \oldpsw, \oldpsw, #0x1
- + beqz \oldpsw, 7001f
- + setgie.e
- +#ifdef CONFIG_CPU_N1213_43U1HA0
- + isb
- +#else
- + dsb
- +#endif
- +7001:
- +.endm
- +
- +
- +#define USER(insn, reg, addr, opr) \
- +9999: insn reg, addr, opr; \
- + .section __ex_table,"a"; \
- + .align 3; \
- + .long 9999b, 9001f; \
- + .previous
- +
- +#else /* __ASSEMBLY__ */
- +
- +__asm__ (".macro gie_disable\n\t"
- + "setgie.d\n\t"
- +#ifdef CONFIG_CPU_N1213_43U1HA0
- + "isb\n\t"
- +#else
- + "dsb\n\t"
- +#endif
- + ".endm\n\t"
- + );
- +
- +__asm__ (".macro gie_enable\n\t"
- + "setgie.e\n\t"
- +#ifdef CONFIG_CPU_N1213_43U1HA0
- + "isb\n\t"
- +#else
- + "dsb\n\t"
- +#endif
- + ".endm\n\t"
- + );
- +
- +#endif /* !__ASSEMBLY__ */
- +#endif /* __NDS32_ASSEMBLER_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/atomic.h linux-3.4.110/arch/nds32/include/asm/atomic.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/atomic.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/atomic.h 2016-04-07 10:20:50.890079013 +0200
- @@ -0,0 +1,267 @@
- +/*
- + * linux/arch/nds32/include/asm/atomic.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_ATOMIC_H__
- +#define __NDS32_ATOMIC_H__
- +
- +#include <linux/types.h>
- +#include <asm/barrier.h>
- +#include <asm/cmpxchg.h>
- +
- +#if defined(CONFIG_SMP) || !defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
- +
- +#define ATOMIC_INIT(i) { (i) }
- +#define atomic_set(v,i) (((v)->counter) = (i))
- +#define atomic_read(v) (*(volatile int *)&(v)->counter)
- +
- +static inline void atomic_add(int i, atomic_t *v)
- +{
- + int temp;
- + __asm__ __volatile__(
- + "movi\t$r15, #0\n"
- + "1:\n"
- + "\tllw\t%0, [%1+$r15]\n"
- + "\tadd\t%0, %0, %2\n"
- + "\tscw\t%0, [%1+$r15]\n"
- + "\tbeqz\t%0, 1b\n"
- + : "=&r" (temp) : "r" (&v->counter), "r" (i));
- +}
- +
- +static inline void atomic_sub(int i, atomic_t *v)
- +{
- + int temp;
- + __asm__ __volatile__(
- + "movi\t$r15, #0\n"
- + "1:\n"
- + "\tllw\t%0, [%1+$r15]\n"
- + "\tsub\t%0, %0, %2\n"
- + "\tscw\t%0, [%1+$r15]\n"
- + "\tbeqz\t%0, 1b\n"
- + : "=&r" (temp) : "r" (&v->counter), "r" (i));
- +}
- +
- +#define atomic_inc(v) atomic_add(1, v)
- +#define atomic_dec(v) atomic_sub(1, v)
- +
- +static inline int atomic_inc_return(atomic_t *v)
- +{
- + int temp1, temp2;
- + __asm__ __volatile__(
- + "movi\t$r15, #0\n"
- + "1:\n"
- + "\tllw\t%1, [%2+$r15]\n"
- + "\taddi\t%1, %1, #1\n"
- + "\tori\t%0, %1, #0\n"
- + "\tscw\t%1, [%2+$r15]\n"
- + "\tbeqz\t%1, 1b\n"
- + : "=&r" (temp2), "=&r" (temp1)
- + : "r" (&v->counter));
- + return temp2;
- +}
- +
- +static inline int atomic_dec_return(atomic_t *v)
- +{
- + int temp1, temp2;
- + __asm__ __volatile__(
- + "movi\t$r15, #0\n"
- + "1:\n"
- + "\tllw\t%1, [%2+$r15]\n"
- + "\taddi\t%1, %1, #-1\n"
- + "\tori\t%0, %1, #0\n"
- + "\tscw\t%1, [%2+$r15]\n"
- + "\tbeqz\t%1, 1b\n"
- + : "=&r" (temp2), "=&r" (temp1)
- + : "r" (&v->counter));
- + return temp2;
- +}
- +
- +static inline int atomic_add_return(int i, atomic_t *v)
- +{
- + int temp1, temp2;
- +
- + smp_mb();
- +
- + __asm__ __volatile__(
- + "movi\t$r15, #0\n"
- + "1:\n"
- + "\tllw\t%1, [%2+$r15]\n"
- + "\tadd\t%1, %1, %3\n"
- + "\tori\t%0, %1, #0\n"
- + "\tscw\t%1, [%2+$r15]\n"
- + "\tbeqz\t%1, 1b\n"
- + : "=&r" (temp2), "=&r" (temp1)
- + : "r" (&v->counter), "r" (i));
- +
- + smp_mb();
- +
- + return temp2;
- +}
- +
- +static inline int atomic_sub_return(int i, atomic_t *v)
- +{
- + int temp1, temp2;
- +
- + smp_mb();
- +
- + __asm__ __volatile__(
- + "movi\t$r15, #0\n"
- + "1:\n"
- + "\tllw\t%1, [%2+$r15]\n"
- + "\tsub\t%1, %1, %3\n"
- + "\tori\t%0, %1, #0\n"
- + "\tscw\t%1, [%2+$r15]\n"
- + "\tbeqz\t%1, 1b\n"
- + : "=&r" (temp2), "=&r" (temp1)
- + : "r" (&v->counter), "r" (i));
- +
- + smp_mb();
- +
- + return temp2;
- +}
- +
- +/*
- + * atomic_dec_if_positive - conditionally subtract one from atomic variable
- + * @v: pointer of type atomic_t
- + *
- + * Atomically test @v and subtract one if @v is greater or equal than one.
- + * The function returns the old value of @v minus one.
- + */
- +static inline int atomic_dec_if_positive(atomic_t * v)
- +{
- + int temp1, temp2, temp3;
- + __asm__ __volatile__(
- + "movi\t$r15, #0\n"
- + "1:\n"
- + "\tllw\t%2, [%3+$r15]\n"
- + "\taddi\t%0, %2, #-1\n"
- + "\tslts\t%1, $r15, %2\n"
- + "\tsub\t%2, %2, %1\n"
- + "\tscw\t%2, [%3+$r15]\n"
- + "\tbeqz\t%2, 1b\n"
- + : "=&r" (temp3), "=&r" (temp2), "=&r" (temp1)
- + : "r" (&v->counter));
- + return temp3;
- +}
- +
- +
- +#define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0)
- +#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)
- +#define atomic_sub_and_test(i,v) (atomic_sub_return((i),(v)) == 0)
- +#define atomic_add_negative(i,v) (atomic_add_return((i),(v)) < 0)
- +
- +
- +static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
- +{
- + int temp1, temp2, temp3;
- +
- + smp_mb();
- +
- + __asm__ __volatile__(
- + "movi\t$r15, #0\n"
- + "1:\n"
- + "\tllw\t%0, [%3+$r15]\n"
- + "\tsub\t%2, %0, %5\n"
- + "\tcmovz\t%1, %4, %2\n"
- + "\tcmovn\t%1, %0, %2\n"
- + "\tscw\t%1, [%3+$r15]\n"
- + "\tbeqz\t%1, 1b\n"
- + : "=&r" (temp3), "=&r" (temp2), "=&r" (temp1)
- + : "r" (&v->counter), "r" (new), "r" (old));
- +
- + smp_mb();
- +
- + return temp3;
- +}
- +
- +static inline int atomic_xchg(atomic_t *v, int new)
- +{
- + int temp1, temp2;
- + __asm__ __volatile__(
- + "movi\t$r15, #0\n"
- + "1:\n"
- + "\tllw\t%0, [%2+$r15]\n"
- + "\tori\t%1, %3, #0\n"
- + "\tscw\t%1, [%2+$r15]\n"
- + "\tbeqz\t%1, 1b\n"
- + : "=&r" (temp2), "=&r" (temp1)
- + : "r" (&v->counter), "r" (new));
- + return temp2;
- +}
- +
- +static inline int __atomic_add_unless(atomic_t *v, int a, int u)
- +{
- + int c, old;
- +
- + c = atomic_read(v);
- + while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c)
- + c = old;
- + return c;
- +}
- +
- +static inline int atomic_inc_not_zero(atomic_t *v)
- +{
- + int temp1, temp2;
- + __asm__ __volatile__(
- + "movi\t$r15, #0\n"
- + "1:\n"
- + "\tllw\t%1, [%2+$r15]\n"
- + "\tslt\t%0, $r15, %1\n"
- + "\tadd\t%1, %1, %0\n"
- + "\tscw\t%1, [%2+$r15]\n"
- + "\tbeqz\t%1, 1b\n"
- + : "=&r" (temp2), "=&r" (temp1)
- + : "r" (&v->counter));
- + return temp2;
- +}
- +
- +#define smp_mb__before_atomic_dec() barrier()
- +#define smp_mb__after_atomic_dec() barrier()
- +#define smp_mb__before_atomic_inc() barrier()
- +#define smp_mb__after_atomic_inc() barrier()
- +
- +//#include <asm-generic/atomic-long.h>
- +#else /* CONFIG_SMP*/
- +
- +
- +
- +#define ATOMIC_INIT(i) { (i) }
- +
- +#ifdef __KERNEL__
- +
- +#include <asm-generic/atomic.h>
- +
- +static inline int atomic_dec_if_positive(atomic_t * v)
- +{
- + unsigned long flags;
- + int result;
- +
- + local_irq_save(flags);
- + result = v->counter;
- + result -= 1;
- + if (result >= 0)
- + v->counter = result;
- + local_irq_restore(flags);
- + return result;
- +}
- +
- +/* Atomic operations are already serializing on ARM */
- +#define smp_mb__before_atomic_dec() barrier()
- +#define smp_mb__after_atomic_dec() barrier()
- +#define smp_mb__before_atomic_inc() barrier()
- +#define smp_mb__after_atomic_inc() barrier()
- +
- +#endif
- +
- +#endif /* CONFIG_SMP */
- +
- +#ifndef CONFIG_GENERIC_ATOMIC64
- +typedef struct {
- + u64 __aligned(8) counter;
- +} atomic64_t;
- +#define ATOMIC64_INIT(i) { (i) }
- +static inline u64 atomic64_add_return(u64 i, atomic64_t *v){ return 0; }
- +#endif /* CONFIG_GENERIC_ATOMIC64 */
- +
- +#endif /* __NDS32_ATOMIC_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/audio.h linux-3.4.110/arch/nds32/include/asm/audio.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/audio.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/audio.h 2016-04-07 10:20:50.890079013 +0200
- @@ -0,0 +1,65 @@
- +/*
- + * linux/arch/nds32/include/asm/audio.h
- + * Copyright (C) 2009 Andes Technology Corporation
- + */
- +
- +#ifndef __ASM_NDS32_AUDIO_H
- +#define __ASM_NDS32_AUDIO_H
- +
- +#ifndef __ASSEMBLY__
- +#include <linux/preempt.h>
- +#include <asm/ptrace.h>
- +
- +extern void save_audio(struct task_struct *tsk);
- +extern void audioload(struct audio_struct *audioregs);
- +extern void save_audio(struct task_struct *__tsk);
- +extern void do_audio_context_switch(unsigned long error_code, struct pt_regs *regs);
- +
- +#ifdef CONFIG_AUDIO
- +
- +#define test_tsk_audio(regs) (regs->NDS32_FUCOP_CTL & FUCOP_CTL_mskAUEN)
- +
- +struct task_struct;
- +
- +static inline void enable_audio(void)
- +{
- + SET_FUCOP_CTL(GET_FUCOP_CTL() | FUCOP_CTL_mskAUEN);
- +}
- +
- +static inline void disable_audio(void)
- +{
- + SET_FUCOP_CTL(GET_FUCOP_CTL() & ~FUCOP_CTL_mskAUEN);
- +}
- +
- +static inline void release_audio(struct pt_regs *regs)
- +{
- + regs->NDS32_FUCOP_CTL &= ~FUCOP_CTL_mskAUEN;
- + regs->NDS32_ipsw &= ~PSW_mskAEN;
- +}
- +
- +static inline void grab_audio(struct pt_regs *regs)
- +{
- + regs->NDS32_FUCOP_CTL |= FUCOP_CTL_mskAUEN;
- + regs->NDS32_ipsw |= PSW_mskAEN;
- +}
- +#ifdef CONFIG_UNLAZY_AUDIO
- +static inline void unlazy_audio(struct task_struct *tsk)
- +{
- + preempt_disable();
- + if (test_tsk_audio(task_pt_regs(tsk)))
- + save_audio(tsk);
- + preempt_enable();
- +}
- +#endif
- +static inline void clear_audio(struct pt_regs *regs)
- +{
- + preempt_disable();
- + if (test_tsk_audio(regs)) {
- + release_audio(regs);
- + }
- + preempt_enable();
- +}
- +#endif /* CONFIG_AUDIO */
- +#endif /* __ASSEMBLY__ */
- +
- +#endif /* __ASM_NDS32_AUDIO_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/auxvec.h linux-3.4.110/arch/nds32/include/asm/auxvec.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/auxvec.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/auxvec.h 2016-04-07 10:20:50.890079013 +0200
- @@ -0,0 +1,9 @@
- +/*
- + * linux/arch/nds32/include/asm/auxvec.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_AUXVEC_H__
- +#define __NDS32_AUXVEC_H__
- +
- +#endif /*__NDS32_AUXVEC_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/barrier.h linux-3.4.110/arch/nds32/include/asm/barrier.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/barrier.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/barrier.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,85 @@
- +/* ============================================================================
- + *
- + * linux/arch/nds32/include/asm/system.h
- + *
- + * Copyright (C) 2007 Andes Technology Corporation
- + * This file is part of Linux and should be licensed under the GPL.
- + * See the file COPYING for conditions for redistribution.
- + *
- + * Abstract:
- + *
- + * This program is for NDS32 architecture.
- + *
- + * Revision History:
- + *
- + * Nov.26.2007 Initial ported by Tom, Shawn, and Steven,
- + * patched for KGDB and refined code by Harry.
- + *
- + * Note:
- + *
- + * ============================================================================
- + */
- +#ifndef __ASM_NDS32_BARRIER_H
- +#define __ASM_NDS32_BARRIER_H
- +
- +#ifdef __KERNEL__
- +
- +/*
- + * This is used to ensure the compiler did actually allocate the register we
- + * asked it for some inline assembly sequences. Apparently we can't trust
- + * the compiler from one version to another so a bit of paranoia won't hurt.
- + * This string is meant to be concatenated with the inline asm string and
- + * will cause compilation to stop on mismatch.
- + * (for details, see gcc PR 15089)
- + */
- +#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t"
- +
- +#ifndef __ASSEMBLY__
- +
- +#include <linux/linkage.h>
- +#include <linux/irqflags.h>
- +
- +struct thread_info;
- +struct task_struct;
- +
- +struct pt_regs;
- +
- +void die(const char *msg, struct pt_regs *regs, int err)
- + __attribute__((noreturn));
- +
- +void die_if_kernel(const char *str, struct pt_regs *regs, int err);
- +
- +#include <asm/proc-fns.h>
- +
- +#define UDBG_UNDEFINED (1 << 0)
- +#define UDBG_SYSCALL (1 << 1)
- +#define UDBG_BADABORT (1 << 2)
- +#define UDBG_SEGV (1 << 3)
- +#define UDBG_BUS (1 << 4)
- +
- +extern unsigned int user_debug;
- +
- +#define mb() __asm__ __volatile__ ("" : : : "memory")
- +#define rmb() mb()
- +#define wmb() mb()
- +#define read_barrier_depends() do { } while(0)
- +#define set_mb(var, value) do { var = value; mb(); } while (0)
- +#define set_wmb(var, value) do { var = value; wmb(); } while (0)
- +
- +#ifdef CONFIG_SMP
- +#define smp_mb() mb()
- +#define smp_rmb() rmb()
- +#define smp_wmb() wmb()
- +#define smp_read_barrier_depends() read_barrier_depends()
- +#else
- +#define smp_mb() barrier()
- +#define smp_rmb() barrier()
- +#define smp_wmb() barrier()
- +#define smp_read_barrier_depends() do { } while(0)
- +#endif
- +
- +#endif /* __ASSEMBLY__ */
- +
- +#endif /* __KERNEL__ */
- +
- +#endif //__ASM_NDS32_SYSTEM_H
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/bitfield.h linux-3.4.110/arch/nds32/include/asm/bitfield.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/bitfield.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/bitfield.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,895 @@
- +/*
- + * linux/arch/nds32/include/asm/bitfield.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_BITFIELD_H__
- +#define __NDS32_BITFIELD_H__
- +/******************************************************************************
- + * cr0: CPU_VER (CPU Version Register)
- + *****************************************************************************/
- +#define CPU_VER_offCFGID 0 /* Minor configuration */
- +#define CPU_VER_offREV 16 /* Revision of the CPU version */
- +#define CPU_VER_offCPUID 24 /* Major CPU versions */
- +
- +#define CPU_VER_mskCFGID ( 0xFFFF << CPU_VER_offCFGID )
- +#define CPU_VER_mskREV ( 0xFF << CPU_VER_offREV )
- +#define CPU_VER_mskCPUID ( 0xFF << CPU_VER_offCPUID )
- +
- +/******************************************************************************
- + * cr1: ICM_CFG (Instruction Cache/Memory Configuration Register)
- + *****************************************************************************/
- +#define ICM_CFG_offISET 0 /* I-cache sets (# of cache lines) per way */
- +#define ICM_CFG_offIWAY 3 /* I-cache ways */
- +#define ICM_CFG_offISZ 6 /* I-cache line size */
- +#define ICM_CFG_offILCK 9 /* I-cache locking support */
- +#define ICM_CFG_offILMB 10 /* On-chip ILM banks */
- +#define ICM_CFG_offBSAV 13 /* ILM base register alignment version */
- +/* bit 15:31 reserved */
- +
- +#define ICM_CFG_mskISET ( 0x7 << ICM_CFG_offISET )
- +#define ICM_CFG_mskIWAY ( 0x7 << ICM_CFG_offIWAY )
- +#define ICM_CFG_mskISZ ( 0x7 << ICM_CFG_offISZ )
- +#define ICM_CFG_mskILCK ( 0x1 << ICM_CFG_offILCK )
- +#define ICM_CFG_mskILMB ( 0x7 << ICM_CFG_offILMB )
- +#define ICM_CFG_mskBSAV ( 0x3 << ICM_CFG_offBSAV )
- +
- +/******************************************************************************
- + * cr2: DCM_CFG (Data Cache/Memory Configuration Register)
- + *****************************************************************************/
- +#define DCM_CFG_offDSET 0 /* D-cache sets (# of cache lines) per way */
- +#define DCM_CFG_offDWAY 3 /* D-cache ways */
- +#define DCM_CFG_offDSZ 6 /* D-cache line size */
- +#define DCM_CFG_offDLCK 9 /* D-cache locking support */
- +#define DCM_CFG_offDLMB 10 /* On-chip DLM banks */
- +#define DCM_CFG_offBSAV 13 /* DLM base register alignment version */
- +/* bit 15:31 reserved */
- +
- +#define DCM_CFG_mskDSET ( 0x7 << DCM_CFG_offDSET )
- +#define DCM_CFG_mskDWAY ( 0x7 << DCM_CFG_offDWAY )
- +#define DCM_CFG_mskDSZ ( 0x7 << DCM_CFG_offDSZ )
- +#define DCM_CFG_mskDLCK ( 0x1 << DCM_CFG_offDLCK )
- +#define DCM_CFG_mskDLMB ( 0x7 << DCM_CFG_offDLMB )
- +#define DCM_CFG_mskBSAV ( 0x3 << DCM_CFG_offBSAV )
- +
- +/******************************************************************************
- + * cr3: MMU_CFG (MMU Configuration Register)
- + *****************************************************************************/
- +#define MMU_CFG_offMMPS 0 /* Memory management protection scheme */
- +#define MMU_CFG_offMMPV 2 /* Memory management protection version number */
- +#define MMU_CFG_offFATB 7 /* Fully-associative or non-fully-associative TLB */
- +
- +#ifdef CONFIG_FULL_ASSOC
- +#define MMU_CFG_offFATBSZ 8 /* TLB entries while using full-associative TLB */
- +#else
- +#define MMU_CFG_offTBW 8 /* TLB ways(non-associative) TBS */
- +#define MMU_CFG_offTBS 11 /* TLB sets per way(non-associative) TBS */
- +/* bit 14:14 reserved */
- +#endif
- +
- +#define MMU_CFG_offEP8MIN4 15 /* 8KB page supported while minimum page is 4KB */
- +#define MMU_CFG_offfEPSZ 16 /* Extra page size supported */
- +#define MMU_CFG_offTLBLCK 24 /* TLB locking support */
- +#define MMU_CFG_offHPTWK 25 /* Hardware Page Table Walker implemented */
- +#define MMU_CFG_offDE 26 /* Default endian */
- +#define MMU_CFG_offNTPT 27 /* Partitions for non-translated attributes */
- +#define MMU_CFG_offIVTB 28 /* Invisible TLB */
- +#define MMU_CFG_offVLPT 29 /* VLPT for fast TLB fill handling implemented */
- +#define MMU_CFG_offNTME 30 /* Non-translated VA to PA mapping */
- +/* bit 31 reserved */
- +
- +#define MMU_CFG_mskMMPS ( 0x3 << MMU_CFG_offMMPS )
- +#define MMU_CFG_mskMMPV ( 0x1F << MMU_CFG_offMMPV )
- +#define MMU_CFG_mskFATB ( 0x1 << MMU_CFG_offFATB )
- +#ifdef CONFIG_FULL_ASSOC
- +#define MMU_CFG_mskFATBSZ ( 0x7f << MMU_CFG_offFATBSZ )
- +#else
- +#define MMU_CFG_mskTBW ( 0x7 << MMU_CFG_offTBW )
- +#define MMU_CFG_mskTBS ( 0x7 << MMU_CFG_offTBS )
- +#endif
- +#define MMU_CFG_mskEP8MIN4 ( 0x1 << MMU_CFG_offEP8MIN4 )
- +#define MMU_CFG_mskfEPSZ ( 0xFF << MMU_CFG_offfEPSZ )
- +#define MMU_CFG_mskTLBLCK ( 0x1 << MMU_CFG_offTLBLCK )
- +#define MMU_CFG_mskHPTWK ( 0x1 << MMU_CFG_offHPTWK )
- +#define MMU_CFG_mskDE ( 0x1 << MMU_CFG_offDE )
- +#define MMU_CFG_mskNTPT ( 0x1 << MMU_CFG_offNTPT )
- +#define MMU_CFG_mskIVTB ( 0x1 << MMU_CFG_offIVTB )
- +#define MMU_CFG_mskVLPT ( 0x1 << MMU_CFG_offVLPT )
- +#define MMU_CFG_mskNTME ( 0x1 << MMU_CFG_offNTME )
- +
- +/******************************************************************************
- + * cr4: MSC_CFG (Misc Configuration Register)
- + *****************************************************************************/
- +#define MSC_CFG_offEDM 0
- +#define MSC_CFG_offLMDMA 1
- +#define MSC_CFG_offPFM 2
- +#define MSC_CFG_offHSMP 3
- +#define MSC_CFG_offTRACE 4
- +#define MSC_CFG_offDIV 5
- +#define MSC_CFG_offMAC 6
- +#define MSC_CFG_offAUDIO 7
- +#define MSC_CFG_offL2C 9
- +#define MSC_CFG_offRDREG 10
- +#define MSC_CFG_offADR24 11
- +#define MSC_CFG_offINTLC 12
- +#define MSC_CFG_offBASEV 13
- +#define MSC_CFG_offNOD 16
- +/* bit 13:31 reserved */
- +
- +#define MSC_CFG_mskEDM ( 0x1 << MSC_CFG_offEDM )
- +#define MSC_CFG_mskLMDMA ( 0x1 << MSC_CFG_offLMDMA )
- +#define MSC_CFG_mskPFM ( 0x1 << MSC_CFG_offPFM )
- +#define MSC_CFG_mskHSMP ( 0x1 << MSC_CFG_offHSMP )
- +#define MSC_CFG_mskTRACE ( 0x1 << MSC_CFG_offTRACE )
- +#define MSC_CFG_mskDIV ( 0x1 << MSC_CFG_offDIV )
- +#define MSC_CFG_mskMAC ( 0x1 << MSC_CFG_offMAC )
- +#define MSC_CFG_mskAUDIO ( 0x3 << MSC_CFG_offAUDIO )
- +#define MSC_CFG_mskL2C ( 0x1 << MSC_CFG_offL2C )
- +#define MSC_CFG_mskRDREG ( 0x1 << MSC_CFG_offRDREG )
- +#define MSC_CFG_mskADR24 ( 0x1 << MSC_CFG_offADR24 )
- +#define MSC_CFG_mskINTLC ( 0x1 << MSC_CFG_offINTLC )
- +#define MSC_CFG_mskBASEV ( 0x7 << MSC_CFG_offBASEV )
- +#define MSC_CFG_mskNOD ( 0x1 << MSC_CFG_offNOD )
- +
- +/******************************************************************************
- + * cr5: CORE_CFG (Core Identification Register)
- + *****************************************************************************/
- +#define CORE_ID_offCOREID 0
- +/* bit 4:31 reserved */
- +
- +#define CORE_ID_mskCOREID ( 0xF << CORE_ID_offCOREID )
- +
- +/******************************************************************************
- + * cr6: FUCOP_EXIST (FPU and Coprocessor Existence Configuration Register)
- + *****************************************************************************/
- +#define FUCOP_EXIST_offCP0EX 0
- +#define FUCOP_EXIST_offCP1EX 1
- +#define FUCOP_EXIST_offCP2EX 2
- +#define FUCOP_EXIST_offCP3EX 3
- +#define FUCOP_EXIST_offCP0ISFPU 31
- +
- +#define FUCOP_EXIST_mskCP0EX ( 0x1 << FUCOP_EXIST_offCP0EX )
- +#define FUCOP_EXIST_mskCP1EX ( 0x1 << FUCOP_EXIST_offCP1EX )
- +#define FUCOP_EXIST_mskCP2EX ( 0x1 << FUCOP_EXIST_offCP2EX )
- +#define FUCOP_EXIST_mskCP3EX ( 0x1 << FUCOP_EXIST_offCP3EX )
- +#define FUCOP_EXIST_mskCP0ISFPU ( 0x1 << FUCOP_EXIST_offCP0ISFPU )
- +
- +/******************************************************************************
- + * ir0: PSW (Processor Status Word Register)
- + * ir1: IPSW (Interruption PSW Register)
- + * ir2: P_IPSW (Previous IPSW Register)
- + *****************************************************************************/
- +#define PSW_offGIE 0 /* Global Interrupt Enable */
- +#define PSW_offINTL 1 /* Interruption Stack Level */
- +#define PSW_offPOM 3 /* Processor Operation Mode, User/Superuser */
- +#define PSW_offBE 5 /* Endianness for data memory access, 1:MSB, 0:LSB */
- +#define PSW_offIT 6 /* Enable instruction address translation */
- +#define PSW_offDT 7 /* Enable data address translation */
- +#define PSW_offIME 8 /* Instruction Machine Error flag */
- +#define PSW_offDME 9 /* Data Machine Error flag */
- +#define PSW_offDEX 10 /* Debug Exception */
- +#define PSW_offHSS 11 /* Hardware Single Stepping */
- +#define PSW_offDRBE 12 /* Device Register Endian Mode */
- +#define PSW_offAEN 13 /* Audio ISA special feature */
- +#define PSW_offWBNA 14 /* Write Back Non-Allocate */
- +#define PSW_offIFCON 15 /* IFC On */
- +#define PSW_offCPL 16 /* Current Priority Level */
- +/* bit 19:31 reserved */
- +
- +#define PSW_mskGIE ( 0x1 << PSW_offGIE )
- +#define PSW_mskINTL ( 0x3 << PSW_offINTL )
- +#define PSW_mskPOM ( 0x3 << PSW_offPOM )
- +#define PSW_mskBE ( 0x1 << PSW_offBE )
- +#define PSW_mskIT ( 0x1 << PSW_offIT )
- +#define PSW_mskDT ( 0x1 << PSW_offDT )
- +#define PSW_mskIME ( 0x1 << PSW_offIME )
- +#define PSW_mskDME ( 0x1 << PSW_offDME )
- +#define PSW_mskDEX ( 0x1 << PSW_offDEX )
- +#define PSW_mskHSS ( 0x1 << PSW_offHSS )
- +#define PSW_mskDRBE ( 0x1 << PSW_offDRBE )
- +#define PSW_mskAEN ( 0x1 << PSW_offAEN )
- +#define PSW_mskWBNA ( 0x1 << PSW_offWBNA )
- +#define PSW_mskIFCON ( 0x1 << PSW_offIFCON )
- +#define PSW_mskCPL ( 0x7 << PSW_offCPL )
- +
- +#define PSW_SYSTEM ( 1 << PSW_offPOM )
- +#define PSW_INTL_1 ( 1 << PSW_offINTL )
- +#define PSW_CPL_NO ( 0 << PSW_offCPL )
- +#define PSW_CPL_ANY ( 7 << PSW_offCPL )
- +/******************************************************************************
- + * ir3: IVB (Interruption Vector Base Register)
- + *****************************************************************************/
- +/* bit 0:12 reserved */
- +#define IVB_offNIVIC 1 /* Number of input for IVIC Controller */
- +#define IVB_offIVIC_VER 11 /* IVIC Version */
- +#define IVB_offEVIC 13 /* External Vector Interrupt Controller mode */
- +#define IVB_offESZ 14 /* Size of each vector entry */
- +#define IVB_offIVBASE 16 /* BasePA of interrupt vector table */
- +
- +#define IVB_mskNIVIC ( 0x7 << IVB_offNIVIC )
- +#define IVB_mskIVIC_VER ( 0x3 << IVB_offIVIC_VER )
- +#define IVB_mskEVIC ( 0x1 << IVB_offEVIC )
- +#define IVB_mskESZ ( 0x3 << IVB_offESZ )
- +#define IVB_mskIVBASE ( 0xFFFF << IVB_offIVBASE )
- +
- +/******************************************************************************
- + * ir4: EVA (Exception Virtual Address Register)
- + * ir5: P_EVA (Previous EVA Register)
- + *****************************************************************************/
- +
- + /* This register contains the VA that causes the exception */
- +
- +/******************************************************************************
- + * ir6: ITYPE (Interruption Type Register)
- + * ir7: P_ITYPE (Previous ITYPE Register)
- + *****************************************************************************/
- +#define ITYPE_offETYPE 0 /* Exception Type */
- +#define ITYPE_offINST 4 /* Exception caused by insn fetch or data access */
- +/* bit 5:15 reserved */
- +#define ITYPE_offSWID 16 /* SWID of debugging exception */
- +/* bit 31:31 reserved */
- +
- +#define ITYPE_mskETYPE ( 0xF << ITYPE_offETYPE )
- +#define ITYPE_mskINST ( 0x1 << ITYPE_offINST )
- +#define ITYPE_mskSWID ( 0x7FFF << ITYPE_offSWID )
- +
- +/* Additional definitions for ITYPE register */
- +#define ITYPE_offSTYPE 16 /* Arithmetic Sub Type */
- +#define ITYPE_offCPID 20 /* Co-Processor ID which generate the exception */
- +
- +#define ITYPE_mskSTYPE ( 0xF << ITYPE_offSTYPE )
- +#define ITYPE_mskCPID ( 0x3 << ITYPE_offCPID )
- +
- +/******************************************************************************
- + * ir8: MERR (Machine Error Log Register)
- + *****************************************************************************/
- +/* bit 0:30 reserved */
- +#define MERR_offBUSERR 31 /* Bus error caused by a load insn */
- +
- +#define MERR_mskBUSERR ( 0x1 << MERR_offBUSERR )
- +
- +/******************************************************************************
- + * ir9: IPC (Interruption Program Counter Register)
- + * ir10: P_IPC (Previous IPC Register)
- + * ir11: OIPC (Overflow Interruption Program Counter Register)
- + *****************************************************************************/
- +
- + /* This is the shadow stack register of the Program Counter */
- +
- +/******************************************************************************
- + * ir12: P_P0 (Previous P0 Register)
- + * ir13: P_P1 (Previous P1 Register)
- + *****************************************************************************/
- +
- + /* These are shadow registers of $p0 and $p1 */
- +
- +/******************************************************************************
- + * ir14: INT_MASK (Interruption Masking Register)
- + *****************************************************************************/
- +#define INT_MASK_offH0IM 0 /* Hardware Interrupt 0 Mask bit */
- +#define INT_MASK_offH1IM 1 /* Hardware Interrupt 1 Mask bit */
- +#define INT_MASK_offH2IM 2 /* Hardware Interrupt 2 Mask bit */
- +#define INT_MASK_offH3IM 3 /* Hardware Interrupt 3 Mask bit */
- +#define INT_MASK_offH4IM 4 /* Hardware Interrupt 4 Mask bit */
- +#define INT_MASK_offH5IM 5 /* Hardware Interrupt 5 Mask bit */
- +/* bit 6:15 reserved */
- +#define INT_MASK_offSIM 16 /* Software Interrupt Mask bit */
- +/* bit 17:29 reserved */
- +#define INT_MASK_offIDIVZE 30 /* Enable detection for Divide-By-Zero */
- +#define INT_MASK_offDSSIM 31 /* Default Single Stepping Interruption Mask */
- +
- +#define INT_MASK_mskH0IM ( 0x1 << INT_MASK_offH0IM )
- +#define INT_MASK_mskH1IM ( 0x1 << INT_MASK_offH1IM )
- +#define INT_MASK_mskH2IM ( 0x1 << INT_MASK_offH2IM )
- +#define INT_MASK_mskH3IM ( 0x1 << INT_MASK_offH3IM )
- +#define INT_MASK_mskH4IM ( 0x1 << INT_MASK_offH4IM )
- +#define INT_MASK_mskH5IM ( 0x1 << INT_MASK_offH5IM )
- +#define INT_MASK_mskSIM ( 0x1 << INT_MASK_offSIM )
- +#define INT_MASK_mskIDIVZE ( 0x1 << INT_MASK_offIDIVZE )
- +#define INT_MASK_mskDSSIM ( 0x1 << INT_MASK_offDSSIM )
- +
- +/******************************************************************************
- + * ir15: INT_PEND (Interrupt Pending Register)
- + *****************************************************************************/
- +#define INT_PEND_offH0I 0 /* Hardware Interrupt 0 pending bit */
- +#define INT_PEND_offH1I 1 /* Hardware Interrupt 1 pending bit */
- +#define INT_PEND_offH2I 2 /* Hardware Interrupt 2 pending bit */
- +#define INT_PEND_offH3I 3 /* Hardware Interrupt 3 pending bit */
- +#define INT_PEND_offH4I 4 /* Hardware Interrupt 4 pending bit */
- +#define INT_PEND_offH5I 5 /* Hardware Interrupt 5 pending bit */
- +
- +#define INT_PEND_offCIPL 0 /* Current Interrupt Priority Level */
- +
- +/* bit 6:15 reserved */
- +#define INT_PEND_offSWI 16 /* Software Interrupt pending bit */
- +/* bit 17:31 reserved */
- +
- +#define INT_PEND_mskH0I ( 0x1 << INT_PEND_offH0I )
- +#define INT_PEND_mskH1I ( 0x1 << INT_PEND_offH1I )
- +#define INT_PEND_mskH2I ( 0x1 << INT_PEND_offH2I )
- +#define INT_PEND_mskH3I ( 0x1 << INT_PEND_offH3I )
- +#define INT_PEND_mskH4I ( 0x1 << INT_PEND_offH4I )
- +#define INT_PEND_mskH5I ( 0x1 << INT_PEND_offH5I )
- +#define INT_PEND_mskCIPL ( 0x1 << INT_PEND_offCIPL )
- +#define INT_PEND_mskSWI ( 0x1 << INT_PEND_offSWI )
- +
- +/******************************************************************************
- + * mr0: MMU_CTL (MMU Control Register)
- + *****************************************************************************/
- +#define MMU_CTL_offD 0 /* Default minimum page size */
- +#define MMU_CTL_offNTC0 1 /* Non-Translated Cachebility of partition 0 */
- +#define MMU_CTL_offNTC1 3 /* Non-Translated Cachebility of partition 1 */
- +#define MMU_CTL_offNTC2 5 /* Non-Translated Cachebility of partition 2 */
- +#define MMU_CTL_offNTC3 7 /* Non-Translated Cachebility of partition 3 */
- +#define MMU_CTL_offTBALCK 9 /* TLB all-lock resolution scheme */
- +#define MMU_CTL_offMPZIU 10 /* Multiple Page Size In Use bit */
- +#define MMU_CTL_offNTM0 11 /* Non-Translated VA to PA of partition 0 */
- +#define MMU_CTL_offNTM1 13 /* Non-Translated VA to PA of partition 1 */
- +#define MMU_CTL_offNTM2 15 /* Non-Translated VA to PA of partition 2 */
- +#define MMU_CTL_offNTM3 17 /* Non-Translated VA to PA of partition 3 */
- +/* bit 19:31 reserved */
- +
- +#define MMU_CTL_mskD ( 0x1 << MMU_CTL_offD )
- +#define MMU_CTL_mskNTC0 ( 0x3 << MMU_CTL_offNTC0 )
- +#define MMU_CTL_mskNTC1 ( 0x3 << MMU_CTL_offNTC1 )
- +#define MMU_CTL_mskNTC2 ( 0x3 << MMU_CTL_offNTC2 )
- +#define MMU_CTL_mskNTC3 ( 0x3 << MMU_CTL_offNTC3 )
- +#define MMU_CTL_mskTBALCK ( 0x1 << MMU_CTL_offTBALCK )
- +#define MMU_CTL_mskMPZIU ( 0x1 << MMU_CTL_offMPZIU )
- +#define MMU_CTL_mskNTM0 ( 0x3 << MMU_CTL_offNTM0 )
- +#define MMU_CTL_mskNTM1 ( 0x3 << MMU_CTL_offNTM1 )
- +#define MMU_CTL_mskNTM2 ( 0x3 << MMU_CTL_offNTM2 )
- +#define MMU_CTL_mskNTM3 ( 0x3 << MMU_CTL_offNTM3 )
- +
- +/******************************************************************************
- + * mr1: L1_PPTB (L1 Physical Page Table Base Register)
- + *****************************************************************************/
- +#define L1_PPTB_offNV 0 /* Enable Hardware Page Table Walker (HPTWK) */
- +/* bit 1:11 reserved */
- +#define L1_PPTB_offBASE 12 /* First level physical page table base address */
- +
- +#define L1_PPTB_mskNV ( 0x1 << L1_PPTB_offNV )
- +#define L1_PPTB_mskBASE ( 0xFFFFF << L1_PPTB_offBASE )
- +
- +/******************************************************************************
- + * mr2: TLB_VPN (TLB Access VPN Register)
- + *****************************************************************************/
- +/* bit 0:11 reserved */
- +#define TLB_VPN_offVPN 12 /* Virtual Page Number */
- +
- +#define TLB_VPN_mskVPN ( 0xFFFFF << TLB_VPN_offVPN )
- +
- +/******************************************************************************
- + * mr3: TLB_DATA (TLB Access Data Register)
- + *****************************************************************************/
- +#define TLB_DATA_offV 0 /* PTE is valid and present */
- +#define TLB_DATA_offM 1 /* Page read/write access privilege */
- +#define TLB_DATA_offD 4 /* Dirty bit */
- +#define TLB_DATA_offX 5 /* Executable bit */
- +#define TLB_DATA_offA 6 /* Access bit */
- +#define TLB_DATA_offG 7 /* Global page (shared across contexts) */
- +#define TLB_DATA_offC 8 /* Cacheability atribute */
- +/* bit 11:11 reserved */
- +#define TLB_DATA_offPPN 12 /* Phisical Page Number */
- +
- +#define TLB_DATA_mskV ( 0x1 << TLB_DATA_offV )
- +#define TLB_DATA_mskM ( 0x7 << TLB_DATA_offM )
- +#define TLB_DATA_mskD ( 0x1 << TLB_DATA_offD )
- +#define TLB_DATA_mskX ( 0x1 << TLB_DATA_offX )
- +#define TLB_DATA_mskA ( 0x1 << TLB_DATA_offA )
- +#define TLB_DATA_mskG ( 0x1 << TLB_DATA_offG )
- +#define TLB_DATA_mskC ( 0x7 << TLB_DATA_offC )
- +#define TLB_DATA_mskPPN ( 0xFFFFF << TLB_DATA_offPPN )
- +
- +/******************************************************************************
- + * mr4: TLB_MISC (TLB Access Misc Register)
- + *****************************************************************************/
- +#define TLB_MISC_offACC_PSZ 0 /* Page size of a PTE entry */
- +#define TLB_MISC_offCID 4 /* Context id */
- +/* bit 13:31 reserved */
- +
- +#define TLB_MISC_mskACC_PSZ ( 0xF << TLB_MISC_offACC_PSZ )
- +#define TLB_MISC_mskCID ( 0x1FF << TLB_MISC_offCID )
- +
- +/******************************************************************************
- + * mr5: VLPT_IDX (Virtual Linear Page Table Index Register)
- + *****************************************************************************/
- +#define VLPT_IDX_offZERO 0 /* Always 0 */
- +#define VLPT_IDX_offEVPN 2 /* Exception Virtual Page Number */
- +#define VLPT_IDX_offVLPTB 22 /* Base VA of VLPT */
- +
- +#define VLPT_IDX_mskZERO ( 0x3 << VLPT_IDX_offZERO )
- +#define VLPT_IDX_mskEVPN ( 0xFFFFF << VLPT_IDX_offEVPN )
- +#define VLPT_IDX_mskVLPTB ( 0x3FF << VLPT_IDX_offVLPTB )
- +
- +/******************************************************************************
- + * mr6: ILMB (Instruction Local Memory Base Register)
- + *****************************************************************************/
- +#define ILMB_offIEN 0 /* Enable ILM */
- +#define ILMB_offILMSZ 1 /* Size of ILM */
- +/* bit 5:19 reserved */
- +#define ILMB_offIBPA 20 /* Base PA of ILM */
- +
- +#define ILMB_mskIEN ( 0x1 << ILMB_offIEN )
- +#define ILMB_mskILMSZ ( 0xF << ILMB_offILMSZ )
- +#define ILMB_mskIBPA ( 0xFFF << ILMB_offIBPA )
- +
- +/******************************************************************************
- + * mr7: DLMB (Data Local Memory Base Register)
- + *****************************************************************************/
- +#define DLMB_offDEN 0 /* Enable DLM */
- +#define DLMB_offDLMSZ 1 /* Size of DLM */
- +#define DLMB_offDBM 5 /* Enable Double-Buffer Mode for DLM */
- +#define DLMB_offDBB 6 /* Double-buffer bank which can be accessed by the processor */
- +/* bit 7:19 reserved */
- +#define DLMB_offDBPA 20 /* Base PA of DLM */
- +
- +#define DLMB_mskDEN ( 0x1 << DLMB_offDEN )
- +#define DLMB_mskDLMSZ ( 0xF << DLMB_offDLMSZ )
- +#define DLMB_mskDBM ( 0x1 << DLMB_offDBM )
- +#define DLMB_mskDBB ( 0x1 << DLMB_offDBB )
- +#define DLMB_mskDBPA ( 0xFFF << DLMB_offDBPA )
- +
- +/******************************************************************************
- + * mr8: CACHE_CTL (Cache Control Register)
- + *****************************************************************************/
- +#define CACHE_CTL_offIC_EN 0 /* Enable I-cache */
- +#define CACHE_CTL_offDC_EN 1 /* Enable D-cache */
- +#define CACHE_CTL_offICALCK 2 /* I-cache all-lock resolution scheme */
- +#define CACHE_CTL_offDCALCK 3 /* D-cache all-lock resolution scheme */
- +#define CACHE_CTL_offDCCWF 4 /* Enable D-cache Critical Word Forwarding */
- +#define CACHE_CTL_offDCPMW 5 /* Enable D-cache concurrent miss and write-back processing */
- +/* bit 6:31 reserved */
- +
- +#define CACHE_CTL_mskIC_EN ( 0x1 << CACHE_CTL_offIC_EN )
- +#define CACHE_CTL_mskDC_EN ( 0x1 << CACHE_CTL_offDC_EN )
- +#define CACHE_CTL_mskICALCK ( 0x1 << CACHE_CTL_offICALCK )
- +#define CACHE_CTL_mskDCALCK ( 0x1 << CACHE_CTL_offDCALCK )
- +#define CACHE_CTL_mskDCCWF ( 0x1 << CACHE_CTL_offDCCWF )
- +#define CACHE_CTL_mskDCPMW ( 0x1 << CACHE_CTL_offDCPMW )
- +
- +/******************************************************************************
- + * mr9: HSMP_SADDR (High Speed Memory Port Starting Address)
- + *****************************************************************************/
- +#define HSMP_SADDR_offEN 0 /* Enable control bit for the High Speed Memory port */
- +/* bit 1:19 reserved */
- +
- +#define HSMP_SADDR_offRANGE 1 /* Denote the address range (only defined in HSMP v2 ) */
- +#define HSMP_SADDR_offSADDR 20 /* Starting base PA of the High Speed Memory Port region */
- +
- +#define HSMP_SADDR_mskEN ( 0x1 << HSMP_SADDR_offEN )
- +#define HSMP_SADDR_mskRANGE ( 0xFFF << HSMP_SADDR_offRANGE )
- +#define HSMP_SADDR_mskSADDR ( 0xFFF << HSMP_SADDR_offSADDR )
- +
- +/******************************************************************************
- + * mr10: HSMP_EADDR (High Speed Memory Port Ending Address)
- + *****************************************************************************/
- +/* bit 0:19 reserved */
- +#define HSMP_EADDR_offEADDR 20
- +
- +#define HSMP_EADDR_mskEADDR ( 0xFFF << HSMP_EADDR_offEADDR )
- +
- +/******************************************************************************
- + * dr0+(n*5): BPCn (n=0-7) (Breakpoint Control Register)
- + *****************************************************************************/
- +#define BPC_offWP 0 /* Configuration of BPAn */
- +#define BPC_offEL 1 /* Enable BPAn */
- +#define BPC_offS 2 /* Data address comparison for a store instruction */
- +#define BPC_offP 3 /* Compared data address is PA */
- +#define BPC_offC 4 /* CID value is compared with the BPCIDn register */
- +#define BPC_offBE0 5 /* Enable byte mask for the comparison with register */
- +#define BPC_offBE1 6 /* Enable byte mask for the comparison with register */
- +#define BPC_offBE2 7 /* Enable byte mask for the comparison with register */
- +#define BPC_offBE3 8 /* Enable byte mask for the comparison with register */
- +#define BPC_offT 9 /* Enable breakpoint Embedded Tracer triggering operation */
- +
- +#define BPC_mskWP ( 0x1 << BPC_offWP )
- +#define BPC_mskEL ( 0x1 << BPC_offEL )
- +#define BPC_mskS ( 0x1 << BPC_offS )
- +#define BPC_mskP ( 0x1 << BPC_offP )
- +#define BPC_mskC ( 0x1 << BPC_offC )
- +#define BPC_mskBE0 ( 0x1 << BPC_offBE0 )
- +#define BPC_mskBE1 ( 0x1 << BPC_offBE1 )
- +#define BPC_mskBE2 ( 0x1 << BPC_offBE2 )
- +#define BPC_mskBE3 ( 0x1 << BPC_offBE3 )
- +#define BPC_mskT ( 0x1 << BPC_offT )
- +
- +/******************************************************************************
- + * dr1+(n*5): BPAn (n=0-7) (Breakpoint Address Register)
- + *****************************************************************************/
- +
- + /* These registers contain break point address */
- +
- +/******************************************************************************
- + * dr2+(n*5): BPAMn (n=0-7) (Breakpoint Address Mask Register)
- + *****************************************************************************/
- +
- + /* These registerd contain the address comparison mask for the BPAn register */
- +
- +/******************************************************************************
- + * dr3+(n*5): BPVn (n=0-7) Breakpoint Data Value Register
- + *****************************************************************************/
- +
- + /* The BPVn register contains the data value that will be compared with the
- + * incoming load/store data value */
- +
- +/******************************************************************************
- + * dr4+(n*5): BPCIDn (n=0-7) (Breakpoint Context ID Register)
- + *****************************************************************************/
- +#define BPCID_offCID 0 /* CID that will be compared with a process's CID */
- +/* bit 9:31 reserved */
- +
- +#define BPCID_mskCID ( 0x1FF << BPCID_offCID )
- +
- +/******************************************************************************
- + * dr40: EDM_CFG (EDM Configuration Register)
- + *****************************************************************************/
- +#define EDM_CFG_offBC 0 /* Number of hardware breakpoint sets implemented */
- +#define EDM_CFG_offDIMU 3 /* Debug Instruction Memory Unit exists */
- +/* bit 4:15 reserved */
- +#define EDM_CFG_offVER 16 /* EDM version */
- +
- +#define EDM_CFG_mskBC ( 0x7 << EDM_CFG_offBC )
- +#define EDM_CFG_mskDIMU ( 0x1 << EDM_CFG_offDIMU )
- +#define EDM_CFG_mskVER ( 0xFFFF << EDM_CFG_offVER )
- +
- +/******************************************************************************
- + * dr41: EDMSW (EDM Status Word)
- + *****************************************************************************/
- +#define EDMSW_offWV 0 /* Write Valid */
- +#define EDMSW_offRV 1 /* Read Valid */
- +#define EDMSW_offDE 2 /* Debug exception has occurred for this core */
- +/* bit 3:31 reserved */
- +
- +#define EDMSW_mskWV ( 0x1 << EDMSW_offWV )
- +#define EDMSW_mskRV ( 0x1 << EDMSW_offRV )
- +#define EDMSW_mskDE ( 0x1 << EDMSW_offDE )
- +
- +/******************************************************************************
- + * dr42: EDM_CTL (EDM Control Register)
- + *****************************************************************************/
- +/* bit 0:30 reserved */
- +#define EDM_CTL_offV3_EDM_MODE 6 /* EDM compatibility control bit */
- +#define EDM_CTL_offDEH_SEL 31 /* Controls where debug exception is directed to */
- +
- +#define EDM_CTL_mskV3_EDM_MODE ( 0x1 << EDM_CTL_offV3_EDM_MODE )
- +#define EDM_CTL_mskDEH_SEL ( 0x1 << EDM_CTL_offDEH_SEL )
- +
- +/******************************************************************************
- + * dr43: EDM_DTR (EDM Data Transfer Register)
- + *****************************************************************************/
- +
- + /* This is used to exchange data between the embedded EDM logic
- + * and the processor core */
- +
- +/******************************************************************************
- + * dr44: BPMTC (Breakpoint Match Trigger Counter Register)
- + *****************************************************************************/
- +#define BPMTC_offBPMTC 0 /* Breakpoint match trigger counter value */
- +/* bit 16:31 reserved */
- +
- +#define BPMTC_mskBPMTC ( 0xFFFF << BPMTC_offBPMTC )
- +
- +/******************************************************************************
- + * dr45: DIMBR (Debug Instruction Memory Base Register)
- + *****************************************************************************/
- +/* bit 0:11 reserved */
- +#define DIMBR_offDIMB 12 /* Base address of the Debug Instruction Memory (DIM) */
- +#define DIMBR_mskDIMB ( 0xFFFFF << DIMBR_offDIMB )
- +
- +/******************************************************************************
- + * dr46: TECR0(Trigger Event Control register 0)
- + * dr47: TECR1 (Trigger Event Control register 1)
- + *****************************************************************************/
- +#define TECR_offBP 0 /* Controld which BP is used as a trigger source */
- +#define TECR_offNMI 8 /* Use NMI as a trigger source */
- +#define TECR_offHWINT 9 /* Corresponding interrupt is used as a trigger source */
- +#define TECR_offEVIC 15 /* Enable HWINT as a trigger source in EVIC mode */
- +#define TECR_offSYS 16 /* Enable SYSCALL instruction as a trigger source */
- +#define TECR_offDBG 17 /* Enable debug exception as a trigger source */
- +#define TECR_offMRE 18 /* Enable MMU related exception as a trigger source */
- +#define TECR_offE 19 /* An exception is used as a trigger source */
- +/* bit 20:30 reserved */
- +#define TECR_offL 31 /* Link/Cascade TECR0 trigger event to TECR1 trigger event */
- +
- +#define TECR_mskBP ( 0xFF << TECR_offBP )
- +#define TECR_mskNMI ( 0x1 << TECR_offBNMI )
- +#define TECR_mskHWINT ( 0x3F << TECR_offBHWINT )
- +#define TECR_mskEVIC ( 0x1 << TECR_offBEVIC )
- +#define TECR_mskSYS ( 0x1 << TECR_offBSYS )
- +#define TECR_mskDBG ( 0x1 << TECR_offBDBG )
- +#define TECR_mskMRE ( 0x1 << TECR_offBMRE )
- +#define TECR_mskE ( 0x1 << TECR_offE )
- +#define TECR_mskL ( 0x1 << TECR_offL )
- +
- +/******************************************************************************
- + * pfr0-2: PFMC0-2 (Performance Counter Register 0-2)
- + *****************************************************************************/
- +
- + /* These registers contains performance event count */
- +
- +/******************************************************************************
- + * pfr3: PFM_CTL (Performance Counter Control Register)
- + *****************************************************************************/
- +#define PFM_CTL_offEN0 0 /* Enable PFMC0 */
- +#define PFM_CTL_offEN1 1 /* Enable PFMC1 */
- +#define PFM_CTL_offEN2 2 /* Enable PFMC2 */
- +#define PFM_CTL_offIE0 3 /* Enable interrupt for PFMC0 */
- +#define PFM_CTL_offIE1 4 /* Enable interrupt for PFMC1 */
- +#define PFM_CTL_offIE2 5 /* Enable interrupt for PFMC2 */
- +#define PFM_CTL_offOVF0 6 /* Overflow bit of PFMC0 */
- +#define PFM_CTL_offOVF1 7 /* Overflow bit of PFMC1 */
- +#define PFM_CTL_offOVF2 8 /* Overflow bit of PFMC2 */
- +#define PFM_CTL_offKS0 9 /* Enable superuser mode event counting for PFMC0 */
- +#define PFM_CTL_offKS1 10 /* Enable superuser mode event counting for PFMC1 */
- +#define PFM_CTL_offKS2 11 /* Enable superuser mode event counting for PFMC2 */
- +#define PFM_CTL_offKU0 12 /* Enable user mode event counting for PFMC0 */
- +#define PFM_CTL_offKU1 13 /* Enable user mode event counting for PFMC1 */
- +#define PFM_CTL_offKU2 14 /* Enable user mode event counting for PFMC2 */
- +#define PFM_CTL_offSEL0 15 /* The event selection for PFMC0 */
- +#define PFM_CTL_offSEL1 21 /* The event selection for PFMC1 */
- +#define PFM_CTL_offSEL2 27 /* The event selection for PFMC2 */
- +/* bit 28:31 reserved */
- +
- +#define PFM_CTL_mskEN0 ( 0x01 << PFM_CTL_offEN0 )
- +#define PFM_CTL_mskEN1 ( 0x01 << PFM_CTL_offEN1 )
- +#define PFM_CTL_mskEN2 ( 0x01 << PFM_CTL_offEN2 )
- +#define PFM_CTL_mskIE0 ( 0x01 << PFM_CTL_offIE0 )
- +#define PFM_CTL_mskIE1 ( 0x01 << PFM_CTL_offIE1 )
- +#define PFM_CTL_mskIE2 ( 0x01 << PFM_CTL_offIE2 )
- +#define PFM_CTL_mskOVF0 ( 0x01 << PFM_CTL_offOVF0 )
- +#define PFM_CTL_mskOVF1 ( 0x01 << PFM_CTL_offOVF1 )
- +#define PFM_CTL_mskOVF2 ( 0x01 << PFM_CTL_offOVF2 )
- +#define PFM_CTL_mskKS0 ( 0x01 << PFM_CTL_offKS0 )
- +#define PFM_CTL_mskKS1 ( 0x01 << PFM_CTL_offKS1 )
- +#define PFM_CTL_mskKS2 ( 0x01 << PFM_CTL_offKS2 )
- +#define PFM_CTL_mskKU0 ( 0x01 << PFM_CTL_offKU0 )
- +#define PFM_CTL_mskKU1 ( 0x01 << PFM_CTL_offKU1 )
- +#define PFM_CTL_mskKU2 ( 0x01 << PFM_CTL_offKU2 )
- +#define PFM_CTL_mskSEL0 ( 0x01 << PFM_CTL_offSEL0 )
- +#define PFM_CTL_mskSEL1 ( 0x3F << PFM_CTL_offSEL1 )
- +#define PFM_CTL_mskSEL2 ( 0x3F << PFM_CTL_offSEL2 )
- +
- +/******************************************************************************
- + * SDZ_CTL (Structure Downsizing Control Register)
- + *****************************************************************************/
- +#define SDZ_CTL_offICDZ 0 /* I-cache downsizing control */
- +#define SDZ_CTL_offDCDZ 3 /* D-cache downsizing control */
- +#define SDZ_CTL_offMTBDZ 6 /* MTLB downsizing control */
- +#define SDZ_CTL_offBTBDZ 9 /* Branch Target Table downsizing control */
- +/* bit 12:31 reserved */
- +#define SDZ_CTL_mskICDZ ( 0x07 << SDZ_CTL_offICDZ )
- +#define SDZ_CTL_mskDCDZ ( 0x07 << SDZ_CTL_offDCDZ )
- +#define SDZ_CTL_mskMTBDZ ( 0x07 << SDZ_CTL_offMTBDZ )
- +#define SDZ_CTL_mskBTBDZ ( 0x07 << SDZ_CTL_offBTBDZ )
- +
- +/******************************************************************************
- + * N12MISC_CTL (N12 Miscellaneous Control Register)
- + *****************************************************************************/
- +#define N12MISC_CTL_offBTB 0 /* Disable Branch Target Buffer */
- +#define N12MISC_CTL_offRTP 1 /* Disable Return Target Predictor */
- +#define N12MISC_CTL_offPTEPF 2 /* Disable HPTWK L2 PTE pefetch */
- +/* bit 3:31 reserved */
- +
- +#define N12MISC_CTL_makBTB ( 0x1 << N12MISC_CTL_offBTB )
- +#define N12MISC_CTL_makRTP ( 0x1 << N12MISC_CTL_offRTP )
- +#define N12MISC_CTL_makPTEPF ( 0x1 << N12MISC_CTL_offPTEPF )
- +
- +/******************************************************************************
- + * PRUSR_ACC_CTL (Privileged Resource User Access Control Registers)
- + *****************************************************************************/
- +#define PRUSR_ACC_CTL_offDMA_EN 0 /* Allow user mode access of DMA registers */
- +#define PRUSR_ACC_CTL_offPFM_EN 1 /* Allow user mode access of PFM registers */
- +
- +#define PRUSR_ACC_CTL_mskDMA_EN ( 0x1 << PRUSR_ACC_CTL_offDMA_EN )
- +#define PRUSR_ACC_CTL_mskPFM_EN ( 0x1 << PRUSR_ACC_CTL_offPFM_EN )
- +
- +/******************************************************************************
- + * dmar0: DMA_CFG (DMA Configuration Register)
- + *****************************************************************************/
- +#define DMA_CFG_offNCHN 0 /* The number of DMA channels implemented */
- +#define DMA_CFG_offUNEA 2 /* Un-aligned External Address transfer feature */
- +#define DMA_CFG_off2DET 3 /* 2-D Element Transfer feature */
- +/* bit 4:15 reserved */
- +#define DMA_CFG_offVER 16 /* DMA architecture and implementation version */
- +
- +#define DMA_CFG_mskNCHN ( 0x3 << DMA_CFG_offNCHN )
- +#define DMA_CFG_mskUNEA ( 0x1 << DMA_CFG_offUNEA )
- +#define DMA_CFG_msk2DET ( 0x1 << DMA_CFG_off2DET )
- +#define DMA_CFG_mskVER ( 0xFFFF << DMA_CFG_offVER )
- +
- +/******************************************************************************
- + * dmar1: DMA_GCSW (DMA Global Control and Status Word Register)
- + *****************************************************************************/
- +#define DMA_GCSW_offC0STAT 0 /* DMA channel 0 state */
- +#define DMA_GCSW_offC1STAT 3 /* DMA channel 1 state */
- +/* bit 6:11 reserved */
- +#define DMA_GCSW_offC0INT 12 /* DMA channel 0 generate interrupt */
- +#define DMA_GCSW_offC1INT 13 /* DMA channel 1 generate interrupt */
- +/* bit 14:30 reserved */
- +#define DMA_GCSW_offEN 31 /* Enable DMA engine */
- +
- +#define DMA_GCSW_mskC0STAT ( 0x7 << DMA_GCSW_offC0STAT )
- +#define DMA_GCSW_mskC1STAT ( 0x7 << DMA_GCSW_offC1STAT )
- +#define DMA_GCSW_mskC0INT ( 0x1 << DMA_GCSW_offC0INT )
- +#define DMA_GCSW_mskC1INT ( 0x1 << DMA_GCSW_offC1INT )
- +#define DMA_GCSW_mskEN ( 0x1 << DMA_GCSW_offEN )
- +
- +/******************************************************************************
- + * dmar2: DMA_CHNSEL (DMA Channel Selection Register)
- + *****************************************************************************/
- +#define DMA_CHNSEL_offCHAN 0 /* Selected channel number */
- +/* bit 2:31 reserved */
- +
- +#define DMA_CHNSEL_mskCHAN ( 0x3 << DMA_CHNSEL_offCHAN )
- +
- +/******************************************************************************
- + * dmar3: DMA_ACT (DMA Action Register)
- + *****************************************************************************/
- +#define DMA_ACT_offACMD 0 /* DMA Action Command */
- +/* bit 2:31 reserved */
- +#define DMA_ACT_mskACMD ( 0x3 << DMA_ACT_offACMD )
- +
- +/******************************************************************************
- + * dmar4: DMA_SETUP (DMA Setup Register)
- + *****************************************************************************/
- +#define DMA_SETUP_offLM 0 /* Local Memory Selection */
- +#define DMA_SETUP_offTDIR 1 /* Transfer Direction */
- +#define DMA_SETUP_offTES 2 /* Transfer Element Size */
- +#define DMA_SETUP_offESTR 4 /* External memory transfer Stride */
- +#define DMA_SETUP_offCIE 16 /* Interrupt Enable on Completion */
- +#define DMA_SETUP_offSIE 17 /* Interrupt Enable on explicit Stop */
- +#define DMA_SETUP_offEIE 18 /* Interrupt Enable on Error */
- +#define DMA_SETUP_offUE 19 /* Enable the Un-aligned External Address */
- +#define DMA_SETUP_off2DE 20 /* Enable the 2-D External Transfer */
- +#define DMA_SETUP_offCOA 21 /* Transfer Coalescable */
- +/* bit 22:31 reserved */
- +
- +#define DMA_SETUP_mskLM ( 0x1 << DMA_SETUP_offLM )
- +#define DMA_SETUP_mskTDIR ( 0x1 << DMA_SETUP_offTDIR )
- +#define DMA_SETUP_mskTES ( 0x3 << DMA_SETUP_offTES )
- +#define DMA_SETUP_mskESTR ( 0xFFF << DMA_SETUP_offESTR )
- +#define DMA_SETUP_mskCIE ( 0x1 << DMA_SETUP_offCIE )
- +#define DMA_SETUP_mskSIE ( 0x1 << DMA_SETUP_offSIE )
- +#define DMA_SETUP_mskEIE ( 0x1 << DMA_SETUP_offEIE )
- +#define DMA_SETUP_mskUE ( 0x1 << DMA_SETUP_offUE )
- +#define DMA_SETUP_msk2DE ( 0x1 << DMA_SETUP_off2DE )
- +#define DMA_SETUP_mskCOA ( 0x1 << DMA_SETUP_offCOA )
- +
- +/******************************************************************************
- + * dmar5: DMA_ISADDR (DMA Internal Start Address Register)
- + *****************************************************************************/
- +#define DMA_ISADDR_offISADDR 0 /* Internal Start Address */
- +/* bit 20:31 reserved */
- +#define DMA_ISADDR_mskISADDR ( 0xFFFFF << DMA_ISADDR_offISADDR )
- +
- +/******************************************************************************
- + * dmar6: DMA_ESADDR (DMA External Start Address Register)
- + *****************************************************************************/
- +/* This register holds External Start Address */
- +
- +/******************************************************************************
- + * dmar7: DMA_TCNT (DMA Transfer Element Count Register)
- + *****************************************************************************/
- +#define DMA_TCNT_offTCNT 0 /* DMA transfer element count */
- +/* bit 18:31 reserved */
- +#define DMA_TCNT_mskTCNT ( 0x3FFFF << DMA_TCNT_offTCNT )
- +
- +/******************************************************************************
- + * dmar8: DMA_STATUS (DMA Status Register)
- + *****************************************************************************/
- +#define DMA_STATUS_offSTAT 0 /* DMA channel state */
- +#define DMA_STATUS_offSTUNA 3 /* Un-aligned error on External Stride value */
- +#define DMA_STATUS_offDERR 4 /* DMA Transfer Disruption Error */
- +#define DMA_STATUS_offEUNA 5 /* Un-aligned error on the External address */
- +#define DMA_STATUS_offIUNA 6 /* Un-aligned error on the Internal address */
- +#define DMA_STATUS_offIOOR 7 /* Out-Of-Range error on the Internal address */
- +#define DMA_STATUS_offEBUS 8 /* Bus Error on an External DMA transfer */
- +#define DMA_STATUS_offESUP 9 /* DMA setup error */
- +/* bit 10:31 reserved */
- +
- +#define DMA_STATUS_mskSTAT ( 0x7 << DMA_STATUS_offSTAT )
- +#define DMA_STATUS_mskSTUNA ( 0x1 << DMDMA_STATUS_offSTUNA )
- +#define DMA_STATUS_mskDERR ( 0x1 << DMDMA_STATUS_offDERR )
- +#define DMA_STATUS_mskEUNA ( 0x1 << DMDMA_STATUS_offEUNA )
- +#define DMA_STATUS_mskIUNA ( 0x1 << DMDMA_STATUS_offIUNA )
- +#define DMA_STATUS_mskIOOR ( 0x1 << DMDMA_STATUS_offIOOR )
- +#define DMA_STATUS_mskEBUS ( 0x1 << DMDMA_STATUS_offEBUS )
- +#define DMA_STATUS_mskESUP ( 0x1 << DMDMA_STATUS_offESUP )
- +
- +/******************************************************************************
- + * dmar9: DMA_2DSET (DMA 2D Setup Register)
- + *****************************************************************************/
- +#define DMA_2DSET_offWECNT 0 /* The Width Element Count for a 2-D region */
- +#define DMA_2DSET_offHTSTR 16 /* The Height Stride for a 2-D region */
- +
- +#define DMA_2DSET_mskHTSTR ( 0xFFFF << DMA_2DSET_offHTSTR )
- +#define DMA_2DSET_mskWECNT ( 0xFFFF << DMA_2DSET_offWECNT )
- +
- +/******************************************************************************
- + * dmar10: DMA_2DSCTL (DMA 2D Startup Control Register)
- + *****************************************************************************/
- +#define DMA_2DSCTL_offSTWECNT 0 /* Startup Width Element Count for a 2-D region */
- +/* bit 16:31 reserved */
- +
- +#define DMA_2DSCTL_mskSTWECNT ( 0xFFFF << DMA_2DSCTL_offSTWECNT )
- +
- +/******************************************************************************
- + * fpcsr: FPCSR (Floating-Point Control Status Register)
- + *****************************************************************************/
- +#define FPCSR_offRM 0
- +#define FPCSR_offIVO 2
- +#define FPCSR_offDBZ 3
- +#define FPCSR_offOVF 4
- +#define FPCSR_offUDF 5
- +#define FPCSR_offIEX 6
- +#define FPCSR_offIVOE 7
- +#define FPCSR_offDBZE 8
- +#define FPCSR_offOVFE 9
- +#define FPCSR_offUDFE 10
- +#define FPCSR_offIEXE 11
- +#define FPCSR_offDNZ 12
- +#define FPCSR_offIVOT 13
- +#define FPCSR_offDBZT 14
- +#define FPCSR_offOVFT 15
- +#define FPCSR_offUDFT 16
- +#define FPCSR_offIEXT 17
- +#define FPCSR_offDNIT 18
- +#define FPCSR_offRIT 19
- +
- +#define FPCSR_mskRM ( 0x3 << FPCSR_offRM )
- +#define FPCSR_mskIVO ( 0x1 << FPCSR_offIVO )
- +#define FPCSR_mskDBZ ( 0x1 << FPCSR_offDBZ )
- +#define FPCSR_mskOVF ( 0x1 << FPCSR_offOVF )
- +#define FPCSR_mskUDF ( 0x1 << FPCSR_offUDF )
- +#define FPCSR_mskIEX ( 0x1 << FPCSR_offIEX )
- +#define FPCSR_mskIVOE ( 0x1 << FPCSR_offIVOE )
- +#define FPCSR_mskDBZE ( 0x1 << FPCSR_offDBZE )
- +#define FPCSR_mskOVFE ( 0x1 << FPCSR_offOVFE )
- +#define FPCSR_mskUDFE ( 0x1 << FPCSR_offUDFE )
- +#define FPCSR_mskIEXE ( 0x1 << FPCSR_offIEXE )
- +#define FPCSR_mskDNZ ( 0x1 << FPCSR_offDNZ )
- +#define FPCSR_mskIVOT ( 0x1 << FPCSR_offIVOT )
- +#define FPCSR_mskDBZT ( 0x1 << FPCSR_offDBZT )
- +#define FPCSR_mskOVFT ( 0x1 << FPCSR_offOVFT )
- +#define FPCSR_mskUDFT ( 0x1 << FPCSR_offUDFT )
- +#define FPCSR_mskIEXT ( 0x1 << FPCSR_offIEXT )
- +#define FPCSR_mskDNIT ( 0x1 << FPCSR_offDNIT )
- +#define FPCSR_mskRIT ( 0x1 << FPCSR_offRIT )
- +#define FPCSR_mskALL (FPCSR_mskIVO | FPCSR_mskDBZ | FPCSR_mskOVF | FPCSR_mskUDF | FPCSR_mskIEX)
- +#define FPCSR_mskALLE (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE | FPCSR_mskUDFE | FPCSR_mskIEXE)
- +#define FPCSR_mskALLT (FPCSR_mskIVOT | FPCSR_mskDBZT | FPCSR_mskOVFT | FPCSR_mskUDFT | FPCSR_mskIEXT |FPCSR_mskDNIT | FPCSR_mskRIT)
- +
- +/******************************************************************************
- + * fpcfg: FPCFG (Floating-Point Configuration Register)
- + *****************************************************************************/
- +#define FPCFG_offSP 0
- +#define FPCFG_offDP 1
- +#define FPCFG_offFREG 2
- +#define FPCFG_offFMA 4
- +#define FPCFG_offIMVER 22
- +#define FPCFG_offAVER 27
- +
- +#define FPCFG_mskSP ( 0x1 << FPCFG_offSP )
- +#define FPCFG_mskDP ( 0x1 << FPCFG_offDP )
- +#define FPCFG_mskFREG ( 0x3 << FPCFG_offFREG )
- +#define FPCFG_mskFMA ( 0x1 << FPCFG_offFMA )
- +#define FPCFG_mskIMVER ( 0x1F << FPCFG_offIMVER )
- +#define FPCFG_mskAVER ( 0x1F << FPCFG_offAVER )
- +
- +/******************************************************************************
- + * fucpr: FUCOP_CTL (FPU and Coprocessor Enable Control Register)
- + *****************************************************************************/
- +#define FUCOP_CTL_offCP0EN 0
- +#define FUCOP_CTL_offCP1EN 1
- +#define FUCOP_CTL_offCP2EN 2
- +#define FUCOP_CTL_offCP3EN 3
- +#define FUCOP_CTL_offAUEN 31
- +
- +#define FUCOP_CTL_mskCP0EN ( 0x1 << FUCOP_CTL_offCP0EN )
- +#define FUCOP_CTL_mskCP1EN ( 0x1 << FUCOP_CTL_offCP1EN )
- +#define FUCOP_CTL_mskCP2EN ( 0x1 << FUCOP_CTL_offCP2EN )
- +#define FUCOP_CTL_mskCP3EN ( 0x1 << FUCOP_CTL_offCP3EN )
- +#define FUCOP_CTL_mskAUEN ( 0x1 << FUCOP_CTL_offAUEN )
- +
- +#endif /* __NDS32_BITFIELD_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/bitops.h linux-3.4.110/arch/nds32/include/asm/bitops.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/bitops.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/bitops.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,256 @@
- +/*
- + * linux/arch/nds32/include/asm/bitops.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_BITOPS_H__
- +#define __NDS32_BITOPS_H__
- +
- +#if defined(CONFIG_SMP) || !defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
- +
- +/*
- +#include <linux/irqflags.h>
- +
- +static inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *p)
- +{
- + unsigned long flags;
- + unsigned long mask = 1UL << (bit & 31);
- +
- + p += bit >> 5;
- +
- + raw_local_irq_save(flags);
- + *p |= mask;
- + raw_local_irq_restore(flags);
- +}
- +
- +static inline void ____atomic_clear_bit(unsigned int bit, volatile unsigned long *p)
- +{
- + unsigned long flags;
- + unsigned long mask = 1UL << (bit & 31);
- +
- + p += bit >> 5;
- +
- + raw_local_irq_save(flags);
- + *p &= ~mask;
- + raw_local_irq_restore(flags);
- +}
- +
- +static inline void ____atomic_change_bit(unsigned int bit, volatile unsigned long *p)
- +{
- + unsigned long flags;
- + unsigned long mask = 1UL << (bit & 31);
- +
- + p += bit >> 5;
- +
- + raw_local_irq_save(flags);
- + *p ^= mask;
- + raw_local_irq_restore(flags);
- +}
- +
- +static inline int
- +____atomic_test_and_set_bit(unsigned int bit, volatile unsigned long *p)
- +{
- + unsigned long flags;
- + unsigned int res;
- + unsigned long mask = 1UL << (bit & 31);
- +
- + p += bit >> 5;
- +
- + raw_local_irq_save(flags);
- + res = *p;
- + *p = res | mask;
- + raw_local_irq_restore(flags);
- +
- + return (res & mask) != 0;
- +}
- +static inline int
- +____atomic_test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
- +{
- + unsigned long flags;
- + unsigned int res;
- + unsigned long mask = 1UL << (bit & 31);
- +
- + p += bit >> 5;
- +
- + raw_local_irq_save(flags);
- + res = *p;
- + *p = res & ~mask;
- + raw_local_irq_restore(flags);
- +
- + return (res & mask) != 0;
- +}
- +
- +static inline int
- +____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
- +{
- + unsigned long flags;
- + unsigned int res;
- + unsigned long mask = 1UL << (bit & 31);
- +
- + p += bit >> 5;
- +
- + raw_local_irq_save(flags);
- + res = *p;
- + *p = res ^ mask;
- + raw_local_irq_restore(flags);
- +
- + return (res & mask) != 0;
- +}
- +
- +#include <asm-generic/bitops/non-atomic.h>
- +#ifndef CONFIG_SMP
- +#define ATOMIC_BITOP(name,nr,p) \
- + (__builtin_constant_p(nr) ? ____atomic_##name(nr, p) : _##name(nr,p))
- +#else
- +#define ATOMIC_BITOP(name,nr,p) _##name(nr,p)
- +#endif
- +
- +#define set_bit(nr,p) ATOMIC_BITOP(set_bit,nr,p)
- +*/
- +
- +static inline void set_bit(int nr,volatile unsigned long *addr)
- +{
- + unsigned long mask = BIT_MASK(nr);
- + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
- + unsigned long tmp;
- +
- + __asm__ __volatile__(
- + "xor\t$r15, $r15, $r15\n"
- + "1:\n"
- + "\tllw\t%0, [%1+$r15]\n"
- + "\tor\t%0, %0, %2\n"
- + "\tscw\t%0, [%1+$r15]\n"
- + "\tbeqz\t%0, 1b\n"
- + : "=&r" (tmp)
- + : "r" (p), "r" (mask)
- + : "memory");
- +}
- +
- +static inline void clear_bit(int nr, volatile unsigned long *addr)
- +{
- + unsigned long mask = BIT_MASK(nr);
- + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
- + unsigned long tmp;
- +
- + mask = ~mask;
- + __asm__ __volatile__(
- + "xor\t$r15, $r15, $r15\n"
- + "1:\n"
- + "\tllw\t%0, [%1+$r15]\n"
- + "\tand\t%0, %0, %2\n"
- + "\tscw\t%0, [%1+$r15]\n"
- + "\tbeqz\t%0, 1b\n"
- + : "=&r" (tmp)
- + : "r" (p), "r" (mask)
- + : "memory");
- +}
- +
- +static inline void change_bit(int nr, volatile unsigned long *addr)
- +{
- + unsigned long mask = BIT_MASK(nr);
- + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
- + unsigned long tmp;
- +
- + __asm__ __volatile__(
- + "xor\t$r15, $r15, $r15\n"
- + "1:\n"
- + "\tllw\t%0, [%1+$r15]\n"
- + "\txor\t%0, %0, %2\n"
- + "\tscw\t%0, [%1+$r15]\n"
- + "\tbeqz\t%0, 1b\n"
- + : "=&r" (tmp)
- + : "r" (p), "r" (mask)
- + : "memory");
- +}
- +
- +static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
- +{
- + unsigned long mask = BIT_MASK(nr);
- + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
- + unsigned long tmp ,ret;
- +
- + __asm__ __volatile__(
- + "xor\t$r15, $r15, $r15\n"
- + "1:\n"
- + "\tllw\t%0, [%2+$r15]\n"
- + "\tor\t%1, %0, %3\n"
- + "\tscw\t%1, [%2+$r15]\n"
- + "\tbeqz\t%1, 1b\n"
- + : "=&r" (ret), "=&r" (tmp)
- + : "r" (p), "r" (mask)
- + : "memory");
- + return (ret & mask) != 0;
- +}
- +
- +static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
- +{
- + unsigned long mask = BIT_MASK(nr);
- + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
- + unsigned long tmp, ret;
- + unsigned long mask2 = ~mask;
- +
- + __asm__ __volatile__(
- + "xor\t$r15, $r15, $r15\n"
- + "1:\n"
- + "\tllw\t%0, [%2+$r15]\n"
- + "\tand\t%1, %0, %3\n"
- + "\tscw\t%1, [%2+$r15]\n"
- + "\tbeqz\t%1, 1b\n"
- + : "=&r" (ret), "=&r" (tmp)
- + : "r" (p), "r" (mask2)
- + : "memory");
- + return (ret & mask) != 0;
- +}
- +
- +static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
- +{
- + unsigned long mask = BIT_MASK(nr);
- + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
- + unsigned long tmp, ret;
- +
- + __asm__ __volatile__(
- + "xor\t$r15, $r15, $r15\n"
- + "1:\n"
- + "\tllw\t%0, [%2+$r15]\n"
- + "\txor\t%1, %0, %3\n"
- + "\tscw\t%1, [%2+$r15]\n"
- + "\tbeqz\t%1, 1b\n"
- + : "=&r" (ret), "=&r" (tmp)
- + : "r" (p), "r" (mask)
- + : "memory");
- + return (ret & mask) != 0;
- +}
- +#else
- +#include <linux/irqflags.h>
- +#include <asm-generic/bitops/atomic.h>
- +#endif
- +
- +#include <linux/compiler.h>
- +#include <asm-generic/bitops/non-atomic.h>
- +#include <asm-generic/bitops/__ffs.h>
- +#include <asm-generic/bitops/ffz.h>
- +#include <asm-generic/bitops/fls.h>
- +#include <asm-generic/bitops/__fls.h>
- +#include <asm-generic/bitops/fls64.h>
- +#include <asm-generic/bitops/find.h>
- +
- +#ifdef __KERNEL__
- +
- +#include <asm-generic/bitops/sched.h>
- +#include <asm-generic/bitops/ffs.h>
- +#include <asm-generic/bitops/hweight.h>
- +#include <asm-generic/bitops/lock.h>
- +
- +#include <asm-generic/bitops/le.h>
- +
- +/*
- + * Ext2 is defined to use little-endian byte ordering.
- + */
- +#include <asm-generic/bitops/ext2-atomic-setbit.h>
- +
- +#endif /* __KERNEL__ */
- +
- +#define smp_mb__before_clear_bit() barrier()
- +#define smp_mb__after_clear_bit() barrier()
- +
- +#endif /* __NDS32_BITOPS_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/bitsperlong.h linux-3.4.110/arch/nds32/include/asm/bitsperlong.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/bitsperlong.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/bitsperlong.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1 @@
- +#include <asm-generic/bitsperlong.h>
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/bug.h linux-3.4.110/arch/nds32/include/asm/bug.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/bug.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/bug.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,18 @@
- +/*
- + * linux/arch/nds32/include/asm/bug.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_BUG_H__
- +#define __NDS32_BUG_H__
- +
- +#define HAVE_ARCH_BUG
- +#include <asm-generic/bug.h>
- +
- +#define BUG() do { \
- + dump_stack(); \
- + printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __FUNCTION__); \
- + panic("BUG!"); \
- +} while (0)
- +
- +#endif /* __NDS32_BUG_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/bugs.h linux-3.4.110/arch/nds32/include/asm/bugs.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/bugs.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/bugs.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/bugs.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_BUGS_H__
- +#define __NDS32_BUGS_H__
- +
- +static inline void check_bugs(void) {}
- +
- +#endif /* __NDS32_BUGS_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/byteorder.h linux-3.4.110/arch/nds32/include/asm/byteorder.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/byteorder.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/byteorder.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,15 @@
- +/*
- + * linux/arch/nds32/include/asm/byteorder.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_BYTEORDER_H__
- +#define __NDS32_BYTEORDER_H__
- +
- +#ifdef __NDS32_EB__
- +#include <linux/byteorder/big_endian.h>
- +#else
- +#include <linux/byteorder/little_endian.h>
- +#endif
- +
- +#endif /* __NDS32_BYTEORDER_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/cacheflush.h linux-3.4.110/arch/nds32/include/asm/cacheflush.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/cacheflush.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/cacheflush.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,55 @@
- +/*
- + * linux/arch/nds32/include/asm/cacheflush.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_CACHEFLUSH_H__
- +#define __NDS32_CACHEFLUSH_H__
- +
- +#include <linux/mm.h>
- +
- +#define PG_dcache_dirty PG_arch_1
- +
- +void flush_cache_mm(struct mm_struct *mm);
- +
- +void flush_cache_dup_mm(struct mm_struct *mm);
- +
- +void flush_cache_range(struct vm_area_struct *vma,
- + unsigned long start, unsigned long end);
- +
- +void flush_cache_page(struct vm_area_struct *vma,
- + unsigned long addr, unsigned long pfn);
- +
- +void flush_cache_kmaps(void);
- +
- +void flush_cache_vmap(unsigned long start, unsigned long end);
- +
- +void flush_cache_vunmap(unsigned long start, unsigned long end);
- +
- +
- +void flush_dcache_page(struct page *page);
- +
- +void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
- + unsigned long vaddr, void *dst, void *src, int len);
- +
- +void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
- + unsigned long vaddr, void *dst, void *src, int len);
- +
- +#ifndef CONFIG_CPU_CACHE_NONALIASING
- +#define ARCH_HAS_FLUSH_ANON_PAGE
- +void flush_anon_page(struct vm_area_struct *vma,
- + struct page *page, unsigned long vaddr);
- +
- +#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
- +void flush_kernel_dcache_page(struct page *page);
- +#endif
- +
- +void flush_icache_range(unsigned long start, unsigned long end);
- +
- +void flush_icache_page(struct vm_area_struct *vma, struct page *page);
- +
- +#define flush_dcache_mmap_lock(mapping) spin_lock_irq(&(mapping)->tree_lock)
- +#define flush_dcache_mmap_unlock(mapping) spin_unlock_irq(&(mapping)->tree_lock)
- +
- +#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
- +#endif /* __NDS32_CACHEFLUSH_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/cache.h linux-3.4.110/arch/nds32/include/asm/cache.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/cache.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/cache.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,22 @@
- +/*
- + * linux/arch/nds32/include/asm/cache.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_CACHE_H__
- +#define __NDS32_CACHE_H__
- +
- +#define L1_CACHE_BYTES 32
- +#define L1_CACHE_SHIFT 5
- +
- +/*
- + * * Memory returned by kmalloc() may be used for DMA, so we must make
- + * * sure that all such allocations are cache aligned. Otherwise,
- + * * unrelated code may cause parts of the buffer to be read into the
- + * * cache before the transfer is done, causing old data to be seen by
- + * * the CPU.
- + * */
- +#define ARCH_DMA_MINALIGN L1_CACHE_BYTES
- +
- +
- +#endif /* __NDS32_CACHE_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/cache_info.h linux-3.4.110/arch/nds32/include/asm/cache_info.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/cache_info.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/cache_info.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,17 @@
- +/*
- + * linux/arch/nds32/include/asm/cache.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +struct cache_info {
- + unsigned char cache_type;
- + unsigned char ways;
- + unsigned char way_bits;
- + unsigned char line_bits;
- + unsigned char line_size;
- + unsigned char set_bits;
- + unsigned short sets;
- + unsigned short size;
- + unsigned short aliasing_num;
- + unsigned int aliasing_mask;
- + unsigned int not_aliasing_mask;
- +};
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/checksum.h linux-3.4.110/arch/nds32/include/asm/checksum.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/checksum.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/checksum.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,173 @@
- +/*
- + * This file is subject to the terms and conditions of the GNU General Public
- + * License. See the file "COPYING" in the main directory of this archive
- + * for more details.
- + *
- + * Copyright (C) 1995, 96, 97, 98, 99, 2001 by Ralf Baechle
- + * Copyright (C) 1999 Silicon Graphics, Inc.
- + * Copyright (C) 2001 Thiemo Seufer.
- + * Copyright (C) 2002 Maciej W. Rozycki
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +#ifndef _ASM_CHECKSUM_H
- +#define _ASM_CHECKSUM_H
- +
- +#include <linux/in6.h>
- +
- +#include <asm/uaccess.h>
- +
- +/*
- + * computes the checksum of a memory block at buff, length len,
- + * and adds in "sum" (32-bit)
- + *
- + * returns a 32-bit number suitable for feeding into itself
- + * or csum_tcpudp_magic
- + *
- + * this function must be called with even lengths, except
- + * for the last fragment, which may be odd
- + *
- + * it's best to have buff aligned on a 32-bit boundary
- + */
- +unsigned int csum_partial(const void *buff, int len, unsigned int sum);
- +
- +/*
- + * this is a new version of the above that records errors it finds in *errp,
- + * but continues and zeros the rest of the buffer.
- + */
- +unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst, int len,
- + unsigned int sum, int *errp);
- +
- +/*
- + * Copy and checksum to user
- + */
- +#define HAVE_CSUM_COPY_USER
- +static inline unsigned int csum_and_copy_to_user (const unsigned char *src,
- + unsigned char __user *dst,
- + int len, int sum,
- + int *err_ptr)
- +{
- + sum = csum_partial(src, len, sum);
- +
- + if (copy_to_user(dst, src, len)) {
- + *err_ptr = -EFAULT;
- + return -1;
- + }
- +
- + return sum;
- +}
- +
- +/*
- + * the same as csum_partial, but copies from user space (but on MIPS
- + * we have just one address space, so this is identical to the above)
- + */
- +unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst,
- + int len, unsigned int sum);
- +
- +/*
- + * Fold a partial checksum without adding pseudo headers
- + */
- +static inline unsigned short int csum_fold(unsigned int sum)
- +{
- + __asm__(
- + "slli\t$p1,%0,16\n\t"
- + "add\t%0,%0,$p1\n\t"
- + "slt\t$p1,%0,$p1\n\t"
- + "srli\t%0,%0,16\n\t"
- + "add\t%0,%0,$p1\n\t"
- + "movi\t$p1,0xffff\n\t"
- + "xor\t%0,%0,$p1"
- + : "=r" (sum)
- + : "0" (sum));
- +
- + return sum;
- +}
- +
- +/*
- + * This is a version of ip_compute_csum() optimized for IP headers,
- + * which always checksum on 4 octet boundaries.
- + *
- + * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
- + * Arnt Gulbrandsen.
- + */
- +static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl)
- +{
- + unsigned int *word = (unsigned int *) iph;
- + unsigned int *stop = word + ihl;
- + unsigned int csum;
- + int carry;
- +
- + csum = word[0];
- + csum += word[1];
- + carry = (csum < word[1]);
- + csum += carry;
- +
- + csum += word[2];
- + carry = (csum < word[2]);
- + csum += carry;
- +
- + csum += word[3];
- + carry = (csum < word[3]);
- + csum += carry;
- +
- + word += 4;
- + do {
- + csum += *word;
- + carry = (csum < *word);
- + csum += carry;
- + word++;
- + } while (word != stop);
- +
- + return csum_fold(csum);
- +}
- +
- +static inline unsigned int csum_tcpudp_nofold(unsigned long saddr,
- + unsigned long daddr, unsigned short len, unsigned short proto,
- + unsigned int sum)
- +{
- + __asm__(
- + "add\t%0, %0, %2\n\t"
- + "slt\t$p1, %0, %2\n\t"
- + "add\t%0, %0, $p1\n\t"
- +
- + "add\t%0, %0, %3\n\t"
- + "slt\t$p1, %0, %3\n\t"
- + "add\t%0, %0, $p1\n\t"
- +
- + "add\t%0, %0, %4\n\t"
- + "slt\t$p1, %0, %4\n\t"
- + "add\t%0, %0, $p1"
- + : "=r" (sum)
- + : "0" (daddr), "r"(saddr),
- +#ifdef __NDS32_EL__
- + "r" (((unsigned long)htons(len)<<16) + proto*256),
- +#else
- + "r" (((unsigned long)(proto)<<16) + len),
- +#endif
- + "r" ((__force unsigned long)sum));
- +
- + return sum;
- +}
- +
- +/*
- + * computes the checksum of the TCP/UDP pseudo-header
- + * returns a 16-bit checksum, already complemented
- + */
- +static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
- + unsigned long daddr,
- + unsigned short len,
- + unsigned short proto,
- + unsigned int sum)
- +{
- + return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
- +}
- +
- +/*
- + * this routine is used for miscellaneous IP-like checksums, mainly
- + * in icmp.c
- + */
- +static inline unsigned short ip_compute_csum(const void * buff, int len)
- +{
- + return csum_fold(csum_partial(buff, len, 0));
- +}
- +
- +#endif /* _ASM_CHECKSUM_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/cmpxchg.h linux-3.4.110/arch/nds32/include/asm/cmpxchg.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/cmpxchg.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/cmpxchg.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,88 @@
- +#ifndef __ASM_NDS32_CMPXCHG_H
- +#define __ASM_NDS32_CMPXCHG_H
- +
- +#include <asm/barrier.h>
- +
- +#define xchg(ptr,x) \
- + ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
- +
- +static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
- +{
- + extern void __bad_xchg(volatile void *, int);
- + unsigned long ret;
- + unsigned long flags;
- +
- + switch (size) {
- + case 4:
- +#if defined(CONFIG_SMP) || !defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
- + __asm__ __volatile__(
- + "xor\t$r15, $r15, $r15\n"
- + "1:\n"
- + "\tllw\t%0, [%2+$r15]\n"
- + "\tori\t%1, %3, #0x0\n"
- + "\tscw\t%1, [%2+$r15]\n"
- + "\tbeqz\t%1, 1b\n"
- + : "=&r" (ret), "=&r" (flags)
- + : "r" (ptr), "r" (x)
- + : "memory");
- +#else
- + raw_local_irq_save(flags);
- + ret = *(volatile unsigned long *)ptr;
- + *(volatile unsigned long *)ptr = x;
- + raw_local_irq_restore(flags);
- +#endif
- + break;
- + default:
- + __bad_xchg(ptr, size);
- + ret = 0;
- + }
- + return ret;
- +}
- +
- +
- +#define __HAVE_ARCH_CMPXCHG 1
- +
- +static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
- + unsigned long new, int size)
- +{
- + extern void __cmpxchg_called_with_bad_pointer(void); /*nonexistence */
- + unsigned long retval, tmp;
- + unsigned long flags;
- + switch (size) {
- + case 4:
- +#if defined(CONFIG_SMP) || !defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
- + __asm__ __volatile__(
- + "xor\t$r15, $r15, $r15\n"
- + "1:\n"
- + "\tllw\t%0, [%3+$r15]\n"
- + "\tsub\t%2, %0, %5\n"
- + "\tcmovz\t%1, %4, %2\n"
- + "\tcmovn\t%1, %0, %2\n"
- + "\tscw\t%1, [%3+$r15]\n"
- + "\tbeqz\t%1, 1b\n"
- + : "=&r" (retval), "=&r" (flags), "=&r" (tmp)
- + : "r" (ptr), "r" (new), "r" (old));
- +#else
- + raw_local_irq_save(flags);
- + retval = *(volatile unsigned long *)ptr;
- + if (retval == old)
- + *(volatile unsigned long *)ptr = new;
- + raw_local_irq_restore(flags);
- +#endif
- + break;
- + default:
- + __cmpxchg_called_with_bad_pointer();
- + tmp = 0;
- + }
- + return retval;
- +}
- +
- +#define cmpxchg(ptr,o,n) \
- + ({ \
- + __typeof__(*(ptr)) _o_ = (o); \
- + __typeof__(*(ptr)) _n_ = (n); \
- + (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
- + (unsigned long)_n_, sizeof(*(ptr))); \
- + })
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/cpu.h linux-3.4.110/arch/nds32/include/asm/cpu.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/cpu.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/cpu.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,25 @@
- +/*
- + * linux/arch/nds32/include/asm/cpu.h
- + *
- + * Copyright (C) 2004-2005 ARM Ltd.
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#ifndef __ASM_NDS32_CPU_H
- +#define __ASM_NDS32_CPU_H
- +
- +#include <linux/percpu.h>
- +
- +struct cpuinfo_nds32 {
- + struct cpu cpu;
- +#ifdef CONFIG_SMP
- + unsigned int loops_per_jiffy;
- +#endif
- +};
- +
- +DECLARE_PER_CPU(struct cpuinfo_nds32, cpu_data);
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/cputime.h linux-3.4.110/arch/nds32/include/asm/cputime.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/cputime.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/cputime.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/cputime.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_CPUTIME_H__
- +#define __NDS32_CPUTIME_H__
- +
- +#include <asm-generic/cputime.h>
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/cpuver.h linux-3.4.110/arch/nds32/include/asm/cpuver.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/cpuver.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/cpuver.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,34 @@
- +/*
- + * linux/arch/nds32/include/asm/cpuver.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_CPUVER_H__
- +#define __NDS32_CPUVER_H__
- +
- +#include <asm/bitfield.h>
- +#include <asm/reg_access.h>
- +
- +#define GET_CPU_ID()\
- + (( GET_CPU_VER() & CPU_VER_mskCPUID) >> CPU_VER_offCPUID)
- +
- +#define GET_CPU_REV()\
- + (( GET_CPU_VER() & CPU_VER_mskREV) >> CPU_VER_offREV)
- +
- +#define GET_CPU_CFGID()\
- + (( GET_CPU_VER() & CPU_VER_mskCFGID) >> CPU_VER_offCFGID)
- +
- +#define CPU_IS_N1213_43U1HA0()\
- + (((GET_CPU_VER() & CPU_VER_mskCPUID) == 0x0c000000) &&\
- + ((GET_CPU_VER() & CPU_VER_mskREV) == 0x00010000))
- +
- +#define CPU_IS_N1213_43U1HB0()\
- + (((GET_CPU_VER() & CPU_VER_mskCPUID) == 0x0c000000) &&\
- + ((GET_CPU_VER() & CPU_VER_mskREV) == 0x00020000))
- +
- +#define CPU_IS_N1033_S()\
- + (((GET_CPU_VER() & CPU_VER_mskCPUID) == 0x0a000000) &&\
- + ((GET_CPU_VER() & CPU_VER_mskREV) == 0x000c0000))
- +
- +#endif
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/current.h linux-3.4.110/arch/nds32/include/asm/current.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/current.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/current.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,18 @@
- +/*
- + * linux/arch/nds32/include/asm/current.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_CURRENT_H__
- +#define __NDS32_CURRENT_H__
- +
- +#include <linux/thread_info.h>
- +
- +static inline struct task_struct *get_current(void)
- +{
- + return current_thread_info()->task;
- +}
- +
- +#define current get_current()
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/delay.h linux-3.4.110/arch/nds32/include/asm/delay.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/delay.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/delay.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,39 @@
- +/*
- + * linux/arch/nds32/include/asm/delay.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_DELAY_H__
- +#define __NDS32_DELAY_H__
- +
- +#include <asm/param.h>
- +
- +static inline void __delay(unsigned long loops)
- +{
- + __asm__ __volatile__ (
- + "1:\n"
- + "\taddi\t%0, %0, -1\n"
- + "\tbgtz\t%0, 1b\n"
- + : "=r" (loops) : "0" (loops));
- +}
- +
- +static inline void __udelay(unsigned long usecs, unsigned long lpj)
- +{
- + usecs *= (unsigned long) (((0x8000000000000000ULL / (500000 / HZ)) +
- + 0x80000000ULL) >> 32);
- + usecs=(unsigned long)(((unsigned long long)usecs*lpj)>>32);
- + __delay(usecs);
- +}
- +
- +#define udelay(usecs) __udelay((usecs), loops_per_jiffy)
- +
- +/* make sure "usecs *= ..." in udelay do not overflow. */
- +#if HZ >= 1000
- +#define MAX_UDELAY_MS 1
- +#elif HZ <= 200
- +#define MAX_UDELAY_MS 5
- +#else
- +#define MAX_UDELAY_MS (1000 / HZ)
- +#endif
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/device.h linux-3.4.110/arch/nds32/include/asm/device.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/device.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/device.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/device.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_DEVICE_H__
- +#define __NDS32_DEVICE_H__
- +
- +#include <asm-generic/device.h>
- +
- +#endif /* __NDS32_DEVICE_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/div64.h linux-3.4.110/arch/nds32/include/asm/div64.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/div64.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/div64.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/div64.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_DIV64_H__
- +#define __NDS32_DIV64_H__
- +
- +#include <asm-generic/div64.h>
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/dmad.h linux-3.4.110/arch/nds32/include/asm/dmad.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/dmad.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/dmad.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,1071 @@
- +/*
- + * Copyright Andes Technology Corporation 2007-2008
- + * All Rights Reserved.
- + *
- + * Revision History:
- + *
- + * Aug.21.2007 Created.
- + *
- + * DESCRIPTION
- + *
- + * DMA controller driver internal supplement library.
- + *
- + */
- +
- +#ifndef __NDS_DMAD_INC__
- +#define __NDS_DMAD_INC__
- +
- +#include <asm/spec.h>
- +
- +/*****************************************************************************
- + * Configuration section
- +*****************************************************************************/
- +
- +/* Debug trace enable switch */
- +#define DMAD_ERROR_TRACE 1 /* message for fatal errors */
- +//MOD by river 2010.10.19
- +#define DMAD_DEBUG_TRACE 0 /* message for debug trace */
- +//End MOD by river 2010.10.19
- +
- +//#ifndef addr_t
- +typedef u32 addr_t;
- +//#endif
- +/* for amerald */
- +#define AMERALD_PRODUCT_ID 0x41471000
- +#define AMERALD_MASK 0xFFFFF000
- +
- +/*****************************************************************************
- + * DMAC - AG101 AHB
- +*****************************************************************************/
- +/* Device base address */
- +#define DMAC_BASE DMAC_FTDMAC020_0_VA_BASE
- +
- +/* DMA controller registers (8-bit width) */
- +#define DMAC_INT (DMAC_BASE + 0x00)
- +#define DMAC_INT_TC (DMAC_BASE + 0x04)
- +#define DMAC_INT_TC_CLR (DMAC_BASE + 0x08)
- +#define DMAC_INT_ERRABT (DMAC_BASE + 0x0c)
- +#define DMAC_INT_ERRABT_CLR (DMAC_BASE + 0x10)
- +#define DMAC_TC (DMAC_BASE + 0x14)
- +#define DMAC_ERRABT (DMAC_BASE + 0x18)
- +#define DMAC_CH_EN (DMAC_BASE + 0x1c)
- +#define DMAC_CH_BUSY (DMAC_BASE + 0x20)
- +#define DMAC_CSR (DMAC_BASE + 0x24)
- +#define DMAC_SYNC (DMAC_BASE + 0x28)
- +
- +/* DMA channel registers base address */
- +#define DMAC_C0_OFFSET 0x100
- +#define DMAC_C1_OFFSET 0x120
- +#define DMAC_C2_OFFSET 0x140
- +#define DMAC_C3_OFFSET 0x160
- +#define DMAC_C4_OFFSET 0x180
- +#define DMAC_C5_OFFSET 0x1a0
- +#define DMAC_C6_OFFSET 0x1c0
- +#define DMAC_C7_OFFSET 0x1e0
- +
- +#define DMAC_C0_BASE (DMAC_BASE + DMAC_C0_OFFSET)
- +#define DMAC_C1_BASE (DMAC_BASE + DMAC_C1_OFFSET)
- +#define DMAC_C2_BASE (DMAC_BASE + DMAC_C2_OFFSET)
- +#define DMAC_C3_BASE (DMAC_BASE + DMAC_C3_OFFSET)
- +#define DMAC_C4_BASE (DMAC_BASE + DMAC_C4_OFFSET)
- +#define DMAC_C5_BASE (DMAC_BASE + DMAC_C5_OFFSET)
- +#define DMAC_C6_BASE (DMAC_BASE + DMAC_C6_OFFSET)
- +#define DMAC_C7_BASE (DMAC_BASE + DMAC_C7_OFFSET)
- +
- +#define DMAC_MAX_CHANNELS 8
- +#define DMAC_BASE_CH(n) (DMAC_C0_BASE + \
- + (DMAC_C1_OFFSET - DMAC_C0_OFFSET) * \
- + (addr_t)(n)) /* n = 0 ~ 3 */
- +
- +#define DMAC_CSR_OFFSET 0x00
- +#define DMAC_CFG_OFFSET 0x04
- +#define DMAC_SRC_ADDR_OFFSET 0x08
- +#define DMAC_DST_ADDR_OFFSET 0x0c
- +#define DMAC_LLP_OFFSET 0x10
- +#define DMAC_SIZE_OFFSET 0x14
- +
- +/* DMA channel 0 registers (32-bit width) */
- +#define DMAC_C0_CSR (DMAC_C0_BASE + DMAC_CSR_OFFSET)
- +#define DMAC_C0_CFG (DMAC_C0_BASE + DMAC_CFG_OFFSET)
- +#define DMAC_C0_SRC_ADDR (DMAC_C0_BASE + DMAC_SRC_ADDR_OFFSET)
- +#define DMAC_C0_DST_ADDR (DMAC_C0_BASE + DMAC_DST_ADDR_OFFSET)
- +#define DMAC_C0_LLP (DMAC_C0_BASE + DMAC_LLP_OFFSET)
- +#define DMAC_C0_SIZE (DMAC_C0_BASE + DMAC_SIZE_OFFSET)
- +
- +/* DMA channel 1 registers (32-bit width) */
- +#define DMAC_C1_CSR (DMAC_C1_BASE + DMAC_CSR_OFFSET)
- +#define DMAC_C1_CFG (DMAC_C1_BASE + DMAC_CFG_OFFSET)
- +#define DMAC_C1_SRC_ADDR (DMAC_C1_BASE + DMAC_SRC_ADDR_OFFSET)
- +#define DMAC_C1_DST_ADDR (DMAC_C1_BASE + DMAC_DST_ADDR_OFFSET)
- +#define DMAC_C1_LLP (DMAC_C1_BASE + DMAC_LLP_OFFSET)
- +#define DMAC_C1_SIZE (DMAC_C1_BASE + DMAC_SIZE_OFFSET)
- +
- +/* DMA channel 2 registers (32-bit width) */
- +#define DMAC_C2_CSR (DMAC_C2_BASE + DMAC_CSR_OFFSET)
- +#define DMAC_C2_CFG (DMAC_C2_BASE + DMAC_CFG_OFFSET)
- +#define DMAC_C2_SRC_ADDR (DMAC_C2_BASE + DMAC_SRC_ADDR_OFFSET)
- +#define DMAC_C2_DST_ADDR (DMAC_C2_BASE + DMAC_DST_ADDR_OFFSET)
- +#define DMAC_C2_LLP (DMAC_C2_BASE + DMAC_LLP_OFFSET)
- +#define DMAC_C2_SIZE (DMAC_C2_BASE + DMAC_SIZE_OFFSET)
- +
- +/* DMA channel 3 registers (32-bit width) */
- +#define DMAC_C3_CSR (DMAC_C3_BASE + DMAC_CSR_OFFSET)
- +#define DMAC_C3_CFG (DMAC_C3_BASE + DMAC_CFG_OFFSET)
- +#define DMAC_C3_SRC_ADDR (DMAC_C3_BASE + DMAC_SRC_ADDR_OFFSET)
- +#define DMAC_C3_DST_ADDR (DMAC_C3_BASE + DMAC_DST_ADDR_OFFSET)
- +#define DMAC_C3_LLP (DMAC_C3_BASE + DMAC_LLP_OFFSET)
- +#define DMAC_C3_SIZE (DMAC_C3_BASE + DMAC_SIZE_OFFSET)
- +
- +/* DMA channel 4 registers (32-bit width) */
- +#define DMAC_C4_CSR (DMAC_C4_BASE + DMAC_CSR_OFFSET)
- +#define DMAC_C4_CFG (DMAC_C4_BASE + DMAC_CFG_OFFSET)
- +#define DMAC_C4_SRC_ADDR (DMAC_C4_BASE + DMAC_SRC_ADDR_OFFSET)
- +#define DMAC_C4_DST_ADDR (DMAC_C4_BASE + DMAC_DST_ADDR_OFFSET)
- +#define DMAC_C4_LLP (DMAC_C4_BASE + DMAC_LLP_OFFSET)
- +#define DMAC_C4_SIZE (DMAC_C4_BASE + DMAC_SIZE_OFFSET)
- +
- +/* DMA channel 5 registers (32-bit width) */
- +#define DMAC_C5_CSR (DMAC_C5_BASE + DMAC_CSR_OFFSET)
- +#define DMAC_C5_CFG (DMAC_C5_BASE + DMAC_CFG_OFFSET)
- +#define DMAC_C5_SRC_ADDR (DMAC_C5_BASE + DMAC_SRC_ADDR_OFFSET)
- +#define DMAC_C5_DST_ADDR (DMAC_C5_BASE + DMAC_DST_ADDR_OFFSET)
- +#define DMAC_C5_LLP (DMAC_C5_BASE + DMAC_LLP_OFFSET)
- +#define DMAC_C5_SIZE (DMAC_C5_BASE + DMAC_SIZE_OFFSET)
- +
- +/* DMA channel 6 registers (32-bit width) */
- +#define DMAC_C6_CSR (DMAC_C6_BASE + DMAC_CSR_OFFSET)
- +#define DMAC_C6_CFG (DMAC_C6_BASE + DMAC_CFG_OFFSET)
- +#define DMAC_C6_SRC_ADDR (DMAC_C6_BASE + DMAC_SRC_ADDR_OFFSET)
- +#define DMAC_C6_DST_ADDR (DMAC_C6_BASE + DMAC_DST_ADDR_OFFSET)
- +#define DMAC_C6_LLP (DMAC_C6_BASE + DMAC_LLP_OFFSET)
- +#define DMAC_C6_SIZE (DMAC_C6_BASE + DMAC_SIZE_OFFSET)
- +
- +/* DMA channel 7 registers (32-bit width) */
- +#define DMAC_C7_CSR (DMAC_C7_BASE + DMAC_CSR_OFFSET)
- +#define DMAC_C7_CFG (DMAC_C7_BASE + DMAC_CFG_OFFSET)
- +#define DMAC_C7_SRC_ADDR (DMAC_C7_BASE + DMAC_SRC_ADDR_OFFSET)
- +#define DMAC_C7_DST_ADDR (DMAC_C7_BASE + DMAC_DST_ADDR_OFFSET)
- +#define DMAC_C7_LLP (DMAC_C7_BASE + DMAC_LLP_OFFSET)
- +#define DMAC_C7_SIZE (DMAC_C7_BASE + DMAC_SIZE_OFFSET)
- +
- +/*****************************************************************************
- + * DMAC defs - AG101 AHB
- +*****************************************************************************/
- +
- +/* Interrupt status register (+00) */
- +#define DMAC_INT0_MASK 0x01
- +#define DMAC_INT0_BIT 0
- +#define DMAC_INT1_MASK 0x02
- +#define DMAC_INT1_BIT 1
- +#define DMAC_INT2_MASK 0x04
- +#define DMAC_INT2_BIT 2
- +#define DMAC_INT3_MASK 0x08
- +#define DMAC_INT3_BIT 3
- +
- +/* Interrupt for terminal count status register (+0x04) */
- +#define DMAC_INT_TC0_MASK 0x01
- +#define DMAC_INT_TC0_BIT 0
- +#define DMAC_INT_TC1_MASK 0x02
- +#define DMAC_INT_TC1_BIT 1
- +#define DMAC_INT_TC2_MASK 0x04
- +#define DMAC_INT_TC2_BIT 2
- +#define DMAC_INT_TC3_MASK 0x08
- +#define DMAC_INT_TC3_BIT 3
- +#define DMAC_INT_TC4_MASK 0x01
- +#define DMAC_INT_TC4_BIT 0
- +#define DMAC_INT_TC5_MASK 0x02
- +#define DMAC_INT_TC5_BIT 1
- +#define DMAC_INT_TC6_MASK 0x04
- +#define DMAC_INT_TC6_BIT 2
- +#define DMAC_INT_TC7_MASK 0x08
- +#define DMAC_INT_TC7_BIT 3
- +
- +#define DMAC_INT_TC_MASK 0xff
- +#define DMAC_INT_TC_SHIFT 0
- +
- +/* Interrupt for terminal count clear register (+0x08) */
- +#define DMAC_INT_TC0_CLR_MASK 0x01
- +#define DMAC_INT_TC0_CLR_BIT 0
- +#define DMAC_INT_TC1_CLR_MASK 0x02
- +#define DMAC_INT_TC1_CLR_BIT 1
- +#define DMAC_INT_TC2_CLR_MASK 0x04
- +#define DMAC_INT_TC2_CLR_BIT 2
- +#define DMAC_INT_TC3_CLR_MASK 0x08
- +#define DMAC_INT_TC3_CLR_BIT 3
- +
- +#define DMAC_INT_TC_CLR_MASK 0x0f
- +#define DMAC_INT_TC_CLR_SHIFT 0
- +
- +/* Interrupt for error/abort status register (+0x0c, 32-bits width) */
- +#define DMAC_INT_ERR0_MASK 0x00000001
- +#define DMAC_INT_ERR0_BIT 0
- +#define DMAC_INT_ERR1_MASK 0x00000002
- +#define DMAC_INT_ERR1_BIT 1
- +#define DMAC_INT_ERR2_MASK 0x00000004
- +#define DMAC_INT_ERR2_BIT 2
- +#define DMAC_INT_ERR3_MASK 0x00000008
- +#define DMAC_INT_ERR3_BIT 3
- +
- +#define DMAC_INT_ERR_MASK 0x0000000f
- +#define DMAC_INT_ERR_SHIFT 0
- +
- +#define DMAC_INT_ABT0_MASK 0x00010000
- +#define DMAC_INT_ABT0_BIT 16
- +#define DMAC_INT_ABT1_MASK 0x00020000
- +#define DMAC_INT_ABT1_BIT 17
- +#define DMAC_INT_ABT2_MASK 0x00040000
- +#define DMAC_INT_ABT2_BIT 18
- +#define DMAC_INT_ABT3_MASK 0x00080000
- +#define DMAC_INT_ABT3_BIT 19
- +
- +#define DMAC_INT_ABT_MASK 0x000f0000
- +#define DMAC_INT_ABT_SHIFT 16
- +
- +/* Interrupt for error/abort status clear register (+0x10, 32-bits width) */
- +#define DMAC_INT_ERR0_CLR_MASK 0x00000001
- +#define DMAC_INT_ERR0_CLR_BIT 0
- +#define DMAC_INT_ERR1_CLR_MASK 0x00000002
- +#define DMAC_INT_ERR1_CLR_BIT 1
- +#define DMAC_INT_ERR2_CLR_MASK 0x00000004
- +#define DMAC_INT_ERR2_CLR_BIT 2
- +#define DMAC_INT_ERR3_CLR_MASK 0x00000008
- +#define DMAC_INT_ERR3_CLR_BIT 3
- +
- +#define DMAC_INT_ERR_CLR_MASK 0x0000000f
- +#define DMAC_INT_ERR_CLR_SHIFT 0
- +
- +#define DMAC_INT_ABT0_CLR_MASK 0x00010000
- +#define DMAC_INT_ABT0_CLR_BIT 16
- +#define DMAC_INT_ABT1_CLR_MASK 0x00020000
- +#define DMAC_INT_ABT1_CLR_BIT 17
- +#define DMAC_INT_ABT2_CLR_MASK 0x00040000
- +#define DMAC_INT_ABT2_CLR_BIT 18
- +#define DMAC_INT_ABT3_CLR_MASK 0x00080000
- +#define DMAC_INT_ABT3_CLR_BIT 19
- +
- +#define DMAC_INT_ABT_CLR_MASK 0x000f0000
- +#define DMAC_INT_ABT_CLR_SHIFT 16
- +
- +/* Terminal count status register (+0x14) */
- +#define DMAC_TC0_MASK 0x01
- +#define DMAC_TC0_BIT 0
- +#define DMAC_TC1_MASK 0x02
- +#define DMAC_TC1_BIT 1
- +#define DMAC_TC2_MASK 0x04
- +#define DMAC_TC2_BIT 2
- +#define DMAC_TC3_MASK 0x08
- +#define DMAC_TC3_BIT 3
- +
- +/* Error/abort status register (+0x18, 32-bits width) */
- +#define DMAC_ERR0_MASK 0x00000001
- +#define DMAC_ERR0_BIT 0
- +#define DMAC_ERR1_MASK 0x00000002
- +#define DMAC_ERR1_BIT 1
- +#define DMAC_ERR2_MASK 0x00000004
- +#define DMAC_ERR2_BIT 2
- +#define DMAC_ERR3_MASK 0x00000008
- +#define DMAC_ERR3_BIT 3
- +
- +#define DMAC_ABT0_MASK 0x00010000
- +#define DMAC_ABT0_BIT 16
- +#define DMAC_ABT1_MASK 0x00020000
- +#define DMAC_ABT1_BIT 17
- +#define DMAC_ABT2_MASK 0x00040000
- +#define DMAC_ABT2_BIT 18
- +#define DMAC_ABT3_MASK 0x00080000
- +#define DMAC_ABT3_BIT 19
- +
- +/* Channel enable status register (+0x1c) */
- +#define DMAC_CH0_EN_MASK 0x01
- +#define DMAC_CH0_EN_BIT 0
- +#define DMAC_CH1_EN_MASK 0x02
- +#define DMAC_CH1_EN_BIT 1
- +#define DMAC_CH2_EN_MASK 0x04
- +#define DMAC_CH2_EN_BIT 2
- +#define DMAC_CH3_EN_MASK 0x08
- +#define DMAC_CH3_EN_BIT 3
- +
- +/* Channel busy status register (+0x20) */
- +#define DMAC_CH0_BUSY_MASK 0x01
- +#define DMAC_CH0_BUSY_BIT 0
- +#define DMAC_CH1_BUSY_MASK 0x02
- +#define DMAC_CH1_BUSY_BIT 1
- +#define DMAC_CH2_BUSY_MASK 0x04
- +#define DMAC_CH2_BUSY_BIT 2
- +#define DMAC_CH3_BUSY_MASK 0x08
- +#define DMAC_CH3_BUSY_BIT 3
- +
- +/* Main configuration status register (+0x24) */
- +#define DMAC_DMACEN_MASK 0x01
- +#define DMAC_DMACEN_BIT 0
- +#define DMAC_M0ENDIAN_MASK 0x02
- +#define DMAC_M0ENDIAN_BIT 1
- +#define DMAC_M1ENDIAN_MASK 0x04
- +#define DMAC_M1ENDIAN_BIT 2
- +
- + #define DMAC_ENDIAN_LITTLE 0
- + #define DMAC_ENDIAN_BIG 1
- +
- +/* Sync register (+0x28) */
- +#define DMAC_SYNC0_MASK 0x01
- +#define DMAC_SYNC0_BIT 0
- +#define DMAC_SYNC1_MASK 0x02
- +#define DMAC_SYNC1_BIT 1
- +#define DMAC_SYNC2_MASK 0x04
- +#define DMAC_SYNC2_BIT 2
- +#define DMAC_SYNC3_MASK 0x08
- +#define DMAC_SYNC3_BIT 3
- +
- +/* DMA channel 0~n Control Registers (CH[n]_BASE + 0x00) */
- +#define DMAC_CSR_CH_EN_MASK 0x00000001
- +#define DMAC_CSR_CH_EN_BIT 0
- +
- +#define DMAC_CSR_DST_SEL_MASK 0x00000002
- +#define DMAC_CSR_DST_SEL_BIT 1
- +#define DMAC_CSR_SRC_SEL_MASK 0x00000004
- +#define DMAC_CSR_SRC_SEL_BIT 2
- + #define DMAC_CSR_SEL_MASTER0 0x00
- + #define DMAC_CSR_SEL_MASTER1 0x01
- +
- +#define DMAC_CSR_DSTAD_CTL_MASK 0x00000018
- +#define DMAC_CSR_DSTAD_CTL_SHIFT 3
- +#define DMAC_CSR_SRCAD_CTL_MASK 0x00000060
- +#define DMAC_CSR_SRCAD_CTL_SHIFT 5
- + #define DMAC_CSR_AD_INC 0x00
- + #define DMAC_CSR_AD_DEC 0x01
- + #define DMAC_CSR_AD_FIX 0x02
- +
- +#define DMAC_CSR_MODE_MASK 0x00000080
- +#define DMAC_CSR_MODE_BIT 7
- + #define DMAC_CSR_MODE_NORMAL 0x00
- + #define DMAC_CSR_MODE_HSHK 0x01
- +
- +#define DMAC_CSR_DST_WIDTH_MASK 0x00000700
- +#define DMAC_CSR_DST_WIDTH_SHIFT 8
- +#define DMAC_CSR_SRC_WIDTH_MASK 0x00003800
- +#define DMAC_CSR_SRC_WIDTH_SHIFT 11
- + #define DMAC_CSR_WIDTH_8 0x00
- + #define DMAC_CSR_WIDTH_16 0x01
- + #define DMAC_CSR_WIDTH_32 0x02
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- +#define DMAC_CYCLE_TO_BYTES(cycle, width) ((cycle) << (width))
- +#define DMAC_BYTES_TO_CYCLE(bytes, width) ((bytes) >> (width))
- +#else
- +#define DMAC_CYCLE_TO_BYTES(cycle, width) 0
- +#define DMAC_BYTES_TO_CYCLE(bytes, width) 0
- +#endif /* CONFIG_PLATFORM_AHBDMA */
- +
- +#define DMAC_CSR_ABT 0x00008000
- +#define DMAC_CSR_ABT_BIT 15
- +
- +#define DMAC_CSR_SRC_SIZE_MASK 0x00070000
- +#define DMAC_CSR_SRC_SIZE_SHIFT 16
- + #define DMAC_CSR_SIZE_1 0x00
- + #define DMAC_CSR_SIZE_4 0x01
- + #define DMAC_CSR_SIZE_8 0x02
- + #define DMAC_CSR_SIZE_16 0x03
- + #define DMAC_CSR_SIZE_32 0x04
- + #define DMAC_CSR_SIZE_64 0x05
- + #define DMAC_CSR_SIZE_128 0x06
- + #define DMAC_CSR_SIZE_256 0x07
- +
- +#define DMAC_CSR_PROT1 0x00080000
- +#define DMAC_CSR_PROT1_BIT 19
- +#define DMAC_CSR_PROT2 0x00100000
- +#define DMAC_CSR_PROT2_BIT 20
- +#define DMAC_CSR_PROT3 0x00200000
- +#define DMAC_CSR_PROT3_BIT 21
- +
- +#define DMAC_CSR_CHPRI_MASK 0x00c00000
- +#define DMAC_CSR_CHPRI_SHIFT 22
- + #define DMAC_CSR_CHPRI_0 0x00
- + #define DMAC_CSR_CHPRI_1 0x01
- + #define DMAC_CSR_CHPRI_2 0x02
- + #define DMAC_CSR_CHPRI_3 0x03
- +
- +#define DMAC_CSR_FF_TH_MASK 0x07000000
- +#define DMAC_CSR_FF_TH_SHIFT 24
- + #define DMAC_CSR_FF_TH_1 0x00
- + #define DMAC_CSR_FF_TH_2 0x01
- + #define DMAC_CSR_FF_TH_4 0x02
- + #define DMAC_CSR_FF_TH_8 0x03
- + #define DMAC_CSR_FF_TH_16 0x04
- +
- +#define DMAC_CSR_TC_MSK_MSK 0x80000000
- +#define DMAC_CSR_TC_MSK_BIT 31
- +
- +/* DMA channel 0~n Configuration Registers (CH[n]_BASE + 0x04) */
- +#define DMAC_CFG_INT_TC_MSK 0x00000001
- +#define DMAC_CFG_INT_TC_MSK_BIT 0
- +#define DMAC_CFG_INT_ERR_MSK 0x00000002
- +#define DMAC_CFG_INT_ERR_MSK_BIT 1
- +#define DMAC_CFG_INT_ABT_MSK 0x00000004
- +#define DMAC_CFG_INT_ABT_MSK_BIT 2
- +
- +#define DMAC_CFG_INT_SRC_RS_MASK 0x00000078
- +#define DMAC_CFG_INT_SRC_RS_SHIFT 3
- +#define DMAC_CFG_INT_SRC_HE_MASK 0x00000080
- +#define DMAC_CFG_INT_SRC_HE_BIT 7
- +
- +#define DMAC_CFG_BUSY_MASK 0x00000100
- +#define DMAC_CFG_BUSY_BIT 8
- +
- +#define DMAC_CFG_INT_DST_RS_MASK 0x00001e00
- +#define DMAC_CFG_INT_DST_RS_SHIFT 9
- +#define DMAC_CFG_INT_DST_HE_MASK 0x00002000
- +#define DMAC_CFG_INT_DST_HE_BIT 13
- +
- +#ifdef CONFIG_PLAT_AG102
- + #define DMAC_REQN_IDERX 0
- + #define DMAC_REQN_IDETX 1
- + #define DMAC_REQN_I2SAC97RX 2
- + #define DMAC_REQN_I2SAC97TX 3
- + #define DMAC_REQN_UART2RX 4
- + #define DMAC_REQN_UART2TX 5
- + #define DMAC_REQN_UART1RX 6
- + #define DMAC_REQN_UART1TX 7
- + #define DMAC_REQN_SDC 8
- + #define DMAC_REQN_CFC 9
- + #define DMAC_REQN_LPCREQ0 10
- + #define DMAC_REQN_LPCREQ1 11
- + #define DMAC_REQN_LPCREQ2 12
- + #define DMAC_REQN_LPCREQ3 13
- + #define DMAC_REQN_NONE 14
- + #define DMAC_REQN_LPCREQ5 15
- + #define DMAC_REQN_MAX 15
- +#else
- + #define DMAC_REQN_NONE PMU_REQN_NONE
- + #define DMAC_REQN_CFC PMU_REQN_CFC
- + #define DMAC_REQN_SSP PMU_REQN_SSP
- + #define DMAC_REQN_UART1TX PMU_REQN_UART1TX
- + #define DMAC_REQN_UART1RX PMU_REQN_UART1RX
- + #define DMAC_REQN_UART2TX PMU_REQN_UART2TX
- + #define DMAC_REQN_UART2RX PMU_REQN_UART2RX
- + #define DMAC_REQN_SDC PMU_REQN_SDC
- + #define DMAC_REQN_I2SAC97TX PMU_REQN_I2SAC97TX
- + #define DMAC_REQN_I2SAC97RX PMU_REQN_I2SAC97RX
- +/* for amerald ac97 ssp2 */
- + #define DMAC_REQN_I2SAC97TX_AMERALD PMU_REQN_I2SAC97TX_AMERALD
- + #define DMAC_REQN_I2SAC97RX_AMERALD PMU_REQN_I2SAC97RX_AMERALD
- + #define DMAC_REQN_USB PMU_REQN_USB
- + #define DMAC_REQN_EXT0 PMU_REQN_EXT0
- + #define DMAC_REQN_EXT1 PMU_REQN_EXT1
- + #define DMAC_REQN_MAX PMU_REQN_MAX
- +#endif
- +#define DMAC_CFG_INT_LLPCNT_MASK 0x000f0000
- +#define DMAC_CFG_INT_LLPCNT_SHIFT 16
- +
- +/* DMA channel 0~n Linked List Descriptor Registers (CH[n]_BASE + 0x10) */
- +#define DMAC_LLP_ADDR_MASK 0xfffffffc
- +#define DMAC_LLP_ADDR_SHIFT 2
- +#define DMAC_LLP_MASTER_MASK 0x00000001
- +#define DMAC_LLP_MASTER_BIT 0
- + #define DMAC_LLP_MASTER_0 0
- + #define DMAC_LLP_MASTER_1 1
- +
- +/* DMA channel 0~3 Transfer Size Registers (CH[n]_BASE + 0x14) */
- +#define DMAC_TOT_SIZE_MASK 0x003fffff
- +#define DMAC_TOT_SIZE_SHIFT 0
- +
- +
- +/*****************************************************************************
- + * APBBR - AG101 AHB to APB Bridge
- +*****************************************************************************/
- +/* Device base address */
- +#ifdef CONFIG_PLAT_AG102
- +#define APBBR_BASE APBBR_VA_BASE
- +#else
- +#define APBBR_BASE APBBRG_FTAPBBRG020S_0_VA_BASE
- +#endif
- +
- +/* DMA channel A registers (32-bit width) */
- +#define APBBR_DMAA_BASE (APBBR_BASE + 0x80)
- +#define APBBR_DMAB_BASE (APBBR_BASE + 0x90)
- +#define APBBR_DMAC_BASE (APBBR_BASE + 0xa0)
- +#define APBBR_DMAD_BASE (APBBR_BASE + 0xb0)
- +
- +#define APBBR_DMA_MAX_CHANNELS APBBRG_FTAPBBRG020S_IRQ_COUNT
- +/* n = 0 ~ APBBRG_FTAPBBRG020S_IRQ_COUNT */
- +#define APBBR_DMA_BASE_CH(n) (APBBR_DMAA_BASE + \
- + (APBBR_DMAB_BASE - APBBR_DMAA_BASE) * \
- + (addr_t)(n))
- +
- +#define APBBR_DMA_SAD_OFFSET 0x00
- +#define APBBR_DMA_DAD_OFFSET 0x04
- +#define APBBR_DMA_CYC_OFFSET 0x08
- +#define APBBR_DMA_CMD_OFFSET 0x0c
- +
- +
- +/*****************************************************************************
- + * APBBR defs - AG101 AHB to APB Bridge
- +*****************************************************************************/
- +
- +/* APBBR slave#n (n = 1~6, 8, 11, 16~23) base/size register */
- +#define APBBR_SLAVE_SIZE_MASK 0x000f0000 /* Size of address space */
- +#define APBBR_SLAVE_SIZE_SHIFT 16
- + #define APBBR_SIZE_1M 0
- + #define APBBR_SIZE_2M 1
- + #define APBBR_SIZE_4M 2
- + #define APBBR_SIZE_8M 3
- + #define APBBR_SIZE_16M 4
- + #define APBBR_SIZE_32M 5
- + #define APBBR_SIZE_64M 6
- + #define APBBR_SIZE_128M 7
- + #define APBBR_SIZE_256M 8
- +
- +#define APBBR_SLAVE_BASE_MASK 0x3ff00000
- +#define APBBR_SLAVE_BASE_SHIFT 20
- +
- +/* APBBR DMA channel transfer cycles register
- + * DMA cycles (data size), 1 or 4 bus data transfer cycles per DMA cycle
- + * => transfer size = cycles * data_width * burst(1 or 4)
- + * so, max = 16M*4*4 = 256M
- + */
- +#define APBBR_DMA_CYC_MASK 0x00ffffff
- +#define APBBR_DMA_CYC_SHIFT 0
- +
- +/* APBBR DMA channel command register */
- +#define APBBR_DMA_CHEN_MASK 0x00000001
- +#define APBBR_DMA_CHEN_BIT 0
- +
- +#define APBBR_DMA_FINTST_MASK 0x00000002
- +#define APBBR_DMA_FINTST_BIT 1
- +#define APBBR_DMA_FINTEN_MASK 0x00000004
- +#define APBBR_DMA_FINTEN_BIT 2
- +
- +#define APBBR_DMA_BURST_MASK 0x00000008
- +#define APBBR_DMA_BURST_BIT 3
- +
- +#define APBBR_DMA_ERRINTST_MASK 0x00000010
- +#define APBBR_DMA_ERRINTST_BIT 4
- +#define APBBR_DMA_ERRINTEN_MASK 0x00000020
- +#define APBBR_DMA_ERRINTEN_BIT 5
- +
- +#define APBBR_DMA_SRCADDRSEL_MASK 0x00000040
- +#define APBBR_DMA_SRCADDRSEL_BIT 6
- +#define APBBR_DMA_DSTADDRSEL_MASK 0x00000080
- +#define APBBR_DMA_DSTADDRSEL_BIT 7
- + #define APBBR_ADDRSEL_APB 0
- + #define APBBR_ADDRSEL_AHB 1
- +
- +#define APBBR_DMA_SRCADDRINC_MASK 0x00000700
- +#define APBBR_DMA_SRCADDRINC_SHIFT 8
- +#define APBBR_DMA_DSTADDRINC_MASK 0x00007000
- +#define APBBR_DMA_DSTADDRINC_SHIFT 12
- + #define APBBR_ADDRINC_FIXED 0 /* no increment */
- + #define APBBR_ADDRINC_I1X 1 /* +1, +4 (burst) */
- + #define APBBR_ADDRINC_I2X 2 /* +2, +8 (burst) */
- + #define APBBR_ADDRINC_I4X 3 /* +4, +16 (burst) */
- + #define APBBR_ADDRINC_D1 5 /* -1 */
- + #define APBBR_ADDRINC_D2 6 /* -2 */
- + #define APBBR_ADDRINC_D4 7 /* -4 */
- +
- +#define APBBR_DMA_DREQSEL_MASK 0x000f0000
- +#define APBBR_DMA_DREQSEL_SHIFT 16
- +#define APBBR_DMA_SREQSEL_MASK 0x0f000000
- +#define APBBR_DMA_SREQSEL_SHIFT 24
- +
- +#ifdef CONFIG_PLAT_AG102
- + #define APBBR_REQN_NONE 0
- + #define APBBR_REQN_CFC 1
- + #define APBBR_REQN_SSP 2
- + #define APBBR_REQN_SDC 8
- + #define APBBR_REQN_I2SAC97TX 6
- + #define APBBR_REQN_SSP2 8
- + #define APBBR_REQN_STUART 9
- + #define APBBR_REQN_BTUART 10
- + #define APBBR_REQN_IRDA 11
- + #define APBBR_REQN_SMMC 12
- +// #define APBBR_REQN_USB 0
- + #define APBBR_REQN_I2SAC97RX 13
- + #define APBBR_REQN_FUSB220 14
- + #define APBBR_REQN_MMSC 15
- + #define APBBR_REQN_MAX 15
- +#else
- + #define APBBR_REQN_NONE 0
- + #define APBBR_REQN_CFC 1
- + #define APBBR_REQN_SSP 2
- + #define APBBR_REQN_SDC 5
- +/* for amerald sd */
- + #define APBBR_REQN_SDC_AMERALD 7
- +/* for amerald ac97 ssp2 */
- + #define APBBR_REQN_I2SAC97TX_AMERALD 8
- + #define APBBR_REQN_I2SAC97RX_AMERALD 9
- +
- + #define APBBR_REQN_I2SAC97TX 6
- + #define APBBR_REQN_SSP2 8
- + #define APBBR_REQN_STUART 9 /* UART1 ? */
- + #define APBBR_REQN_BTUART 10 /* UART2 ? */
- + #define APBBR_REQN_IRDA 11
- + #define APBBR_REQN_SMMC 12
- + //#define APBBR_REQN_USB 13
- + #define APBBR_REQN_I2SAC97RX 13
- + #define APBBR_REQN_FUSB220 14
- + #define APBBR_REQN_MMSC 15
- + #define APBBR_REQN_MAX 15
- +#endif
- +
- +#define APBBR_DMA_DATAWIDTH_MASK 0x00300000 /* Data width of transfer */
- +#define APBBR_DMA_DATAWIDTH_SHIFT 20
- + #define APBBR_DATAWIDTH_4 0 /* word */
- + #define APBBR_DATAWIDTH_2 1 /* half-word */
- + #define APBBR_DATAWIDTH_1 2 /* byte */
- +
- +#ifdef CONFIG_PLATFORM_APBDMA
- +#define APBBR_DMA_CYCLE_TO_BYTES(cycle, width) ((cycle) << (2-(width)))
- +#define APBBR_DMA_BYTES_TO_CYCLE(bytes, width) ((bytes) >> (2-(width)))
- +#else
- +#define APBBR_DMA_CYCLE_TO_BYTES(cycle, width) 0
- +#define APBBR_DMA_BYTES_TO_CYCLE(bytes, width) 0
- +#endif /* CONFIG_PLATFORM_APBDMA */
- +
- +
- +#ifdef CONFIG_PLAT_AG102
- +
- +/*****************************************************************************
- + * PCU - AG102 Core APB
- +*****************************************************************************/
- +/* Device base address */
- +#define PCU_BASE PCU_VA_BASE
- +/* PMU registers (32-bit width) */
- +/* Add by Dennis on 2011.03.09 */
- +#define PCU_DMA_SEL (PCU_BASE+ 0x38)
- +
- +#else /* CONFIG_PLAT_AG102 */
- +
- +/*****************************************************************************
- + * PMU - AG101 Core APB
- +*****************************************************************************/
- +/* Device base address */
- +#define PMU_BASE PMU_FTPMU010_0_VA_BASE
- +
- +/* PMU registers (32-bit width) */
- +#define PMU_AHBDMA_REQACK (PMU_BASE + 0x90)
- +
- +#define PMU_CFC_REQACK_CFG (PMU_BASE + 0xa0)
- +#define PMU_SSP1_REQACK_CFG (PMU_BASE + 0xa4)
- +#define PMU_UART1TX_REQACK_CFG (PMU_BASE + 0xa8)
- +#define PMU_UART1RX_REQACK_CFG (PMU_BASE + 0xac)
- +#define PMU_UART2TX_REQACK_CFG (PMU_BASE + 0xb0)
- +#define PMU_UART2RX_REQACK_CFG (PMU_BASE + 0xb4)
- +#define PMU_SDC_REQACK_CFG (PMU_BASE + 0xb8)
- +#define PMU_I2SAC97TX_REQACK_CFG (PMU_BASE + 0xbc)
- +#define PMU_I2SAC97RX_REQACK_CFG (PMU_BASE + 0xc4)
- +#define PMU_UART3TX_REQACK_CFG (PMU_BASE + 0xc0)
- +#define PMU_UART3RX_REQACK_CFG (PMU_BASE + 0xcc)
- +#define PMU_USB_REQACK_CFG (PMU_BASE + 0xc8)
- +#define PMU_IRDA_REQACK_CFG (PMU_BASE + 0xd0)
- +#define PMU_EXT0_REQACK_CFG (PMU_BASE + 0xd4)
- +#define PMU_EXT1_REQACK_CFG (PMU_BASE + 0xd8)
- +
- +
- +/*****************************************************************************
- + * PMU - AG101 Core APB
- +*****************************************************************************/
- +
- +/* Driving capability and slew rate control register 2 (+0x48) */
- +#define PMU_STUART_DCSR_MASK 0x0000000f
- +#define PMU_STUART_DCSR_SHIFT 0
- +#define PMU_BTUART_DCSR_MASK 0x00000f00
- +#define PMU_BTUART_DCSR_SHIFT 8
- +/*#define PMU_FFUART_DCSR_MASK 0x0000f000*/
- +/*#define PMU_FFUART_DCSR_SHIFT 12 */
- +#define PMU_PMU_DCSR_MASK 0x000f0000
- +#define PMU_PMU_DCSR_SHIFT 16
- +#define PMU_I2SAC97_DCSR_MASK 0x00f00000
- +#define PMU_I2SAC97_DCSR_SHIFT 20
- +#define PMU_SSP_DCSR_MASK 0x0f000000
- +#define PMU_SSP_DCSR_SHIFT 24
- +#define PMU_SD_DCSR_MASK 0xf0000000
- +#define PMU_SD_DCSR_SHIFT 28
- +
- +/* AHB DMA REQ/ACK connection configuration status register (+0x90) */
- +#define PMU_CH0_REQACK_MASK 0x0000000f
- +#define PMU_CH0_REQACK_SHIFT 0
- +#define PMU_CH1_REQACK_MASK 0x000000f0
- +#define PMU_CH1_REQACK_SHIFT 4
- +#define PMU_CH2_REQACK_MASK 0x00000f00
- +#define PMU_CH2_REQACK_SHIFT 8
- +#define PMU_CH3_REQACK_MASK 0x0000f000
- +#define PMU_CH3_REQACK_SHIFT 12
- +#define PMU_CH4_REQACK_MASK 0x000f0000
- +#define PMU_CH4_REQACK_SHIFT 16
- +#define PMU_CH5_REQACK_MASK 0x00f00000
- +#define PMU_CH5_REQACK_SHIFT 20
- +#define PMU_CH6_REQACK_MASK 0x0f000000
- +#define PMU_CH6_REQACK_SHIFT 24
- +#define PMU_CH7_REQACK_MASK 0xf0000000
- +#define PMU_CH7_REQACK_SHIFT 28
- +
- + #define PMU_REQN_NONE 0
- + #define PMU_REQN_CFC 1
- + #define PMU_REQN_SSP 2
- + #define PMU_REQN_UART1TX 3
- + #define PMU_REQN_UART1RX 4
- + #define PMU_REQN_UART2TX 5
- + #define PMU_REQN_UART2RX 6
- + #define PMU_REQN_SDC 7
- + #define PMU_REQN_I2SAC97TX 8
- + #define PMU_REQN_I2SAC97RX 10
- +/* for amerald ac97 ssp2 */
- + #define PMU_REQN_I2SAC97TX_AMERALD 8
- + #define PMU_REQN_I2SAC97RX_AMERALD 9
- + #define PMU_REQN_USB 11
- + #define PMU_REQN_EXT0 14
- + #define PMU_REQN_EXT1 15
- + #define PMU_REQN_MAX 15
- +
- +/* CFC ..., etc, REQ/ACK connection configuration registers (0xa0 ~ 0xd8) */
- +#define PMU_CHANNEL_MASK 0x00000007
- +#define PMU_CHANNEL_SHIFT 0
- +#define PMU_DMACUSED_MASK 0x00000008
- +#define PMU_DMACUSED_BIT 3
- +
- +#endif /* CONFIG_PLAT_AG102 */
- +
- +
- +/*****************************************************************************
- + * DMAD globals section
- + */
- +
- +enum DMAD_DMAC_CORE {
- + DMAD_DMAC_AHB_CORE,
- + DMAD_DMAC_APB_CORE
- +};
- +
- +enum DMAD_CHREG_FLAGS {
- + DMAD_FLAGS_NON_BLOCK = 0x00000000,
- + DMAD_FLAGS_SLEEP_BLOCK = 0x00000001,
- + DMAD_FLAGS_SPIN_BLOCK = 0x00000002,
- + DMAD_FLAGS_RING_MODE = 0x00000008, /* ring submission mode */
- + DMAD_FLAGS_BIDIRECTION = 0x00000010, /* indicates both tx and rx */
- +};
- +
- +enum DMAD_CHDIR
- +{
- + DMAD_DIR_A0_TO_A1 = 0,
- + DMAD_DIR_A1_TO_A0 = 1,
- +};
- +
- +/* AHB Channel Request
- + *
- + * Notes for developers:
- + * These should be channel-only properties. Controller-specific properties
- + * should be separated as other driver structure or driver buildin-hardcode.
- + * If controller properties are embeded in this union, request for a channel
- + * may unexpectedly override the controller setting of the request of other
- + * channels.
- + */
- +typedef struct dmad_ahb_chreq
- +{
- + /* channel property */
- + u32 sync; /* (in) different clock domain */
- + u32 priority; /* (in) DMAC_CSR_CHPRI_xxx */
- + u32 hw_handshake; /* (in) hardware handshaking on/off */
- + u32 burst_size; /* (in) DMAC_CSR_SIZE_xxx */
- +
- + /* source property */
- + union {
- + u32 src_width; /* (in) DMAC_CSR_WIDTH_xxx */
- + u32 addr0_width; /* (in) bi-direction mode alias */
- + u32 ring_width; /* (in) ring-mode alias */
- + };
- + union {
- + u32 src_ctrl; /* (in) DMAC_CSR_AD_xxx */
- + u32 addr0_ctrl; /* (in) bi-direction mode alias */
- + u32 ring_ctrl; /* (in) ring-mode alias */
- + };
- + union {
- + u32 src_reqn; /* (in) DMAC_REQN_xxx */
- + u32 addr0_reqn; /* (in) bi-direction mode alias */
- + u32 ring_reqn; /* (in) ring-mode alias */
- + };
- +
- + /* destination property */
- + union {
- + u32 dst_width; /* (in) DMAC_CSR_WIDTH_xxx */
- + u32 addr1_width; /* (in) bi-direction mode alias */
- + u32 dev_width; /* (in) ring-mode alias */
- + };
- + union {
- + u32 dst_ctrl; /* (in) DMAC_CSR_AD_xxx */
- + u32 addr1_ctrl; /* (in) bi-direction mode alias */
- + u32 dev_ctrl; /* (in) ring-mode alias */
- + };
- + union {
- + u32 dst_reqn; /* (in) DMAC_REQN_xxx */
- + u32 addr1_reqn; /* (in) bi-direction mode alias */
- + u32 dev_reqn; /* (in) ring-mode alias */
- + };
- +
- + /* (in) transfer direction, valid only if following flags were set ...
- + * DMAD_FLAGS_BIDIRECTION or
- + * DMAD_FLAGS_RING_MODE
- + * value:
- + * 0 (addr0 -> addr1, or ring-buff to device)
- + * 1 (addr0 <- addr1, or device to ring-buff)
- + */
- + u32 tx_dir;
- +
- +} dmad_ahb_chreq;
- +
- +/* APB Channel Request
- + *
- + * Notes for developers:
- + * These should be channel-only properties. Controller-specific properties
- + * should be separated as other driver structure or driver buildin-hardcode.
- + * If controller properties are embeded in this union, request for a channel
- + * may unexpectedly override the controller setting of the request of other
- + * channels.
- + */
- +typedef struct dmad_apb_chreq
- +{
- + /* controller property (removed! should not exist in this struct) */
- +
- + /* channel property */
- + u32 burst_mode; /* (in) Burst mode (0/1) */
- + u32 data_width; /* (in) APBBR_DATAWIDTH_xxx */
- +
- + /* source property */
- + union {
- + u32 src_ctrl; /* (in) APBBR_ADDRINC_xxx */
- + u32 addr0_ctrl; /* (in) bi-direction mode alias */
- + u32 ring_ctrl; /* (in) ring-mode alias */
- + };
- + union {
- + u32 src_reqn; /* (in) APBBR_REQN_xxx */
- + u32 addr0_reqn; /* (in) bi-direction mode alias */
- + u32 ring_reqn; /* (in) ring-mode alias */
- + };
- +
- + /* destination property */
- + union {
- + u32 dst_ctrl; /* (in) APBBR_ADDRINC_xxx */
- + u32 addr1_ctrl; /* (in) bi-direction mode alias */
- + u32 dev_ctrl; /* (in) ring-mode alias */
- + };
- + union {
- + u32 dst_reqn; /* (in) APBBR_REQN_xxx */
- + u32 addr1_reqn; /* (in) bi-direction mode alias */
- + u32 dev_reqn; /* (in) ring-mode alias */
- + };
- +
- + /* (in) transfer direction, valid only if following flags were set ...
- + * DMAD_FLAGS_BIDIRECTION or
- + * DMAD_FLAGS_RING_MODE
- + * value:
- + * 0 (addr0 -> addr1, or ring-buff to device)
- + * 1 (addr0 <- addr1, or device to ring-buff)
- + */
- + u32 tx_dir;
- +
- +} dmad_apb_chreq;
- +
- +/* Channel Request Descriptor */
- +typedef struct dmad_chreq
- +{
- + /* common fields */
- + u32 controller; /* (in) enum DMAD_DMAC_CORE */
- + u32 flags; /* (in) enum DMAD_CHREQ_FLAGS */
- +
- + /**********************************************************************
- + * ring mode specific fields (valid only for DMAD_FLAGS_RING_MODE)
- + * note:
- + * - size fields are in unit of data width
- + * * for AHB, ring size is limited to 4K * data_width of data if
- + * hw-LLP is not used
- + * * for AHB, ring size is limited to 4K * data_width * LLP-count
- + * hw-if LLP is used
- + * * for APB, ring size is limited to 16M * data_width of data
- + * - currently sw ring mode dma supports only fixed or incremental
- + * src/dst addressing
- + * - ring_size shoule >= periods * period_size
- + */
- + dma_addr_t ring_base; /* (in) ring buffer base (pa) */
- + dma_addr_t ring_size; /* (in) unit of data width */
- + addr_t dev_addr; /* (in) device data port address */
- + dma_addr_t periods; /* (in) number of ints per ring */
- + dma_addr_t period_size; /* (in) size per int, data-width */
- +
- +
- + /* channel-wise completion callback - called when hw-ptr catches sw-ptr
- + * (i.e., channel stops)
- + *
- + * completion_cb: (in) client supplied callback function, executed in
- + * interrupt context.
- + * completion_data: (in) client private data to be passed to data
- + * argument of completion_cb().
- + */
- + void (*completion_cb)(int channel, u16 status, void *data);
- + void *completion_data;
- + /*********************************************************************/
- +
- + /* channel allocation output */
- + u32 channel; /* (out) allocated channel */
- + void *drq; /* (out) internal use (DMAD_DRQ *)*/
- +
- + /* channel-alloc parameters (channel-wise properties) */
- + union {
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + dmad_ahb_chreq ahb_req; /* (in) for AHB DMA parameters */
- +#endif
- +#ifdef CONFIG_PLATFORM_APBDMA
- + dmad_apb_chreq apb_req; /* (in) APB Bridge DMA params */
- +#endif
- + };
- +
- +} dmad_chreq;
- +
- +/* drb states are mutual exclusive */
- +enum DMAD_DRB_STATE
- +{
- + DMAD_DRB_STATE_FREE = 0,
- + DMAD_DRB_STATE_READY = 0x00000001,
- + DMAD_DRB_STATE_SUBMITTED = 0x00000002,
- + DMAD_DRB_STATE_EXECUTED = 0x00000004,
- + DMAD_DRB_STATE_COMPLETED = 0x00000008,
- + //DMAD_DRB_STATE_ERROR = 0x00000010,
- + DMAD_DRB_STATE_ABORT = 0x00000020,
- +};
- +
- +/* DMA request block
- + * todo: replaced link with kernel struct list_head ??
- + */
- +typedef struct dmad_drb
- +{
- + u32 prev; /* (internal) previous node */
- + u32 next; /* (internal) next node */
- + u32 node; /* (internal) this node */
- +
- + u32 state; /* (out) DRB's current state */
- +
- + union {
- + dma_addr_t src_addr; /* (in) source pa */
- + dma_addr_t addr0; /* (in) bi-direction mode alias */
- + };
- +
- + union {
- + dma_addr_t dst_addr; /* (in) destination pa */
- + dma_addr_t addr1; /* (in) bi-direction mode alias */
- + };
- +
- + /* (in) AHB DMA (22 bits): 0 ~ 4M-1, unit is "data width"
- + * APB DMA (24 bits): 0 ~ 16M-1, unit is "data width * burst size"
- + * => for safe without mistakes, use dmad_make_req_cycles() to
- + * compose this value if the addressing mode is incremental
- + * mode (not working yet for decremental mode).
- + */
- + dma_addr_t req_cycle;
- +
- + /* (in) if non-null, this sync object will be signaled upon dma
- + * completion (for blocked-waiting dma completion)
- + */
- + struct completion *sync;
- +
- +} dmad_drb;
- +
- +
- +/******************************************************************************
- + * Debug Trace Mechanism
- + */
- +#if (DMAD_ERROR_TRACE)
- +#define dmad_err(format, arg...) printk(KERN_ERR format , ## arg)
- +#else
- +#define dmad_err(format, arg...) (void)(0)
- +#endif
- +
- +#if (DMAD_DEBUG_TRACE)
- +#define dmad_dbg(format, arg...) printk(KERN_INFO format , ## arg)
- +#else
- +#define dmad_dbg(format, arg...) (void)(0)
- +#endif
- +
- +#if (defined(CONFIG_PLATFORM_AHBDMA) || defined(CONFIG_PLATFORM_APBDMA))
- +
- +/******************************************************************************
- + * DMAD Driver Interface
- +******************************************************************************/
- +
- +extern int dmad_channel_alloc(dmad_chreq *ch_req);
- +extern int dmad_channel_free(dmad_chreq *ch_req);
- +extern int dmad_channel_enable(const dmad_chreq *ch_req, u8 enable);
- +extern u32 dmad_max_size_per_drb(dmad_chreq *ch_req);
- +extern u32 dmad_bytes_to_cycles(dmad_chreq *ch_req, u32 byte_size);
- +
- +extern int dmad_kickoff_requests(dmad_chreq *ch_req);
- +extern int dmad_drain_requests(dmad_chreq *ch_req, u8 shutdown);
- +
- +/* for performance reason, these two functions are platform-specific */
- +#ifdef CONFIG_PLATFORM_AHBDMA
- +extern int dmad_probe_irq_source_ahb(void);
- +#endif
- +#ifdef CONFIG_PLATFORM_APBDMA
- +extern int dmad_probe_irq_source_apb(void);
- +#endif
- +
- +/* note: hw_ptr here is phyical address of dma source or destination */
- +extern dma_addr_t dmad_probe_hw_ptr_src(dmad_chreq *ch_req);
- +extern dma_addr_t dmad_probe_hw_ptr_dst(dmad_chreq *ch_req);
- +
- +/*****************************************************************************
- + * routines only valid in discrete (non-ring) mode
- + */
- +extern int dmad_config_channel_dir(dmad_chreq *ch_req, u8 dir);
- +extern int dmad_alloc_drb(dmad_chreq *ch_req, dmad_drb **drb);
- +extern int dmad_free_drb(dmad_chreq *ch_req, dmad_drb *drb);
- +extern int dmad_submit_request(dmad_chreq *ch_req,
- + dmad_drb *drb, u8 keep_fired);
- +extern int dmad_withdraw_request(dmad_chreq *ch_req, dmad_drb *drb);
- +/****************************************************************************/
- +
- +/*****************************************************************************
- + * routines only valid in ring mode
- + * note: sw_ptr and hw_ptr are values offset from the ring buffer base
- + * unit of sw_ptr is data-width
- + * unit of hw_ptr returned is byte
- + */
- +extern int dmad_update_ring(dmad_chreq *ch_req);
- +extern int dmad_update_ring_sw_ptr(dmad_chreq *ch_req,
- + dma_addr_t sw_ptr, u8 keep_fired);
- +extern dma_addr_t dmad_probe_ring_hw_ptr(dmad_chreq *ch_req);
- +/****************************************************************************/
- +
- +#else /* CONFIG_PLATFORM_AHBDMA || CONFIG_PLATFORM_APBDMA */
- +
- +static inline int dmad_channel_alloc(dmad_chreq *ch_req) { return -EFAULT; }
- +static inline int dmad_channel_free(dmad_chreq *ch_req) { return -EFAULT; }
- +static inline int dmad_channel_enable(const dmad_chreq *ch_req, u8 enable)
- + { return -EFAULT; }
- +static inline u32 dmad_max_size_per_drb(dmad_chreq *ch_req) { return 0; }
- +static inline u32 dmad_bytes_to_cycles(dmad_chreq *ch_req, u32 byte_size)
- + { return 0; }
- +static inline int dmad_kickoff_requests(dmad_chreq *ch_req) { return -EFAULT; }
- +static inline int dmad_drain_requests(dmad_chreq *ch_req, u8 shutdown)
- + { return -EFAULT; }
- +static inline int dmad_probe_irq_source_ahb(void) { return -EFAULT; }
- +static inline int dmad_probe_irq_source_apb(void) { return -EFAULT; }
- +static inline dma_addr_t dmad_probe_hw_ptr_src(dmad_chreq *ch_req)
- + { return (dma_addr_t)NULL; }
- +static inline dma_addr_t dmad_probe_hw_ptr_dst(dmad_chreq *ch_req)
- + { return (dma_addr_t)NULL; }
- +static inline int dmad_config_channel_dir(dmad_chreq *ch_req, u8 dir)
- + { return -EFAULT; }
- +static inline int dmad_alloc_drb(dmad_chreq *ch_req, dmad_drb **drb)
- + { return -EFAULT; }
- +static inline int dmad_free_drb(dmad_chreq *ch_req, dmad_drb *drb)
- + { return -EFAULT; }
- +static inline int dmad_submit_request(dmad_chreq *ch_req,
- + dmad_drb *drb, u8 keep_fired) { return -EFAULT; }
- +static inline int dmad_withdraw_request(dmad_chreq *ch_req, dmad_drb *drb)
- + { return -EFAULT; }
- +static inline int dmad_update_ring(dmad_chreq *ch_req)
- + { return -EFAULT; }
- +static inline int dmad_update_ring_sw_ptr(dmad_chreq *ch_req,
- + dma_addr_t sw_ptr, u8 keep_fired) { return -EFAULT; }
- +static inline dma_addr_t dmad_probe_ring_hw_ptr(dmad_chreq *ch_req)
- + { return (dma_addr_t)NULL; }
- +
- +#endif /* CONFIG_PLATFORM_AHBDMA || CONFIG_PLATFORM_APBDMA */
- +
- +#endif /* __NDS_DMAD_INC__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/dma.h linux-3.4.110/arch/nds32/include/asm/dma.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/dma.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/dma.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,17 @@
- +/*
- + * linux/arch/nds32/include/asm/dma.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_DMA_H__
- +#define __NDS32_DMA_H__
- +
- +#define MAX_DMA_ADDRESS 0xffffffff
- +
- +#ifdef CONFIG_PCI
- +extern int isa_dma_bridge_buggy;
- +#else
- +#define isa_dma_bridge_buggy (0)
- +#endif
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/dma-mapping.h linux-3.4.110/arch/nds32/include/asm/dma-mapping.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/dma-mapping.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/dma-mapping.h 2016-04-07 10:20:50.894079168 +0200
- @@ -0,0 +1,453 @@
- +/*
- + * linux/arch/nds32/include/asm/dma-mapping.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef ASMNDS32_DMA_MAPPING_H
- +#define ASMNDS32_DMA_MAPPING_H
- +
- +#ifdef __KERNEL__
- +
- +#include <linux/mm.h> /* need struct page */
- +#include <linux/highmem.h>
- +
- +#include <asm/scatterlist.h>
- +
- +/*
- + * DMA-consistent mapping functions. These allocate/free a region of
- + * uncached, unwrite-buffered mapped memory space for use with DMA
- + * devices. This is the "generic" version. The PCI specific version
- + * is in pci.h
- + */
- +extern void consistent_sync(void *kaddr, size_t size, int rw);
- +
- +/*
- + * Return whether the given device DMA address mask can be supported
- + * properly. For example, if your device can only drive the low 24-bits
- + * during bus mastering, then you would pass 0x00ffffff as the mask
- + * to this function.
- + */
- +static inline int dma_supported(struct device *dev, u64 mask)
- +{
- + return dev->dma_mask && *dev->dma_mask != 0;
- +}
- +
- +static inline int dma_set_mask(struct device *dev, u64 dma_mask)
- +{
- + if (!dev->dma_mask || !dma_supported(dev, dma_mask))
- + return -EIO;
- +
- + *dev->dma_mask = dma_mask;
- +
- + return 0;
- +}
- +
- +static inline int dma_is_consistent(dma_addr_t handle)
- +{
- + return 0;
- +}
- +
- +/*
- + * DMA errors are defined by all-bits-set in the DMA address.
- + */
- +static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
- +{
- + return dma_addr == ~0;
- +}
- +
- +/*
- + * Dummy noncoherent implementation. We don't provide a dma_cache_sync
- + * function so drivers using this API are highlighted with build warnings.
- + */
- +static inline void *
- +dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
- +{
- + return NULL;
- +}
- +
- +static inline void
- +dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr,
- + dma_addr_t handle)
- +{
- +}
- +
- +/**
- + * dma_alloc_coherent - allocate consistent memory for DMA
- + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- + * @size: required memory size
- + * @handle: bus-specific DMA address
- + *
- + * Allocate some uncached, unbuffered memory for a device for
- + * performing DMA. This function allocates pages, and will
- + * return the CPU-viewed address, and sets @handle to be the
- + * device-viewed address.
- + */
- +extern void *
- +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp);
- +
- +/**
- + * dma_free_coherent - free memory allocated by dma_alloc_coherent
- + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- + * @size: size of memory originally requested in dma_alloc_coherent
- + * @cpu_addr: CPU-view address returned from dma_alloc_coherent
- + * @handle: device-view address returned from dma_alloc_coherent
- + *
- + * Free (and unmap) a DMA buffer previously allocated by
- + * dma_alloc_coherent().
- + *
- + * References to memory and mappings associated with cpu_addr/handle
- + * during and after this call executing are illegal.
- + */
- +extern void
- +dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
- + dma_addr_t handle);
- +
- +/**
- + * dma_mmap_coherent - map a coherent DMA allocation into user space
- + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- + * @vma: vm_area_struct describing requested user mapping
- + * @cpu_addr: kernel CPU-view address returned from dma_alloc_coherent
- + * @handle: device-view address returned from dma_alloc_coherent
- + * @size: size of memory originally requested in dma_alloc_coherent
- + *
- + * Map a coherent DMA buffer previously allocated by dma_alloc_coherent
- + * into user space. The coherent DMA buffer must not be freed by the
- + * driver until the user space mapping has been released.
- + */
- +int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
- + void *cpu_addr, dma_addr_t handle, size_t size);
- +
- +
- +/**
- + * dma_alloc_writecombine - allocate writecombining memory for DMA
- + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- + * @size: required memory size
- + * @handle: bus-specific DMA address
- + *
- + * Allocate some uncached, buffered memory for a device for
- + * performing DMA. This function allocates pages, and will
- + * return the CPU-viewed address, and sets @handle to be the
- + * device-viewed address.
- + */
- +extern void *
- +dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp);
- +
- +#define dma_free_writecombine(dev,size,cpu_addr,handle) \
- + dma_free_coherent(dev,size,cpu_addr,handle)
- +
- +int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma,
- + void *cpu_addr, dma_addr_t handle, size_t size);
- +
- +
- +/**
- + * dma_map_single - map a single buffer for streaming DMA
- + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- + * @cpu_addr: CPU direct mapped address of buffer
- + * @size: size of buffer to map
- + * @dir: DMA transfer direction
- + *
- + * Ensure that any data held in the cache is appropriately discarded
- + * or written back.
- + *
- + * The device owns this memory once this call has completed. The CPU
- + * can regain ownership by calling dma_unmap_single() or
- + * dma_sync_single_for_cpu().
- + */
- +#ifndef CONFIG_DMABOUNCE
- +static inline dma_addr_t
- +dma_map_single(struct device *dev, void *cpu_addr, size_t size,
- + enum dma_data_direction dir)
- +{
- + consistent_sync(cpu_addr, size, dir);
- + return virt_to_dma(dev, (unsigned long)cpu_addr);
- +}
- +#else
- +extern dma_addr_t dma_map_single(struct device *,void *, size_t, enum dma_data_direction);
- +#endif
- +
- +/**
- + * dma_map_page - map a portion of a page for streaming DMA
- + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- + * @page: page that buffer resides in
- + * @offset: offset into page for start of buffer
- + * @size: size of buffer to map
- + * @dir: DMA transfer direction
- + *
- + * Ensure that any data held in the cache is appropriately discarded
- + * or written back.
- + *
- + * The device owns this memory once this call has completed. The CPU
- + * can regain ownership by calling dma_unmap_page() or
- + * dma_sync_single_for_cpu().
- + */
- +static inline dma_addr_t
- +dma_map_page(struct device *dev, struct page *page,
- + unsigned long offset, size_t size,
- + enum dma_data_direction dir)
- +{
- + return dma_map_single(dev, page_address(page) + offset, size, (int)dir);
- +}
- +
- +/**
- + * dma_unmap_single - unmap a single buffer previously mapped
- + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- + * @handle: DMA address of buffer
- + * @size: size of buffer to map
- + * @dir: DMA transfer direction
- + *
- + * Unmap a single streaming mode DMA translation. The handle and size
- + * must match what was provided in the previous dma_map_single() call.
- + * All other usages are undefined.
- + *
- + * After this call, reads by the CPU to the buffer are guaranteed to see
- + * whatever the device wrote there.
- + */
- +#ifndef CONFIG_DMABOUNCE
- +static inline void
- +dma_unmap_single(struct device *dev, dma_addr_t handle, size_t size,
- + enum dma_data_direction dir)
- +{
- + /* nothing to do */
- +}
- +#else
- +extern void dma_unmap_single(struct device *, dma_addr_t, size_t, enum dma_data_direction);
- +#endif
- +
- +/**
- + * dma_unmap_page - unmap a buffer previously mapped through dma_map_page()
- + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- + * @handle: DMA address of buffer
- + * @size: size of buffer to map
- + * @dir: DMA transfer direction
- + *
- + * Unmap a single streaming mode DMA translation. The handle and size
- + * must match what was provided in the previous dma_map_single() call.
- + * All other usages are undefined.
- + *
- + * After this call, reads by the CPU to the buffer are guaranteed to see
- + * whatever the device wrote there.
- + */
- +static inline void
- +dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
- + enum dma_data_direction dir)
- +{
- + dma_unmap_single(dev, handle, size, (int)dir);
- +}
- +
- +/**
- + * dma_map_sg - map a set of SG buffers for streaming mode DMA
- + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- + * @sg: list of buffers
- + * @nents: number of buffers to map
- + * @dir: DMA transfer direction
- + *
- + * Map a set of buffers described by scatterlist in streaming
- + * mode for DMA. This is the scatter-gather version of the
- + * above dma_map_single interface. Here the scatter gather list
- + * elements are each tagged with the appropriate dma address
- + * and length. They are obtained via sg_dma_{address,length}(SG).
- + *
- + * NOTE: An implementation may be able to use a smaller number of
- + * DMA address/length pairs than there are SG table elements.
- + * (for example via virtual mapping capabilities)
- + * The routine returns the number of addr/length pairs actually
- + * used, at most nents.
- + *
- + * Device ownership issues as mentioned above for dma_map_single are
- + * the same here.
- + */
- +#ifndef CONFIG_DMABOUNCE
- +static inline int
- +dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
- + enum dma_data_direction dir)
- +{
- + int i;
- +
- + for (i = 0; i < nents; i++, sg++) {
- + void *virt;
- + unsigned long pfn;
- + struct page *page = sg_page(sg);
- +
- + sg->dma_address = page_to_dma(dev, page) + sg->offset;
- + pfn = page_to_pfn(page) + sg->offset / PAGE_SIZE;
- + page = pfn_to_page(pfn);
- + if (PageHighMem(page)) {
- + virt = kmap_atomic(page);
- + consistent_sync(virt, sg->length, dir);
- + kunmap_atomic(virt);
- + } else {
- + if (sg->offset > PAGE_SIZE)
- + panic("sg->offset:%08x > PAGE_SIZE\n", sg->offset);
- + virt = page_address(page) + sg->offset;
- + consistent_sync(virt, sg->length, dir);
- + }
- + }
- + return nents;
- +}
- +#else
- +extern int dma_map_sg(struct device *, struct scatterlist *, int, enum dma_data_direction);
- +#endif
- +
- +/**
- + * dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg
- + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- + * @sg: list of buffers
- + * @nents: number of buffers to map
- + * @dir: DMA transfer direction
- + *
- + * Unmap a set of streaming mode DMA translations.
- + * Again, CPU read rules concerning calls here are the same as for
- + * dma_unmap_single() above.
- + */
- +#ifndef CONFIG_DMABOUNCE
- +static inline void
- +dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
- + enum dma_data_direction dir)
- +{
- +
- + /* nothing to do */
- +}
- +#else
- +extern void dma_unmap_sg(struct device *, struct scatterlist *, int, enum dma_data_direction);
- +#endif
- +
- +
- +/**
- + * dma_sync_single_for_cpu
- + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- + * @handle: DMA address of buffer
- + * @size: size of buffer to map
- + * @dir: DMA transfer direction
- + *
- + * Make physical memory consistent for a single streaming mode DMA
- + * translation after a transfer.
- + *
- + * If you perform a dma_map_single() but wish to interrogate the
- + * buffer using the cpu, yet do not wish to teardown the PCI dma
- + * mapping, you must call this function before doing so. At the
- + * next point you give the PCI dma address back to the card, you
- + * must first the perform a dma_sync_for_device, and then the
- + * device again owns the buffer.
- + */
- +#ifndef CONFIG_DMABOUNCE
- +static inline void
- +dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle, size_t size,
- + enum dma_data_direction dir)
- +{
- + consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
- +}
- +
- +static inline void
- +dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size,
- + enum dma_data_direction dir)
- +{
- + consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
- +}
- +#else
- +extern void dma_sync_single_for_cpu(struct device*, dma_addr_t, size_t, enum dma_data_direction);
- +extern void dma_sync_single_for_device(struct device*, dma_addr_t, size_t, enum dma_data_direction);
- +#endif
- +
- +
- +/**
- + * dma_sync_sg_for_cpu
- + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- + * @sg: list of buffers
- + * @nents: number of buffers to map
- + * @dir: DMA transfer direction
- + *
- + * Make physical memory consistent for a set of streaming
- + * mode DMA translations after a transfer.
- + *
- + * The same as dma_sync_single_for_* but for a scatter-gather list,
- + * same rules and usage.
- + */
- +#ifndef CONFIG_DMABOUNCE
- +static inline void
- +dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
- + enum dma_data_direction dir)
- +{
- + int i;
- +
- + for (i = 0; i < nents; i++, sg++) {
- + char *virt = page_address( (struct page *)sg->page_link) + sg->offset;
- + consistent_sync(virt, sg->length, dir);
- + }
- +}
- +
- +static inline void
- +dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
- + enum dma_data_direction dir)
- +{
- + int i;
- +
- + for (i = 0; i < nents; i++, sg++) {
- + char *virt = page_address( (struct page *)sg->page_link) + sg->offset;
- + consistent_sync(virt, sg->length, dir);
- + }
- +}
- +#else
- +extern void dma_sync_sg_for_cpu(struct device*, struct scatterlist*, int, enum dma_data_direction);
- +extern void dma_sync_sg_for_device(struct device*, struct scatterlist*, int, enum dma_data_direction);
- +#endif
- +
- +#ifdef CONFIG_DMABOUNCE
- +/*
- + * For SA-1111, IXP425, and ADI systems the dma-mapping functions are "magic"
- + * and utilize bounce buffers as needed to work around limited DMA windows.
- + *
- + * On the SA-1111, a bug limits DMA to only certain regions of RAM.
- + * On the IXP425, the PCI inbound window is 64MB (256MB total RAM)
- + * On some ADI engineering systems, PCI inbound window is 32MB (12MB total RAM)
- + *
- + * The following are helper functions used by the dmabounce subystem
- + *
- + */
- +
- +/**
- + * dmabounce_register_dev
- + *
- + * @dev: valid struct device pointer
- + * @small_buf_size: size of buffers to use with small buffer pool
- + * @large_buf_size: size of buffers to use with large buffer pool (can be 0)
- + *
- + * This function should be called by low-level platform code to register
- + * a device as requireing DMA buffer bouncing. The function will allocate
- + * appropriate DMA pools for the device.
- + *
- + */
- +extern int dmabounce_register_dev(struct device *, unsigned long, unsigned long);
- +
- +/**
- + * dmabounce_unregister_dev
- + *
- + * @dev: valid struct device pointer
- + *
- + * This function should be called by low-level platform code when device
- + * that was previously registered with dmabounce_register_dev is removed
- + * from the system.
- + *
- + */
- +extern void dmabounce_unregister_dev(struct device *);
- +
- +/**
- + * dma_needs_bounce
- + *
- + * @dev: valid struct device pointer
- + * @dma_handle: dma_handle of unbounced buffer
- + * @size: size of region being mapped
- + *
- + * Platforms that utilize the dmabounce mechanism must implement
- + * this function.
- + *
- + * The dmabounce routines call this function whenever a dma-mapping
- + * is requested to determine whether a given buffer needs to be bounced
- + * or not. The function must return 0 if the buffer is OK for
- + * DMA access and 1 if the buffer needs to be bounced.
- + *
- + */
- +extern int dma_needs_bounce(struct device*, dma_addr_t, size_t);
- +#endif /* CONFIG_DMABOUNCE */
- +
- +#endif /* __KERNEL__ */
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/elf.h linux-3.4.110/arch/nds32/include/asm/elf.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/elf.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/elf.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,145 @@
- +/*
- + * linux/arch/nds32/include/asm/elf.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __ASMNDS32_ELF_H
- +#define __ASMNDS32_ELF_H
- +
- +/*
- + * ELF register definitions..
- + */
- +
- +#include <asm/ptrace.h>
- +#include <asm/user.h>
- +
- +typedef unsigned long elf_greg_t;
- +typedef unsigned long elf_freg_t[3];
- +
- +extern unsigned int elf_hwcap;
- +
- +#define EM_NDS32 167
- +
- +
- +#define R_NDS32_NONE 0
- +#define R_NDS32_16_RELA 19
- +#define R_NDS32_32_RELA 20
- +#define R_NDS32_9_PCREL_RELA 22
- +#define R_NDS32_15_PCREL_RELA 23
- +#define R_NDS32_17_PCREL_RELA 24
- +#define R_NDS32_25_PCREL_RELA 25
- +#define R_NDS32_HI20_RELA 26
- +#define R_NDS32_LO12S3_RELA 27
- +#define R_NDS32_LO12S2_RELA 28
- +#define R_NDS32_LO12S1_RELA 29
- +#define R_NDS32_LO12S0_RELA 30
- +#define R_NDS32_SDA15S3_RELA 31
- +#define R_NDS32_SDA15S2_RELA 32
- +#define R_NDS32_SDA15S1_RELA 33
- +#define R_NDS32_SDA15S0_RELA 34
- +#define R_NDS32_GOT20 37
- +#define R_NDS32_25_PLTREL 38
- +#define R_NDS32_COPY 39
- +#define R_NDS32_GLOB_DAT 40
- +#define R_NDS32_JMP_SLOT 41
- +#define R_NDS32_RELATIVE 42
- +#define R_NDS32_GOTOFF 43
- +#define R_NDS32_GOTPC20 44
- +#define R_NDS32_GOT_HI20 45
- +#define R_NDS32_GOT_LO12 46
- +#define R_NDS32_GOTPC_HI20 47
- +#define R_NDS32_GOTPC_LO12 48
- +#define R_NDS32_GOTOFF_HI20 49
- +#define R_NDS32_GOTOFF_LO12 50
- +#define R_NDS32_INSN16 51
- +#define R_NDS32_LABEL 52
- +#define R_NDS32_LONGCALL1 53
- +#define R_NDS32_LONGCALL2 54
- +#define R_NDS32_LONGCALL3 55
- +#define R_NDS32_LONGJUMP1 56
- +#define R_NDS32_LONGJUMP2 57
- +#define R_NDS32_LONGJUMP3 58
- +#define R_NDS32_LOADSTORE 59
- +#define R_NDS32_9_FIXED_RELA 60
- +#define R_NDS32_15_FIXED_RELA 61
- +#define R_NDS32_17_FIXED_RELA 62
- +#define R_NDS32_25_FIXED_RELA 63
- +#define R_NDS32_PLTREL_HI20 64
- +#define R_NDS32_PLTREL_LO12 65
- +#define R_NDS32_PLT_GOTREL_HI20 66
- +#define R_NDS32_PLT_GOTREL_LO12 67
- +#define R_NDS32_LO12S0_ORI_RELA 72
- +#define R_NDS32_DWARF2_OP1_RELA 77
- +#define R_NDS32_DWARF2_OP2_RELA 78
- +#define R_NDS32_DWARF2_LEB_RELA 79
- +#define R_NDS32_WORD_9_PCREL_RELA 94
- +#define R_NDS32_LONGCALL4 107
- +#define R_NDS32_RELA_NOP_MIX 192
- +#define R_NDS32_RELA_NOP_MAX 255
- +
- +#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
- +typedef elf_greg_t elf_gregset_t[ELF_NGREG];
- +
- +typedef struct user_fp elf_fpregset_t;
- +
- +struct elf32_hdr;
- +extern int elf_check_arch(const struct elf32_hdr *hdr);
- +
- +/*
- + * These are used to set parameters in the core dumps.
- + */
- +#define ELF_CLASS ELFCLASS32
- +#ifdef __NDS32_EB__
- +#define ELF_DATA ELFDATA2MSB;
- +#else
- +#define ELF_DATA ELFDATA2LSB;
- +#endif
- +#define ELF_ARCH EM_NDS32
- +#define USE_ELF_CORE_DUMP
- +#define ELF_EXEC_PAGESIZE PAGE_SIZE
- +
- +/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
- + use of this is to invoke "./ld.so someprog" to test out a new version of
- + the loader. We need to make sure that it is out of the way of the program
- + that it will "exec", and that there is sufficient room for the brk. */
- +
- +#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
- +
- +/* When the program starts, a1 contains a pointer to a function to be
- + registered with atexit, as per the SVR4 ABI. A value of 0 means we
- + have no such handler. */
- +#define ELF_PLAT_INIT(_r, load_addr) (_r)->NDS32_r0 = 0
- +
- +/* This yields a mask that user programs can use to figure out what
- + instruction set this cpu supports. */
- +
- +#define ELF_HWCAP (elf_hwcap)
- +
- +/* This yields a string that ld.so will use to load implementation
- + specific libraries for optimization. This is more specific in
- + intent than poking at uname or /proc/cpuinfo. */
- +
- +/* For now we just provide a fairly general string that describes the
- + processor family. This could be made more specific later if someone
- + implemented optimisations that require it. 26-bit CPUs give you
- + "v1l" for ARM2 (no SWP) and "v2l" for anything else (ARM1 isn't
- + supported). 32-bit CPUs give you "v3[lb]" for anything based on an
- + ARM6 or ARM7 core and "armv4[lb]" for anything based on a StrongARM-1
- + core. */
- +
- +#define ELF_PLATFORM_SIZE 16
- +extern char elf_platform[];
- +#define ELF_PLATFORM (elf_platform)
- +
- +#ifdef __KERNEL__
- +
- +/* Old NetWinder binaries were compiled in such a way that the iBCS
- + heuristic always trips on them. Until these binaries become uncommon
- + enough not to care, don't trust the `ibcs' flag here. In any case
- + there is no other ELF system currently supported by iBCS.
- + @@ Could print a warning message to encourage users to upgrade. */
- +#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
- +
- +#endif
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/emergency-restart.h linux-3.4.110/arch/nds32/include/asm/emergency-restart.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/emergency-restart.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/emergency-restart.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/emergency-restart.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_EMERGENCY_RESTART_H__
- +#define __NDS32_EMERGENCY_RESTART_H__
- +
- +#include <asm-generic/emergency-restart.h>
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/errno.h linux-3.4.110/arch/nds32/include/asm/errno.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/errno.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/errno.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/errno.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_ERRNO_H__
- +#define __NDS32_ERRNO_H__
- +
- +#include <asm-generic/errno.h>
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/exec.h linux-3.4.110/arch/nds32/include/asm/exec.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/exec.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/exec.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,6 @@
- +#ifndef __ASM_NDS32_EXEC_H
- +#define __ASM_NDS32_EXEC_H
- +
- +#define arch_align_stack(x) (x)
- +
- +#endif /* __ASM_ARM_EXEC_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/fb.h linux-3.4.110/arch/nds32/include/asm/fb.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/fb.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/fb.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,25 @@
- +/*
- + * linux/arch/nds32/include/asm/fb.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_FB_H__
- +#define __NDS32_FB_H__
- +
- +
- +#include <linux/fb.h>
- +#include <linux/fs.h>
- +#include <asm/page.h>
- +
- +static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
- + unsigned long off)
- +{
- + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- +}
- +
- +static inline int fb_is_primary_device(struct fb_info *info)
- +{
- + return 0;
- +}
- +
- +#endif /* __NDS32_FB_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/fcntl.h linux-3.4.110/arch/nds32/include/asm/fcntl.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/fcntl.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/fcntl.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,37 @@
- +/*
- + * This file is subject to the terms and conditions of the GNU General Public
- + * License. See the file "COPYING" in the main directory of this archive
- + * for more details.
- + *
- + * Copyright (C) 1995, 96, 97, 98, 99, 2003, 05 Ralf Baechle
- + */
- +#ifndef _ASM_FCNTL_H
- +#define _ASM_FCNTL_H
- +
- +/*
- + * The flavours of struct flock. "struct flock" is the ABI compliant
- + * variant. Finally struct flock64 is the LFS variant of struct flock. As
- + * a historic accident and inconsistence with the ABI definition it doesn't
- + * contain all the same fields as struct flock.
- + */
- +
- +#ifdef CONFIG_32BIT
- +#include <linux/types.h>
- +
- +struct flock {
- + short l_type;
- + short l_whence;
- + off_t l_start;
- + off_t l_len;
- + long l_sysid;
- + __kernel_pid_t l_pid;
- + long pad[4];
- +};
- +
- +#define HAVE_ARCH_STRUCT_FLOCK
- +
- +#endif /* CONFIG_32BIT */
- +
- +#include <asm-generic/fcntl.h>
- +
- +#endif /* _ASM_FCNTL_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/fixmap.h linux-3.4.110/arch/nds32/include/asm/fixmap.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/fixmap.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/fixmap.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,88 @@
- +/*
- + * fixmap.h: compile-time virtual memory allocation
- + *
- + * This file is subject to the terms and conditions of the GNU General Public
- + * License. See the file "COPYING" in the main directory of this archive
- + * for more details.
- + *
- + * Copyright (C) 1998 Ingo Molnar
- + *
- + * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
- + */
- +
- +#ifndef __ASM_NDS32_FIXMAP_H
- +#define __ASM_NDS32_FIXMAP_H
- +
- +#ifdef CONFIG_HIGHMEM
- +#include <linux/threads.h>
- +#include <asm/kmap_types.h>
- +#endif
- +
- +/*
- + * Here we define all the compile-time 'special' virtual
- + * addresses. The point is to have a constant address at
- + * compile time, but to set the physical address only
- + * in the boot process. We allocate these special addresses
- + * from the end of the consistent memory region backwards.
- + * Also this lets us do fail-safe vmalloc(), we
- + * can guarantee that these special addresses and
- + * vmalloc()-ed addresses never overlap.
- + *
- + * these 'compile-time allocated' memory buffers are
- + * fixed-size 4k pages. (or larger if used with an increment
- + * higher than 1) use fixmap_set(idx,phys) to associate
- + * physical memory with fixmap indices.
- + *
- + * TLB entries of such buffers will not be flushed across
- + * task switches.
- + */
- +enum fixed_addresses {
- + FIX_KMAP_RESERVED,
- + FIX_KMAP_BEGIN,
- +#ifdef CONFIG_HIGHMEM
- + FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS),
- +#endif
- +#ifdef CONFIG_EARLY_PRINTK
- + FIX_EARLY_DEBUG,
- +#endif
- + FIX_RETURN_SYSCALL,
- + __end_of_fixed_addresses
- +};
- +#define FIXADDR_TOP ((unsigned long) (-(16 * PAGE_SIZE)))
- +#define FIXADDR_SIZE ((__end_of_fixed_addresses) << PAGE_SHIFT)
- +#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
- +
- +#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
- +#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
- +
- +#define __this_fixmap_does_not_exist() WARN_ON(1)
- +/*
- + * 'index to address' translation. If anyone tries to use the idx
- + * directly without tranlation, we catch the bug with a NULL-deference
- + * kernel oops. Illegal ranges of incoming indices are caught too.
- + */
- +
- +static inline unsigned long fix_to_virt(const unsigned int idx)
- +{
- + /*
- + * this branch gets completely eliminated after inlining,
- + * except when someone tries to use fixaddr indices in an
- + * illegal way. (such as mixing up address types or using
- + * out-of-range indices).
- + *
- + * If it doesn't get removed, the linker will complain
- + * loudly with a reasonably clear error message..
- + */
- + if (idx >= __end_of_fixed_addresses)
- + __this_fixmap_does_not_exist();
- +
- + return __fix_to_virt(idx);
- +}
- +
- +static inline unsigned long virt_to_fix(const unsigned long vaddr)
- +{
- + BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
- + return __virt_to_fix(vaddr);
- +}
- +
- +#endif /* __ASM_NDS32_FIXMAP_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/fpu.h linux-3.4.110/arch/nds32/include/asm/fpu.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/fpu.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/fpu.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,100 @@
- +/*
- + * linux/arch/nds32/include/asm/fpu.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __ASM_NDS32_FPU_H
- +#define __ASM_NDS32_FPU_H
- +
- +#ifndef __ASSEMBLY__
- +#include <linux/preempt.h>
- +#include <asm/ptrace.h>
- +
- +extern void save_fpu(struct task_struct *__tsk);
- +extern void fpload(struct fpu_struct *fpregs);
- +extern void do_fpu_exception(unsigned long error_code, struct pt_regs *regs);
- +extern int do_fpu_inst(unsigned short, struct pt_regs *);
- +
- +#ifdef CONFIG_FPU
- +
- +#define test_tsk_fpu(regs) (regs->NDS32_FUCOP_CTL & FUCOP_CTL_mskCP0EN)
- +
- +struct task_struct;
- +
- +static inline void release_fpu(struct pt_regs *regs)
- +{
- + regs->NDS32_FUCOP_CTL &= ~FUCOP_CTL_mskCP0EN;
- +}
- +
- +static inline void grab_fpu(struct pt_regs *regs)
- +{
- + regs->NDS32_FUCOP_CTL |= FUCOP_CTL_mskCP0EN;
- +}
- +
- +static inline void enable_fpu(void)
- +{
- + SET_FUCOP_CTL(GET_FUCOP_CTL() | FUCOP_CTL_mskCP0EN);
- +}
- +
- +static inline void disable_fpu(void)
- +{
- + SET_FUCOP_CTL(GET_FUCOP_CTL() & ~FUCOP_CTL_mskCP0EN);
- +}
- +
- +static inline void lose_fpu(int save)
- +{
- + preempt_disable();
- + if (test_tsk_fpu(task_pt_regs(current))) {
- + if (save)
- + {
- + save_fpu(current);
- +# ifndef CONFIG_UNLAZY_FPU
- + last_task_used_math=NULL;
- +# endif
- + }
- + release_fpu(task_pt_regs(current));
- + }
- + preempt_enable();
- +}
- +
- +static inline void own_fpu(int restore)
- +{
- + preempt_disable();
- + if (!test_tsk_fpu(task_pt_regs(current))) {
- + if (restore)
- + {
- +# ifdef CONFIG_UNLAZY_FPU
- + fpload(¤t->thread.fpu);
- +# else
- + if((last_task_used_math!=NULL)
- + &&(last_task_used_math!=current))
- + save_fpu(last_task_used_math);
- + fpload(¤t->thread.fpu);
- + last_task_used_math=current;
- +#endif
- + }
- + grab_fpu(task_pt_regs(current));
- + }
- + preempt_enable();
- +}
- +# ifdef CONFIG_UNLAZY_FPU
- +static inline void unlazy_fpu(struct task_struct *tsk)
- +{
- + preempt_disable();
- + if (test_tsk_fpu(task_pt_regs(tsk)))
- + save_fpu(tsk);
- + preempt_enable();
- +}
- +# endif /* CONFIG_UNLAZY_FPU */
- +static inline void clear_fpu(struct pt_regs *regs)
- +{
- + preempt_disable();
- + if (test_tsk_fpu(regs)) {
- + release_fpu(regs);
- + }
- + preempt_enable();
- +}
- +#endif /* CONFIG_FPU */
- +#endif /* __ASSEMBLY__ */
- +
- +#endif /* __ASM_NDS32_FPU_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/ftpci.h linux-3.4.110/arch/nds32/include/asm/ftpci.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/ftpci.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/ftpci.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,30 @@
- +/*
- + * linux/arch/nds32/include/asm/ftpci.h
- + *
- + * Faraday FTPCI010 PCI Bridge Device Driver Interface
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * ChangeLog
- + *
- + * Peter Liao 09/26/2005 Created, heavily modified from Faraday A320 platform code.
- + */
- +
- +#ifndef __FARADAY_PLATFORM_PCI_HEADER__
- +#define __FARADAY_PLATFORM_PCI_HEADER__
- +
- +
- +#define PCI_BRIDGE_DEVID 0x4321
- +#define PCI_BRIDGE_VENID 0x159b
- +
- +extern int ftpci_probed;
- +extern void ftpci_clear_irq(unsigned int irq);
- +extern void ftpci_mask_irq(unsigned int irq);
- +extern void ftpci_unmask_irq(unsigned int irq);
- +extern int ftpci_get_irq(void);
- +#endif /* __FARADAY_PLATFORM_PCI_HEADER__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/ftrace.h linux-3.4.110/arch/nds32/include/asm/ftrace.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/ftrace.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/ftrace.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,17 @@
- +#ifndef _ASM_POWERPC_FTRACE
- +#define _ASM_POWERPC_FTRACE
- +
- +#ifdef CONFIG_FUNCTION_TRACER
- +#define MCOUNT_ADDR ((long)(_mcount))
- +#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
- +
- +#ifdef __ASSEMBLY__
- +
- +#else /* !__ASSEMBLY__ */
- +extern void _mcount(void);
- +
- +#endif /* __ASSEMBLY__ */
- +
- +#endif
- +
- +#endif /* _ASM_POWERPC_FTRACE */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/futex.h linux-3.4.110/arch/nds32/include/asm/futex.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/futex.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/futex.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/futex.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_FUTEX_H__
- +#define __NDS32_FUTEX_H__
- +
- +#include <asm-generic/futex.h>
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/glue.h linux-3.4.110/arch/nds32/include/asm/glue.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/glue.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/glue.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,26 @@
- +/*
- + * linux/arch/nds32/include/asm/glue.h
- + *
- + * Copyright (C) 1997-1999 Russell King
- + * Copyright (C) 2000-2002 Deep Blue Solutions Ltd.
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * This file provides the glue to stick the processor-specific bits
- + * into the kernel in an efficient manner. The idea is to use branches
- + * when we're only targetting one class of TLB, or indirect calls
- + * when we're targetting multiple classes of TLBs.
- + */
- +#ifdef __KERNEL__
- +
- +#ifdef __STDC__
- +#define ____glue(name,fn) name##fn
- +#else
- +#define ____glue(name,fn) name/**/fn
- +#endif
- +#define __glue(name,fn) ____glue(name,fn)
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/gpio.h linux-3.4.110/arch/nds32/include/asm/gpio.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/gpio.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/gpio.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,10 @@
- +#ifndef _ARCH_NDS32_GPIO_H
- +#define _ARCH_NDS32_GPIO_H
- +
- +#include <asm-generic/gpio.h>
- +#define gpio_get_value __gpio_get_value
- +#define gpio_set_value __gpio_set_value
- +#define gpio_cansleep __gpio_cansleep
- +#define gpio_to_irq __gpio_to_irq
- +
- +#endif /* _ARCH_NDS32_GPIO_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/hardirq.h linux-3.4.110/arch/nds32/include/asm/hardirq.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/hardirq.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/hardirq.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,36 @@
- +/*
- + * linux/arch/nds32/include/asm/hardirq.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +#ifndef __ASM_HARDIRQ_H
- +#define __ASM_HARDIRQ_H
- +
- +#include <linux/cache.h>
- +#include <linux/threads.h>
- +#include <asm/irq.h>
- +
- +typedef struct {
- + unsigned int __softirq_pending;
- +} ____cacheline_aligned irq_cpustat_t;
- +
- +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
- +
- +#if NR_IRQS > 256
- +#define HARDIRQ_BITS 9
- +#else
- +#define HARDIRQ_BITS 8
- +#endif
- +
- +/*
- + * The hardirq mask has to be large enough to have space
- + * for potentially all IRQ sources in the system nesting
- + * on a single CPU:
- + */
- +#if (1 << HARDIRQ_BITS) < NR_IRQS
- +# error HARDIRQ_BITS is too low!
- +#endif
- +
- +#define __ARCH_IRQ_EXIT_IRQS_DISABLED 1
- +
- +extern void ack_bad_irq(unsigned int irq);
- +#endif /* __ASM_HARDIRQ_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/hardware.h linux-3.4.110/arch/nds32/include/asm/hardware.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/hardware.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/hardware.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,61 @@
- +/*
- + * linux/arch/nds32/include/asm/hardware.h
- + *
- + * Faraday Platform Independent Hardware Configuration
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + * ChangeLog
- + *
- + * Luke Lee 09/16/2005 Created.
- + * Peter Liao 10/04/2005 Modified for uClinux
- + * Harry Pan 11/02/2007 Added REGxx macros.
- + */
- +
- +#ifndef __FARADAY_PLATFORM_HARDWARE_HEADER__
- +#define __FARADAY_PLATFORM_HARDWARE_HEADER__
- +
- +#include <asm/spec.h>
- +
- +#ifndef PCIBIOS_MIN_IO
- +/* the mini io address is 0x6000,that is IO will allocate from 0-0x6000 offset*/
- +#define PCIBIOS_MIN_IO 0x0
- +#endif
- +
- +#ifndef PCIBIOS_MIN_MEM
- +/* the mini MEM address is 0x100000,that is MEM will allocate from 0-0x100000 offset*/
- +#define PCIBIOS_MIN_MEM 0x0
- +#endif
- +
- +#define pcibios_assign_all_busses() 1
- +
- +/* Pliauo add 5 to resolve __alloc_bootmem_core return NULL pointer in bootmem.c */
- +#if defined(CPU_MEM_PA_BASE) && defined(CPU_MEM_PA_SIZE)
- + #define PA_SDRAM_BASE (CPU_MEM_PA_BASE)
- +#else
- + #define PA_SDRAM_BASE (0x00000000)
- +#endif
- +
- +/*
- + * Define a simple register accessing method by Harry@Nov.02.2007
- + */
- +#define REG32(a) (*(volatile unsigned int *)(a))
- +#define REG16(a) (*(volatile unsigned short *)(a))
- +#define REG8(a) (*(volatile unsigned char *)(a))
- +
- +#endif /* __FARADAY_PLATFORM_HARDWARE_HEADER__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/highmem.h linux-3.4.110/arch/nds32/include/asm/highmem.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/highmem.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/highmem.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,61 @@
- +#ifndef _ASM_HIGHMEM_H
- +#define _ASM_HIGHMEM_H
- +
- +#include <asm/kmap_types.h>
- +#include <asm/fixmap.h>
- +#include <asm/pgtable.h>
- +
- +/*
- + * Right now we initialize only a single pte table. It can be extended
- + * easily, subsequent pte tables have to be allocated in one physical
- + * chunk of RAM.
- + */
- +/*
- + * Ordering is (from lower to higher memory addresses):
- + *
- + * high_memory
- + * Persistent kmap area
- + * PKMAP_BASE
- + * fixed_addresses
- + * FIXADDR_START
- + * FIXADDR_TOP
- + * Vmalloc area
- + * VMALLOC_START
- + * VMALLOC_END
- + */
- +#define PKMAP_BASE ((FIXADDR_START - PGDIR_SIZE) & (PGDIR_MASK))
- +#define LAST_PKMAP PTRS_PER_PTE
- +#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
- +#define PKMAP_NR(virt) (((virt) - (PKMAP_BASE)) >> PAGE_SHIFT)
- +#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
- +#define kmap_prot PAGE_KERNEL
- +
- +static inline void flush_cache_kmaps(void)
- +{
- + cpu_dcache_wbinval_all();
- +}
- +
- +/* declarations for highmem.c */
- +extern unsigned long highstart_pfn, highend_pfn;
- +
- +extern pte_t *pkmap_page_table;
- +
- +extern void *kmap_high(struct page *page);
- +extern void kunmap_high(struct page *page);
- +
- +extern void kmap_init(void);
- +
- +/*
- + * The following functions are already defined by <linux/highmem.h>
- + * when CONFIG_HIGHMEM is not set.
- + */
- +#ifdef CONFIG_HIGHMEM
- +extern void *kmap(struct page *page);
- +extern void kunmap(struct page *page);
- +extern void *kmap_atomic(struct page *page);
- +extern void __kunmap_atomic(void *kvaddr);
- +extern void *kmap_atomic_pfn(unsigned long pfn);
- +extern struct page *kmap_atomic_to_page(void *ptr);
- +#endif
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/hw_irq.h linux-3.4.110/arch/nds32/include/asm/hw_irq.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/hw_irq.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/hw_irq.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/hw_irq.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_HW_IRQ_H__
- +#define __NDS32_HW_IRQ_H__
- +
- +
- +#endif /* __NDS32_HW_IRQ_H__ */
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/intc.h linux-3.4.110/arch/nds32/include/asm/intc.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/intc.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/intc.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,45 @@
- +/*
- + * linux/arch/nds32/include/asm/intc.h
- + *
- + * Faraday FTINTC010 Interrupt Controller Device Driver Interface
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + * ChangeLog
- + *
- + * Luke Lee 09/14/2005 Created, heavily modified from Faraday CPE platform code.
- + */
- +
- +#ifndef __FARADAY_INTC_FTINTC010_HEADER__
- +#define __FARADAY_INTC_FTINTC010_HEADER__
- +
- +#define IRQ_SOURCE_REG 0
- +#define IRQ_MASK_REG 0x04
- +#define IRQ_CLEAR_REG 0x08
- +#define IRQ_MODE_REG 0x0c
- +#define IRQ_LEVEL_REG 0x10
- +#define IRQ_STATUS_REG 0x14
- +
- +#define FIQ_SOURCE_REG 0x20
- +#define FIQ_MASK_REG 0x24
- +#define FIQ_CLEAR_REG 0x28
- +#define FIQ_MODE_REG 0x2c
- +#define FIQ_LEVEL_REG 0x30
- +#define FIQ_STATUS_REG 0x34
- +
- +#endif /* __FARADAY_INTC_FTINTC010_HEADER__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/ioctl.h linux-3.4.110/arch/nds32/include/asm/ioctl.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/ioctl.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/ioctl.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/ioctl.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_IOCTL_H__
- +#define __NDS32_IOCTL_H__
- +
- +#include <asm-generic/ioctl.h>
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/ioctls.h linux-3.4.110/arch/nds32/include/asm/ioctls.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/ioctls.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/ioctls.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,13 @@
- +/*
- + * linux/arch/nds32/include/asm/ioctls.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __ASM_NDS32_IOCTLS_H
- +#define __ASM_NDS32_IOCTLS_H
- +
- +#define FIOQSIZE 0x545E
- +
- +#include <asm-generic/ioctls.h>
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/io.h linux-3.4.110/arch/nds32/include/asm/io.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/io.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/io.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,343 @@
- +/*
- + * linux/arch/nds32/include/asm/io.h
- + *
- + * Copyright (C) 1996-2000 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * Modifications:
- + * 16-Sep-1996 RMK Inlined the inx/outx functions & optimised for both
- + * constant addresses and variable addresses.
- + * 04-Dec-1997 RMK Moved a lot of this stuff to the new architecture
- + * specific IO header files.
- + * 27-Mar-1999 PJB Second parameter of memcpy_toio is const..
- + * 04-Apr-1999 PJB Added check_signature.
- + * 12-Dec-1999 RMK More cleanups
- + * 18-Jun-2000 RMK Removed virt_to_* and friends definitions
- + * 05-Oct-2004 BJD Moved memory string functions to use void __iomem
- + */
- +#ifndef __ASM_NDS32_IO_H
- +#define __ASM_NDS32_IO_H
- +
- +#ifdef __KERNEL__
- +
- +#include <linux/types.h>
- +#include <asm/byteorder.h>
- +#include <asm/memory.h>
- +#include <asm/hardware.h>
- +#include <asm-generic/iomap.h>
- +
- +
- +/*
- + * ISA I/O bus memory addresses are 1:1 with the physical address.
- + */
- +#define isa_virt_to_bus virt_to_phys
- +#define isa_page_to_bus page_to_phys
- +#define isa_bus_to_virt phys_to_virt
- +
- +/*
- + * Generic IO read/write. These perform native-endian accesses. Note
- + * that some architectures will want to re-define __raw_{read,write}w.
- + */
- +
- +#define __raw_writeb(v,a) (*(volatile unsigned char __force *)(a) = (v))
- +#define __raw_writew(v,a) (*(volatile unsigned short __force *)(a) = (v))
- +#define __raw_writel(v,a) (*(volatile unsigned int __force *)(a) = (v))
- +
- +#define __raw_readb(a) (*(volatile unsigned char __force *)(a))
- +#define __raw_readw(a) (*(volatile unsigned short __force *)(a))
- +#define __raw_readl(a) (*(volatile unsigned int __force *)(a))
- +
- +/*
- + * Bad read/write accesses...
- + */
- +extern void __readwrite_bug(const char *fn);
- +
- +/*
- + * Now, pick up the machine-defined IO definitions
- + */
- +#ifndef __FARADAY_PLATFORM_IO_HEADER__
- +#define __FARADAY_PLATFORM_IO_HEADER__
- +
- +#include <linux/compiler.h>
- +#include <asm/spec.h>
- +
- +#ifndef IO_SPACE_LIMIT
- +#define IO_SPACE_LIMIT 0xffffffff
- +#endif
- +
- +#ifndef __io
- +#define __io(a) ((void __iomem *)(a))
- +#endif
- +#define IO_ADDRESS(a) __io(a)
- +#ifndef __mem_pci
- +#define __mem_pci(a) (a)
- +#endif
- +
- +#endif
- +
- +#ifdef __io_pci
- +#warning machine class uses buggy __io_pci
- +#endif
- +#if defined(__arch_putb) || defined(__arch_putw) || defined(__arch_putl) || \
- + defined(__arch_getb) || defined(__arch_getw) || defined(__arch_getl)
- +//-Tom for debug
- +//#warning machine class uses old __arch_putw or __arch_getw
- +#endif
- +
- +/*
- + * IO port access primitives
- + * -------------------------
- + *
- + * The ARM doesn't have special IO access instructions; all IO is memory
- + * mapped. Note that these are defined to perform little endian accesses
- + * only. Their primary purpose is to access PCI and ISA peripherals.
- + *
- + * Note that for a big endian machine, this implies that the following
- + * big endian mode connectivity is in place, as described by numerious
- + * ARM documents:
- + *
- + * PCI: D0-D7 D8-D15 D16-D23 D24-D31
- + * ARM: D24-D31 D16-D23 D8-D15 D0-D7
- + *
- + * The machine specific io.h include defines __io to translate an "IO"
- + * address to a memory address.
- + *
- + * Note that we prevent GCC re-ordering or caching values in expressions
- + * by introducing sequence points into the in*() definitions. Note that
- + * __raw_* do not guarantee this behaviour.
- + *
- + * The {in,out}[bwl] macros are for emulating x86-style PCI/ISA IO space.
- + */
- +#ifdef __io
- +#ifdef __NDS32_EB__
- +#define inw(p) ({ unsigned int __v = be16_to_cpu(__raw_readw(__io(p))); __v; })
- +#define inl(p) ({ unsigned int __v = be32_to_cpu(__raw_readl(__io(p))); __v; })
- +#define outw(v,p) __raw_writew(cpu_to_be16(v),__io(p))
- +#define outl(v,p) __raw_writel(cpu_to_be32(v),__io(p))
- +#else
- +#define inw(p) ({ unsigned int __v = le16_to_cpu(__raw_readw(__io(p))); __v; })
- +#define inl(p) ({ unsigned int __v = le32_to_cpu(__raw_readl(__io(p))); __v; })
- +#define outw(v,p) __raw_writew(cpu_to_le16(v),__io(p))
- +#define outl(v,p) __raw_writel(cpu_to_le32(v),__io(p))
- +#endif
- +
- +#define inb(p) ({ unsigned int __v = __raw_readb(__io(p)); __v; })
- +#define outb(v,p) __raw_writeb(v,__io(p))
- +
- +#endif
- +
- +#define outb_p(val,port) outb((val),(port))
- +#define outw_p(val,port) outw((val),(port))
- +#define outl_p(val,port) outl((val),(port))
- +#define inb_p(port) inb((port))
- +#define inw_p(port) inw((port))
- +#define inl_p(port) inl((port))
- +
- +/*
- + * String version of IO memory access ops:
- + */
- +extern void _memcpy_fromio(void *, const volatile void __iomem *, size_t);
- +extern void _memcpy_toio(volatile void __iomem *, const void *, size_t);
- +extern void _memset_io(volatile void __iomem *, int, size_t);
- +
- +#define mmiowb()
- +
- +/*
- + * Memory access primitives
- + * ------------------------
- + *
- + * These perform PCI memory accesses via an ioremap region. They don't
- + * take an address as such, but a cookie.
- + *
- + * Again, this are defined to perform little endian accesses. See the
- + * IO port primitives for more information.
- + */
- +#ifdef __mem_pci
- +#ifdef __NDS32_EB__
- +#define readw(c) ({ unsigned int __v = be16_to_cpu(__raw_readw(__mem_pci(c))); __v; })
- +#define readl(c) ({ unsigned int __v = be32_to_cpu(__raw_readl(__mem_pci(c))); __v; })
- +#define writew(v,c) __raw_writew(cpu_to_be16(v),__mem_pci(c))
- +#define writel(v,c) __raw_writel(cpu_to_be32(v),__mem_pci(c))
- +#else
- +#define readw(c) ({ unsigned int __v = le16_to_cpu(__raw_readw(__mem_pci(c))); __v; })
- +#define readl(c) ({ unsigned int __v = le32_to_cpu(__raw_readl(__mem_pci(c))); __v; })
- +#define writew(v,c) __raw_writew(cpu_to_le16(v),__mem_pci(c))
- +#define writel(v,c) __raw_writel(cpu_to_le32(v),__mem_pci(c))
- +#endif
- +
- +#define readb(c) ({ unsigned int __v = __raw_readb(__mem_pci(c)); __v; })
- +#define writeb(v,c) __raw_writeb(v,__mem_pci(c))
- +
- +#define readb_relaxed(addr) readb(addr)
- +#define readw_relaxed(addr) readw(addr)
- +#define readl_relaxed(addr) readl(addr)
- +
- +#define memset_io(c,v,l) _memset_io(__mem_pci(c),(v),(l))
- +#define memcpy_fromio(a,c,l) _memcpy_fromio((a),__mem_pci(c),(l))
- +#define memcpy_toio(c,a,l) _memcpy_toio(__mem_pci(c),(a),(l))
- +
- +#define eth_io_copy_and_sum(s,c,l,b) \
- + eth_copy_and_sum((s),__mem_pci(c),(l),(b))
- +
- +#elif !defined(readb)
- +
- +#define readb(c) (__readwrite_bug("readb"),0)
- +#define readw(c) (__readwrite_bug("readw"),0)
- +#define readl(c) (__readwrite_bug("readl"),0)
- +#define writeb(v,c) __readwrite_bug("writeb")
- +#define writew(v,c) __readwrite_bug("writew")
- +#define writel(v,c) __readwrite_bug("writel")
- +
- +#define eth_io_copy_and_sum(s,c,l,b) __readwrite_bug("eth_io_copy_and_sum")
- +
- +#endif /* __mem_pci */
- +
- +/*
- + * If this architecture has ISA IO, then define the isa_read/isa_write
- + * macros.
- + */
- +#ifdef __mem_isa
- +
- +#define isa_readb(addr) __raw_readb(__mem_isa(addr))
- +#define isa_readw(addr) __raw_readw(__mem_isa(addr))
- +#define isa_readl(addr) __raw_readl(__mem_isa(addr))
- +#define isa_writeb(val,addr) __raw_writeb(val,__mem_isa(addr))
- +#define isa_writew(val,addr) __raw_writew(val,__mem_isa(addr))
- +#define isa_writel(val,addr) __raw_writel(val,__mem_isa(addr))
- +#define isa_memset_io(a,b,c) _memset_io(__mem_isa(a),(b),(c))
- +#define isa_memcpy_fromio(a,b,c) _memcpy_fromio((a),__mem_isa(b),(c))
- +#define isa_memcpy_toio(a,b,c) _memcpy_toio(__mem_isa((a)),(b),(c))
- +
- +#define isa_eth_io_copy_and_sum(a,b,c,d) \
- + eth_copy_and_sum((a),__mem_isa(b),(c),(d))
- +
- +#else /* __mem_isa */
- +
- +#define isa_readb(addr) (__readwrite_bug("isa_readb"),0)
- +#define isa_readw(addr) (__readwrite_bug("isa_readw"),0)
- +#define isa_readl(addr) (__readwrite_bug("isa_readl"),0)
- +#define isa_writeb(val,addr) __readwrite_bug("isa_writeb")
- +#define isa_writew(val,addr) __readwrite_bug("isa_writew")
- +#define isa_writel(val,addr) __readwrite_bug("isa_writel")
- +#define isa_memset_io(a,b,c) __readwrite_bug("isa_memset_io")
- +#define isa_memcpy_fromio(a,b,c) __readwrite_bug("isa_memcpy_fromio")
- +#define isa_memcpy_toio(a,b,c) __readwrite_bug("isa_memcpy_toio")
- +
- +#define isa_eth_io_copy_and_sum(a,b,c,d) \
- + __readwrite_bug("isa_eth_io_copy_and_sum")
- +
- +#endif /* __mem_isa */
- +
- +/*
- + * ioremap and friends.
- + *
- + * ioremap takes a PCI memory address, as specified in
- + * Documentation/IO-mapping.txt.
- + */
- +extern void __iomem * __ioremap(unsigned long, size_t, unsigned long, unsigned long);
- +extern void __iounmap(void __iomem *addr);
- +
- +#ifndef __arch_ioremap
- +#define ioremap(cookie,size) __ioremap(cookie,size,0,1)
- +#define ioremap_nocache(cookie,size) __ioremap(cookie,size,0,1)
- +#define iounmap(cookie) __iounmap(cookie)
- +#else
- +#define ioremap(cookie,size) __arch_ioremap((cookie),(size),0,1)
- +#define ioremap_nocache(cookie,size) __arch_ioremap((cookie),(size),0,1)
- +#define iounmap(cookie) __arch_iounmap(cookie)
- +#endif
- +
- +/*
- + * can the hardware map this into one segment or not, given no other
- + * constraints.
- + */
- +#define BIOVEC_MERGEABLE(vec1, vec2) \
- + ((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2)))
- +
- +/*
- + * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- + * access
- + */
- +#define xlate_dev_mem_ptr(p) __va(p)
- +
- +/*
- + * Convert a virtual cached pointer to an uncached pointer
- + */
- +#define xlate_dev_kmem_ptr(p) p
- +static inline void readsb(const void __iomem *addr, void * data, int bytelen)
- +{
- + unsigned char *ptr = (unsigned char *)addr;
- + unsigned char *ptr2 = (unsigned char *)data;
- + while(bytelen) {
- + *ptr2 = *ptr;
- + ptr2++;
- + bytelen--;
- + }
- +}
- +
- +static inline void readsw(const void __iomem *addr, void * data, int wordlen)
- +{
- + unsigned short *ptr = (unsigned short *)addr;
- + unsigned short *ptr2 = (unsigned short *)data;
- + while(wordlen) {
- + *ptr2 = *ptr;
- + ptr2++;
- + wordlen--;
- + }
- +}
- +
- +static inline void readsl(const void __iomem *addr, void * data, int longlen)
- +{
- + unsigned int *ptr = (unsigned int *)addr;
- + unsigned int *ptr2 = (unsigned int *)data;
- + while(longlen) {
- + *ptr2 = *ptr;
- + ptr2++;
- + longlen--;
- + }
- +}
- +static inline void writesb(void __iomem *addr, const void * data, int bytelen)
- +{
- + unsigned char *ptr = (unsigned char *)addr;
- + unsigned char *ptr2 = (unsigned char *)data;
- + while(bytelen) {
- + *ptr = *ptr2;
- + ptr2++;
- + bytelen--;
- + }
- +}
- +static inline void writesw(void __iomem *addr, const void * data, int wordlen)
- +{
- + unsigned short *ptr = (unsigned short *)addr;
- + unsigned short *ptr2 = (unsigned short *)data;
- + while(wordlen) {
- + *ptr = *ptr2;
- + ptr2++;
- + wordlen--;
- + }
- +}
- +static inline void writesl(void __iomem *addr, const void * data, int longlen)
- +{
- + unsigned int *ptr = (unsigned int *)addr;
- + unsigned int *ptr2 = (unsigned int *)data;
- + while(longlen) {
- + *ptr = *ptr2;
- + ptr2++;
- + longlen--;
- + }
- +}
- +
- +
- +#define insb(p,d,l) BUG()
- +#define insw(p,d,l) BUG()
- +#define insl(p,d,l) BUG()
- +#define outsb(p,d,l) BUG()
- +#define outsw(p,d,l) BUG()
- +#define outsl(p,d,l) BUG()
- +
- +#endif /* __KERNEL__ */
- +#endif /* __ASM_NDS32_IO_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/ipcbuf.h linux-3.4.110/arch/nds32/include/asm/ipcbuf.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/ipcbuf.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/ipcbuf.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,34 @@
- +/*
- + * linux/arch/nds32/include/asm/ipcbuf.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __ASMNDS32_IPCBUF_H
- +#define __ASMNDS32_IPCBUF_H
- +
- +/*
- + * The ipc64_perm structure for arm architecture.
- + * Note extra padding because this structure is passed back and forth
- + * between kernel and user space.
- + *
- + * Pad space is left for:
- + * - 32-bit mode_t and seq
- + * - 2 miscellaneous 32-bit values
- + */
- +
- +struct ipc64_perm
- +{
- + __kernel_key_t key;
- + __kernel_uid32_t uid;
- + __kernel_gid32_t gid;
- + __kernel_uid32_t cuid;
- + __kernel_gid32_t cgid;
- + __kernel_mode_t mode;
- + unsigned short __pad1;
- + unsigned short seq;
- + unsigned short __pad2;
- + unsigned long __unused1;
- + unsigned long __unused2;
- +};
- +
- +#endif /* __ASMNDS32_IPCBUF_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/irqflags.h linux-3.4.110/arch/nds32/include/asm/irqflags.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/irqflags.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/irqflags.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,65 @@
- +/*
- + * linux/arch/nds32/include/asm/irqflags.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#include <asm/nds32.h>
- +#include <asm/assembler.h>
- +
- +#define arch_local_irq_disable() \
- + GIE_DISABLE();
- +
- +#define arch_local_irq_enable() \
- + GIE_ENABLE();
- +static inline unsigned long arch_local_irq_save(void)
- +{
- + unsigned long flags;
- + __asm__ __volatile__(
- + "mfsr %0, $PSW\n"
- + "andi %0, %0, #0x1\n"
- + "gie_disable\n"
- + : "=r" (flags) );
- + return flags;
- +}
- +static inline unsigned long arch_local_save_flags(void)
- +{
- + unsigned long flags;
- + __asm__ __volatile__(
- + "mfsr %0, $PSW\n"
- + "andi %0, %0, #0x1"
- + : "=r" (flags) );
- + return flags;
- +}
- +static inline void arch_local_irq_restore(unsigned long flags)
- +{
- + __asm__ __volatile__(
- + "beqz %0, 1f\n"
- + "gie_enable\n"
- + "1:"
- + :: "r" (flags) );
- +}
- +static inline int arch_irqs_disabled_flags(unsigned long flags)
- +{
- + return !flags;
- +}
- +#if 0
- +#define raw_local_irq_save(x) \
- + __asm__ __volatile__( \
- + "mfsr %0, $PSW\n" \
- + "andi %0, %0, #0x1\n" \
- + "gie_disable\n" \
- + : "=r" (x) )
- +#define raw_local_save_flags(x) \
- + __asm__ __volatile__( \
- + "mfsr %0, $PSW\n" \
- + "andi %0, %0, #0x1" \
- + : "=r" (x) )
- +#define raw_local_irq_restore(x) \
- + __asm__ __volatile__( \
- + "beqz %0, 1f\n" \
- + "gie_enable\n" \
- + "1:" \
- + :: "r" (x) )
- +
- +#define raw_irqs_disabled_flags(x) !(x)
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/irq.h linux-3.4.110/arch/nds32/include/asm/irq.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/irq.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/irq.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,50 @@
- +/*
- + * linux/arch/nds32/include/asm/irq.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __ASM_NDS32_IRQ_H
- +#define __ASM_NDS32_IRQ_H
- +
- +#include <asm/spec.h>
- +
- +#ifndef irq_canonicalize
- +#define irq_canonicalize(i) (i)
- +#endif
- +
- +#ifndef NR_IRQS
- +#define NR_IRQS 128
- +#endif
- +
- +/*
- + * Use this value to indicate lack of interrupt
- + * capability
- + */
- +#ifndef NO_IRQ
- +#define NO_IRQ ((unsigned int)(-1))
- +#endif
- +
- +struct irqaction;
- +
- +extern void disable_irq_nosync(unsigned int);
- +extern void disable_irq(unsigned int);
- +extern void enable_irq(unsigned int);
- +
- +#define __IRQT_FALEDGE IRQ_TYPE_EDGE_FALLING
- +#define __IRQT_RISEDGE IRQ_TYPE_EDGE_RISING
- +#define __IRQT_LOWLVL IRQ_TYPE_LEVEL_LOW
- +#define __IRQT_HIGHLVL IRQ_TYPE_LEVEL_HIGH
- +
- +#define IRQT_NOEDGE (0)
- +#define IRQT_RISING (__IRQT_RISEDGE)
- +#define IRQT_FALLING (__IRQT_FALEDGE)
- +#define IRQT_BOTHEDGE (__IRQT_RISEDGE|__IRQT_FALEDGE)
- +#define IRQT_LOW (__IRQT_LOWLVL)
- +#define IRQT_HIGH (__IRQT_HIGHLVL)
- +#define IRQT_PROBE IRQ_TYPE_PROBE
- +
- +struct irqaction;
- +struct pt_regs;
- +
- +#endif
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/irq_regs.h linux-3.4.110/arch/nds32/include/asm/irq_regs.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/irq_regs.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/irq_regs.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,9 @@
- +/*
- + * linux/arch/nds32/include/asm/irq_regs.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_IRQ_REGS_H__
- +#define __NDS32_IRQ_REGS_H__
- +#include <asm-generic/irq_regs.h>
- +#endif /* __NDS32_IRQ_REGS_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/Kbuild linux-3.4.110/arch/nds32/include/asm/Kbuild
- --- linux-3.4.110.orig/arch/nds32/include/asm/Kbuild 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/Kbuild 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,3 @@
- +include include/asm-generic/Kbuild.asm
- +
- +header-y += pfm.h
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/kdebug.h linux-3.4.110/arch/nds32/include/asm/kdebug.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/kdebug.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/kdebug.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,14 @@
- +/*
- + * linux/arch/nds32/include/asm/kdebug.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_KDEBUG_H__
- +#define __NDS32_KDEBUG_H__
- +
- +enum die_val {
- + DIE_OOPS = 1,
- + DIE_DEBUG,
- +};
- +
- +#endif /* __NDS32_KDEBUG_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/kexec.h linux-3.4.110/arch/nds32/include/asm/kexec.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/kexec.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/kexec.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,31 @@
- +#ifndef _NDS32_KEXEC_H
- +#define _NDS32_KEXEC_H
- +
- +#ifdef CONFIG_KEXEC
- +
- +/* Maximum physical address we can use pages from */
- +#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
- +/* Maximum address we can reach in physical address mode */
- +#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
- +/* Maximum address we can use for the control code buffer */
- +#define KEXEC_CONTROL_MEMORY_LIMIT (-1UL)
- +
- +#define KEXEC_CONTROL_PAGE_SIZE 4096
- +
- +#define KEXEC_ARCH KEXEC_ARCH_NDS32
- +
- +#define KEXEC_NDS32_ATAGS_OFFSET 0x1000
- +#define KEXEC_NDS32_ZIMAGE_OFFSET 0x500000
- +
- +#ifndef __ASSEMBLY__
- +
- +struct kimage;
- +/* Provide a dummy definition to avoid build failures. */
- +static inline void crash_setup_regs(struct pt_regs *newregs,
- + struct pt_regs *oldregs) { }
- +
- +#endif /* __ASSEMBLY__ */
- +
- +#endif /* CONFIG_KEXEC */
- +
- +#endif /* _NDS32_KEXEC_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/kgdb.h linux-3.4.110/arch/nds32/include/asm/kgdb.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/kgdb.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/kgdb.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,90 @@
- +/* ============================================================================
- + *
- + * linux/arch/nds32/include/asm/kgdb.h
- + *
- + * Copyright (C) 2007 Andes Technology Corporation
- + * This file is part of Linux and should be licensed under the GPL.
- + * See the file COPYING for conditions for redistribution.
- + *
- + * Abstract:
- + *
- + * This program is for NDS32 KGDB support.
- + *
- + * Author: Harry Pan
- + *
- + * Revision History:
- + *
- + * Jul.14.2007 Initial ported by Harry.
- + *
- + * Note:
- + *
- + * ============================================================================
- + */
- +#ifndef __ASM_NDS32_KGDB_H__
- +#define __ASM_NDS32_KGDB_H__
- +
- +#include <asm/ptrace.h>
- +
- +#define BREAK_INSTR_SIZE 2
- +#define CACHE_FLUSH_IS_SAFE 1
- +
- +#ifndef __ASSEMBLY__
- +
- +/*
- + * Define numbers of registers we have in NDS32 arch
- + */
- +#define NDS32_NUM_GR 32 // general registers.
- +#define NDS32_NUM_SPR 5 // special registers. (PC, D0, D1)
- +#define NDS32_NUM_CR 6 // ctrl registers.
- +#define NDS32_NUM_IR 16 // interruption registers.
- +#define NDS32_NUM_MR 11 // MMU registers.
- +#define NDS32_NUM_DR 48 // debug registers.
- +#define NDS32_NUM_PFR 4 // performance monitoring registers.
- +#define NDS32_NUM_DMAR 11 // local memory DMA registers
- +#define NDS32_NUM_RACR 1 // resource access control registers.
- +#define NDS32_NUM_IDR 2 // implementation dependent registers.
- +#define NDS32_NUM_SR (NDS32_NUM_CR + NDS32_NUM_IR + NDS32_NUM_MR + \
- + NDS32_NUM_DR + NDS32_NUM_PFR + NDS32_NUM_DMAR + \
- + NDS32_NUM_RACR + NDS32_NUM_IDR)
- +#define NDS32_NUM_REGS (NDS32_NUM_GR + NDS32_NUM_SPR + NDS32_NUM_SR)
- +
- +#define KGDB_MAX_NO_CPUS 1
- +#define BUFMAX 2048
- +#define NUMREGBYTES (NDS32_NUM_REGS << 2)
- +
- +/*
- + * NDS32 virtual registers layout for GDB.
- + */
- +enum nds32_regnum
- +{
- + NDS32_R0_REGNUM = 0, // first integer-like argument.
- + NDS32_R5_REGNUM = 5, // last integer-like argument.
- + NDS32_FP_REGNUM = 28, // frame register
- + NDS32_LP_REGNUM = 30, // link pointer
- + NDS32_SP_REGNUM = 31, // address of stack top.
- + NDS32_PC_REGNUM = 32,
- + NDS32_D0LO_REGNUM = 33,
- + NDS32_D0HI_REGNUM = 34,
- + NDS32_D1LO_REGNUM = 35,
- + NDS32_D1HI_REGNUM = 36,
- + NDS32_CR0_REGNUM = 37,
- + NDS32_IR0_REGNUM = (NDS32_CR0_REGNUM + NDS32_NUM_CR),
- + NDS32_MR0_REGNUM = (NDS32_IR0_REGNUM + NDS32_NUM_IR),
- + NDS32_DR0_REGNUM = (NDS32_MR0_REGNUM + NDS32_NUM_MR),
- + NDS32_PFR0_REGNUM = (NDS32_DR0_REGNUM + NDS32_NUM_DR),
- + NDS32_DMAR0_REGNUM = (NDS32_PFR0_REGNUM + NDS32_NUM_PFR),
- + NDS32_RACR0_REGNUM = (NDS32_DMAR0_REGNUM + NDS32_NUM_DMAR),
- + NDS32_IDR0_REGNUM = (NDS32_RACR0_REGNUM + NDS32_NUM_RACR),
- + /* nds32 calling convention. */
- + NDS32_ARG0_REGNUM = NDS32_R0_REGNUM,
- + NDS32_ARGN_REGNUM = NDS32_R5_REGNUM,
- + NDS32_RET_REGNUM = NDS32_R0_REGNUM,
- +};
- +
- +static inline void arch_kgdb_breakpoint(void)
- +{
- + asm __volatile__ ( "break 0x1ff\n" );
- +}
- +
- +#endif /* !__ASSEMBLY__ */
- +#endif /* __ASM_NDS32_KGDB_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/kmap_types.h linux-3.4.110/arch/nds32/include/asm/kmap_types.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/kmap_types.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/kmap_types.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,29 @@
- +/*
- + * linux/arch/nds32/include/asm/kmap-types.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_KMAP_TYPES_H
- +#define __NDS32_KMAP_TYPES_H
- +
- +/*
- + * This is the "bare minimum". AIO seems to require this.
- + */
- +enum km_type {
- + KM_BOUNCE_READ,
- + KM_SKB_SUNRPC_DATA,
- + KM_SKB_DATA_SOFTIRQ,
- + KM_USER0,
- + KM_USER1,
- + KM_BIO_SRC_IRQ,
- + KM_BIO_DST_IRQ,
- + KM_PTE0,
- + KM_PTE1,
- + KM_IRQ0,
- + KM_IRQ1,
- + KM_SOFTIRQ0,
- + KM_SOFTIRQ1,
- + KM_TYPE_NR
- +};
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/kprobes.h linux-3.4.110/arch/nds32/include/asm/kprobes.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/kprobes.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/kprobes.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,86 @@
- +#ifndef _ASM_ANDES_KPROBES_H
- +#define _ASM_ANDES_KPROBES_H
- +/*
- + * Kernel Probes (KProbes)
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- + *
- + * Copyright (C) IBM Corporation, 2002, 2004
- + *
- + * See arch/x86/kernel/kprobes.c for x86 kprobes history.
- + */
- +#include <linux/types.h>
- +#include <linux/ptrace.h>
- +#include <linux/percpu.h>
- +
- +#define __ARCH_WANT_KPROBES_INSN_SLOT
- +
- +struct pt_regs;
- +struct kprobe;
- +
- +typedef unsigned short kprobe_opcode_t;
- +
- +#define MAX_INSN_SIZE 2
- +#define MAX_STACK_SIZE 64
- +#define MIN_STACK_SIZE(ADDR) \
- + (((MAX_STACK_SIZE) < (((unsigned long)current_thread_info()) + \
- + THREAD_SIZE - (unsigned long)(ADDR))) \
- + ? (MAX_STACK_SIZE) \
- + : (((unsigned long)current_thread_info()) + \
- + THREAD_SIZE - (unsigned long)(ADDR)))
- +#define regs_return_value(regs) ((regs)->NDS32_r0)
- +#define flush_insn_slot(p) do { } while (0)
- +#define kretprobe_blacklist_size 0
- +
- +void arch_remove_kprobe(struct kprobe *p);
- +void kretprobe_trampoline(void);
- +
- +/* Architecture specific copy of original instruction*/
- +struct arch_specific_insn {
- + /* copy of the original instruction */
- + kprobe_opcode_t *insn;
- + /*
- + * boostable = -1: This instruction type is not boostable.
- + * boostable = 0: This instruction type is boostable.
- + * boostable = 1: This instruction has been boosted: we have
- + * added a relative jump after the instruction copy in insn,
- + * so no single-step and fixup are needed (unless there's
- + * a post_handler or break_handler).
- + */
- + int boostable;
- +};
- +
- +struct prev_kprobe {
- + struct kprobe *kp;
- + unsigned long status;
- + unsigned long old_flags;
- + unsigned long saved_flags;
- +};
- +
- +/* per-cpu kprobe control block */
- +struct kprobe_ctlblk {
- + unsigned long kprobe_status;
- + unsigned long kprobe_old_flags;
- + unsigned long kprobe_saved_flags;
- + unsigned long *jprobe_saved_sp;
- + struct pt_regs jprobe_saved_regs;
- + kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
- + struct prev_kprobe prev_kprobe;
- +};
- +
- +extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
- +extern int kprobe_exceptions_notify(struct notifier_block *self,
- + unsigned long val, void *data);
- +#endif /* _ASM_ANDES_KPROBES_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/kvm.h linux-3.4.110/arch/nds32/include/asm/kvm.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/kvm.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/kvm.h 2016-04-07 10:20:50.898079322 +0200
- @@ -0,0 +1,9 @@
- +/*
- + * linux/arch/nds32/include/asm/kvm.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_KVM_H__
- +#define __NDS32_KVM_H__
- +
- +#endif /* __NDS32_KVM_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/l2_cache.h linux-3.4.110/arch/nds32/include/asm/l2_cache.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/l2_cache.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/l2_cache.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,134 @@
- +/*
- + * linux/arch/nds32/include/asm/l2_cache.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef L2_CACHE_H
- +#define L2_CACHE_H
- +
- +// CCTL_CMD_OP
- +#define L2_CA_CONF_OFF 0x0
- +#define L2_IF_CONF_OFF 0x4
- +#define L2CC_SETUP_OFF 0x8
- +#define L2CC_PROT_OFF 0xC
- +#define L2CC_CTRL_OFF 0x10
- +#define L2_INT_EN_OFF 0x20
- +#define L2_STA_OFF 0x24
- +#define RDERR_ADDR_OFF 0x28
- +#define WRERR_ADDR_OFF 0x2c
- +#define EVDPTERR_ADDR_OFF 0x30
- +#define IMPL3ERR_ADDR_OFF 0x34
- +#define L2_CNT0_CTRL_OFF 0x40
- +#define L2_EVNT_CNT0_OFF 0x44
- +#define L2_CNT1_CTRL_OFF 0x48
- +#define L2_EVNT_CNT1_OFF 0x4c
- +#define L2_CCTL_CMD_OFF 0x60
- +#define L2_CCTL_STATUS_OFF 0x64
- +#define L2_LINE_TAG_OFF 0x68
- +#define L2_LINE_DPT_OFF 0x70
- +
- +#define CCTL_CMD_L2_IX_INVAL 0x0
- +#define CCTL_CMD_L2_PA_INVAL 0x1
- +#define CCTL_CMD_L2_IX_WB 0x2
- +#define CCTL_CMD_L2_PA_WB 0x3
- +#define CCTL_CMD_L2_PA_WBINVAL 0x5
- +#define CCTL_CMD_L2_SYNC 0xa
- +// CCTL_CMD_TYPE
- +#define CCTL_SINGLE_CMD 0
- +#define CCTL_BLOCK_CMD 0x10
- +#define CCTL_ALL_CMD 0x10
- +
- +/******************************************************************************
- + * L2_CA_CONF (Cache architecture configuration)
- + *****************************************************************************/
- +#define L2_CA_CONF_offL2SET 0
- +#define L2_CA_CONF_offL2WAY 4
- +#define L2_CA_CONF_offL2CLSZ 8
- +#define L2_CA_CONF_offL2DW 11
- +#define L2_CA_CONF_offL2PT 14
- +#define L2_CA_CONF_offL2VER 16
- +
- +#define L2_CA_CONF_mskL2SET (0xFUL << L2_CA_CONF_offL2SET)
- +#define L2_CA_CONF_mskL2WAY (0xFUL << L2_CA_CONF_offL2WAY)
- +#define L2_CA_CONF_mskL2CLSZ (0x7UL << L2_CA_CONF_offL2CLSZ)
- +#define L2_CA_CONF_mskL2DW (0x7UL << L2_CA_CONF_offL2DW)
- +#define L2_CA_CONF_mskL2PT (0x3UL << L2_CA_CONF_offL2PT)
- +#define L2_CA_CONF_mskL2VER (0xFFFFUL << L2_CA_CONF_offL2VER)
- +
- +/******************************************************************************
- + * L2CC_SETUP (L2CC Setup register)
- + *****************************************************************************/
- +#define L2CC_SETUP_offPART 0
- +#define L2CC_SETUP_mskPART (0x3UL << L2CC_SETUP_offPART)
- +#define L2CC_SETUP_offDDLATC 4
- +#define L2CC_SETUP_mskDDLATC (0x3UL << L2CC_SETUP_offDDLATC)
- +#define L2CC_SETUP_offTDLATC 8
- +#define L2CC_SETUP_mskTDLATC (0x3UL << L2CC_SETUP_offTDLATC)
- +
- +/******************************************************************************
- + * L2CC_PROT (L2CC Protect register)
- + *****************************************************************************/
- +#define L2CC_PROT_offMRWEN 31
- +#define L2CC_PROT_mskMRWEN (0x1UL << L2CC_PROT_offMRWEN)
- +//TODO finish this table
- +//
- +/******************************************************************************
- + * L2_CCTL_STATUS_Mn (The L2CCTL command working status for Master n)
- + *****************************************************************************/
- +#define L2CC_CTRL_offEN 31
- +#define L2CC_CTRL_mskEN (0x1UL << L2CC_CTRL_offEN)
- +
- +/******************************************************************************
- + * L2_CCTL_STATUS_Mn (The L2CCTL command working status for Master n)
- + *****************************************************************************/
- +#define L2_CCTL_STATUS_offCMD_COMP 31
- +#define L2_CCTL_STATUS_mskCMD_COMP (0x1 << L2_CCTL_STATUS_offCMD_COMP)
- +//TODO finish this table
- +
- +#ifndef __ASSEMBLY__
- +
- +#include <linux/smp.h>
- +#include <asm/io.h>
- +#include <asm/bitfield.h>
- +
- +#define L2C_R_REG(offset) inl(L2CC_VA_BASE + offset)
- +#define L2C_W_REG(offset, value) outl(value, L2CC_VA_BASE + offset)
- +
- +#define L2_CMD_RDY() \
- + do{;}while((L2C_R_REG(L2_CCTL_STATUS_OFF) & L2_CCTL_STATUS_mskCMD_COMP) == 0)
- +
- +static inline unsigned long L2_CACHE_SET(void){
- + return 64 << ( ( L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2SET) >> L2_CA_CONF_offL2SET);
- +}
- +
- +static inline unsigned long L2_CACHE_WAY(void){
- + return 1 + ( ( L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2WAY) >> L2_CA_CONF_offL2WAY);
- +}
- +
- +static inline unsigned long L2_CACHE_LINE_SIZE(void){
- +
- + return 4 << ( ( L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2CLSZ) >> L2_CA_CONF_offL2CLSZ);
- +}
- +
- +static inline unsigned long GET_L2CC_CTRL_CPU(unsigned long cpu){
- + if(cpu == smp_processor_id())
- + return L2C_R_REG(L2CC_CTRL_OFF);
- + return L2C_R_REG(L2CC_CTRL_OFF+(cpu<<8));
- +}
- +
- +static inline void SET_L2CC_CTRL_CPU(unsigned long cpu , unsigned long val){
- + if(cpu == smp_processor_id())
- + L2C_W_REG(L2CC_CTRL_OFF,val);
- + else
- + L2C_W_REG(L2CC_CTRL_OFF+(cpu<<8),val);
- +}
- +
- +static inline unsigned long GET_L2CC_STATUS_CPU(unsigned long cpu){
- + if(cpu == smp_processor_id())
- + return L2C_R_REG(L2_CCTL_STATUS_OFF);
- + return L2C_R_REG(L2_CCTL_STATUS_OFF+(cpu<<8));
- +}
- +
- +#endif
- +
- +#endif //L2_CACHE_H
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/leds.h linux-3.4.110/arch/nds32/include/asm/leds.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/leds.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/leds.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,51 @@
- +/*
- + * linux/arch/nds32/include/asm/leds.h
- + *
- + * Copyright (C) 1998 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * Event-driven interface for LEDs on machines
- + * Added led_start and led_stop- Alex Holden, 28th Dec 1998.
- + */
- +#ifndef ASM_NDS32_LEDS_H
- +#define ASM_NDS32_LEDS_H
- +
- +
- +typedef enum {
- + led_idle_start,
- + led_idle_end,
- + led_timer,
- + led_start,
- + led_stop,
- + led_claim, /* override idle & timer leds */
- + led_release, /* restore idle & timer leds */
- + led_start_timer_mode,
- + led_stop_timer_mode,
- + led_green_on,
- + led_green_off,
- + led_amber_on,
- + led_amber_off,
- + led_red_on,
- + led_red_off,
- + led_blue_on,
- + led_blue_off,
- + /*
- + * I want this between led_timer and led_start, but
- + * someone has decided to export this to user space
- + */
- + led_halted
- +} led_event_t;
- +
- +/* Use this routine to handle LEDs */
- +
- +#ifdef CONFIG_LEDS
- +extern void (*leds_event)(led_event_t);
- +#else
- +#define leds_event(e)
- +#endif
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/limits.h linux-3.4.110/arch/nds32/include/asm/limits.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/limits.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/limits.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,16 @@
- +/*
- + * linux/arch/nds32/include/asm/limits.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __ASM_PIPE_H
- +#define __ASM_PIPE_H
- +
- +#ifndef PAGE_SIZE
- +#include <asm/page.h>
- +#endif
- +
- +#define PIPE_BUF PAGE_SIZE
- +
- +#endif
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/linkage.h linux-3.4.110/arch/nds32/include/asm/linkage.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/linkage.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/linkage.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,12 @@
- +/*
- + * linux/arch/nds32/include/asm/linkage.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_LINKAGE_H__
- +#define __NDS32_LINKAGE_H__
- +
- +#define __ALIGN .align 2
- +#define __ALIGN_STR ".align 2"
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/local.h linux-3.4.110/arch/nds32/include/asm/local.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/local.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/local.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/local.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_LOCAL_H__
- +#define __NDS32_LOCAL_H__
- +
- +#include <asm-generic/local.h>
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/arch.h linux-3.4.110/arch/nds32/include/asm/mach/arch.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/mach/arch.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/mach/arch.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,86 @@
- +/*
- + * linux/arch/nds32/include/asm/mach/arch.h
- + *
- + * Copyright (C) 2000 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#ifndef __ASSEMBLY__
- +
- +struct tag;
- +struct meminfo;
- +struct sys_timer;
- +
- +struct machine_desc {
- + /*
- + * Note! The first four elements are used
- + * by assembler code in head-armv.S
- + */
- + unsigned int nr; /* architecture number */
- +
- + const char *name; /* architecture name */
- + unsigned int param_offset; /* parameter page */
- +
- + unsigned int video_start; /* start of video RAM */
- + unsigned int video_end; /* end of video RAM */
- +
- + unsigned int reserve_lp0 :1; /* never has lp0 */
- + unsigned int reserve_lp1 :1; /* never has lp1 */
- + unsigned int reserve_lp2 :1; /* never has lp2 */
- + unsigned int soft_reboot :1; /* soft reboot */
- + void (*fixup)(struct machine_desc *,
- + struct tag *, char **,
- + struct meminfo *);
- + void (*map_io)(void);/* IO mapping function */
- + void (*init_irq)(void);
- + struct sys_timer *timer; /* system tick timer */
- + void (*init_machine)(void);
- +};
- +
- +/*
- + * * Current machine - only accessible during boot.
- + * */
- +extern struct machine_desc *machine_desc;
- +
- +/*
- + * Set of macros to define architecture features. This is built into
- + * a table by the linker.
- + */
- +#define MACHINE_START(_type,_name) \
- +const struct machine_desc __mach_desc_##_type \
- + __attribute__((__section__(".arch.info"))) = { \
- + .nr = MACH_TYPE_##_type, \
- + .name = _name,
- +
- +#define MAINTAINER(n)
- +
- +#define BOOT_PARAMS(_params) \
- + .param_offset = _params,
- +
- +#define VIDEO(_start,_end) \
- + .video_start = _start, \
- + .video_end = _end,
- +
- +#define DISABLE_PARPORT(_n) \
- + .reserve_lp##_n = 1,
- +
- +#define SOFT_REBOOT \
- + .soft_reboot = 1,
- +
- +#define MAPIO(_func) \
- + .map_io = _func,
- +
- +#define INITIRQ(_func) \
- + .init_irq = _func,
- +
- +#define INIT_MACHINE(_func) \
- + .init_machine = _func,
- +
- +#define MACHINE_END \
- +};
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/dma.h linux-3.4.110/arch/nds32/include/asm/mach/dma.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/mach/dma.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/mach/dma.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,56 @@
- +/*
- + * linux/arch/nds32/include/asm/mach/dma.h
- + *
- + * Copyright (C) 1998-2000 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * This header file describes the interface between the generic DMA handler
- + * (dma.c) and the architecture-specific DMA backends (dma-*.c)
- + */
- +
- +struct dma_struct;
- +typedef struct dma_struct dma_t;
- +
- +struct dma_ops {
- + int (*request)(dmach_t, dma_t *); /* optional */
- + void (*free)(dmach_t, dma_t *); /* optional */
- + void (*enable)(dmach_t, dma_t *); /* mandatory */
- + void (*disable)(dmach_t, dma_t *); /* mandatory */
- + int (*residue)(dmach_t, dma_t *); /* optional */
- + int (*setspeed)(dmach_t, dma_t *, int); /* optional */
- + char *type;
- +};
- +
- +struct dma_struct {
- + struct scatterlist buf; /* single DMA */
- + int sgcount; /* number of DMA SG */
- + struct scatterlist *sg; /* DMA Scatter-Gather List */
- +
- + unsigned int active:1; /* Transfer active */
- + unsigned int invalid:1; /* Address/Count changed */
- + unsigned int using_sg:1; /* using scatter list? */
- + dmamode_t dma_mode; /* DMA mode */
- + int speed; /* DMA speed */
- +
- + unsigned int lock; /* Device is allocated */
- + const char *device_id; /* Device name */
- +
- + unsigned int dma_base; /* Controller base address */
- + int dma_irq; /* Controller IRQ */
- + struct scatterlist cur_sg; /* Current controller buffer */
- + unsigned int state;
- +
- + struct dma_ops *d_ops;
- +};
- +
- +/* Prototype: void arch_dma_init(dma)
- + * Purpose : Initialise architecture specific DMA
- + * Params : dma - pointer to array of DMA structures
- + */
- +extern void arch_dma_init(dma_t *dma);
- +
- +extern void isa_init_dma(dma_t *dma);
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/flash.h linux-3.4.110/arch/nds32/include/asm/mach/flash.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/mach/flash.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/mach/flash.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,35 @@
- +/*
- + * linux/arch/nds32/include/asm/mach/flash.h
- + *
- + * Copyright (C) 2003 Russell King, All Rights Reserved.
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#ifndef ASMNDS32_MACH_FLASH_H
- +#define ASMNDS32_MACH_FLASH_H
- +
- +struct mtd_partition;
- +
- +/*
- + * map_name: the map probe function name
- + * width: width of mapped device
- + * init: method called at driver/device initialisation
- + * exit: method called at driver/device removal
- + * set_vpp: method called to enable or disable VPP
- + * parts: optional array of mtd_partitions for static partitioning
- + * nr_parts: number of mtd_partitions for static partitoning
- + */
- +struct flash_platform_data {
- + const char *map_name;
- + unsigned int width;
- + int (*init)(void);
- + void (*exit)(void);
- + void (*set_vpp)(int on);
- + struct mtd_partition *parts;
- + unsigned int nr_parts;
- +};
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/irda.h linux-3.4.110/arch/nds32/include/asm/mach/irda.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/mach/irda.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/mach/irda.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,21 @@
- +/*
- + * linux/arch/nds32/include/asm/mach/irda.h
- + *
- + * Copyright (C) 2004 Russell King.
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#ifndef __ASM_NDS32_MACH_IRDA_H
- +#define __ASM_NDS32_MACH_IRDA_H
- +
- +struct irda_platform_data {
- + int (*startup)(struct device *);
- + void (*shutdown)(struct device *);
- + int (*set_power)(struct device *, unsigned int state);
- + void (*set_speed)(struct device *, unsigned int speed);
- +};
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/map.h linux-3.4.110/arch/nds32/include/asm/mach/map.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/mach/map.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/mach/map.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,37 @@
- +/*
- + * linux/arch/nds32/include/asm/mach/map.h
- + *
- + * Copyright (C) 1999-2000 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * Page table mapping constructs and function prototypes
- + */
- +struct map_desc {
- + unsigned long virtual;
- + unsigned long physical;
- + unsigned long length;
- + unsigned int type;
- +};
- +
- +struct meminfo;
- +
- +#define MT_DEVICE_NCB MT_DEVICE
- +#define MT_DEVICE_NCNB MT_DEVICE
- +#define MT_DEVICE 0
- +#define MT_CACHECLEAN 1
- +#define MT_MINICLEAN 2
- +#define MT_CACHE_L1 3
- +#define MT_UXKRWX_V1 4
- +#define MT_UXKRWX_V2 5
- +#define MT_MEMORY 6
- +#define MT_ROM 7
- +#define MT_ILM 8
- +#define MT_DLM 9
- +
- +extern void create_memmap_holes(struct meminfo *);
- +extern void iotable_init(struct map_desc *, int);
- +extern void setup_io_desc(void);
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/mmc.h linux-3.4.110/arch/nds32/include/asm/mach/mmc.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/mach/mmc.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/mach/mmc.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,16 @@
- +/*
- + * linux/arch/nds32/include/asm/mach/mmc.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +#ifndef ASMNDS32_MACH_MMC_H
- +#define ASMNDS32_MACH_MMC_H
- +
- +#include <linux/mmc/protocol.h>
- +
- +struct mmc_platform_data {
- + unsigned int ocr_mask; /* available voltages */
- + u32 (*translate_vdd)(struct device *, unsigned int);
- + unsigned int (*status)(struct device *);
- +};
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/pci.h linux-3.4.110/arch/nds32/include/asm/mach/pci.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/mach/pci.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/mach/pci.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,76 @@
- +/*
- + * linux/arch/nds32/include/asm/mach/pci.h
- + *
- + * Copyright (C) 2000 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +struct pci_sys_data;
- +struct pci_bus;
- +
- +struct hw_pci {
- + struct list_head buses;
- + int nr_controllers;
- + int (*setup)(int nr, struct pci_sys_data *);
- + struct pci_bus *(*scan)(int nr, struct pci_sys_data *);
- + void (*preinit)(void);
- + void (*postinit)(void);
- + u8 (*swizzle)(struct pci_dev *dev, u8 *pin);
- + int (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin);
- +};
- +
- +/*
- + * Per-controller structure
- + */
- +struct pci_sys_data {
- + struct list_head node;
- + int busnr; /* primary bus number */
- + unsigned long mem_offset; /* bus->cpu memory mapping offset */
- + unsigned long io_offset; /* bus->cpu IO mapping offset */
- + struct pci_bus *bus; /* PCI bus */
- + struct resource *resource[3]; /* Primary PCI bus resources */
- + /* Bridge swizzling */
- + u8 (*swizzle)(struct pci_dev *, u8 *);
- + /* IRQ mapping */
- + int (*map_irq)(struct pci_dev *, u8, u8);
- + struct hw_pci *hw;
- +};
- +
- +/*
- + * This is the standard PCI-PCI bridge swizzling algorithm.
- + */
- +u8 pci_std_swizzle(struct pci_dev *dev, u8 *pinp);
- +
- +/*
- + * Call this with your hw_pci struct to initialise the PCI system.
- + */
- +void pci_common_init(struct hw_pci *);
- +
- +/*
- + * PCI controllers
- + */
- +extern int iop321_setup(int nr, struct pci_sys_data *);
- +extern struct pci_bus *iop321_scan_bus(int nr, struct pci_sys_data *);
- +extern void iop321_init(void);
- +
- +extern int iop331_setup(int nr, struct pci_sys_data *);
- +extern struct pci_bus *iop331_scan_bus(int nr, struct pci_sys_data *);
- +extern void iop331_init(void);
- +
- +extern int dc21285_setup(int nr, struct pci_sys_data *);
- +extern struct pci_bus *dc21285_scan_bus(int nr, struct pci_sys_data *);
- +extern void dc21285_preinit(void);
- +extern void dc21285_postinit(void);
- +
- +extern int via82c505_setup(int nr, struct pci_sys_data *);
- +extern struct pci_bus *via82c505_scan_bus(int nr, struct pci_sys_data *);
- +extern void via82c505_init(void *sysdata);
- +
- +extern int pci_v3_setup(int nr, struct pci_sys_data *);
- +extern struct pci_bus *pci_v3_scan_bus(int nr, struct pci_sys_data *);
- +extern void pci_v3_preinit(void);
- +extern void pci_v3_postinit(void);
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/serial_sa1100.h linux-3.4.110/arch/nds32/include/asm/mach/serial_sa1100.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/mach/serial_sa1100.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/mach/serial_sa1100.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,31 @@
- +/*
- + * linux/include/asm-arm/mach/serial_sa1100.h
- + *
- + * Author: Nicolas Pitre
- + *
- + * Moved to include/asm-arm/mach and changed lots, Russell King
- + *
- + * Low level machine dependent UART functions.
- + */
- +
- +struct uart_port;
- +struct uart_info;
- +
- +/*
- + * This is a temporary structure for registering these
- + * functions; it is intended to be discarded after boot.
- + */
- +struct sa1100_port_fns {
- + void (*set_mctrl)(struct uart_port *, u_int);
- + u_int (*get_mctrl)(struct uart_port *);
- + void (*pm)(struct uart_port *, u_int, u_int);
- + int (*set_wake)(struct uart_port *, u_int);
- +};
- +
- +#ifdef CONFIG_SERIAL_SA1100
- +void sa1100_register_uart_fns(struct sa1100_port_fns *fns);
- +void sa1100_register_uart(int idx, int port);
- +#else
- +#define sa1100_register_uart_fns(fns) do { } while (0)
- +#define sa1100_register_uart(idx,port) do { } while (0)
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/time.h linux-3.4.110/arch/nds32/include/asm/mach/time.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/mach/time.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/mach/time.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,62 @@
- +/*
- + * linux/arch/nds32/include/asm/mach/time.h
- + *
- + * Copyright (C) 2004 MontaVista Software, Inc.
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#ifndef __ASM_NDS32_MACH_TIME_H
- +#define __ASM_NDS32_MACH_TIME_H
- +
- +//#include <linux/sysdev.h>
- +
- +/*
- + * This is our kernel timer structure.
- + *
- + * - init
- + * Initialise the kernels jiffy timer source, claim interrupt
- + * using setup_irq. This is called early on during initialisation
- + * while interrupts are still disabled on the local CPU.
- + * - suspend
- + * Suspend the kernel jiffy timer source, if necessary. This
- + * is called with interrupts disabled, after all normal devices
- + * have been suspended. If no action is required, set this to
- + * NULL.
- + * - resume
- + * Resume the kernel jiffy timer source, if necessary. This
- + * is called with interrupts disabled before any normal devices
- + * are resumed. If no action is required, set this to NULL.
- + * - offset
- + * Return the timer offset in microseconds since the last timer
- + * interrupt. Note: this must take account of any unprocessed
- + * timer interrupt which may be pending.
- + */
- +
- +/* + Tom from newlib
- + * Have the 32 bit jiffies value wrap 5 minutes after boot
- + * so jiffies wrap bugs show up earlier.
- + */
- +//#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))
- +
- +struct sys_timer {
- +// struct sys_device dev;
- + void (*init)(void);
- + void (*suspend)(void);
- + void (*resume)(void);
- + unsigned long (*offset)(void);
- +};
- +
- +extern struct sys_timer *system_timer;
- +extern void timer_tick( void);
- +
- +/*
- + * Kernel time keeping support.
- + */
- +extern int (*set_rtc)(void);
- +extern void save_time_delta(struct timespec *delta, struct timespec *rtc);
- +extern void restore_time_delta(struct timespec *delta, struct timespec *rtc);
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach-types.h linux-3.4.110/arch/nds32/include/asm/mach-types.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/mach-types.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/mach-types.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,14 @@
- +#ifndef __ASSEMBLY__
- +/* The type of machine we're running on */
- +extern unsigned int __machine_arch_type;
- +#endif
- +
- +#define MACH_TYPE_FARADAY 758
- +
- +# ifdef machine_arch_type
- +# undef machine_arch_type
- +# define machine_arch_type __machine_arch_type
- +# else
- +# define machine_arch_type MACH_TYPE_FARADAY
- +# endif
- +# define machine_is_faraday() (machine_arch_type == MACH_TYPE_FARADAY)
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/memory.h linux-3.4.110/arch/nds32/include/asm/memory.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/memory.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/memory.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,218 @@
- +/*
- + * linux/arch/nds32/include/asm/memory.h
- + *
- + * Copyright (C) 2000-2002 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * Note: this file should not be included by non-asm/.h files
- + */
- +#ifndef __ASM_NDS32_MEMORY_H
- +#define __ASM_NDS32_MEMORY_H
- +
- +#include <linux/compiler.h>
- +#ifndef __FARADAY_PLATFORM_INDEPENDENT_MEMORY_HEADER__
- +#define __FARADAY_PLATFORM_INDEPENDENT_MEMORY_HEADER__
- +
- +#include <asm/spec.h>
- +
- +#ifndef __ASSEMBLY__
- +#include <asm/page.h>
- +#endif
- +
- +#ifndef PHYS_OFFSET
- +#define PHYS_OFFSET CPU_MEM_PA_BASE
- +#endif
- +
- +#ifndef PAGE_OFFSET
- +#define PAGE_OFFSET (0xC0000000)
- +#endif
- +
- +#ifndef END_MEM
- +#define END_MEM (CPU_MEM_PA_LIMIT)
- +#endif
- +
- +#ifndef __virt_to_bus
- +#define __virt_to_bus __virt_to_phys
- +#endif
- +
- +#ifndef __bus_to_virt
- +#define __bus_to_virt __phys_to_virt
- +#endif
- +
- +#endif /* __FARADAY_PLATFORM_INDEPENDENT_MEMORY_HEADER__ */
- +
- +#ifndef TASK_SIZE
- +/*
- + * TASK_SIZE - the maximum size of a user space task.
- + * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area
- + */
- +#define TASK_SIZE (0xbf000000UL)
- +#define TASK_UNMAPPED_BASE (0x40000000UL)
- +#endif
- +
- +/*
- + * Page offset: 3GB
- + */
- +#ifndef PAGE_OFFSET
- +#define PAGE_OFFSET (0xc0000000)
- +#endif
- +
- +/*
- + * Physical vs virtual RAM address space conversion. These are
- + * private definitions which should NOT be used outside memory.h
- + * files. Use virt_to_phys/phys_to_virt/__pa/__va instead.
- + */
- +#ifndef __virt_to_phys
- +#define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
- +#define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET)
- +#endif
- +
- +/*
- + * The module space lives between the addresses given by TASK_SIZE
- + * and PAGE_OFFSET - it must be within 32MB of the kernel text.
- + */
- +#define MODULES_END (PAGE_OFFSET)
- +#define MODULES_VADDR (MODULES_END - 16*1048576)
- +
- +#if TASK_SIZE > MODULES_VADDR
- +#error Top of user space clashes with start of module space
- +#endif
- +
- +#ifndef __ASSEMBLY__
- +
- +/*
- + * The DMA mask corresponding to the maximum bus address allocatable
- + * using GFP_DMA. The default here places no restriction on DMA
- + * allocations. This must be the smallest DMA mask in the system,
- + * so a successful GFP_DMA allocation will always satisfy this.
- + */
- +#ifndef ISA_DMA_THRESHOLD
- +#define ISA_DMA_THRESHOLD (0xffffffffULL)
- +#endif
- +
- +#ifndef arch_adjust_zones
- +#define arch_adjust_zones(node,size,holes) do { } while (0)
- +#endif
- +
- +/*
- + * PFNs are used to describe any physical page; this means
- + * PFN 0 == physical address 0.
- + *
- + * This is the PFN of the first RAM page in the kernel
- + * direct-mapped view. We assume this is the first page
- + * of RAM in the mem_map as well.
- + */
- +#define PHYS_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT)
- +
- +/*
- + * These are *only* valid on the kernel direct mapped RAM memory.
- + * Note: Drivers should NOT use these. They are the wrong
- + * translation for translating DMA addresses. Use the driver
- + * DMA support - see dma-mapping.h.
- + */
- +static inline unsigned long virt_to_phys(void *x)
- +{
- + return __virt_to_phys((unsigned long)(x));
- +}
- +
- +static inline void *phys_to_virt(unsigned long x)
- +{
- + return (void *)(__phys_to_virt((unsigned long)(x)));
- +}
- +
- +/*
- + * Drivers should NOT use these either.
- + */
- +#define __pa(x) __virt_to_phys((unsigned long)(x))
- +#define __va(x) ((void *)__phys_to_virt((unsigned long)(x)))
- +
- +/*
- + * Virtual <-> DMA view memory address translations
- + * Again, these are *only* valid on the kernel direct mapped RAM
- + * memory. Use of these is *deprecated* (and that doesn't mean
- + * use the __ prefixed forms instead.) See dma-mapping.h.
- + */
- +static inline __deprecated unsigned long virt_to_bus(void *x)
- +{
- + return __virt_to_bus((unsigned long)x);
- +}
- +
- +static inline __deprecated void *bus_to_virt(unsigned long x)
- +{
- + return (void *)__bus_to_virt(x);
- +}
- +
- +/*
- + * Conversion between a struct page and a physical address.
- + *
- + * Note: when converting an unknown physical address to a
- + * struct page, the resulting pointer must be validated
- + * using VALID_PAGE(). It must return an invalid struct page
- + * for any physical address not corresponding to a system
- + * RAM address.
- + *
- + * pfn_valid(pfn) indicates whether a PFN number is valid
- + *
- + * virt_to_page(k) convert a _valid_ virtual address to struct page *
- + * virt_addr_valid(k) indicates whether a virtual address is valid
- + */
- +#ifndef CONFIG_DISCONTIGMEM
- +
- +#define ARCH_PFN_OFFSET PHYS_PFN_OFFSET
- +#define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
- +
- +#define virt_to_page(kaddr) (pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
- +#define virt_addr_valid(kaddr) ((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
- +
- +#define PHYS_TO_NID(addr) (0)
- +
- +#else /* CONFIG_DISCONTIGMEM */
- +
- +/*
- + * This is more complex. We have a set of mem_map arrays spread
- + * around in memory.
- + */
- +#include <linux/numa.h>
- +
- +#define pfn_valid(pfn) (PFN_TO_NID(pfn) < MAX_NUMNODES)
- +
- +#define virt_to_page(kaddr) \
- + (ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr))
- +#define virt_addr_valid(kaddr) (KVADDR_TO_NID(kaddr) < MAX_NUMNODES)
- +
- +/*
- + * Common discontigmem stuff.
- + * PHYS_TO_NID is used by the NDS32 kernel/setup.c
- + */
- +#define PHYS_TO_NID(addr) PFN_TO_NID((addr) >> PAGE_SHIFT)
- +
- +#endif /* !CONFIG_DISCONTIGMEM */
- +
- +/*
- + * For BIO. "will die". Kill me when bio_to_phys() and bvec_to_phys() die.
- + */
- +#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
- +
- +/*
- + * Optional device DMA address remapping. Do _not_ use directly!
- + * We should really eliminate virt_to_bus() here - it's deprecated.
- + */
- +#ifndef __arch_page_to_dma
- +#define page_to_dma(dev, page) ((dma_addr_t)__virt_to_bus((unsigned long)page_address(page)))
- +#define dma_to_virt(dev, addr) ((void *)__bus_to_virt(addr))
- +#define virt_to_dma(dev, addr) ((dma_addr_t)__virt_to_bus((unsigned long)(addr)))
- +#else
- +#define page_to_dma(dev, page) (__arch_page_to_dma(dev, page))
- +#define dma_to_virt(dev, addr) (__arch_dma_to_virt(dev, addr))
- +#define virt_to_dma(dev, addr) (__arch_virt_to_dma(dev, addr))
- +#endif
- +
- +#endif
- +
- +#include <asm-generic/memory_model.h>
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/misc_spec.h linux-3.4.110/arch/nds32/include/asm/misc_spec.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/misc_spec.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/misc_spec.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,75 @@
- +/*
- + * linux/arch/nds32/include/asm/misc_spec.h
- + *
- + * Faraday A320D platform dependent definitions
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + * ChangeLog
- + *
- + * Luke Lee 09/14/2005 Created
- + * Luke Lee 10/06/2005 Modified for automatic system clock rate
- + */
- +
- +#ifndef __A320_PLATFORM_MANUAL_DEFINITION__
- +#define __A320_PLATFORM_MANUAL_DEFINITION__
- +
- +#define BOOT_PARAMETER_PA_BASE (PHYS_OFFSET + 0x400)
- +
- +#ifdef CONFIG_AUTO_SYS_CLK
- +
- +#ifndef __ASSEMBLY__
- +extern int ag101_get_ahb_clk(void);
- +extern int ag102_get_ahb_clk(void);
- +
- +#if defined(CONFIG_PLAT_AG101)
- +#define AHB_CLK_IN ag101_get_ahb_clk()
- +#elif defined(CONFIG_PLAT_AG102)
- +#define AHB_CLK_IN ag102_get_ahb_clk()
- +
- +#endif
- +
- +#endif
- +#define TIMER_CLK_IN (CONFIG_SYS_CLK/2)
- +
- +#else
- +
- +/* Timer clock input is APB CLOCK */
- +#define TIMER_CLK_IN (CONFIG_SYS_CLK/2)
- +#define AHB_CLK_IN (CONFIG_SYS_CLK)
- +
- +#endif
- +
- +#ifndef __ASSEMBLY__
- +#include <linux/init.h>
- +
- +#ifdef CONFIG_PLATFORM_INTC
- +extern void __init intc_ftintc010_init_irq(void);
- +#define platform_init_irq intc_ftintc010_init_irq
- +#endif
- +
- +#ifdef CONFIG_PLATFORM_NOINTC
- +extern void __init nointc_init_irq(void);
- +#define platform_init_irq nointc_init_irq
- +#endif
- +
- +#endif
- +
- +#define daughter_platform_init_irq(x) /* NOP */
- +
- +#endif /*__A320_PLATFORM_MANUAL_DEFINITION__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mman.h linux-3.4.110/arch/nds32/include/asm/mman.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/mman.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/mman.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,22 @@
- +/*
- + * linux/arch/nds32/include/asm/mman.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_MMAN_H__
- +#define __NDS32_MMAN_H__
- +
- +#include <asm-generic/mman.h>
- +
- +#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
- +#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
- +#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
- +#define MAP_LOCKED 0x2000 /* pages are locked */
- +#define MAP_NORESERVE 0x4000 /* don't check for reservations */
- +#define MAP_POPULATE 0x8000 /* populate (prefault) page tables */
- +#define MAP_NONBLOCK 0x10000 /* do not block on IO */
- +
- +#define MCL_CURRENT 1 /* lock all current mappings */
- +#define MCL_FUTURE 2 /* lock all future mappings */
- +
- +#endif /* __NDS32_MMAN_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mmu_context.h linux-3.4.110/arch/nds32/include/asm/mmu_context.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/mmu_context.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/mmu_context.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,84 @@
- +/*
- + * linux/arch/nds32/include/asm/mmu_context.h
- + *
- + * Copyright (C) 1996 Russell King.
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * Changelog:
- + * 27-06-1996 RMK Created
- + */
- +#ifndef __ASM_NDS32_MMU_CONTEXT_H
- +#define __ASM_NDS32_MMU_CONTEXT_H
- +
- +#include <linux/spinlock.h>
- +#include <asm/tlbflush.h>
- +#include <asm-generic/mm_hooks.h>
- +
- +static inline int
- +init_new_context(struct task_struct *tsk, struct mm_struct *mm)
- +{
- + mm->context.id = 0;
- + return 0;
- +}
- +
- +#define destroy_context(mm) do { } while(0)
- +
- +#ifndef CONFIG_CPU_NO_CONTEXT_ID
- +#define CID_BITS 9
- +extern spinlock_t cid_lock;
- +extern unsigned int cpu_last_cid;
- +
- +static inline void
- +__new_context(struct mm_struct *mm)
- +{
- + unsigned int cid;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&cid_lock, flags);
- + cid = cpu_last_cid;
- + cpu_last_cid += 1 << TLB_MISC_offCID;
- + if (cpu_last_cid == 0)
- + cpu_last_cid = 1 << TLB_MISC_offCID << CID_BITS;
- + spin_unlock_irqrestore(&cid_lock, flags);
- +
- + if ((cid & TLB_MISC_mskCID ) == 0)
- + flush_tlb_all();
- +
- + mm->context.id = cid;
- +}
- +
- +static inline void
- +check_context(struct mm_struct *mm)
- +{
- + if (unlikely((mm->context.id ^ cpu_last_cid) >> TLB_MISC_offCID >> CID_BITS))
- + __new_context(mm);
- +}
- +#else
- +#define check_context(m)
- +#endif
- +
- +static inline void
- +enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
- +{
- +}
- +
- +static inline void
- +switch_mm(struct mm_struct *prev, struct mm_struct *next,
- + struct task_struct *tsk)
- +{
- + unsigned int cpu = smp_processor_id();
- +
- + if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) {
- + check_context(next);
- + cpu_switch_mm(next);
- + }
- +}
- +
- +#define deactivate_mm(tsk,mm) do { } while (0)
- +#define activate_mm(prev,next) switch_mm(prev, next, NULL)
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mmu.h linux-3.4.110/arch/nds32/include/asm/mmu.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/mmu.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/mmu.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,42 @@
- +/*
- + * linux/arch/nds32/include/asm/mmu.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_MMU_H
- +#define __NDS32_MMU_H
- +
- +typedef struct {
- + unsigned int id;
- +} mm_context_t;
- +
- +#define ASID(mm) ((mm)->context.id & (TLB_MISC_mskCID >> TLB_MISC_offCID))
- +inline static unsigned long ACC_PSZ(unsigned long page_size)
- +{
- + switch(page_size) {
- + case(1<<12):
- + return 0;
- + case(1<<13):
- + return 1;
- + case(1<<14):
- + return 2;
- + case(1<<16):
- + return 3;
- + case(1<<18):
- + return 4;
- + case(1<<20):
- + return 5;
- + case(1<<22):
- + return 6;
- + case(1<<24):
- + return 7;
- + case(1<<26):
- + return 8;
- + case(1<<28):
- + return 9;
- + default:
- + printk("Huge Page Size is not supported \n");
- + return 0xffffffff;
- + }
- +}
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/module.h linux-3.4.110/arch/nds32/include/asm/module.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/module.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/module.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,23 @@
- +/*
- + * linux/arch/nds32/include/asm/module.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASM_NDS32_MODULE_H
- +#define _ASM_NDS32_MODULE_H
- +
- +struct mod_arch_specific
- +{
- + int foo;
- +};
- +
- +#define Elf_Shdr Elf32_Shdr
- +#define Elf_Sym Elf32_Sym
- +#define Elf_Ehdr Elf32_Ehdr
- +
- +/*
- + * Include the ARM architecture version.
- + */
- +#define MODULE_ARCH_VERMAGIC "NDS32vN10" __stringify(__LINUX_NDS32_ARCH__) " "
- +
- +#endif /* _ASM_NDS32_MODULE_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/msgbuf.h linux-3.4.110/arch/nds32/include/asm/msgbuf.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/msgbuf.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/msgbuf.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,36 @@
- +/*
- + * linux/arch/nds32/include/asm/msgbuf.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASMNDS32_MSGBUF_H
- +#define _ASMNDS32_MSGBUF_H
- +
- +/*
- + * The msqid64_ds structure for arm architecture.
- + * Note extra padding because this structure is passed back and forth
- + * between kernel and user space.
- + *
- + * Pad space is left for:
- + * - 64-bit time_t to solve y2038 problem
- + * - 2 miscellaneous 32-bit values
- + */
- +
- +struct msqid64_ds {
- + struct ipc64_perm msg_perm;
- + __kernel_time_t msg_stime; /* last msgsnd time */
- + unsigned long __unused1;
- + __kernel_time_t msg_rtime; /* last msgrcv time */
- + unsigned long __unused2;
- + __kernel_time_t msg_ctime; /* last change time */
- + unsigned long __unused3;
- + unsigned long msg_cbytes; /* current number of bytes on queue */
- + unsigned long msg_qnum; /* number of messages in queue */
- + unsigned long msg_qbytes; /* max number of bytes on queue */
- + __kernel_pid_t msg_lspid; /* pid of last msgsnd */
- + __kernel_pid_t msg_lrpid; /* last receive pid */
- + unsigned long __unused4;
- + unsigned long __unused5;
- +};
- +
- +#endif /* _ASMNDS32_MSGBUF_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mutex.h linux-3.4.110/arch/nds32/include/asm/mutex.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/mutex.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/mutex.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/mutex.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_MUTEX_H__
- +#define __NDS32_MUTEX_H__
- +
- +#include <asm-generic/mutex-dec.h>
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/namei.h linux-3.4.110/arch/nds32/include/asm/namei.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/namei.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/namei.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/namei.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_NAMEI_H__
- +#define __NDS32_NAMEI_H__
- +
- +#define __emul_prefix() NULL
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/nds32.h linux-3.4.110/arch/nds32/include/asm/nds32.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/nds32.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/nds32.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,90 @@
- +/*
- + * linux/arch/nds32/include/asm/nds32.h -- Andes NDS32 processor register interface
- + *
- + * This file is subject to the terms and conditions of the GNU General Public
- + * License. See the file "COPYING" in the main directory of this archive
- + * for more details.
- + *
- + * Copyright (C) 2006 Andes Technology Corporation
- + *
- + */
- +#ifndef _ASM_NDS32_NDS32_H_
- +#define _ASM_NDS32_NDS32_H_
- +
- +#include <asm/bitfield.h>
- +#include <asm/reg_access.h>
- +
- +#define MSYNC( subtype) __asm__ ("\n\tmsync "#subtype);
- +#define STANDBY( cond) __asm__ ("\n\tstandby "#cond);
- +
- +#ifndef __ASSEMBLY__
- +
- +static inline void ISB( void) { __asm__ ("\n\tisb"); }
- +static inline void DSB( void) { __asm__ ("\n\tdsb"); }
- +
- +static inline void GIE_ENABLE( void)
- +{
- + __asm__ ("gie_enable\n\t");
- +}
- +
- +static inline void GIE_DISABLE( void)
- +{
- + __asm__ ("gie_disable\n\t");
- +}
- +
- +enum cache_t{ ICACHE, DCACHE};
- +
- +static inline unsigned long CACHE_SET( enum cache_t cache){
- +
- + if( cache == ICACHE)
- + return 64 << ( ( GET_ICM_CFG() & ICM_CFG_mskISET) >> ICM_CFG_offISET);
- + else
- + return 64 << ( ( GET_DCM_CFG() & DCM_CFG_mskDSET) >> DCM_CFG_offDSET);
- +}
- +
- +static inline unsigned long CACHE_WAY( enum cache_t cache){
- +
- + if( cache == ICACHE)
- + return 1 + ( ( GET_ICM_CFG() & ICM_CFG_mskIWAY) >> ICM_CFG_offIWAY);
- + else
- + return 1 + ( ( GET_DCM_CFG() & DCM_CFG_mskDWAY) >> DCM_CFG_offDWAY);
- +}
- +
- +static inline unsigned long CACHE_LINE_SIZE( enum cache_t cache){
- +
- + if( cache == ICACHE)
- + return 8 << ( ( ( GET_ICM_CFG() & ICM_CFG_mskISZ) >> ICM_CFG_offISZ) - 1);
- + else
- + return 8 << ( ( ( GET_DCM_CFG() & DCM_CFG_mskDSZ) >> DCM_CFG_offDSZ) - 1);
- +}
- +
- +static inline void GIE_SAVE( unsigned long *var){
- +
- + *var = GET_PSW();
- + GIE_DISABLE();
- +}
- +
- +static inline void GIE_RESTORE( unsigned long var){
- +
- + if( var & PSW_mskGIE){
- + GIE_ENABLE();
- + }
- +}
- +
- +#endif /* __ASSEMBLY__ */
- +
- +#define IVB_BASE PHYS_OFFSET /* in user space for intr/exc/trap/break table base, 64KB aligned
- + * We defined at the start of the physical memory */
- +
- +/* The following dispatching entry */
- +#define ENTRY_TLB_MISC (IVB_BASE + nrTLB_MISC*vENTRY_SZ) /* TLB misc eh# */
- +/* dispatched sub-entry exception handler numbering */
- +#define RD_PROT 0 /* read protrection */
- +#define WRT_PROT 1 /* write protection */
- +#define NOEXEC 2 /* non executable */
- +#define PAGE_MODIFY 3 /* page modified */
- +#define ACC_BIT 4 /* access bit */
- +#define RESVED_PTE 5 /* reserved PTE attribute */
- +/* reserved 6 ~ 16 */
- +
- +#endif /* _ASM_NDS32_NDS32_H_ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/numnodes.h linux-3.4.110/arch/nds32/include/asm/numnodes.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/numnodes.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/numnodes.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,25 @@
- +/*
- + * linux/arch/nds32/include/asm/numnodes.h
- + *
- + * Copyright (C) 2002 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +/* This declaration for the size of the NUMA (CONFIG_DISCONTIGMEM)
- + * memory node table is the default.
- + *
- + * A good place to override this value is include/asm/arch/memory.h.
- + */
- +
- +#ifndef __ASM_NDS32_NUMNODES_H
- +#define __ASM_NDS32_NUMNODES_H
- +
- +#ifndef NODES_SHIFT
- +# define NODES_SHIFT 2 /* Normally, Max 4 Nodes */
- +#endif
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/page.h linux-3.4.110/arch/nds32/include/asm/page.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/page.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/page.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,153 @@
- +/*
- + * linux/arch/nds32/include/asm/page.h
- + *
- + * Copyright (C) 1995-2003 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#ifndef _ASMNDS32_PAGE_H
- +#define _ASMNDS32_PAGE_H
- +
- +
- +#ifdef CONFIG_ANDES_PAGE_SIZE_4KB
- +#define PAGE_SHIFT 12
- +#endif
- +#ifdef CONFIG_ANDES_PAGE_SIZE_8KB
- +#define PAGE_SHIFT 13
- +#endif
- +#include <linux/const.h>
- +#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
- +#define PAGE_MASK (~(PAGE_SIZE-1))
- +#define PTE_MASK PAGE_MASK
- +
- +/* PAGE_SHIFT determines the page size */
- +#define EXEC_PAGESIZE PAGE_SIZE
- +
- +#ifdef CONFIG_ANDES_HUGETLB_PAGE_SIZE_16KB
- +#define LARGE_PAGE_SHIFT 14
- +#define HPAGE_SHIFT 14
- +#endif
- +
- +#ifdef CONFIG_ANDES_HUGETLB_PAGE_SIZE_64KB
- +#define LARGE_PAGE_SHIFT 16
- +#define HPAGE_SHIFT 16
- +#endif
- +
- +#ifdef CONFIG_ANDES_HUGETLB_PAGE_SIZE_256KB
- +#define LARGE_PAGE_SHIFT 18
- +#define HPAGE_SHIFT 18
- +#endif
- +#ifdef CONFIG_ANDES_HUGETLB_PAGE_SIZE_1MB
- +#define LARGE_PAGE_SHIFT 20
- +#define HPAGE_SHIFT 20
- +#endif
- +
- +#ifdef CONFIG_ANDES_HUGETLB_PAGE_SIZE_4MB
- +#define LARGE_PAGE_SHIFT 22
- +#define HPAGE_SHIFT 22
- +#endif
- +
- +#ifdef CONFIG_ANDES_HUGETLB_PAGE_SIZE_16MB
- +#define LARGE_PAGE_SHIFT 24
- +#define HPAGE_SHIFT 24
- +#endif
- +
- +#ifdef CONFIG_ANDES_HUGETLB_PAGE_SIZE_64MB
- +#define LARGE_PAGE_SHIFT 26
- +#define HPAGE_SHIFT 26
- +#endif
- +
- +#ifdef CONFIG_ANDES_HUGETLB_PAGE_SIZE_256MB
- +#define LARGE_PAGE_SHIFT 28
- +#define HPAGE_SHIFT 28
- +#endif
- +
- +#ifdef CONFIG_HUGETLB_PAGE
- +// taken for i386 style
- +#define LARGE_PAGE_SIZE (1UL << LARGE_PAGE_SHIFT)
- +#define LARGE_PAGE_MASK (~(LARGE_PAGE_SIZE-1))
- +// taken for SH style
- +#define HPAGE_SIZE (1UL << HPAGE_SHIFT)
- +#define HPAGE_MASK (~(HPAGE_SIZE-1))
- +#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT-PAGE_SHIFT)
- +#endif
- +
- +
- +#ifdef __KERNEL__
- +
- +#ifndef __ASSEMBLY__
- +
- +struct page;
- +struct vm_area_struct;
- +#ifndef CONFIG_CPU_CACHE_NONALIASING
- +extern void copy_user_highpage(struct page *to, struct page *from,
- + unsigned long vaddr, struct vm_area_struct *vma);
- +extern void clear_user_highpage(struct page *page, unsigned long vaddr);
- +
- +#define __HAVE_ARCH_COPY_USER_HIGHPAGE
- +#define clear_user_highpage clear_user_highpage
- +#else
- +#define clear_user_page(page, vaddr, pg) clear_page(page)
- +#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
- +#endif
- +
- +void clear_page(void *page);
- +void copy_page(void *to, void *from);
- +
- +#undef STRICT_MM_TYPECHECKS
- +
- +#ifdef STRICT_MM_TYPECHECKS
- +/*
- + * These are used to make use of C type-checking..
- + */
- +typedef struct { unsigned long pte; } pte_t;
- +typedef struct { unsigned long pmd; } pmd_t;
- +typedef struct { unsigned long pgd; } pgd_t;
- +typedef struct { unsigned long pgprot; } pgprot_t;
- +
- +#define pte_val(x) ((x).pte)
- +#define pmd_val(x) ((x).pmd)
- +#define pgd_val(x) ((x).pgd)
- +#define pgprot_val(x) ((x).pgprot)
- +
- +#define __pte(x) ((pte_t) { (x) } )
- +#define __pmd(x) ((pmd_t) { (x) } )
- +#define __pgd(x) ((pgd_t) { (x) } )
- +#define __pgprot(x) ((pgprot_t) { (x) } )
- +
- +#else
- +/*
- + * .. while these make it easier on the compiler
- + */
- +typedef unsigned long pte_t;
- +typedef unsigned long pmd_t;
- +typedef unsigned long pgd_t;
- +typedef unsigned long pgprot_t;
- +
- +#define pte_val(x) (x)
- +#define pmd_val(x) (x)
- +#define pgd_val(x) (x)
- +#define pgprot_val(x) (x)
- +
- +#define __pte(x) (x)
- +#define __pmd(x) (x)
- +#define __pgd(x) (x)
- +#define __pgprot(x) (x)
- +
- +#endif /* STRICT_MM_TYPECHECKS */
- +typedef struct page *pgtable_t;
- +
- +#include <asm/memory.h>
- +#include <asm-generic/getorder.h>
- +
- +#endif /* !__ASSEMBLY__ */
- +
- +#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
- + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
- +
- +#endif /* __KERNEL__ */
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/param.h linux-3.4.110/arch/nds32/include/asm/param.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/param.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/param.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,36 @@
- +/*
- + * linux/arch/nds32/include/asm/param.h
- + *
- + * Copyright (C) 1995-1999 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#ifndef __ASM_PARAM_H
- +#define __ASM_PARAM_H
- +
- +#ifdef __KERNEL__
- +
- +# ifndef HZ
- +# define HZ CONFIG_HZ /* Internal kernel timer frequency */
- +# endif
- +
- +# define USER_HZ HZ /* User interfaces are in "ticks" */
- +# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
- +#else
- +# define HZ 100
- +#endif
- +
- +//#define EXEC_PAGESIZE 4096
- +
- +#ifndef NOGROUP
- +#define NOGROUP (-1)
- +#endif
- +
- +/* max length of hostname */
- +#define MAXHOSTNAMELEN 64
- +
- +#endif
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/parport.h linux-3.4.110/arch/nds32/include/asm/parport.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/parport.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/parport.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,19 @@
- +/*
- + * linux/arch/nds32/include/asm/parport.h: NDS32-specific parport initialisation
- + *
- + * Copyright (C) 1999, 2000 Tim Waugh <tim@cyberelk.demon.co.uk>
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This file should only be included by drivers/parport/parport_pc.c.
- + */
- +
- +#ifndef __ASMNDS32_PARPORT_H
- +#define __ASMNDS32_PARPORT_H
- +
- +static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
- +static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
- +{
- + return parport_pc_find_isa_ports (autoirq, autodma);
- +}
- +
- +#endif /* !(_ASMNDS32_PARPORT_H) */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/pci.h linux-3.4.110/arch/nds32/include/asm/pci.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/pci.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/pci.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,77 @@
- +/*
- + * linux/arch/nds32/include/asm/pci.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef ASMNDS32_PCI_H
- +#define ASMNDS32_PCI_H
- +
- +#ifdef __KERNEL__
- +#include <asm-generic/pci-dma-compat.h>
- +
- +#include <asm/hardware.h> /* for PCIBIOS_MIN_* */
- +
- +#define pcibios_scan_all_fns(a, b) 0
- +
- +static inline void pcibios_set_master(struct pci_dev *dev)
- +{
- + /* No special bus mastering setup handling */
- +}
- +
- +static inline void pcibios_penalize_isa_irq(int irq)
- +{
- + /* We don't do dynamic PCI IRQ allocation */
- +}
- +
- +/*
- + * The PCI address space does equal the physical memory address space.
- + * The networking and block device layers use this boolean for bounce
- + * buffer decisions.
- + */
- +#define PCI_DMA_BUS_IS_PHYS (0)
- +
- +/*
- + * Whether pci_unmap_{single,page} is a nop depends upon the
- + * configuration.
- + */
- +#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME;
- +#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) __u32 LEN_NAME;
- +#define pci_unmap_addr(PTR, ADDR_NAME) ((PTR)->ADDR_NAME)
- +#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) (((PTR)->ADDR_NAME) = (VAL))
- +#define pci_unmap_len(PTR, LEN_NAME) ((PTR)->LEN_NAME)
- +#define pci_unmap_len_set(PTR, LEN_NAME, VAL) (((PTR)->LEN_NAME) = (VAL))
- +
- +#define HAVE_PCI_MMAP
- +extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
- + enum pci_mmap_state mmap_state, int write_combine);
- +
- +extern void
- +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
- + struct resource *res);
- +
- +extern void
- +pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
- + struct pci_bus_region *region);
- +
- +static inline struct resource *
- +pcibios_select_root(struct pci_dev *pdev, struct resource *res)
- +{
- + struct resource *root = NULL;
- +
- + if (res->flags & IORESOURCE_IO)
- + root = &ioport_resource;
- + if (res->flags & IORESOURCE_MEM)
- + root = &iomem_resource;
- +
- + return root;
- +}
- +
- +#endif /* __KERNEL__ */
- +
- +/* Chances are this interrupt is wired PC-style ... */
- +static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
- +{
- + return channel ? 15 : 14;
- +}
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/percpu.h linux-3.4.110/arch/nds32/include/asm/percpu.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/percpu.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/percpu.h 2016-04-07 10:20:50.902079477 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/percpu.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_PERCPU
- +#define __NDS32_PERCPU
- +
- +#include <asm-generic/percpu.h>
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/pfm.h linux-3.4.110/arch/nds32/include/asm/pfm.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/pfm.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/pfm.h 2016-04-07 10:20:50.906079632 +0200
- @@ -0,0 +1,16 @@
- +#ifndef __PFM_H_
- +#define __PFM_H_
- +
- +struct pcounter {
- + unsigned long long pfm0; /* value of $PFMC0 */
- + unsigned long long pfm1; /* value of $PFMC1 */
- + unsigned long long pfm2; /* value of $PFMC2 */
- +};
- +
- +#ifdef __KERNEL__
- +void sys_pfmctl(int event0, int event1, int event2, int start);
- +int sys_getpfm(struct pcounter __user *p);
- +int sys_setpfm(int pfm0, int pfm1, int pfm2, struct pcounter __user *p);
- +#endif
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/pgalloc.h linux-3.4.110/arch/nds32/include/asm/pgalloc.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/pgalloc.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/pgalloc.h 2016-04-07 10:20:50.906079632 +0200
- @@ -0,0 +1,104 @@
- +/*
- + * linux/arch/nds32/include/asm/pgalloc.h
- + *
- + * Copyright (C) 2000-2001 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#ifndef _ASMNDS32_PGALLOC_H
- +#define _ASMNDS32_PGALLOC_H
- +
- +#include <asm/processor.h>
- +#include <asm/cacheflush.h>
- +#include <asm/tlbflush.h>
- +
- +/*
- + * Since we have only two-level page tables, these are trivial
- + */
- +#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); })
- +#define pmd_free(mm, pmd) do { } while (0)
- +#define pgd_populate(mm, pmd, pte) BUG()
- +#define pmd_pgtable(pmd) pmd_page(pmd)
- +
- +extern pgd_t *get_pgd_slow(struct mm_struct *mm);
- +extern void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd);
- +
- +#define pgd_alloc(mm) get_pgd_slow(mm)
- +#define pgd_free(mm, pgd) free_pgd_slow(mm, pgd)
- +
- +#define check_pgt_cache() do { } while (0)
- +
- +static inline pte_t *
- +pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
- +{
- + pte_t *pte;
- +
- + pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
- +
- + return pte;
- +}
- +
- +static inline pgtable_t
- +pte_alloc_one(struct mm_struct *mm, unsigned long addr)
- +{
- + pgtable_t pte;
- +
- + pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
- + if (pte)
- + cpu_dcache_wb_page((unsigned long)page_address(pte));
- +
- + return pte;
- +}
- +
- +/*
- + * Free one PTE table.
- + */
- +static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
- +{
- + if (pte) {
- + free_page((unsigned long)pte);
- + }
- +}
- +
- +static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
- +{
- + __free_page(pte);
- +}
- +
- +/*
- + * Populate the pmdp entry with a pointer to the pte. This pmd is part
- + * of the mm address space.
- + *
- + * Ensure that we always set both PMD entries.
- + */
- +static inline void
- +pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
- +{
- + unsigned long pte_ptr = (unsigned long)ptep;
- + unsigned long pmdval;
- +
- + BUG_ON(mm != &init_mm);
- +
- + /*
- + * The pmd must be loaded with the physical
- + * address of the PTE table
- + */
- + pmdval = __pa(pte_ptr) | _PAGE_KERNEL_TABLE;
- + set_pmd(pmdp, __pmd(pmdval));
- +}
- +
- +static inline void
- +pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep)
- +{
- + unsigned long pmdval;
- +
- + BUG_ON(mm == &init_mm);
- +
- + pmdval = page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE;
- + set_pmd(pmdp, __pmd(pmdval));
- +}
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/pgtable.h linux-3.4.110/arch/nds32/include/asm/pgtable.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/pgtable.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/pgtable.h 2016-04-07 10:20:50.910079787 +0200
- @@ -0,0 +1,429 @@
- +/*
- + * linux/arch/nds32/include/asm/pgtable.h
- + *
- + * Copyright (C) 1995-2002 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#ifndef _ASMNDS32_PGTABLE_H
- +#define _ASMNDS32_PGTABLE_H
- +
- +#include <asm-generic/4level-fixup.h>
- +#include <asm-generic/sizes.h>
- +
- +#include <asm/memory.h>
- +#include <asm/vmalloc.h>
- +#include <asm/nds32.h>
- +#ifndef __ASSEMBLY__
- +#include <asm/fixmap.h>
- +#endif
- +
- +#ifdef CONFIG_CACHE_L2
- +#include <asm/l2_cache.h>
- +#endif
- +
- +#ifdef CONFIG_ANDES_PAGE_SIZE_4KB
- +#define PGDIR_SHIFT 22
- +#define PTRS_PER_PGD 1024
- +#define PMD_SHIFT 22
- +#define PTRS_PER_PMD 1
- +#define PTRS_PER_PTE 1024
- +#endif
- +
- +#ifdef CONFIG_ANDES_PAGE_SIZE_8KB
- +#define PGDIR_SHIFT 24
- +#define PTRS_PER_PGD 256
- +#define PMD_SHIFT 24
- +#define PTRS_PER_PMD 1
- +#define PTRS_PER_PTE 2048
- +#endif
- +
- +#ifndef __ASSEMBLY__
- +extern void __pte_error(const char *file, int line, unsigned long val);
- +extern void __pmd_error(const char *file, int line, unsigned long val);
- +extern void __pgd_error(const char *file, int line, unsigned long val);
- +
- +#define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte_val(pte))
- +#define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd_val(pmd))
- +#define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd))
- +#endif /* !__ASSEMBLY__ */
- +
- +#define PMD_SIZE (1UL << PMD_SHIFT)
- +#define PMD_MASK (~(PMD_SIZE-1))
- +#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
- +#define PGDIR_MASK (~(PGDIR_SIZE-1))
- +
- +/*
- + * This is the lowest virtual address we can permit any user space
- + * mapping to be mapped at. This is particularly important for
- + * non-high vector CPUs.
- + */
- +#define FIRST_USER_ADDRESS 0x8000
- +
- +#define VMALLOC_OFFSET (8 * 1024 * 1024)
- +#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
- +#define VMALLOC_VMADDR(x) ((unsigned long)(x))
- +
- +
- +#ifdef CONFIG_HIGHMEM
- +#define CONSISTENT_BASE ((PKMAP_BASE) - (SZ_2M))
- +#define CONSISTENT_END (PKMAP_BASE)
- +#else
- +#define CONSISTENT_BASE (FIXADDR_START - SZ_2M)
- +#define CONSISTENT_END (FIXADDR_START)
- +#endif
- +#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
- +
- +#ifdef CONFIG_HIGHMEM
- +#ifndef __ASSEMBLY__
- +#include <asm/highmem.h>
- +#endif
- +#endif
- +
- +//# define VMALLOC_END (CONSISTENT_START - PAGE_SIZE)
- +# define VMALLOC_END (0xf9000000)
- +
- +#define VMALLOC_RESERVE (128 << 20)
- +#define MAXMEM (VMALLOC_END - PAGE_OFFSET - VMALLOC_RESERVE)
- +#define MAXMEM_PFN PFN_DOWN(MAXMEM)
- +
- +#define FIRST_USER_PGD_NR 0
- +#define USER_PTRS_PER_PGD ((TASK_SIZE/PGDIR_SIZE) + FIRST_USER_PGD_NR)
- +
- +/* L2 PTE */
- +#define _PAGE_V (1UL << 0)
- +
- +#define _PAGE_M_XKRW (0UL << 1)
- +#define _PAGE_M_UR_KR (1UL << 1)
- +#define _PAGE_M_UR_KRW (2UL << 1)
- +#define _PAGE_M_URW_KRW (3UL << 1)
- +#define _PAGE_M_KR (5UL << 1)
- +#define _PAGE_M_KRW (7UL << 1)
- +
- +#define _PAGE_D (1UL << 4)
- +#define _PAGE_E (1UL << 5)
- +#define _PAGE_A (1UL << 6)
- +#define _PAGE_G (1UL << 7)
- +
- +#define _PAGE_C_DEV (0UL << 8)
- +#define _PAGE_C_DEV_WB (1UL << 8)
- +#define _PAGE_C_MEM (2UL << 8)
- +#define _PAGE_C_MEM_SHRD_WB (4UL << 8)
- +#define _PAGE_C_MEM_SHRD_WT (5UL << 8)
- +#define _PAGE_C_MEM_WB (6UL << 8)
- +#define _PAGE_C_MEM_WT (7UL << 8)
- +
- +#define _PAGE_L (1UL << 11)
- +
- +#ifndef CONFIG_NO_KERNEL_LARGE_PAGE
- +#define _HAVE_PAGE_L (_PAGE_L)
- +#else
- +#define _HAVE_PAGE_L 0
- +#endif
- +#define _PAGE_FILE (1UL << 1)
- +#define _PAGE_YOUNG 0
- +#define _PAGE_M_MASK _PAGE_M_KRW
- +#define _PAGE_C_MASK _PAGE_C_MEM_WT
- +
- +#ifdef CONFIG_SMP
- +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
- +#define _PAGE_CACHE_SHRD _PAGE_C_MEM_SHRD_WT
- +#else
- +#define _PAGE_CACHE_SHRD _PAGE_C_MEM_SHRD_WB
- +#endif
- +#else
- +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
- +#define _PAGE_CACHE_SHRD _PAGE_C_MEM_WT
- +#else
- +#define _PAGE_CACHE_SHRD _PAGE_C_MEM_WB
- +#endif
- +#endif
- +
- +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
- +#define _PAGE_CACHE _PAGE_C_MEM_WT
- +#else
- +#define _PAGE_CACHE _PAGE_C_MEM_WB
- +#endif
- +
- +/*
- + * + Level 1 descriptor (PMD)
- + */
- +#define PMD_TYPE_TABLE 0
- +
- +#ifndef __ASSEMBLY__
- +
- +#define _PAGE_USER_TABLE PMD_TYPE_TABLE
- +#define _PAGE_KERNEL_TABLE PMD_TYPE_TABLE
- +
- +#define PAGE_EXEC __pgprot(_PAGE_V | _PAGE_M_XKRW | _PAGE_E)
- +#define PAGE_NONE __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_A)
- +#define PAGE_READ __pgprot(_PAGE_V | _PAGE_M_UR_KR)
- +#define PAGE_RDWR __pgprot(_PAGE_V | _PAGE_M_URW_KRW | _PAGE_D)
- +#define PAGE_COPY __pgprot(_PAGE_V | _PAGE_M_UR_KR)
- +
- +#define PAGE_UXKRWX_V1 __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE_SHRD)
- +#define PAGE_UXKRWX_V2 __pgprot(_PAGE_V | _PAGE_M_XKRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE_SHRD)
- +#define PAGE_CACHE_L1 __pgprot(_HAVE_PAGE_L | _PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE)
- +#define PAGE_MEMORY __pgprot(_HAVE_PAGE_L | _PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE_SHRD)
- +#define PAGE_KERNEL __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE_SHRD)
- +#define PAGE_DEVICE __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_G | _PAGE_C_DEV)
- +#endif /* __ASSEMBLY__ */
- +
- +/* xwr */
- +#define __P000 (PAGE_NONE | _PAGE_CACHE_SHRD)
- +#define __P001 (PAGE_READ | _PAGE_CACHE_SHRD)
- +#define __P010 (PAGE_COPY | _PAGE_CACHE_SHRD)
- +#define __P011 (PAGE_COPY | _PAGE_CACHE_SHRD)
- +#define __P100 (PAGE_EXEC | _PAGE_CACHE_SHRD)
- +#define __P101 (PAGE_READ | _PAGE_E | _PAGE_CACHE_SHRD)
- +#define __P110 (PAGE_COPY | _PAGE_E | _PAGE_CACHE_SHRD)
- +#define __P111 (PAGE_COPY | _PAGE_E | _PAGE_CACHE_SHRD)
- +
- +#define __S000 (PAGE_NONE | _PAGE_CACHE_SHRD)
- +#define __S001 (PAGE_READ | _PAGE_CACHE_SHRD)
- +#define __S010 (PAGE_RDWR | _PAGE_CACHE_SHRD)
- +#define __S011 (PAGE_RDWR | _PAGE_CACHE_SHRD)
- +#define __S100 (PAGE_EXEC | _PAGE_CACHE_SHRD)
- +#define __S101 (PAGE_READ | _PAGE_E | _PAGE_CACHE_SHRD)
- +#define __S110 (PAGE_RDWR | _PAGE_E | _PAGE_CACHE_SHRD)
- +#define __S111 (PAGE_RDWR | _PAGE_E | _PAGE_CACHE_SHRD)
- +
- +#ifndef __ASSEMBLY__
- +/*
- + * ZERO_PAGE is a global shared page that is always zero: used
- + * for zero-mapped memory areas etc..
- + */
- +extern struct page *empty_zero_page;
- +#define ZERO_PAGE(vaddr) (empty_zero_page)
- +
- +#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
- +#define pfn_pte(pfn,prot) (__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)))
- +
- +#define pte_none(pte) !(pte_val(pte))
- +#define pte_clear(mm,addr,ptep) set_pte_at((mm),(addr),(ptep), __pte(0))
- +#define pte_page(pte) (pfn_to_page(pte_pfn(pte)))
- +
- +#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
- +#define pte_offset_kernel(dir, address) ((pte_t *)pmd_page_kernel(*(dir)) + pte_index(address))
- +#define pte_offset_map(dir, address) ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
- +#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
- +#define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
- +
- +#define pte_unmap(pte) do { } while (0)
- +#define pte_unmap_nested(pte) do { } while (0)
- +
- +#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
- +
- +static inline pgd_t *get_pgd( void){
- +
- + return ( pgd_t *)phys_to_virt( GET_L1_PPTB() & L1_PPTB_mskBASE);
- +}
- +
- +static inline void set_pgd( pgd_t *pgdp, pgd_t pgd){
- +
- + /* TODO */
- +}
- +/*
- + * Set a level 1 translation table entry, and clean it out of
- + * any caches such that the MMUs can load it correctly.
- + */
- +static inline void set_pmd( pmd_t *pmdp, pmd_t pmd){
- +
- + *pmdp = pmd;
- +#if !defined(CONFIG_CPU_DCACHE_DISABLE) && !defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
- + __asm__ volatile ( "\n\tcctl %0, L1D_VA_WB" ::"r" ( pmdp) :"memory");
- + MSYNC( all);
- + DSB();
- +#endif
- +}
- +
- +/*
- + * Set a PTE and flush it out
- + */
- +static inline void set_pte( pte_t *ptep, pte_t pte){
- +
- + *ptep = pte;
- +#if !defined(CONFIG_CPU_DCACHE_DISABLE) && !defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
- + __asm__ volatile ( "\n\tcctl %0, L1D_VA_WB" ::"r" ( ptep) :"memory");
- + MSYNC( all);
- + DSB();
- +#endif
- +}
- +
- +
- +/*
- + * The following only work if pte_present() is true.
- + * Undefined behaviour if not..
- + */
- +
- +/*
- + * pte_write: this page is writeable for user mode
- + * pte_read: this page is readable for user mode
- + * pte_kernel_write: this page is writeable for kernel mode
- + *
- + * We don't have pte_kernel_read because kernel always can read.
- + *
- + * */
- +
- +#define pte_present(pte) (pte_val(pte) & _PAGE_V)
- +#define pte_write(pte) ((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_URW_KRW)
- +#define pte_read(pte) (((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_UR_KR) || \
- + ((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_UR_KRW) || \
- + ((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_URW_KRW))
- +#define pte_kernel_write(pte) (((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_URW_KRW) || \
- + ((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_UR_KRW) || \
- + ((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_KRW) || \
- + (((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_XKRW) && pte_exec(pte)))
- +#define pte_exec(pte) (pte_val(pte) & _PAGE_E)
- +#define pte_dirty(pte) (pte_val(pte) & _PAGE_D)
- +#define pte_young(pte) (pte_val(pte) & _PAGE_YOUNG)
- +
- +/*
- + * The following only works if pte_present() is not true.
- + */
- +#define pte_file(pte) (pte_val(pte) & _PAGE_FILE)
- +#define pte_to_pgoff(x) (pte_val(x) >> 2)
- +#define pgoff_to_pte(x) __pte(((x) << 2) | _PAGE_FILE)
- +
- +#define PTE_FILE_MAX_BITS 29
- +
- +#define PTE_BIT_FUNC(fn,op) \
- +static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
- +
- +static inline pte_t pte_wrprotect(pte_t pte)
- +{
- + pte_val(pte) = pte_val(pte) & ~_PAGE_M_MASK;
- + pte_val(pte) = pte_val(pte) | _PAGE_M_UR_KR;
- + return pte;
- +}
- +
- +static inline pte_t pte_mkwrite(pte_t pte)
- +{
- + pte_val(pte) = pte_val(pte) & ~_PAGE_M_MASK;
- + pte_val(pte) = pte_val(pte) | _PAGE_M_URW_KRW;
- + return pte;
- +}
- +
- +PTE_BIT_FUNC(exprotect, &= ~_PAGE_E);
- +PTE_BIT_FUNC(mkexec, |= _PAGE_E);
- +PTE_BIT_FUNC(mkclean, &= ~_PAGE_D);
- +PTE_BIT_FUNC(mkdirty, |= _PAGE_D);
- +PTE_BIT_FUNC(mkold, &= ~_PAGE_YOUNG);
- +PTE_BIT_FUNC(mkyoung, |= _PAGE_YOUNG);
- +static inline int pte_special(pte_t pte) { return 0; }
- +static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
- +
- +/*
- + * Mark the prot value as uncacheable and unbufferable.
- + */
- +#define pgprot_noncached(prot) __pgprot((pgprot_val(prot)&~_PAGE_C_MASK) | _PAGE_C_DEV)
- +#define pgprot_writecombine(prot) __pgprot((pgprot_val(prot)&~_PAGE_C_MASK) | _PAGE_C_DEV_WB)
- +
- +#define pmd_none(pmd) (pmd_val(pmd)&0x1)
- +#define pmd_present(pmd) (!pmd_none(pmd))
- +#define pmd_bad(pmd) pmd_none(pmd)
- +
- +#define copy_pmd(pmdpd,pmdps) set_pmd((pmdpd), *(pmdps))
- +#define pmd_clear(pmdp) set_pmd((pmdp), __pmd(1))
- +
- +static inline pmd_t __mk_pmd(pte_t *ptep, unsigned long prot)
- +{
- + unsigned long ptr = (unsigned long)ptep;
- + pmd_t pmd;
- +
- + /*
- + * The pmd must be loaded with the physical
- + * address of the PTE table
- + */
- +
- + pmd_val(pmd) = __virt_to_phys(ptr) | prot;
- + return pmd;
- +}
- +
- +
- +#define pmd_page(pmd) virt_to_page(__va(pmd_val(pmd)))
- +
- +/*
- + * Permanent address of a page. We never have highmem, so this is trivial.
- + */
- +#define pages_to_mb(x) ((x) >> (20 - PAGE_SHIFT))
- +
- +/*
- + * Conversion functions: convert a page and protection to a page entry,
- + * and a page entry and page directory to the page they refer to.
- + */
- +#define mk_pte(page,prot) pfn_pte(page_to_pfn(page),prot)
- +
- +/*
- + * The "pgd_xxx()" functions here are trivial for a folded two-level
- + * setup: the pgd is never bad, and a pmd always exists (as it's folded
- + * into the pgd entry)
- + */
- +#define pgd_none(pgd) (0)
- +#define pgd_bad(pgd) (0)
- +#define pgd_present(pgd) (1)
- +#define pgd_clear(pgdp) do { } while (0)
- +
- +#define page_pte_prot(page,prot) mk_pte(page, prot)
- +#define page_pte(page) mk_pte(page, __pgprot(0))
- +/* Tom:
- + * L1PTE = $mr1 + ((virt >> PMD_SHIFT) << 2);
- + * L2PTE = (((virt >> PAGE_SHIFT) & (PTRS_PER_PTE -1 )) << 2);
- + * PPN = (phys & 0xfffff000);
- + *
- +*/
- +
- +/* to find an entry in a page-table-directory */
- +#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
- +#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address))
- +/* to find an entry in a kernel page-table-directory */
- +#define pgd_offset_k(addr) pgd_offset(&init_mm, addr)
- +
- +/* Find an entry in the second-level page table.. */
- +#define pmd_offset(dir, addr) ((pmd_t *)(dir))
- +
- +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
- +{
- + const unsigned long mask = 0xfff;
- + pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
- + return pte;
- +}
- +
- +extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
- +
- +/* Encode and decode a swap entry.
- + *
- + * We support up to 32GB of swap on 4k machines
- + */
- +#define __swp_type(x) (((x).val >> 2) & 0x7f)
- +#define __swp_offset(x) ((x).val >> 9)
- +#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 9) })
- +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
- +#define __swp_entry_to_pte(swp) ((pte_t) { (swp).val })
- +
- +/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
- +/* FIXME: this is not correct */
- +#define kern_addr_valid(addr) (1)
- +
- +#include <asm-generic/pgtable.h>
- +
- +/*
- + * We provide our own arch_get_unmapped_area to cope with VIPT caches.
- + */
- +#define HAVE_ARCH_UNMAPPED_AREA
- +
- +/*
- + * remap a physical address `phys' of size `size' with page protection `prot'
- + * into virtual address `from'
- + */
- +#define io_remap_pfn_range(vma,from,pfn,size,prot) \
- + remap_pfn_range(vma, from, pfn, size, prot)
- +
- +#define pgtable_cache_init() do { } while (0)
- +
- +#endif /* !__ASSEMBLY__ */
- +
- +#endif /* _ASMNDS32_PGTABLE_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/poll.h linux-3.4.110/arch/nds32/include/asm/poll.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/poll.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/poll.h 2016-04-07 10:20:50.910079787 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/poll.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __ASMNDS32_POLL_H
- +#define __ASMNDS32_POLL_H
- +
- +#include <asm-generic/poll.h>
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/posix_types.h linux-3.4.110/arch/nds32/include/asm/posix_types.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/posix_types.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/posix_types.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,40 @@
- +/*
- + * arch/arm/include/asm/posix_types.h
- + *
- + * Copyright (C) 1996-1998 Russell King.
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * Changelog:
- + * 27-06-1996 RMK Created
- + */
- +#ifndef __ARCH_NDS32_POSIX_TYPES_H
- +#define __ARCH_NDS32_POSIX_TYPES_H
- +
- +/*
- + * This file is generally used by user-level software, so you need to
- + * be a little careful about namespace pollution etc. Also, we cannot
- + * assume GCC is being used.
- + */
- +
- +typedef unsigned short __kernel_mode_t;
- +#define __kernel_mode_t __kernel_mode_t
- +
- +typedef unsigned short __kernel_nlink_t;
- +#define __kernel_nlink_t __kernel_nlink_t
- +
- +typedef unsigned short __kernel_ipc_pid_t;
- +#define __kernel_ipc_pid_t __kernel_ipc_pid_t
- +
- +typedef unsigned short __kernel_uid_t;
- +typedef unsigned short __kernel_gid_t;
- +#define __kernel_uid_t __kernel_uid_t
- +
- +typedef unsigned short __kernel_old_dev_t;
- +#define __kernel_old_dev_t __kernel_old_dev_t
- +
- +#include <asm-generic/posix_types.h>
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/processor.h linux-3.4.110/arch/nds32/include/asm/processor.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/processor.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/processor.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,133 @@
- +/*
- + * linux/arch/nds32/include/asm/processor.h
- + */
- +/* Copyright (C) 1995-1999 Russell King
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +/* ============================================================================
- + * Copyright (C) 2007 Andes Technology Corporation
- + * This file is part of Linux and should be licensed under the GPL.
- + * See the file COPYING for conditions for redistribution.
- + *
- + * Abstract:
- + *
- + * This program is ptrace relative code for Andes NDS32 architecture.
- + * Original referred from ARM, fit to NDS32.
- + *
- + * Revision History:
- + *
- + * Oct.03.2007 Original from Tom, Shawn and Steven, refined by Harry.
- + *
- + * Note:
- + *
- + * ============================================================================
- + */
- +#ifndef __ASM_NDS32_PROCESSOR_H
- +#define __ASM_NDS32_PROCESSOR_H
- +
- +/*
- + * Default implementation of macro that returns current
- + * instruction pointer ("program counter").
- + */
- +#define current_text_addr() ({ __label__ _l; _l: &&_l;})
- +
- +#ifdef __KERNEL__
- +
- +#include <asm/ptrace.h>
- +#include <asm/procinfo.h>
- +#include <asm/types.h>
- +#include <asm/cpuver.h>
- +#include <asm/sigcontext.h>
- +
- +#define KERNEL_STACK_SIZE PAGE_SIZE
- +#define STACK_TOP TASK_SIZE
- +#define STACK_TOP_MAX TASK_SIZE
- +
- +struct debug_info {
- + u32 address;
- + u16 insn;
- + u8 valid;
- +};
- +
- +struct thread_struct {
- + /* fault info */
- + unsigned long address;
- + unsigned long trap_no;
- + unsigned long error_code;
- +
- + struct fpu_struct fpu; /* Saved fpu/fpu emulator stuff. */
- + struct audio_struct audio;
- + struct debug_info debug; /* debugging */
- +};
- +
- +#define INIT_THREAD { }
- +
- +#ifdef __NDS32_EB__
- +#define PSW_DE PSW_mskBE
- +#else
- +#define PSW_DE 0x0
- +#endif
- +
- +#ifdef CONFIG_WBNA
- +#define PSW_valWBNA PSW_mskWBNA
- +#else
- +#define PSW_valWBNA 0x0
- +#endif
- +
- +#define start_thread(regs,pc,sp) \
- +({ \
- + unsigned long *stack = (unsigned long *)sp; \
- + set_fs(USER_DS); \
- + memzero(regs->uregs, sizeof(regs->uregs)); \
- + regs->NDS32_ipsw = (PSW_CPL_ANY | PSW_valWBNA | PSW_mskDT | PSW_mskIT | PSW_DE | PSW_mskGIE); \
- + regs->NDS32_ir0 = (PSW_CPL_ANY | PSW_valWBNA | PSW_mskDT | PSW_mskIT | PSW_DE | PSW_SYSTEM | PSW_INTL_1); \
- + regs->NDS32_ipc = pc; /* pc */ \
- + regs->NDS32_sp = sp; /* $sp */ \
- + regs->NDS32_r2 = stack[4]; /* $r2 (envp) */ \
- + regs->NDS32_r1 = stack[1]; /* $r1 (argv) */ \
- + regs->NDS32_r0 = stack[0]; /* $r0 (argc) */ \
- +})
- +
- +
- +/* Forward declaration, a strange C thing */
- +struct task_struct;
- +
- +/* Free all resources held by a thread. */
- +extern void release_thread(struct task_struct *);
- +#ifdef CONFIG_FPU
- +#ifndef CONFIG_UNLAZU_FPU //lazy fpu
- +extern struct task_struct *last_task_used_math;
- +#endif
- +#endif
- +#ifdef CONFIG_AUDIO
- +#ifndef CONFIG_UNLAZY_AUDIO //lazy audio
- +extern struct task_struct *last_task_used_audio;
- +#endif
- +#endif
- +
- +/* Prepare to copy thread state - unlazy all lazy status */
- +#define prepare_to_copy(tsk) do { } while (0)
- +
- +unsigned long get_wchan(struct task_struct *p);
- +
- +#define cpu_relax() barrier()
- +
- +#define task_pt_regs(task) \
- + ((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE \
- + - 8) - 1)
- +
- +/*
- + * Create a new kernel thread
- + */
- +extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
- +
- +#define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)task_thread_info(tsk)))[1019])
- +#define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)task_thread_info(tsk)))[1017])
- +
- +
- +#endif
- +
- +#endif /* __ASM_NDS32_PROCESSOR_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/proc-fns.h linux-3.4.110/arch/nds32/include/asm/proc-fns.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/proc-fns.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/proc-fns.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,88 @@
- +/*
- + * linux/arch/nds32/include/asm/proc-fns.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_PROCFNS_H__
- +#define __NDS32_PROCFNS_H__
- +
- +#define CPU_NAME n12
- +
- +#ifdef __KERNEL__
- +
- +#ifdef __STDC__
- +#define ____cpu_fn(name,fn) name##fn
- +#else
- +#define ____cpu_fn(name,fn) name/**/fn
- +#endif
- +#define __cpu_fn(name,fn) ____cpu_fn(name,fn)
- +
- +#define cpu_proc_init __cpu_fn( CPU_NAME, _proc_init)
- +#define cpu_proc_fin __cpu_fn( CPU_NAME, _proc_fin)
- +#define cpu_do_idle __cpu_fn( CPU_NAME, _do_idle)
- +#define cpu_reset __cpu_fn( CPU_NAME, _reset)
- +#define cpu_switch_mm __cpu_fn( CPU_NAME, _switch_mm)
- +
- +#define cpu_dcache_inval_all __cpu_fn( CPU_NAME, _dcache_inval_all)
- +#define cpu_dcache_wbinval_all __cpu_fn( CPU_NAME, _dcache_wbinval_all)
- +#define cpu_dcache_inval_page __cpu_fn( CPU_NAME, _dcache_inval_page)
- +#define cpu_dcache_wb_page __cpu_fn( CPU_NAME, _dcache_wb_page)
- +#define cpu_dcache_wbinval_page __cpu_fn( CPU_NAME, _dcache_wbinval_page)
- +#define cpu_dcache_inval_range __cpu_fn( CPU_NAME, _dcache_inval_range)
- +#define cpu_dcache_wb_range __cpu_fn( CPU_NAME, _dcache_wb_range)
- +#define cpu_dcache_wbinval_range __cpu_fn( CPU_NAME, _dcache_wbinval_range)
- +
- +#define cpu_icache_inval_all __cpu_fn( CPU_NAME, _icache_inval_all)
- +#define cpu_icache_inval_page __cpu_fn( CPU_NAME, _icache_inval_page)
- +#define cpu_icache_inval_range __cpu_fn( CPU_NAME, _icache_inval_range)
- +
- +#define cpu_cache_wbinval_page __cpu_fn( CPU_NAME, _cache_wbinval_page)
- +#define cpu_cache_wbinval_range __cpu_fn( CPU_NAME, _cache_wbinval_range)
- +#define cpu_cache_wbinval_range_check __cpu_fn( CPU_NAME, _cache_wbinval_range_check)
- +
- +#define cpu_dma_wb_range __cpu_fn( CPU_NAME, _dma_wb_range)
- +#define cpu_dma_inval_range __cpu_fn( CPU_NAME, _dma_inval_range)
- +#define cpu_dma_wbinval_range __cpu_fn( CPU_NAME, _dma_wbinval_range)
- +
- +#include <asm/page.h>
- +
- +struct mm_struct;
- +struct vm_area_struct;
- +extern void cpu_proc_init(void);
- +extern void cpu_proc_fin(void);
- +extern void cpu_do_idle(void);
- +extern void cpu_reset(unsigned long reset);
- +extern void cpu_switch_mm(struct mm_struct *mm);
- +
- +extern void cpu_dcache_inval_all(void);
- +extern void cpu_dcache_wbinval_all(void);
- +extern void cpu_dcache_inval_page(unsigned long page);
- +extern void cpu_dcache_wb_page(unsigned long page);
- +extern void cpu_dcache_wbinval_page(unsigned long page);
- +extern void cpu_dcache_inval_range(unsigned long start, unsigned long end);
- +extern void cpu_dcache_wb_range(unsigned long start, unsigned long end);
- +extern void cpu_dcache_wbinval_range(unsigned long start, unsigned long end);
- +
- +extern void cpu_icache_inval_all(void);
- +extern void cpu_icache_inval_page(unsigned long page);
- +extern void cpu_icache_inval_range(unsigned long start, unsigned long end);
- +
- +extern void cpu_cache_wbinval_page(unsigned long page, int flushi);
- +extern void cpu_cache_wbinval_range(unsigned long start,
- + unsigned long end, int flushi);
- +extern void cpu_cache_wbinval_range_check(struct vm_area_struct *vma,
- + unsigned long start, unsigned long end);
- +
- +extern void cpu_dma_wb_range(unsigned long start, unsigned long end);
- +extern void cpu_dma_inval_range(unsigned long start, unsigned long end);
- +extern void cpu_dma_wbinval_range(unsigned long start, unsigned long end);
- +
- +#ifdef CONFIG_CACHE_L2
- +#define cpu_L2cache_inval __cpu_fn(CPU_NAME, _L2cache_inval)
- +#define cpu_L2cache_wb __cpu_fn(CPU_NAME, _L2cache_wb)
- +extern void cpu_L2cache_inval(void);
- +extern void cpu_L2cache_wb(void);
- +#endif
- +
- +#endif /* __KERNEL__ */
- +#endif /* __NDS32_PROCFNS_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/procinfo.h linux-3.4.110/arch/nds32/include/asm/procinfo.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/procinfo.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/procinfo.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,71 @@
- +/*
- + * linux/arch/nds32/include/asm/procinfo.h
- + *
- + * Copyright (C) 1996-1999 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#ifndef __ASM_PROCINFO_H
- +#define __ASM_PROCINFO_H
- +
- +#ifndef __ASSEMBLY__
- +
- +/*
- + * These structure are defined in assembly
- + * ( nds32/mm/proc-nds32.S)
- + */
- +struct proc_info_item {
- +
- + const char *manufacturer;
- + const char *cpu_name;
- +};
- +
- +/*
- + * Note! struct processor is always defined if we're
- + * using MULTI_CPU, otherwise this entry is unused,
- + * but still exists.
- + *
- + * NOTE! The following structure is defined by assembly
- + * language, NOT C code. For more information, check:
- + * arch/arm/mm/proc-*.S and arch/arm/kernel/head.S
- + */
- +struct proc_info_list {
- +
- + unsigned int cpu_val;
- + unsigned int cpu_mask;
- + const char *arch_name;
- + const char *elf_name;
- + unsigned int elf_hwcap;
- + struct proc_info_item *info;
- +};
- +
- +extern unsigned int elf_hwcap;
- +
- +#endif /* __ASSEMBLY__ */
- +
- +#define HWCAP_MFUSR_PC 0x000001
- +#define HWCAP_EXT 0x000002
- +#define HWCAP_EXT2 0x000004
- +#define HWCAP_FPU 0x000008
- +#define HWCAP_AUDIO 0x000010
- +#define HWCAP_BASE16 0x000020
- +#define HWCAP_STRING 0x000040
- +#define HWCAP_REDUCED_REGS 0x000080
- +#define HWCAP_VIDEO 0x000100
- +#define HWCAP_ENCRYPT 0x000200
- +#define HWCAP_EDM 0x000400
- +#define HWCAP_LMDMA 0x000800
- +#define HWCAP_PFM 0x001000
- +#define HWCAP_HSMP 0x002000
- +#define HWCAP_TRACE 0x004000
- +#define HWCAP_DIV 0x008000
- +#define HWCAP_MAC 0x010000
- +#define HWCAP_L2C 0x020000
- +#define HWCAP_FPU_DP 0x040000
- +#define HWCAP_V2 0x080000
- +#define HWCAP_DX_REGS 0x100000
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/ptrace.h linux-3.4.110/arch/nds32/include/asm/ptrace.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/ptrace.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/ptrace.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,119 @@
- +/*
- + * linux/arch/nds32/include/asm/ptrace.h
- + *
- + * Copyright (C) 1996-2003 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#ifndef __ASM_NDS32_PTRACE_H
- +#define __ASM_NDS32_PTRACE_H
- +
- +#define PTRACE_GETREGS 12
- +#define PTRACE_SETREGS 13
- +#define PTRACE_GETFPREGS 14
- +#define PTRACE_SETFPREGS 15
- +#define PTRACE_GETAUREGS 18
- +#define PTRACE_SETAUREGS 19
- +
- +#define PTRACE_OLDSETOPTIONS 21
- +
- +#define PTRACE_GET_THREAD_AREA 22
- +
- +#ifndef __ASSEMBLY__
- +/* this struct defines the way the registers are stored on the
- + stack during a system call. */
- +
- +struct pt_regs {
- +#if defined(CONFIG_ABI1)
- + long dummy[6];
- +#endif
- + long uregs[44];
- +};
- +#define NDS32_osp uregs[43]
- +#define NDS32_FUCOP_CTL uregs[42]
- +#define NDS32_lp uregs[41]
- +#define NDS32_gp uregs[40]
- +#define NDS32_fp uregs[39]
- +#define NDS32_r25 uregs[38]
- +#define NDS32_r24 uregs[37]
- +#define NDS32_r23 uregs[36]
- +#define NDS32_r22 uregs[35]
- +#define NDS32_r21 uregs[34]
- +#define NDS32_r20 uregs[33]
- +#define NDS32_r19 uregs[32]
- +#define NDS32_r18 uregs[31]
- +#define NDS32_r17 uregs[30]
- +#define NDS32_r16 uregs[29]
- +#define NDS32_r15 uregs[28]
- +#define NDS32_r14 uregs[27]
- +#define NDS32_r13 uregs[26]
- +#define NDS32_r12 uregs[25]
- +#define NDS32_r11 uregs[24]
- +#define NDS32_r10 uregs[23]
- +#define NDS32_r9 uregs[22]
- +#define NDS32_r8 uregs[21]
- +#define NDS32_r7 uregs[20]
- +#define NDS32_r6 uregs[19]
- +#define NDS32_r5 uregs[18]
- +#define NDS32_r4 uregs[17]
- +#define NDS32_r3 uregs[16]
- +#define NDS32_r2 uregs[15]
- +#define NDS32_r1 uregs[14]
- +#define NDS32_r0 uregs[13]
- +#if defined(CONFIG_HWZOL)
- +#define NDS32_lc uregs[11]
- +#define NDS32_le uregs[10]
- +#define NDS32_lb uregs[9]
- +#endif
- +#define NDS32_pp1 uregs[8]
- +#define NDS32_pp0 uregs[7]
- +#define NDS32_pipc uregs[6]
- +#define NDS32_pipsw uregs[5]
- +#define NDS32_ORIG_r0 uregs[4]
- +#define NDS32_sp uregs[3]
- +#define NDS32_ipc uregs[2]
- +#define NDS32_ipsw uregs[1]
- +#define NDS32_ir0 uregs[0]
- +
- +#ifdef __KERNEL__
- +#include <asm/bitfield.h>
- +
- +#define arch_has_single_step() (1)
- +struct task_struct;
- +extern void user_enable_single_step(struct task_struct *);
- +extern void user_disable_single_step(struct task_struct *);
- +
- +#define user_mode(regs) (((regs)->NDS32_ipsw & PSW_mskPOM) == 0)
- +
- +#define interrupts_enabled(regs) (!((regs)->NDS32_ipsw & ~PSW_mskGIE))
- +
- +extern void show_regs(struct pt_regs *);
- +
- +/* Are the current registers suitable for user mode?
- + * (used to maintain security in signal handlers)
- + */
- +static inline int valid_user_regs(struct pt_regs *regs)
- +{
- + return user_mode(regs) && ((regs->NDS32_ipsw & PSW_mskGIE) == 1);
- +}
- +
- +static inline unsigned long regs_return_value(struct pt_regs *regs)
- +{
- + return regs->NDS32_r0;
- +}
- +
- +
- +#define instruction_pointer(regs) ((regs)->NDS32_ipc)
- +
- +#ifdef CONFIG_SMP
- +extern unsigned long profile_pc(struct pt_regs *regs);
- +#else
- +#define profile_pc(regs) instruction_pointer(regs)
- +#endif
- +
- +#endif /* __KERNEL__ */
- +#endif /* __ASSEMBLY__ */
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/reg_access.h linux-3.4.110/arch/nds32/include/asm/reg_access.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/reg_access.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/reg_access.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,153 @@
- +/*
- + * linux/arch/nds32/include/asm/reg_access.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_REG_ACCESS_H__
- +#define __NDS32_REG_ACCESS_H__
- +
- +#ifndef __ASSEMBLY__
- +#define DEFINE_GET_SYS_REG( reg) \
- +inline static unsigned long GET_##reg( void){ \
- + unsigned long val; \
- + __asm__ volatile ( "mfsr %0, $"#reg :"=&r" (val) ::"memory"); \
- + return val; \
- +}
- +
- +#define DEFINE_PUT_SYS_REG( reg) \
- +inline static void SET_##reg( unsigned long val){ \
- + __asm__ volatile ( "\n\tmtsr %0, $"#reg \
- + "\n\tdsb" ::"r" ( val) :"memory"); \
- +}
- +
- +#define DEFINE_PUT_SYS_REG_i( reg) \
- +inline static void SET_##reg( unsigned long val){ \
- + __asm__ volatile ( "\n\tmtsr %0, $"#reg \
- + "\n\tisb" ::"r" ( val) :"memory"); \
- +}
- +#define DEFINE_SYS_REG_OP( reg) \
- +DEFINE_GET_SYS_REG( reg); \
- +DEFINE_PUT_SYS_REG( reg);
- +
- +#define DEFINE_SYS_REG_OP_i( reg) \
- +DEFINE_GET_SYS_REG( reg); \
- +DEFINE_PUT_SYS_REG_i( reg);
- +
- +DEFINE_SYS_REG_OP( CPU_VER);
- +DEFINE_SYS_REG_OP( ICM_CFG);
- +DEFINE_SYS_REG_OP( DCM_CFG);
- +DEFINE_SYS_REG_OP( MMU_CFG);
- +DEFINE_SYS_REG_OP( MSC_CFG);
- +DEFINE_SYS_REG_OP( CORE_ID);
- +DEFINE_SYS_REG_OP( FUCOP_EXIST);
- +
- +DEFINE_SYS_REG_OP_i( PSW);
- +DEFINE_SYS_REG_OP( IPSW);
- +DEFINE_SYS_REG_OP( P_IPSW);
- +DEFINE_SYS_REG_OP( IVB);
- +DEFINE_SYS_REG_OP( EVA);
- +DEFINE_SYS_REG_OP( P_EVA);
- +DEFINE_SYS_REG_OP( ITYPE);
- +DEFINE_SYS_REG_OP( P_ITYPE);
- +DEFINE_SYS_REG_OP( MERR);
- +DEFINE_SYS_REG_OP( IPC);
- +DEFINE_SYS_REG_OP( P_IPC);
- +DEFINE_SYS_REG_OP( OIPC);
- +DEFINE_SYS_REG_OP( P_P0);
- +DEFINE_SYS_REG_OP( P_P1);
- +DEFINE_SYS_REG_OP( INT_MASK);
- +DEFINE_SYS_REG_OP( INT_PEND);
- +DEFINE_SYS_REG_OP( INT_MASK2);
- +DEFINE_SYS_REG_OP( INT_PEND2);
- +DEFINE_SYS_REG_OP( INT_TRIGGER);
- +
- +DEFINE_SYS_REG_OP( MMU_CTL);
- +DEFINE_SYS_REG_OP( L1_PPTB);
- +DEFINE_SYS_REG_OP( TLB_VPN);
- +DEFINE_SYS_REG_OP( TLB_DATA);
- +DEFINE_SYS_REG_OP( TLB_MISC);
- +DEFINE_SYS_REG_OP( VLPT_IDX);
- +DEFINE_SYS_REG_OP( ILMB);
- +DEFINE_SYS_REG_OP( DLMB);
- +DEFINE_SYS_REG_OP( CACHE_CTL);
- +DEFINE_SYS_REG_OP( HSMP_SADDR);
- +DEFINE_SYS_REG_OP( HSMP_EADDR);
- +
- +DEFINE_SYS_REG_OP( EDM_CFG);
- +DEFINE_SYS_REG_OP( EDMSW);
- +DEFINE_SYS_REG_OP( EDM_CTL);
- +DEFINE_SYS_REG_OP( EDM_DTR);
- +DEFINE_SYS_REG_OP( BPMTC);
- +DEFINE_SYS_REG_OP( DIMBR);
- +DEFINE_SYS_REG_OP( TECR0);
- +DEFINE_SYS_REG_OP( TECR1);
- +
- +DEFINE_SYS_REG_OP( BPC0);
- +DEFINE_SYS_REG_OP( BPA0);
- +DEFINE_SYS_REG_OP( BPAM0);
- +DEFINE_SYS_REG_OP( BPV0);
- +DEFINE_SYS_REG_OP( BPCID0);
- +DEFINE_SYS_REG_OP( BPC1);
- +DEFINE_SYS_REG_OP( BPA1);
- +DEFINE_SYS_REG_OP( BPAM1);
- +DEFINE_SYS_REG_OP( BPV1);
- +DEFINE_SYS_REG_OP( BPCID1);
- +DEFINE_SYS_REG_OP( BPC2);
- +DEFINE_SYS_REG_OP( BPA2);
- +DEFINE_SYS_REG_OP( BPAM2);
- +DEFINE_SYS_REG_OP( BPV2);
- +DEFINE_SYS_REG_OP( BPCID2);
- +DEFINE_SYS_REG_OP( BPC3);
- +DEFINE_SYS_REG_OP( BPA3);
- +DEFINE_SYS_REG_OP( BPAM3);
- +DEFINE_SYS_REG_OP( BPV3);
- +DEFINE_SYS_REG_OP( BPCID3);
- +DEFINE_SYS_REG_OP( BPC4);
- +DEFINE_SYS_REG_OP( BPA4);
- +DEFINE_SYS_REG_OP( BPAM4);
- +DEFINE_SYS_REG_OP( BPV4);
- +DEFINE_SYS_REG_OP( BPCID4);
- +DEFINE_SYS_REG_OP( BPC5);
- +DEFINE_SYS_REG_OP( BPA5);
- +DEFINE_SYS_REG_OP( BPAM5);
- +DEFINE_SYS_REG_OP( BPV5);
- +DEFINE_SYS_REG_OP( BPCID5);
- +DEFINE_SYS_REG_OP( BPC6);
- +DEFINE_SYS_REG_OP( BPA6);
- +DEFINE_SYS_REG_OP( BPAM6);
- +DEFINE_SYS_REG_OP( BPV6);
- +DEFINE_SYS_REG_OP( BPCID6);
- +DEFINE_SYS_REG_OP( BPC7);
- +DEFINE_SYS_REG_OP( BPA7);
- +DEFINE_SYS_REG_OP( BPAM7);
- +DEFINE_SYS_REG_OP( BPV7);
- +DEFINE_SYS_REG_OP( BPCID7);
- +
- +DEFINE_SYS_REG_OP( PFMC0);
- +DEFINE_SYS_REG_OP( PFMC1);
- +DEFINE_SYS_REG_OP( PFMC2);
- +DEFINE_SYS_REG_OP( PFM_CTL);
- +
- +DEFINE_SYS_REG_OP( SDZ_CTL);
- +DEFINE_SYS_REG_OP( N12MISC_CTL);
- +DEFINE_SYS_REG_OP( PRUSR_ACC_CTL);
- +
- +DEFINE_SYS_REG_OP( DMA_CFG);
- +DEFINE_SYS_REG_OP( DMA_GCSW);
- +DEFINE_SYS_REG_OP( DMA_CHNSEL);
- +DEFINE_SYS_REG_OP( DMA_ACT);
- +DEFINE_SYS_REG_OP( DMA_SETUP);
- +DEFINE_SYS_REG_OP( DMA_ISADDR);
- +DEFINE_SYS_REG_OP( DMA_ESADDR);
- +DEFINE_SYS_REG_OP( DMA_TCNT);
- +DEFINE_SYS_REG_OP( DMA_STATUS);
- +DEFINE_SYS_REG_OP( DMA_2DSET);
- +DEFINE_SYS_REG_OP( DMA_2DSCTL);
- +
- +DEFINE_SYS_REG_OP( FPCSR);
- +DEFINE_SYS_REG_OP( FPCFG);
- +DEFINE_SYS_REG_OP( FUCOP_CTL);
- +
- +#endif /* !__ASSEMBLY__ */
- +
- +#endif /* __NDS32_REG_ACCESS_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/resource.h linux-3.4.110/arch/nds32/include/asm/resource.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/resource.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/resource.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/resource.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_RESOURCE_H__
- +#define __NDS32_RESOURCE_H__
- +
- +#include <asm-generic/resource.h>
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/rtc.h linux-3.4.110/arch/nds32/include/asm/rtc.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/rtc.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/rtc.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,43 @@
- +/*
- + * linux/arch/nds32/include/asm/rtc.h
- + *
- + * Copyright (C) 2003 Deep Blue Solutions Ltd.
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#ifndef ASMNDS32_RTC_H
- +#define ASMNDS32_RTC_H
- +
- +struct module;
- +
- +struct rtc_ops {
- + struct module *owner;
- + int (*open)(void);
- + void (*release)(void);
- + int (*ioctl)(unsigned int, unsigned long);
- +
- + int (*read_time)(struct rtc_time *);
- + int (*set_time)(struct rtc_time *);
- + int (*read_alarm)(struct rtc_wkalrm *);
- + int (*set_alarm)(struct rtc_wkalrm *);
- + int (*proc)(char *buf);
- +};
- +
- +void rtc_update(unsigned long, unsigned long);
- +int register_rtc(struct rtc_ops *);
- +void unregister_rtc(struct rtc_ops *);
- +
- +static inline int rtc_periodic_alarm(struct rtc_time *tm)
- +{
- + return (tm->tm_year == -1) ||
- + ((unsigned)tm->tm_mon >= 12) ||
- + ((unsigned)(tm->tm_mday - 1) >= 31) ||
- + ((unsigned)tm->tm_hour > 23) ||
- + ((unsigned)tm->tm_min > 59) ||
- + ((unsigned)tm->tm_sec > 59);
- +}
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/scatterlist.h linux-3.4.110/arch/nds32/include/asm/scatterlist.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/scatterlist.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/scatterlist.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,35 @@
- +/*
- + * linux/arch/nds32/include/asm/scatterlist.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASMNDS32_SCATTERLIST_H
- +#define _ASMNDS32_SCATTERLIST_H
- +
- +#include <asm/memory.h>
- +#include <asm/types.h>
- +#include <asm-generic/scatterlist.h>
- +
- +#if 0
- +struct scatterlist {
- +#ifdef CONFIG_DEBUG_SG
- + unsigned long sg_magic;
- +#endif
- + unsigned long page_link;
- + unsigned int offset; /* buffer offset */
- + dma_addr_t dma_address; /* dma address */
- + unsigned int length; /* length */
- +};
- +
- +/*
- + * These macros should be used after a pci_map_sg call has been done
- + * to get bus addresses of each of the SG entries and their lengths.
- + * You should only work with the number of sg entries pci_map_sg
- + * returns, or alternatively stop on the first sg_dma_len(sg) which
- + * is 0.
- + */
- +#define sg_dma_address(sg) ((sg)->dma_address)
- +#define sg_dma_len(sg) ((sg)->length)
- +#endif
- +
- +#endif /* _ASMNDS32_SCATTERLIST_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/sections.h linux-3.4.110/arch/nds32/include/asm/sections.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/sections.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/sections.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/sections.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __NDS32_SECTIONS_H__
- +#define __NDS32_SECTIONS_H__
- +
- +#include <asm-generic/sections.h>
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/segment.h linux-3.4.110/arch/nds32/include/asm/segment.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/segment.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/segment.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,16 @@
- +/*
- + * linux/arch/nds32/include/asm/segment.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __ASM_NDS32_SEGMENT_H
- +#define __ASM_NDS32_SEGMENT_H
- +
- +#define __KERNEL_CS 0x0
- +#define __KERNEL_DS 0x0
- +
- +#define __USER_CS 0x1
- +#define __USER_DS 0x1
- +
- +#endif /* __ASM_NDS32_SEGMENT_H */
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/semaphore.h linux-3.4.110/arch/nds32/include/asm/semaphore.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/semaphore.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/semaphore.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,6 @@
- +/*
- + * linux/arch/nds32/include/asm/semaphore.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#include <linux/semaphore.h>
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/semaphore-helper.h linux-3.4.110/arch/nds32/include/asm/semaphore-helper.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/semaphore-helper.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/semaphore-helper.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,89 @@
- +/*
- + * linux/arch/nds32/include/asm/semaphore-helper.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef ASMNDS32_SEMAPHORE_HELPER_H
- +#define ASMNDS32_SEMAPHORE_HELPER_H
- +
- +/*
- + * These two _must_ execute atomically wrt each other.
- + */
- +static inline void wake_one_more(struct semaphore * sem)
- +{
- + unsigned long flags;
- +
- + spin_lock_irqsave(&semaphore_wake_lock, flags);
- + if (atomic_read(&sem->count) <= 0)
- + sem->waking++;
- + spin_unlock_irqrestore(&semaphore_wake_lock, flags);
- +}
- +
- +static inline int waking_non_zero(struct semaphore *sem)
- +{
- + unsigned long flags;
- + int ret = 0;
- +
- + spin_lock_irqsave(&semaphore_wake_lock, flags);
- + if (sem->waking > 0) {
- + sem->waking--;
- + ret = 1;
- + }
- + spin_unlock_irqrestore(&semaphore_wake_lock, flags);
- + return ret;
- +}
- +
- +/*
- + * waking non zero interruptible
- + * 1 got the lock
- + * 0 go to sleep
- + * -EINTR interrupted
- + *
- + * We must undo the sem->count down_interruptible() increment while we are
- + * protected by the spinlock in order to make this atomic_inc() with the
- + * atomic_read() in wake_one_more(), otherwise we can race. -arca
- + */
- +static inline int waking_non_zero_interruptible(struct semaphore *sem,
- + struct task_struct *tsk)
- +{
- + unsigned long flags;
- + int ret = 0;
- +
- + spin_lock_irqsave(&semaphore_wake_lock, flags);
- + if (sem->waking > 0) {
- + sem->waking--;
- + ret = 1;
- + } else if (signal_pending(tsk)) {
- + atomic_inc(&sem->count);
- + ret = -EINTR;
- + }
- + spin_unlock_irqrestore(&semaphore_wake_lock, flags);
- + return ret;
- +}
- +
- +/*
- + * waking_non_zero_try_lock:
- + * 1 failed to lock
- + * 0 got the lock
- + *
- + * We must undo the sem->count down_interruptible() increment while we are
- + * protected by the spinlock in order to make this atomic_inc() with the
- + * atomic_read() in wake_one_more(), otherwise we can race. -arca
- + */
- +static inline int waking_non_zero_trylock(struct semaphore *sem)
- +{
- + unsigned long flags;
- + int ret = 1;
- +
- + spin_lock_irqsave(&semaphore_wake_lock, flags);
- + if (sem->waking <= 0)
- + atomic_inc(&sem->count);
- + else {
- + sem->waking--;
- + ret = 0;
- + }
- + spin_unlock_irqrestore(&semaphore_wake_lock, flags);
- + return ret;
- +}
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/sembuf.h linux-3.4.110/arch/nds32/include/asm/sembuf.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/sembuf.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/sembuf.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,30 @@
- +/*
- + * linux/arch/nds32/include/asm/sembuf.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASMNDS32_SEMBUF_H
- +#define _ASMNDS32_SEMBUF_H
- +
- +/*
- + * The semid64_ds structure for arm architecture.
- + * Note extra padding because this structure is passed back and forth
- + * between kernel and user space.
- + *
- + * Pad space is left for:
- + * - 64-bit time_t to solve y2038 problem
- + * - 2 miscellaneous 32-bit values
- + */
- +
- +struct semid64_ds {
- + struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
- + __kernel_time_t sem_otime; /* last semop time */
- + unsigned long __unused1;
- + __kernel_time_t sem_ctime; /* last change time */
- + unsigned long __unused2;
- + unsigned long sem_nsems; /* no. of semaphores in array */
- + unsigned long __unused3;
- + unsigned long __unused4;
- +};
- +
- +#endif /* _ASMNDS32_SEMBUF_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/serial.h linux-3.4.110/arch/nds32/include/asm/serial.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/serial.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/serial.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,20 @@
- +/*
- + * linux/arch/nds32/include/asm/serial.h
- + *
- + * Copyright (C) 1996 Russell King.
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * Changelog:
- + * 15-10-1996 RMK Created
- + */
- +
- +#ifndef __ASM_SERIAL_H
- +#define __ASM_SERIAL_H
- +
- +#define BASE_BAUD (CONFIG_UART_CLK / 16)
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/setup.h linux-3.4.110/arch/nds32/include/asm/setup.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/setup.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/setup.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,232 @@
- +/*
- + * linux/arch/nds32/include/asm/setup.h
- + *
- + * Copyright (C) 1997-1999 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * Structure passed to kernel to tell it about the
- + * hardware it's running on. See Documentation/arm/Setup
- + * for more info.
- + */
- +#ifndef __ASMNDS32_SETUP_H
- +#define __ASMNDS32_SETUP_H
- +
- +#define COMMAND_LINE_SIZE 256
- +
- +/* The list ends with an ATAG_NONE node. */
- +#define ATAG_NONE 0x00000000
- +
- +struct tag_header {
- + u32 size;
- + u32 tag;
- +};
- +
- +/* The list must start with an ATAG_CORE node */
- +#define ATAG_CORE 0x54410001
- +
- +struct tag_core {
- + u32 flags; /* bit 0 = read-only */
- + u32 pagesize;
- + u32 rootdev;
- +};
- +
- +/* it is allowed to have multiple ATAG_MEM nodes */
- +#define ATAG_MEM 0x54410002
- +
- +struct tag_mem32 {
- + u32 size;
- + u32 start; /* physical start address */
- +};
- +
- +/* VGA text type displays */
- +#define ATAG_VIDEOTEXT 0x54410003
- +
- +struct tag_videotext {
- + u8 x;
- + u8 y;
- + u16 video_page;
- + u8 video_mode;
- + u8 video_cols;
- + u16 video_ega_bx;
- + u8 video_lines;
- + u8 video_isvga;
- + u16 video_points;
- +};
- +
- +/* describes how the ramdisk will be used in kernel */
- +#define ATAG_RAMDISK 0x54410004
- +
- +struct tag_ramdisk {
- + u32 flags; /* bit 0 = load, bit 1 = prompt */
- + u32 size; /* decompressed ramdisk size in _kilo_ bytes */
- + u32 start; /* starting block of floppy-based RAM disk image */
- +};
- +
- +/*M Tom
- + * this one accidentally used virtual addresses - as such,
- + * it's deprecated.
- + * describes where the compressed ramdisk image lives (virtual address)
- + */
- +#define ATAG_INITRD 0x54410005
- +
- +/* describes where the compressed ramdisk image lives (physical address) */
- +#define ATAG_INITRD2 0x54420005
- +
- +struct tag_initrd {
- + u32 start; //M Tom va of start addr /* physical start address */
- + u32 size; //M Tom unzipped size /* size of compressed ramdisk image in bytes */
- +};
- +
- +/* board serial number. "64 bits should be enough for everybody" */
- +#define ATAG_SERIAL 0x54410006
- +
- +struct tag_serialnr {
- + u32 low;
- + u32 high;
- +};
- +
- +/* board revision */
- +#define ATAG_REVISION 0x54410007
- +
- +struct tag_revision {
- + u32 rev;
- +};
- +
- +/* initial values for vesafb-type framebuffers. see struct screen_info
- + * in include/linux/tty.h
- + */
- +#define ATAG_VIDEOLFB 0x54410008
- +
- +struct tag_videolfb {
- + u16 lfb_width;
- + u16 lfb_height;
- + u16 lfb_depth;
- + u16 lfb_linelength;
- + u32 lfb_base;
- + u32 lfb_size;
- + u8 red_size;
- + u8 red_pos;
- + u8 green_size;
- + u8 green_pos;
- + u8 blue_size;
- + u8 blue_pos;
- + u8 rsvd_size;
- + u8 rsvd_pos;
- +};
- +
- +/* command line: \0 terminated string */
- +#define ATAG_CMDLINE 0x54410009
- +
- +struct tag_cmdline {
- + char cmdline[COMMAND_LINE_SIZE];//M Tom
- +};
- +
- +/* acorn RiscPC specific information */
- +/*-d Tom
- +#define ATAG_ACORN 0x41000101
- +
- +struct tag_acorn {
- + u32 memc_control_reg;
- + u32 vram_pages;
- + u8 sounddefault;
- + u8 adfsdrives;
- +};
- +*/
- +#define ATAG_CPE 0x41000101
- +struct tag_cpe {
- + u32 memc_control_reg;
- + u32 vram_pages;
- + u8 sounddefault;
- + u8 adfsdrives;
- +};
- +
- +
- +/* footbridge memory clock, see arch/arm/mach-footbridge/arch.c */
- +#define ATAG_MEMCLK 0x41000402
- +
- +struct tag_memclk {
- + u32 fmemclk;
- +};
- +
- +struct tag {
- + struct tag_header hdr;
- + union {
- + struct tag_core core;
- + struct tag_mem32 mem;
- + struct tag_videotext videotext;
- + struct tag_ramdisk ramdisk;
- + struct tag_initrd initrd;
- + struct tag_serialnr serialnr;
- + struct tag_revision revision;
- + struct tag_videolfb videolfb;
- + struct tag_cmdline cmdline;
- +
- + /*
- + * Andes specific
- + */
- + struct tag_cpe cpe;
- +
- + /*
- + * DC21285 specific
- + */
- + struct tag_memclk memclk;
- + } u;
- +};
- +
- +struct tagtable {
- + u32 tag;
- + int (*parse)(const struct tag *);
- +};
- +
- +#define tag_member_present(tag,member) \
- + ((unsigned long)(&((struct tag *)0L)->member + 1) \
- + <= (tag)->hdr.size * 4)
- +
- +#define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size))
- +#define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)
- +
- +#define for_each_tag(t,base) \
- + for (t = base; t->hdr.size; t = tag_next(t))
- +
- +#ifdef __KERNEL__
- +
- +#define __tag __used __attribute__((__section__(".taglist")))
- +#define __tagtable(tag, fn) \
- +static struct tagtable __tagtable_##fn __tag = { tag, fn }
- +
- +/*
- + * Memory map description
- + */
- +#ifdef CONFIG_ARCH_LH7A40X
- +# define NR_BANKS 16
- +#else
- +# define NR_BANKS 8
- +#endif
- +
- +struct meminfo {
- + int nr_banks;
- + struct {
- + unsigned long start;
- + unsigned long size;
- + int node;
- + } bank[NR_BANKS];
- +};
- +
- +/*
- + * Early command line parameters.
- + */
- +struct early_params {
- + const char *arg;
- + void (*fn)(char **p);
- +};
- +
- +#define __early_param(name,fn) \
- +static struct early_params __early_##fn __used \
- +__attribute__((__section__("__early_param"))) = { name, fn }
- +
- +#endif
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/shmbuf.h linux-3.4.110/arch/nds32/include/asm/shmbuf.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/shmbuf.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/shmbuf.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,47 @@
- +/*
- + * linux/arch/nds32/include/asm/shmbuf.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASMNDS32_SHMBUF_H
- +#define _ASMNDS32_SHMBUF_H
- +
- +/*
- + * The shmid64_ds structure for arm architecture.
- + * Note extra padding because this structure is passed back and forth
- + * between kernel and user space.
- + *
- + * Pad space is left for:
- + * - 64-bit time_t to solve y2038 problem
- + * - 2 miscellaneous 32-bit values
- + */
- +
- +struct shmid64_ds {
- + struct ipc64_perm shm_perm; /* operation perms */
- + size_t shm_segsz; /* size of segment (bytes) */
- + __kernel_time_t shm_atime; /* last attach time */
- + unsigned long __unused1;
- + __kernel_time_t shm_dtime; /* last detach time */
- + unsigned long __unused2;
- + __kernel_time_t shm_ctime; /* last change time */
- + unsigned long __unused3;
- + __kernel_pid_t shm_cpid; /* pid of creator */
- + __kernel_pid_t shm_lpid; /* pid of last operator */
- + unsigned long shm_nattch; /* no. of current attaches */
- + unsigned long __unused4;
- + unsigned long __unused5;
- +};
- +
- +struct shminfo64 {
- + unsigned long shmmax;
- + unsigned long shmmin;
- + unsigned long shmmni;
- + unsigned long shmseg;
- + unsigned long shmall;
- + unsigned long __unused1;
- + unsigned long __unused2;
- + unsigned long __unused3;
- + unsigned long __unused4;
- +};
- +
- +#endif /* _ASMNDS32_SHMBUF_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/shmparam.h linux-3.4.110/arch/nds32/include/asm/shmparam.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/shmparam.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/shmparam.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,27 @@
- +/*
- + * linux/arch/nds32/include/asm/shmparam.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASMNDS32_SHMPARAM_H
- +#define _ASMNDS32_SHMPARAM_H
- +
- +/*
- + * This should be the size of the virtually indexed cache/ways,
- + * whichever is greater since the cache aliases every size/ways
- + * bytes.
- + */
- +/*
- + * Reference ARM architecture, retain the previous code
- + * #define SHMLBA 0x4000
- + * #define REALSHMLBA (CACHE_SET( DCACHE) * CACHE_LINE_SIZE( DCACHE))
- + */
- +#define SHMLBA (4 * PAGE_SIZE) /* attach addr a multiple of this */
- +#define REALSHMLBA SHMLBA
- +
- +/*
- + * Enforce SHMLBA in shmat
- + */
- +#define __ARCH_FORCE_SHMLBA
- +
- +#endif /* _ASMNDS32_SHMPARAM_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/sigcontext.h linux-3.4.110/arch/nds32/include/asm/sigcontext.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/sigcontext.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/sigcontext.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,81 @@
- +/*
- + * linux/arch/nds32/include/asm/sigcontext.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASMNDS32_SIGCONTEXT_H
- +#define _ASMNDS32_SIGCONTEXT_H
- +
- +/*
- + * Signal context structure - contains all info to do with the state
- + * before the signal handler was invoked. Note: only add new entries
- + * to the end of the structure.
- + */
- +struct fpu_struct {
- + unsigned long fs_regs[32];
- + unsigned long long fd_regs[16];
- + unsigned long fpcsr;
- +};
- +
- +struct audio_struct {
- + unsigned long auregs[32];
- +};
- +
- +struct zol_struct {
- + unsigned long nds32_lc; /* $LC */
- + unsigned long nds32_le; /* $LE */
- + unsigned long nds32_lb; /* $LB */
- +};
- +
- +struct sigcontext {
- + unsigned long trap_no;
- + unsigned long error_code;
- + unsigned long oldmask;
- + unsigned long nds32_r0;
- + unsigned long nds32_r1;
- + unsigned long nds32_r2;
- + unsigned long nds32_r3;
- + unsigned long nds32_r4;
- + unsigned long nds32_r5;
- + unsigned long nds32_r6;
- + unsigned long nds32_r7;
- + unsigned long nds32_r8;
- + unsigned long nds32_r9;
- + unsigned long nds32_r10;
- + unsigned long nds32_r11;
- + unsigned long nds32_r12;
- + unsigned long nds32_r13;
- + unsigned long nds32_r14;
- + unsigned long nds32_r15;
- + unsigned long nds32_r16;
- + unsigned long nds32_r17;
- + unsigned long nds32_r18;
- + unsigned long nds32_r19;
- + unsigned long nds32_r20;
- + unsigned long nds32_r21;
- + unsigned long nds32_r22;
- + unsigned long nds32_r23;
- + unsigned long nds32_r24;
- + unsigned long nds32_r25;
- + unsigned long nds32_fp; /* $r28 */
- + unsigned long nds32_gp; /* $r29 */
- + unsigned long nds32_lr; /* $r30 */
- + unsigned long nds32_sp; /* $r31 */
- + unsigned long nds32_ipc;
- + unsigned long fault_address;
- +#if defined(CONFIG_FPU)
- + unsigned long used_math_flag;
- + /* FPU Registers */
- + struct fpu_struct fpu;
- +#endif
- + /* Audio Registers */
- +#if defined(CONFIG_AUDIO)
- + unsigned long used_audio_flag;
- + struct audio_struct audio;
- +#endif
- +#if defined(CONFIG_HWZOL)
- + struct zol_struct zol;
- +#endif
- +};
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/siginfo.h linux-3.4.110/arch/nds32/include/asm/siginfo.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/siginfo.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/siginfo.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/siginfo.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASMNDS32_SIGINFO_H
- +#define _ASMNDS32_SIGINFO_H
- +
- +#include <asm-generic/siginfo.h>
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/signal.h linux-3.4.110/arch/nds32/include/asm/signal.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/signal.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/signal.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,173 @@
- +/*
- + * linux/arch/nds32/include/asm/signal.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASMNDS32_SIGNAL_H
- +#define _ASMNDS32_SIGNAL_H
- +
- +#include <linux/types.h>
- +
- +/* Avoid too many header ordering problems. */
- +struct siginfo;
- +
- +#ifdef __KERNEL__
- +/* Most things should be clean enough to redefine this at will, if care
- + is taken to make libc match. */
- +
- +#define _NSIG 64
- +#define _NSIG_BPW 32
- +#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
- +
- +typedef unsigned long old_sigset_t; /* at least 32 bits */
- +
- +typedef struct {
- + unsigned long sig[_NSIG_WORDS];
- +} sigset_t;
- +
- +#else
- +/* Here we must cater to libcs that poke about in kernel headers. */
- +
- +#define NSIG 32
- +typedef unsigned long sigset_t;
- +
- +#endif /* __KERNEL__ */
- +
- +#define SIGHUP 1
- +#define SIGINT 2
- +#define SIGQUIT 3
- +#define SIGILL 4
- +#define SIGTRAP 5
- +#define SIGABRT 6
- +#define SIGIOT 6
- +#define SIGBUS 7
- +#define SIGFPE 8
- +#define SIGKILL 9
- +#define SIGUSR1 10
- +#define SIGSEGV 11
- +#define SIGUSR2 12
- +#define SIGPIPE 13
- +#define SIGALRM 14
- +#define SIGTERM 15
- +#define SIGSTKFLT 16
- +#define SIGCHLD 17
- +#define SIGCONT 18
- +#define SIGSTOP 19
- +#define SIGTSTP 20
- +#define SIGTTIN 21
- +#define SIGTTOU 22
- +#define SIGURG 23
- +#define SIGXCPU 24
- +#define SIGXFSZ 25
- +#define SIGVTALRM 26
- +#define SIGPROF 27
- +#define SIGWINCH 28
- +#define SIGIO 29
- +#define SIGPOLL SIGIO
- +/*
- +#define SIGLOST 29
- +*/
- +#define SIGPWR 30
- +#define SIGSYS 31
- +#define SIGUNUSED 31
- +
- +/* These should not be considered constants from userland. */
- +#define SIGRTMIN 32
- +#define SIGRTMAX _NSIG
- +
- +#define SIGSWI 32
- +
- +/*
- + * SA_FLAGS values:
- + *
- + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- + * SA_SIGINFO deliver the signal with SIGINFO structs
- + * SA_THIRTYTWO delivers the signal in 32-bit mode, even if the task
- + * is running in 26-bit.
- + * SA_ONSTACK allows alternate signal stacks (see sigaltstack(2)).
- + * SA_RESTART flag to get restarting signals (which were the default long ago)
- + * SA_NODEFER prevents the current signal from being masked in the handler.
- + * SA_RESETHAND clears the handler when the signal is delivered.
- + *
- + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- + * Unix names RESETHAND and NODEFER respectively.
- + */
- +#define SA_NOCLDSTOP 0x00000001
- +#define SA_NOCLDWAIT 0x00000002
- +#define SA_SIGINFO 0x00000004
- +#define SA_THIRTYTWO 0x02000000
- +#define SA_RESTORER 0x04000000
- +#define SA_ONSTACK 0x08000000
- +#define SA_RESTART 0x10000000
- +#define SA_NODEFER 0x40000000
- +#define SA_RESETHAND 0x80000000
- +
- +#define SA_NOMASK SA_NODEFER
- +#define SA_ONESHOT SA_RESETHAND
- +
- +
- +/*
- + * sigaltstack controls
- + */
- +#define SS_ONSTACK 1
- +#define SS_DISABLE 2
- +
- +#define MINSIGSTKSZ 2048
- +#define SIGSTKSZ 8192
- +
- +#ifdef __KERNEL__
- +#define SA_IRQNOMASK 0x08000000
- +#endif
- +
- +#include <asm-generic/signal-defs.h>
- +
- +#ifdef __KERNEL__
- +struct old_sigaction {
- + __sighandler_t sa_handler;
- + old_sigset_t sa_mask;
- + unsigned long sa_flags;
- + __sigrestore_t sa_restorer;
- +};
- +
- +struct sigaction {
- + __sighandler_t sa_handler;
- + unsigned long sa_flags;
- + __sigrestore_t sa_restorer;
- + sigset_t sa_mask; /* mask last for extensibility */
- +};
- +
- +struct k_sigaction {
- + struct sigaction sa;
- +};
- +
- +#else
- +/* Here we must cater to libcs that poke about in kernel headers. */
- +
- +struct sigaction {
- + union {
- + __sighandler_t _sa_handler;
- + void (*_sa_sigaction)(int, struct siginfo *, void *);
- + } _u;
- + sigset_t sa_mask;
- + unsigned long sa_flags;
- + void (*sa_restorer)(void);
- +};
- +
- +#define sa_handler _u._sa_handler
- +#define sa_sigaction _u._sa_sigaction
- +
- +#endif /* __KERNEL__ */
- +
- +typedef struct sigaltstack {
- + void __user *ss_sp;
- + int ss_flags;
- + size_t ss_size;
- +} stack_t;
- +
- +#ifdef __KERNEL__
- +#include <asm/sigcontext.h>
- +#define ptrace_signal_deliver(regs, cookie) do { } while (0)
- +#endif
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/sizes.h linux-3.4.110/arch/nds32/include/asm/sizes.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/sizes.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/sizes.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,53 @@
- +/*
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + */
- +/* DO NOT EDIT!! - this file automatically generated
- + * from .s file by awk -f s2h.awk
- + */
- +/* Size definitions
- + * Copyright (C) ARM Limited 1998. All rights reserved.
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __sizes_h
- +#define __sizes_h 1
- +
- +/* handy sizes */
- +#define SZ_1K 0x00000400
- +#define SZ_4K 0x00001000
- +#define SZ_8K 0x00002000
- +#define SZ_16K 0x00004000
- +#define SZ_64K 0x00010000
- +#define SZ_128K 0x00020000
- +#define SZ_256K 0x00040000
- +#define SZ_512K 0x00080000
- +
- +#define SZ_1M 0x00100000
- +#define SZ_2M 0x00200000
- +#define SZ_4M 0x00400000
- +#define SZ_8M 0x00800000
- +#define SZ_16M 0x01000000
- +#define SZ_32M 0x02000000
- +#define SZ_64M 0x04000000
- +#define SZ_128M 0x08000000
- +#define SZ_256M 0x10000000
- +#define SZ_512M 0x20000000
- +
- +#define SZ_1G 0x40000000
- +#define SZ_2G 0x80000000
- +
- +#endif
- +
- +/* END */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/smp.h linux-3.4.110/arch/nds32/include/asm/smp.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/smp.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/smp.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,42 @@
- +/*
- + * linux/arch/nds32/include/asm/smp.h
- + *
- + * Copyright (C) 2004-2005 ARM Ltd.
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#ifndef __ASM_NDS32_SMP_H
- +#define __ASM_NDS32_SMP_H
- +
- +#include <linux/threads.h>
- +#include <linux/cpumask.h>
- +#include <linux/thread_info.h>
- +
- +#ifndef CONFIG_SMP
- +# error "<asm-nds32/smp.h> included in non-SMP build"
- +#endif
- +
- +/*
- + * at the moment, there's not a big penalty for changing CPUs
- + * (the >big< penalty is running SMP in the first place)
- + */
- +#define PROC_CHANGE_PENALTY 15
- +
- +struct seq_file;
- +
- +/*
- + * Move global data into per-processor storage.
- + */
- +extern void smp_store_cpu_info(unsigned int cpuid);
- +
- +#define raw_smp_processor_id() (unsigned int)(GET_CORE_ID()&CORE_ID_mskCOREID)
- +
- +extern void smp_init_cpus(void);
- +extern void smp_send_timer(void);
- +extern void arch_send_call_function_single_ipi(int cpu);
- +extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
- +
- +#endif /* ifndef __ASM_NDS32_SMP_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/socket.h linux-3.4.110/arch/nds32/include/asm/socket.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/socket.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/socket.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/socket.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASMNDS32_SOCKET_H
- +#define _ASMNDS32_SOCKET_H
- +
- +#include <asm-generic/socket.h>
- +
- +#endif /* _ASMNDS32_SOCKET_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/sockios.h linux-3.4.110/arch/nds32/include/asm/sockios.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/sockios.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/sockios.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,18 @@
- +/*
- + * linux/arch/nds32/include/asm/sockios.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __ARCH_NDS32_SOCKIOS_H
- +#define __ARCH_NDS32_SOCKIOS_H
- +
- +/* Socket-level I/O control calls. */
- +#define FIOSETOWN 0x8901
- +#define SIOCSPGRP 0x8902
- +#define FIOGETOWN 0x8903
- +#define SIOCGPGRP 0x8904
- +#define SIOCATMARK 0x8905
- +#define SIOCGSTAMP 0x8906 /* Get stamp */
- +#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/spec-ag101.h linux-3.4.110/arch/nds32/include/asm/spec-ag101.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/spec-ag101.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/spec-ag101.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,237 @@
- +#ifndef __NDS32_AG101_SPECIFICATION_H__
- +#define __NDS32_AG101_SPECIFICATION_H__
- +
- +#define UART0_PA_BASE 0x99600000
- +#define UART0_VA_BASE 0xF9960000
- +#define UART0_IRQ 7
- +#define UART1_PA_BASE 0x98300000
- +#define UART1_VA_BASE 0xF9830000
- +#define UART1_IRQ 11
- +#define CFC_FTCFC010_0_PA_BASE 0x98D00000
- +#define CFC_FTCFC010_0_VA_BASE 0xF98D0000
- +#define SDC_FTSDC010_0_PA_BASE 0x98e00000
- +#define SDC_FTSDC010_0_VA_BASE 0xF98e0000
- +#define SDMC_FTSDMC021_PA_BASE 0x90300000
- +#define SDMC_FTSDMC021_VA_BASE 0xF9030000
- +#define PCIC_FTPCI100_0_PA_BASE 0x90C00000
- +#define PCIC_FTPCI100_0_VA_BASE 0xF90C0000
- +#define PCIC_FTPCI100_0_VA_LIMIT 0xF90CFFFF
- +#define PCIIO_PA_BASE 0x90C01000
- +#define PCIIO_VA_BASE 0xFE901000
- +#define PCIIO_0_PA_BASE 0x90C01000
- +#define PCIIO_0_VA_BASE 0xFE901000
- +#define PCIIO_VA_LIMIT 0xFE9FFFFF
- +#define AHB_ATFAHBC020S_0_PA_BASE 0x90100000
- +#define AHB_ATFAHBC020S_0_VA_BASE 0xF9010000
- +
- +/* DMAC */
- +#define DMAC_FTDMAC020_PA_COUNT 1
- +#define DMAC_FTDMAC020_PA_BASE 0x90400000
- +#define DMAC_FTDMAC020_PA_LIMIT 0x90400FFF
- +#define DMAC_FTDMAC020_PA_SIZE 0x00001000
- +#define DMAC_FTDMAC020_0_PA_BASE 0x90400000
- +#define DMAC_FTDMAC020_0_PA_LIMIT 0x90400FFF
- +#define DMAC_FTDMAC020_0_PA_SIZE 0x00001000
- +#define DMAC_FTDMAC020_VA_COUNT 1
- +#define DMAC_FTDMAC020_VA_BASE 0xF9040000
- +#define DMAC_FTDMAC020_VA_LIMIT 0xF9040FFF
- +#define DMAC_FTDMAC020_VA_SIZE 0x00001000
- +#define DMAC_FTDMAC020_0_VA_BASE 0xF9040000
- +#define DMAC_FTDMAC020_0_VA_LIMIT 0xF9040FFF
- +#define DMAC_FTDMAC020_0_VA_SIZE 0x00001000
- +
- +/* TIMER */
- +#define TIMER_FTTMR010_PA_COUNT 1
- +#define TIMER_FTTMR010_PA_BASE 0x98400000
- +#define TIMER_FTTMR010_PA_LIMIT 0x98400FFF
- +#define TIMER_FTTMR010_PA_SIZE 0x00001000
- +#define TIMER_FTTMR010_0_PA_BASE 0x98400000
- +#define TIMER_FTTMR010_0_PA_LIMIT 0x98400FFF
- +#define TIMER_FTTMR010_0_PA_SIZE 0x00001000
- +#define TIMER_FTTMR010_VA_COUNT 1
- +#define TIMER_FTTMR010_VA_BASE 0xF9840000
- +#define TIMER_FTTMR010_VA_LIMIT 0xF9840FFF
- +#define TIMER_FTTMR010_VA_SIZE 0x00001000
- +#define TIMER_FTTMR010_0_VA_BASE 0xF9840000
- +#define TIMER_FTTMR010_0_VA_LIMIT 0xF9840FFF
- +#define TIMER_FTTMR010_0_VA_SIZE 0x00001000
- +
- +/* RTC */
- +#define RTC_FTRTC010_PA_COUNT 1
- +#define RTC_FTRTC010_PA_BASE 0x98600000
- +#define RTC_FTRTC010_PA_LIMIT 0x98600FFF
- +#define RTC_FTRTC010_PA_SIZE 0x00001000
- +#define RTC_FTRTC010_0_PA_BASE 0x98600000
- +#define RTC_FTRTC010_0_PA_LIMIT 0x98600FFF
- +#define RTC_FTRTC010_0_PA_SIZE 0x00001000
- +#define RTC_FTRTC010_VA_COUNT 1
- +#define RTC_FTRTC010_VA_BASE 0xF9860000
- +#define RTC_FTRTC010_VA_LIMIT 0xF9860FFF
- +#define RTC_FTRTC010_VA_SIZE 0x00001000
- +#define RTC_FTRTC010_0_VA_BASE 0xF9860000
- +#define RTC_FTRTC010_0_VA_LIMIT 0xF9860FFF
- +#define RTC_FTRTC010_0_VA_SIZE 0x00001000
- +
- +/* WDT */
- +#define WDT_FTWDT010_PA_COUNT 1
- +#define WDT_FTWDT010_PA_BASE 0x98500000
- +#define WDT_FTWDT010_PA_LIMIT 0x98500FFF
- +#define WDT_FTWDT010_PA_SIZE 0x00001000
- +#define WDT_FTWDT010_0_PA_BASE 0x98500000
- +#define WDT_FTWDT010_0_PA_LIMIT 0x98500FFF
- +#define WDT_FTWDT010_0_PA_SIZE 0x00001000
- +#define WDT_FTWDT010_VA_COUNT 1
- +#define WDT_FTWDT010_VA_BASE 0xF9850000
- +#define WDT_FTWDT010_VA_LIMIT 0xF9850FFF
- +#define WDT_FTWDT010_VA_SIZE 0x00001000
- +#define WDT_FTWDT010_0_VA_BASE 0xF9850000
- +#define WDT_FTWDT010_0_VA_LIMIT 0xF9850FFF
- +#define WDT_FTWDT010_0_VA_SIZE 0x00001000
- +
- +/* GPIO */
- +#define GPIO_FTGPIO010_PA_COUNT 1
- +#define GPIO_FTGPIO010_PA_BASE 0x98700000
- +#define GPIO_FTGPIO010_PA_LIMIT 0x98700FFF
- +#define GPIO_FTGPIO010_PA_SIZE 0x00001000
- +#define GPIO_FTGPIO010_0_PA_BASE 0x98700000
- +#define GPIO_FTGPIO010_0_PA_LIMIT 0x98700FFF
- +#define GPIO_FTGPIO010_0_PA_SIZE 0x00001000
- +#define GPIO_FTGPIO010_VA_COUNT 1
- +#define GPIO_FTGPIO010_VA_BASE 0xF9870000
- +#define GPIO_FTGPIO010_VA_LIMIT 0xF9870FFF
- +#define GPIO_FTGPIO010_VA_SIZE 0x00001000
- +#define GPIO_FTGPIO010_0_VA_BASE 0xF9870000
- +#define GPIO_FTGPIO010_0_VA_LIMIT 0xF9870FFF
- +#define GPIO_FTGPIO010_0_VA_SIZE 0x00001000
- +
- +
- +/* USB OTG */
- +#define USB_FOTG2XX_0_PA_COUNT 1
- +#define USB_FOTG2XX_0_PA_BASE 0x90B00000
- +#define USB_FOTG2XX_0_PA_LIMIT 0x90B00FFF
- +#define USB_FOTG2XX_0_PA_SIZE 0x00001000
- +#define USB_FOTG2XX_0_VA_BASE 0xF90B0000
- +#define USB_FOTG2XX_0_VA_LIMIT 0xF90B0FFF
- +#define USB_FOTG2XX_0_VA_SIZE 0x00001000
- +#define USB_FOTG2XX_0_IRQ 26
- +#define USB_FOTG2XX_PA_COUNT 1
- +#define USB_FOTG2XX_PA_BASE 0x90B00000
- +#define USB_FOTG2XX_PA_LIMIT 0x90B00FFF
- +#define USB_FOTG2XX_PA_SIZE 0x00001000
- +#define USB_FOTG2XX_VA_BASE 0xF90B0000
- +#define USB_FOTG2XX_VA_LIMIT 0xF90B0FFF
- +#define USB_FOTG2XX_VA_SIZE 0x00001000
- +#define USB_FOTG2XX_IRQ 26
- +#define USB_FOTG2XX_IRQ_COUNT 1
- +
- +/* SSP */
- +#define SSP_FTSSP010_PA_COUNT 1
- +#define SSP_FTSSP010_PA_BASE 0x99400000
- +#define SSP_FTSSP010_PA_LIMIT 0x99400FFF
- +#define SSP_FTSSP010_PA_SIZE 0x00001000
- +#define SSP_FTSSP010_0_PA_BASE 0x99400000
- +#define SSP_FTSSP010_0_PA_LIMIT 0x99400FFF
- +#define SSP_FTSSP010_0_PA_SIZE 0x00001000
- +#define SSP_FTSSP010_VA_COUNT 1
- +#define SSP_FTSSP010_VA_BASE 0xF9940000
- +#define SSP_FTSSP010_VA_LIMIT 0xF9940FFF
- +#define SSP_FTSSP010_VA_SIZE 0x00001000
- +#define SSP_FTSSP010_0_VA_BASE 0xF9940000
- +#define SSP_FTSSP010_0_VA_LIMIT 0xF9940FFF
- +#define SSP_FTSSP010_0_VA_SIZE 0x00001000
- +
- +/* APBBRG */
- +#define APBBRG_FTAPBBRG020S_PA_COUNT 1
- +#define APBBRG_FTAPBBRG020S_PA_BASE 0x90500000
- +#define APBBRG_FTAPBBRG020S_PA_LIMIT 0x90500FFF
- +#define APBBRG_FTAPBBRG020S_PA_SIZE 0x00001000
- +#define APBBRG_FTAPBBRG020S_0_PA_BASE 0x90500000
- +#define APBBRG_FTAPBBRG020S_0_PA_LIMIT 0x90500FFF
- +#define APBBRG_FTAPBBRG020S_0_PA_SIZE 0x00001000
- +#define APBBRG_FTAPBBRG020S_1_PA_BASE 0x90E00000
- +#define APBBRG_FTAPBBRG020S_1_PA_LIMIT 0x90E00FFF
- +#define APBBRG_FTAPBBRG020S_1_PA_SIZE 0x00001000
- +#define APBBRG_FTAPBBRG020S_VA_COUNT 1
- +#define APBBRG_FTAPBBRG020S_VA_BASE 0xF9050000
- +#define APBBRG_FTAPBBRG020S_VA_LIMIT 0xF9050FFF
- +#define APBBRG_FTAPBBRG020S_VA_SIZE 0x00001000
- +#define APBBRG_FTAPBBRG020S_0_VA_BASE 0xF9050000
- +#define APBBRG_FTAPBBRG020S_0_VA_LIMIT 0xF9050FFF
- +#define APBBRG_FTAPBBRG020S_0_VA_SIZE 0x00001000
- +#define APBBRG_FTAPBBRG020S_1_VA_BASE 0xF90E0000
- +#define APBBRG_FTAPBBRG020S_1_VA_LIMIT 0xF90E0FFF
- +#define APBBRG_FTAPBBRG020S_1_VA_SIZE 0x00001000
- +
- +/* I2C */
- +#define I2C_FTI2C010_PA_COUNT 1
- +#define I2C_FTI2C010_PA_BASE 0x98A00000
- +#define I2C_FTI2C010_PA_LIMIT 0x98A00FFF
- +#define I2C_FTI2C010_PA_SIZE 0x00001000
- +#define I2C_FTI2C010_0_PA_BASE 0x98A00000
- +#define I2C_FTI2C010_0_PA_LIMIT 0x98A00FFF
- +#define I2C_FTI2C010_0_PA_SIZE 0x00001000
- +#define I2C_FTI2C010_VA_COUNT 1
- +#define I2C_FTI2C010_VA_BASE 0xF98A0000
- +#define I2C_FTI2C010_VA_LIMIT 0xF98A0FFF
- +#define I2C_FTI2C010_VA_SIZE 0x00001000
- +#define I2C_FTI2C010_0_VA_BASE 0xF98A0000
- +#define I2C_FTI2C010_0_VA_LIMIT 0xF98A0FFF
- +#define I2C_FTI2C010_0_VA_SIZE 0x00001000
- +
- +/* L2CC */
- +#define L2CC_PA_BASE 0x90F00000 /* reserved */
- +#define L2CC_VA_BASE 0xF90F0000 /* FIXME */
- +
- +#define LED_PA_COUNT 1
- +#define LED_PA_BASE 0x902FF000
- +#define LED_PA_LIMIT 0x90200FFF
- +#define LED_PA_SIZE 0x00001000
- +#define LED_0_PA_BASE 0x90200000
- +#define LED_0_PA_LIMIT 0x90200FFF
- +#define LED_0_PA_SIZE 0x00001000
- +#define LED_VA_COUNT 1
- +#define LED_VA_BASE 0xF9020000
- +#define LED_VA_LIMIT 0xF9020000
- +#define LED_VA_SIZE 0x00001000
- +#define LED_0_VA_BASE 0xF9020000
- +#define LED_0_VA_LIMIT 0xF9020000
- +#define LED_0_VA_SIZE 0x00001000
- +
- +/* MAC */
- +#define MAC_FTMAC100_PA_COUNT 1
- +#define MAC_FTMAC100_PA_BASE 0x90900000
- +#define MAC_FTMAC100_PA_LIMIT 0x90900FFF
- +#define MAC_FTMAC100_PA_SIZE 0x00001000
- +#define MAC_FTMAC100_0_PA_BASE 0x90900000
- +#define MAC_FTMAC100_0_PA_LIMIT 0x90900FFF
- +#define MAC_FTMAC100_0_PA_SIZE 0x00001000
- +#define MAC_FTMAC100_1_PA_BASE 0x92000000
- +#define MAC_FTMAC100_1_PA_LIMIT 0x92000FFF
- +#define MAC_FTMAC100_1_PA_SIZE 0x00001000
- +#define MAC_FTMAC100_VA_COUNT 1
- +#define MAC_FTMAC100_VA_BASE 0xF9090000
- +#define MAC_FTMAC100_VA_LIMIT 0xF9090FFF
- +#define MAC_FTMAC100_VA_SIZE 0x00001000
- +#define MAC_FTMAC100_0_VA_BASE 0xF9090000
- +#define MAC_FTMAC100_0_VA_LIMIT 0xF9090FFF
- +#define MAC_FTMAC100_0_VA_SIZE 0x00001000
- +#define MAC_FTMAC100_1_VA_BASE 0xF9200000
- +#define MAC_FTMAC100_1_VA_LIMIT 0xF9200FFF
- +#define MAC_FTMAC100_1_VA_SIZE 0x00001000
- +
- +/* LCD */
- +#define LCD_FTLCDC100_PA_COUNT 1
- +#define LCD_FTLCDC100_PA_BASE 0x90600000
- +#define LCD_FTLCDC100_PA_LIMIT 0x90600FFF
- +#define LCD_FTLCDC100_PA_SIZE 0x00001000
- +#define LCD_FTLCDC100_0_PA_BASE 0x90600000
- +#define LCD_FTLCDC100_0_PA_LIMIT 0x90600FFF
- +#define LCD_FTLCDC100_0_PA_SIZE 0x00001000
- +#define LCD_FTLCDC100_VA_COUNT 1
- +#define LCD_FTLCDC100_VA_BASE 0xF9060000
- +#define LCD_FTLCDC100_VA_LIMIT 0xF9060FFF
- +#define LCD_FTLCDC100_VA_SIZE 0x00001000
- +#define LCD_FTLCDC100_0_VA_BASE 0xF9060000
- +#define LCD_FTLCDC100_0_VA_LIMIT 0xF9060FFF
- +#define LCD_FTLCDC100_0_VA_SIZE 0x00001000
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/spec-ag102.h linux-3.4.110/arch/nds32/include/asm/spec-ag102.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/spec-ag102.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/spec-ag102.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,167 @@
- +#ifndef __NDS32_AG102_SPECIFICATION_H__
- +#define __NDS32_AG102_SPECIFICATION_H__
- +
- +#define UART0_PA_BASE 0x94200000
- +#define UART0_VA_BASE 0xF9420000
- +#define UART0_IRQ 10
- +#define UART1_PA_BASE 0x94600000
- +#define UART1_VA_BASE 0xF9460000
- +#define UART1_IRQ 11
- +#define AMIC_PA_BASE 0x90F00000
- +#define AMIC_VA_BASE 0xF90F0000
- +#define GMAC_PA_BASE 0x90B00000
- +#define GMAC_VA_BASE 0xF90B0000
- +#define APBBR_PA_BASE 0x90D00000
- +#define APBBR_VA_BASE 0xF90D0000
- +#define GMAC_IRQ 25
- +#define TIMER_PA_BASE 0x94900000
- +#define TIMER_VA_BASE 0xF9490000
- +#define L2CC_PA_BASE 0x90900000
- +#define L2CC_VA_BASE 0xF9090000
- +#define CFC_FTCFC010_0_PA_BASE 0x94000000
- +#define CFC_FTCFC010_0_VA_BASE 0xF9400000
- +#define SDC_FTSDC010_0_PA_BASE 0x94400000
- +#define SDC_FTSDC010_0_VA_BASE 0xF9440000
- +#define PCU_PA_BASE 0x94800000
- +#define PCU_VA_BASE 0xF9480000
- +#define PCIC_FTPCI100_0_PA_BASE 0x90000000
- +#define PCIC_FTPCI100_0_VA_BASE 0xF9000000
- +#define PCIC_FTPCI100_0_VA_LIMIT 0xF9000FFF
- +#define PCIIO_PA_BASE 0x90001000
- +#define PCIIO_VA_BASE 0xF8901000
- +#define PCIIO_0_PA_BASE 0x90001000
- +#define PCIIO_0_VA_BASE 0xF8901000
- +#define PCIIO_VA_LIMIT 0xF89FFFFF
- +#define LPC_IO_PA_BASE 0x90100000
- +#define LPC_IO_VA_BASE 0xF9010000
- +#define LPC_REG_PA_BASE 0x90200000
- +#define LPC_REG_VA_BASE 0xF9020000
- +#define LPC_IRQ 29
- +#define GPU_PA_BASE 0x90A00000
- +#define GPU_VA_BASE 0xFEA00000
- +#define IDE_FTIDE020_VA_BASE 0xF9070000
- +#define IDE_FTIDE020_PA_BASE 0x90700000
- +#define IDE_FTIDE020_IRQ 1
- +#define USB_FOTG2XX_0_PA_BASE 0x90800000
- +#define USB_FOTG2XX_0_VA_BASE 0xF9080000
- +#define USB_FOTG2XX_0_IRQ 26
- +#define DDR2C_PA_BASE 0x90500000
- +#define DDR2C_VA_BASE 0xF9050000
- +#define GPIO_VA_BASE 0xF94C0000
- +#define GPIO_PA_BASE 0x94C00000
- +
- +#define PLATFORM_LPC_IRQ_BASE 180
- +#define PLATFORM_LPC_IRQ_TOTALCOUNT 22
- +
- +/* DMAC */
- +#define DMAC_FTDMAC020_PA_COUNT 1
- +#define DMAC_FTDMAC020_PA_BASE 0x90600000
- +#define DMAC_FTDMAC020_PA_LIMIT 0x90600FFF
- +#define DMAC_FTDMAC020_PA_SIZE 0x00001000
- +#define DMAC_FTDMAC020_0_PA_BASE 0x90600000
- +#define DMAC_FTDMAC020_0_PA_LIMIT 0x90600FFF
- +#define DMAC_FTDMAC020_0_PA_SIZE 0x00001000
- +#define DMAC_FTDMAC020_VA_COUNT 1
- +#define DMAC_FTDMAC020_VA_BASE 0xF9060000
- +#define DMAC_FTDMAC020_VA_LIMIT 0xF9060FFF
- +#define DMAC_FTDMAC020_VA_SIZE 0x00001000
- +#define DMAC_FTDMAC020_0_VA_BASE 0xF9060000
- +#define DMAC_FTDMAC020_0_VA_LIMIT 0xF9060FFF
- +#define DMAC_FTDMAC020_0_VA_SIZE 0x00001000
- +
- +/* TIMER */
- +#define TIMER_FTTMR010_PA_COUNT 1
- +#define TIMER_FTTMR010_PA_BASE 0x94900000
- +#define TIMER_FTTMR010_PA_LIMIT 0x94900FFF
- +#define TIMER_FTTMR010_PA_SIZE 0x00001000
- +#define TIMER_FTTMR010_0_PA_BASE 0x94900000
- +#define TIMER_FTTMR010_0_PA_LIMIT 0x94900FFF
- +#define TIMER_FTTMR010_0_PA_SIZE 0x00001000
- +#define TIMER_FTTMR010_VA_COUNT 1
- +#define TIMER_FTTMR010_VA_BASE 0xF9490000
- +#define TIMER_FTTMR010_VA_LIMIT 0xF9490FFF
- +#define TIMER_FTTMR010_VA_SIZE 0x00001000
- +#define TIMER_FTTMR010_0_VA_BASE 0xF9490000
- +#define TIMER_FTTMR010_0_VA_LIMIT 0xF9490FFF
- +#define TIMER_FTTMR010_0_VA_SIZE 0x00001000
- +
- +/* WDT */
- +#define WDT_FTWDT010_PA_COUNT 1
- +#define WDT_FTWDT010_PA_BASE 0x94A00000
- +#define WDT_FTWDT010_PA_LIMIT 0x94A00FFF
- +#define WDT_FTWDT010_PA_SIZE 0x00001000
- +#define WDT_FTWDT010_0_PA_BASE 0x94A00000
- +#define WDT_FTWDT010_0_PA_LIMIT 0x94A00FFF
- +#define WDT_FTWDT010_0_PA_SIZE 0x00001000
- +#define WDT_FTWDT010_VA_COUNT 1
- +#define WDT_FTWDT010_VA_BASE 0xF94A0000
- +#define WDT_FTWDT010_VA_LIMIT 0xF94A0FFF
- +#define WDT_FTWDT010_VA_SIZE 0x00001000
- +#define WDT_FTWDT010_0_VA_BASE 0xF94A0000
- +#define WDT_FTWDT010_0_VA_LIMIT 0xF94A0FFF
- +#define WDT_FTWDT010_0_VA_SIZE 0x00001000
- +
- +/* RTC */
- +#define RTC_FTRTC010_PA_COUNT 1
- +#define RTC_FTRTC010_PA_BASE 0x94B00000
- +#define RTC_FTRTC010_PA_LIMIT 0x94B00FFF
- +#define RTC_FTRTC010_PA_SIZE 0x00001000
- +#define RTC_FTRTC010_0_PA_BASE 0x94B00000
- +#define RTC_FTRTC010_0_PA_LIMIT 0x94B00FFF
- +#define RTC_FTRTC010_0_PA_SIZE 0x00001000
- +#define RTC_FTRTC010_VA_COUNT 1
- +#define RTC_FTRTC010_VA_BASE 0xF94B0000
- +#define RTC_FTRTC010_VA_LIMIT 0xF94B0FFF
- +#define RTC_FTRTC010_VA_SIZE 0x00001000
- +#define RTC_FTRTC010_0_VA_BASE 0xF94B0000
- +#define RTC_FTRTC010_0_VA_LIMIT 0xF94B0FFF
- +#define RTC_FTRTC010_0_VA_SIZE 0x00001000
- +
- +/* GPIO */
- +#define GPIO_FTGPIO010_PA_COUNT 1
- +#define GPIO_FTGPIO010_PA_BASE 0x94C00000
- +#define GPIO_FTGPIO010_PA_LIMIT 0x94C00FFF
- +#define GPIO_FTGPIO010_PA_SIZE 0x00001000
- +#define GPIO_FTGPIO010_0_PA_BASE 0x94C00000
- +#define GPIO_FTGPIO010_0_PA_LIMIT 0x94C00FFF
- +#define GPIO_FTGPIO010_0_PA_SIZE 0x00001000
- +#define GPIO_FTGPIO010_VA_COUNT 1
- +#define GPIO_FTGPIO010_VA_BASE 0xF94C0000
- +#define GPIO_FTGPIO010_VA_LIMIT 0xF94C0FFF
- +#define GPIO_FTGPIO010_VA_SIZE 0x00001000
- +#define GPIO_FTGPIO010_0_VA_BASE 0xF94C0000
- +#define GPIO_FTGPIO010_0_VA_LIMIT 0xF94C0FFF
- +#define GPIO_FTGPIO010_0_VA_SIZE 0x00001000
- +
- +/* SSP */
- +#define SSP_FTSSP010_PA_BASE 0x94500000
- +#define SSP_FTSSP010_0_PA_BASE 0x94500000
- +#define SSP_FTSSP010_VA_BASE 0xF9450000
- +#define SSP_FTSSP010_0_VA_BASE 0xF9450000
- +
- +/* SPI */
- +#define SPI_FTSSP010_PA_BASE 0x94100000
- +#define SPI_FTSSP010_0_PA_BASE 0x94100000
- +#define SPI_FTSSP010_VA_BASE 0xF9410000
- +#define SPI_FTSSP010_0_VA_BASE 0xF9410000
- +
- +/* AHB Controller */
- +#define AHB_ATFAHBC020S_0_PA_BASE 0x90C00000
- +#define AHB_ATFAHBC020S_0_VA_BASE 0xF90C0000
- +
- +#define I2C_FTI2C010_PA_COUNT 1
- +#define I2C_FTI2C010_PA_BASE 0x94E00000
- +#define I2C_FTI2C010_PA_LIMIT 0x94E00FFF
- +#define I2C_FTI2C010_PA_SIZE 0x00001000
- +#define I2C_FTI2C010_0_PA_BASE 0x94E00000
- +#define I2C_FTI2C010_0_PA_LIMIT 0x94E00FFF
- +#define I2C_FTI2C010_0_PA_SIZE 0x00001000
- +#define I2C_FTI2C010_VA_COUNT 1
- +#define I2C_FTI2C010_VA_BASE 0xF94E0000
- +#define I2C_FTI2C010_VA_LIMIT 0xF94E0FFF
- +#define I2C_FTI2C010_VA_SIZE 0x00001000
- +#define I2C_FTI2C010_0_VA_BASE 0xF94E0000
- +#define I2C_FTI2C010_0_VA_LIMIT 0xF94E0FFF
- +#define I2C_FTI2C010_0_VA_SIZE 0x00001000
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/spec.h linux-3.4.110/arch/nds32/include/asm/spec.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/spec.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/spec.h 2016-04-07 10:20:50.914079941 +0200
- @@ -0,0 +1,510 @@
- +/*
- + * linux/arch/nds32/include/asm/spec.h
- + *
- + * AG101 Platform Independent Specification
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + * ChangeLog
- + *
- + * Luke Lee 09/14/2005 Created.
- + * 09/15/2005 Completed.
- + */
- +
- +#ifndef __FARADAY_PLATFORM_INDEPENDENT_SPECIFICATION__
- +#define __FARADAY_PLATFORM_INDEPENDENT_SPECIFICATION__
- +
- +#include <asm/glue.h>
- +#ifdef CONFIG_PLAT_AG102
- +#include <asm/spec-ag102.h>
- +#else
- +#include <asm/spec-ag101.h>
- +#endif
- +
- +/*
- + * Platform dependent specification
- + */
- +#define PLATFORM_NAME "Andes AG101"
- +
- +/*
- + * Component counts
- + */
- +
- +/* INTC */
- +#define INTC_COUNT 2
- +#define INTC_FTINTC010_COUNT 2
- +/* TIMER */
- +#define TIMER_COUNT 1
- +#define TIMER_FTTMR010_COUNT 1
- +/* SSP */
- +#define SSP_COUNT 1
- +#define SSP_FTSSP010_COUNT 1
- +/* PMU */
- +#define PMU_COUNT 1
- +#define PMU_FTPMU010_COUNT 1
- +/* MAC */
- +#define MAC_COUNT 1
- +#define MAC_FTMAC100_COUNT 1
- +
- +/* SDC */
- +#define SDC_COUNT 1
- +#define SDC_FTSDC010_COUNT 1
- +/* AHBDMA */
- +#define AHBDMA_COUNT 1
- +/* APBDMA */
- +#define APBDMA_COUNT 1
- +/* RTC */
- +#define RTC_COUNT 1
- +#define RTC_FTRTC010_COUNT 1
- +/* WDT */
- +#define WDT_COUNT 1
- +#define WDT_FTWDT010_COUNT 1
- +/* GPIO */
- +#define GPIO_COUNT 1
- +#define GPIO_FTGPIO010_COUNT 1
- +/* CFC */
- +#define CFC_COUNT 1
- +#define CFC_FTCFC010_COUNT 1
- +/* LCD */
- +#define LCD_COUNT 1
- +#define LCD_FTLCDC100_COUNT 1
- +/* I2C */
- +#define I2C_COUNT 1
- +#define I2C_FTI2C010_COUNT 1
- +/* USB */
- +#define USB_COUNT 3
- +#define USB_FOTG2XX_COUNT 1
- +#define USB_FUSBH200_COUNT 1
- +#define USB_FUSB220_COUNT 1
- +/* DMAC */
- +#define DMAC_COUNT 1
- +#define DMAC_FTDMAC020_COUNT 1
- +/* KMI */
- +#define KMI_COUNT 2
- +#define KMI_FTKBC010_COUNT 2
- +/* PCI */
- +#define PCI_COUNT 1
- +/* PCIMEM */
- +#define PCIMEM_COUNT 1
- +/* PCIIO */
- +#define PCIIO_COUNT 1
- +/* PCIC */
- +#define PCIC_COUNT 1
- +#define PCIC_FTPCI100_COUNT 1
- +
- +/*
- + * Hierarchial Component IDs
- + */
- +
- +#define PLATFORM_AHBDMA_DMAC_FTDMAC020_ID 0
- +#define PLATFORM_APBDMA_APBBRG_FTAPBBRG020S_ID 0
- +
- +/*
- + * Number of interrupts
- + */
- +
- +#define PLATFORM_IRQ_TOTALCOUNT 32
- +#define PLATFORM_AHBDMA_IRQ_TOTALCOUNT 8
- +#define PLATFORM_APBDMA_IRQ_TOTALCOUNT 4
- +
- +#define PLATFORM_IRQ_BASE 0
- +#define PLATFORM_AHBDMA_IRQ_BASE 64
- +#define PLATFORM_APBDMA_IRQ_BASE 72
- +#define PLATFORM_PCI_IRQ_BASE 176
- +#define PLATFORM_INTERRUPTS 202
- +
- +/*
- + * IRQ trigger level and trigger mode
- + */
- +
- +#define PLATFORM_IRQ_TRIGGER_MODE 0x000EC880
- +#define PLATFORM_IRQ_TRIGGER_LEVEL 0x10000000
- +#define PLATFORM_AHBDMA_IRQ_TRIGGER_MODE 0x00000000
- +#define PLATFORM_AHBDMA_IRQ_TRIGGER_LEVEL 0xFFFFFFFF
- +#define PLATFORM_APBDMA_IRQ_TRIGGER_MODE 0x00000000
- +#define PLATFORM_APBDMA_IRQ_TRIGGER_LEVEL 0xFFFFFFFF
- +
- +/*
- + * Interrupt numbers of Hierarchical Architecture
- + */
- +
- +/* AHBDMA */
- +#define PLATFORM_AHBDMA_IRQ 21
- +
- +/* APBDMA */
- +#define PLATFORM_APBDMA_IRQ 24
- +
- +/* PCI */
- +#ifdef CONFIG_XC5_PCI
- +#define PLATFORM_PCI_IRQ 10
- +#else
- +#define PLATFORM_PCI_IRQ 28
- +#endif
- +
- +
- +/*
- + * Interrrupt numbers
- + */
- +
- +/* TIMER */
- +#define TIMER_FTTMR010_IRQ_COUNT 3
- +#define TIMER_FTTMR010_IRQ0 19
- +#define TIMER_FTTMR010_0_IRQ0 19
- +#define TIMER_FTTMR010_IRQ1 14
- +#define TIMER_FTTMR010_0_IRQ1 14
- +#define TIMER_FTTMR010_IRQ2 15
- +#define TIMER_FTTMR010_0_IRQ2 15
- +
- +/* SSP */
- +#define SSP_FTSSP010_IRQ_COUNT 1
- +#define SSP_FTSSP010_IRQ 6
- +#define SSP_FTSSP010_0_IRQ 6
- +
- +/* MAC */
- +#define MAC_FTMAC100_IRQ_COUNT 1
- +#define MAC_FTMAC100_IRQ 25
- +#define MAC_FTMAC100_0_IRQ 25
- +#define MAC_FTMAC100_1_IRQ 133
- +
- +/* SDC */
- +#define SDC_FTSDC010_IRQ_COUNT 1
- +#define SDC_FTSDC010_IRQ 5
- +#define SDC_FTSDC010_0_IRQ 5
- +
- +/* RTC */
- +#define RTC_FTRTC010_IRQ_COUNT 2
- +#define RTC_FTRTC010_IRQ0 17
- +#define RTC_FTRTC010_0_IRQ0 17
- +#define RTC_FTRTC010_IRQ1 18
- +#define RTC_FTRTC010_0_IRQ1 18
- +
- +/* WDT */
- +#define WDT_FTWDT010_IRQ_COUNT 1
- +#define WDT_FTWDT010_IRQ 16
- +#define WDT_FTWDT010_0_IRQ 16
- +
- +/* GPIO */
- +#define GPIO_FTGPIO010_IRQ_COUNT 1
- +#define GPIO_FTGPIO010_IRQ 13
- +#define GPIO_FTGPIO010_0_IRQ 13
- +
- +/* CFC */
- +#define CFC_FTCFC010_IRQ_COUNT 2
- +#define CFC_FTCFC010_IRQ0 0
- +#define CFC_FTCFC010_0_IRQ0 0
- +#define CFC_FTCFC010_IRQ1 1
- +#define CFC_FTCFC010_0_IRQ1 1
- +
- +/* LCD */
- +#define LCD_FTLCDC100_IRQ_COUNT 1
- +#define LCD_FTLCDC100_IRQ 20
- +#define LCD_FTLCDC100_0_IRQ 20
- +
- +/* I2C */
- +#define I2C_FTI2C010_IRQ_COUNT 1
- +#define I2C_FTI2C010_IRQ 3
- +#define I2C_FTI2C010_0_IRQ 3
- +
- +/* USB */
- +#define USB_FUSBH200_IRQ_COUNT 1
- +#define USB_FUSBH200_IRQ 29
- +#define USB_FUSBH200_0_IRQ 29
- +#define USB_FUSB220_IRQ_COUNT 1
- +#define USB_FUSB220_IRQ 26
- +#define USB_FUSB220_0_IRQ 26
- +
- +/* DMAC */
- +#define DMAC_FTDMAC020_IRQ_COUNT 8
- +#define DMAC_FTDMAC020_IRQ0 64
- +#define DMAC_FTDMAC020_0_IRQ0 64
- +#define DMAC_FTDMAC020_IRQ1 65
- +#define DMAC_FTDMAC020_0_IRQ1 65
- +#define DMAC_FTDMAC020_IRQ2 66
- +#define DMAC_FTDMAC020_0_IRQ2 66
- +#define DMAC_FTDMAC020_IRQ3 67
- +#define DMAC_FTDMAC020_0_IRQ3 67
- +#define DMAC_FTDMAC020_IRQ4 68
- +#define DMAC_FTDMAC020_0_IRQ4 68
- +#define DMAC_FTDMAC020_IRQ5 69
- +#define DMAC_FTDMAC020_0_IRQ5 69
- +#define DMAC_FTDMAC020_IRQ6 70
- +#define DMAC_FTDMAC020_0_IRQ6 70
- +#define DMAC_FTDMAC020_IRQ7 71
- +#define DMAC_FTDMAC020_0_IRQ7 71
- +
- +/* APBBRG */
- +#define APBBRG_FTAPBBRG020S_IRQ_COUNT 4
- +#define APBBRG_FTAPBBRG020S_IRQ0 72
- +#define APBBRG_FTAPBBRG020S_0_IRQ0 72
- +#define APBBRG_FTAPBBRG020S_IRQ1 73
- +#define APBBRG_FTAPBBRG020S_0_IRQ1 73
- +#define APBBRG_FTAPBBRG020S_IRQ2 74
- +#define APBBRG_FTAPBBRG020S_0_IRQ2 74
- +#define APBBRG_FTAPBBRG020S_IRQ3 75
- +#define APBBRG_FTAPBBRG020S_0_IRQ3 75
- +#define APBBRG_FTAPBBRG020S_1_IRQ0 172
- +#define APBBRG_FTAPBBRG020S_1_IRQ1 173
- +#define APBBRG_FTAPBBRG020S_1_IRQ2 174
- +#define APBBRG_FTAPBBRG020S_1_IRQ3 175
- +
- +/* KMI */
- +#define KMI_FTKBC010_IRQ_COUNT 1
- +#define KMI_FTKBC010_IRQ 30
- +#define KMI_FTKBC010_0_IRQ 30
- +#define KMI_FTKBC010_1_IRQ 31
- +
- +/* PCIC */
- +#define PCIC_FTPCI100_IRQ_COUNT 4
- +#define PCIC_FTPCI100_IRQ0 176
- +#define PCIC_FTPCI100_0_IRQ0 176
- +#define PCIC_FTPCI100_IRQ1 177
- +#define PCIC_FTPCI100_0_IRQ1 177
- +#define PCIC_FTPCI100_IRQ2 178
- +#define PCIC_FTPCI100_0_IRQ2 178
- +#define PCIC_FTPCI100_IRQ3 179
- +#define PCIC_FTPCI100_0_IRQ3 179
- +
- +/*
- + * Base addresses
- + */
- +
- +/* CPU */
- +#define CPU_MEM_PA_BASE CONFIG_MEMORY_START
- +
- +
- +/* INTC */
- +#define INTC_FTINTC010_PA_COUNT 1
- +#define INTC_FTINTC010_PA_BASE 0x98800000
- +#define INTC_FTINTC010_PA_LIMIT 0x98800FFF
- +#define INTC_FTINTC010_PA_SIZE 0x00001000
- +#define INTC_FTINTC010_0_PA_BASE 0x98800000
- +#define INTC_FTINTC010_0_PA_LIMIT 0x98800FFF
- +#define INTC_FTINTC010_0_PA_SIZE 0x00001000
- +#define INTC_FTINTC010_1_PA_BASE 0xB0800000
- +#define INTC_FTINTC010_1_PA_LIMIT 0xB0800FFF
- +#define INTC_FTINTC010_1_PA_SIZE 0x00001000
- +#define INTC_FTINTC010_VA_COUNT 1
- +#define INTC_FTINTC010_VA_BASE 0xF9880000
- +#define INTC_FTINTC010_VA_LIMIT 0xF9880FFF
- +#define INTC_FTINTC010_VA_SIZE 0x00001000
- +#define INTC_FTINTC010_0_VA_BASE 0xF9880000
- +#define INTC_FTINTC010_0_VA_LIMIT 0xF9880FFF
- +#define INTC_FTINTC010_0_VA_SIZE 0x00001000
- +#define INTC_FTINTC010_1_VA_BASE 0xFB080000
- +#define INTC_FTINTC010_1_VA_LIMIT 0xFB080FFF
- +#define INTC_FTINTC010_1_VA_SIZE 0x00001000
- +
- +/* PMU */
- +#define PMU_FTPMU010_PA_COUNT 1
- +#define PMU_FTPMU010_PA_BASE 0x98100000
- +#define PMU_FTPMU010_PA_LIMIT 0x98100FFF
- +#define PMU_FTPMU010_PA_SIZE 0x00001000
- +#define PMU_FTPMU010_0_PA_BASE 0x98100000
- +#define PMU_FTPMU010_0_PA_LIMIT 0x98100FFF
- +#define PMU_FTPMU010_0_PA_SIZE 0x00001000
- +#define PMU_FTPMU010_VA_COUNT 1
- +#define PMU_FTPMU010_VA_BASE 0xF9810000
- +#define PMU_FTPMU010_VA_LIMIT 0xF9810FFF
- +#define PMU_FTPMU010_VA_SIZE 0x00001000
- +#define PMU_FTPMU010_0_VA_BASE 0xF9810000
- +#define PMU_FTPMU010_0_VA_LIMIT 0xF9810FFF
- +#define PMU_FTPMU010_0_VA_SIZE 0x00001000
- +
- +/* USB */
- +#define USB_FUSBH200_PA_COUNT 1
- +#define USB_FUSBH200_PA_BASE 0x92000000
- +#define USB_FUSBH200_PA_LIMIT 0x92000FFF
- +#define USB_FUSBH200_PA_SIZE 0x00001000
- +#define USB_FUSBH200_0_PA_BASE 0x92000000
- +#define USB_FUSBH200_0_PA_LIMIT 0x92000FFF
- +#define USB_FUSBH200_0_PA_SIZE 0x00001000
- +#define USB_FUSBH200_VA_COUNT 1
- +#define USB_FUSBH200_VA_BASE 0xF9200000
- +#define USB_FUSBH200_VA_LIMIT 0xF9200FFF
- +#define USB_FUSBH200_VA_SIZE 0x00001000
- +#define USB_FUSBH200_0_VA_BASE 0xF9200000
- +#define USB_FUSBH200_0_VA_LIMIT 0xF9200FFF
- +#define USB_FUSBH200_0_VA_SIZE 0x00001000
- +#define USB_FUSB220_PA_COUNT 1
- +#define USB_FUSB220_PA_BASE 0x90B00000
- +#define USB_FUSB220_PA_LIMIT 0x90B00FFF
- +#define USB_FUSB220_PA_SIZE 0x00001000
- +#define USB_FUSB220_0_PA_BASE 0x90B00000
- +#define USB_FUSB220_0_PA_LIMIT 0x90B00FFF
- +#define USB_FUSB220_0_PA_SIZE 0x00001000
- +#define USB_FUSB220_VA_COUNT 1
- +#define USB_FUSB220_VA_BASE 0xF90B0000
- +#define USB_FUSB220_VA_LIMIT 0xF90B0FFF
- +#define USB_FUSB220_VA_SIZE 0x00001000
- +#define USB_FUSB220_0_VA_BASE 0xF90B0000
- +#define USB_FUSB220_0_VA_LIMIT 0xF90B0FFF
- +#define USB_FUSB220_0_VA_SIZE 0x00001000
- +
- +/* KMI */
- +#define KMI_FTKBC010_PA_COUNT 1
- +#define KMI_FTKBC010_PA_BASE 0x97200000
- +#define KMI_FTKBC010_PA_LIMIT 0x97200FFF
- +#define KMI_FTKBC010_PA_SIZE 0x00001000
- +#define KMI_FTKBC010_0_PA_BASE 0x97200000
- +#define KMI_FTKBC010_0_PA_LIMIT 0x97200FFF
- +#define KMI_FTKBC010_0_PA_SIZE 0x00001000
- +#define KMI_FTKBC010_1_PA_BASE 0x97300000
- +#define KMI_FTKBC010_1_PA_LIMIT 0x97300FFF
- +#define KMI_FTKBC010_1_PA_SIZE 0x00001000
- +#define KMI_FTKBC010_VA_COUNT 1
- +#define KMI_FTKBC010_VA_BASE 0xF9720000
- +#define KMI_FTKBC010_VA_LIMIT 0xF9720FFF
- +#define KMI_FTKBC010_VA_SIZE 0x00001000
- +#define KMI_FTKBC010_0_VA_BASE 0xF9720000
- +#define KMI_FTKBC010_0_VA_LIMIT 0xF9720FFF
- +#define KMI_FTKBC010_0_VA_SIZE 0x00001000
- +#define KMI_FTKBC010_1_VA_BASE 0xF9730000
- +#define KMI_FTKBC010_1_VA_LIMIT 0xF9730FFF
- +#define KMI_FTKBC010_1_VA_SIZE 0x00001000
- +
- +/* PCIMEM */
- +#define PCIMEM_PA_COUNT 1
- +#define PCIMEM_PA_BASE 0xA0000000
- +#define PCIMEM_PA_LIMIT 0xAFFFFFFF
- +#define PCIMEM_PA_SIZE 0x10000000
- +#define PCIMEM_0_PA_BASE 0xA0000000
- +#define PCIMEM_0_PA_LIMIT 0xAFFFFFFF
- +#define PCIMEM_0_PA_SIZE 0x10000000
- +
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA_MODULE
- +#define CONFIG_PLATFORM_AHBDMA
- +#endif
- +
- +#ifdef CONFIG_PLATFORM_APBDMA_MODULE
- +#define CONFIG_PLATFORM_APBDMA
- +#endif
- +
- +#include <asm/misc_spec.h> /* Manual defined spec */
- +
- +/*
- + * Platform independent specification
- + */
- +
- +#define NR_IRQS PLATFORM_INTERRUPTS
- +
- +#ifndef TIMER_CLK_IN
- +#error Missing platform dependent symbol TIMER_CLK_IN in <asm/arch/platform/misc_spec.h> file.
- +#endif
- +
- +/*
- + * Macros for retrieving IP related information
- + */
- +#define IP_IDENTIFIER __glue(__glue(IPMODULE,_),__glue(IPNAME,_))
- +
- +#define IP_COUNT __glue(IP_IDENTIFIER,COUNT)
- +
- +#define IP_IRQ_COUNT __glue(IP_IDENTIFIER,IRQ_COUNT)
- +#define IP_IRQ(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ)
- +#define IP_irq __glue(IP_IDENTIFIER,irq)
- +
- +#define IP_PA_COUNT __glue(IP_IDENTIFIER,PA_COUNT)
- +#define IP_PA_BASE(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE)
- +#define IP_PA_LIMIT(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT)
- +#define IP_PA_SIZE(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE)
- +#define IP_pa_base __glue(IP_IDENTIFIER,pa_base)
- +#define IP_pa_limit __glue(IP_IDENTIFIER,pa_limit)
- +#define IP_pa_size __glue(IP_IDENTIFIER,pa_size)
- +
- +#define IP_VA_COUNT __glue(IP_IDENTIFIER,VA_COUNT)
- +#define IP_VA_BASE(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE)
- +#define IP_VA_LIMIT(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT)
- +#define IP_VA_SIZE(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE)
- +#define IP_va_base __glue(IP_IDENTIFIER,va_base)
- +#define IP_va_limit __glue(IP_IDENTIFIER,va_limit)
- +#define IP_va_size __glue(IP_IDENTIFIER,va_size)
- +
- +/*
- + * Facility macros
- + */
- +/* IRQ0~7 */
- +#define IP_IRQ0(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ0)
- +#define IP_IRQ1(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ1)
- +#define IP_IRQ2(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ2)
- +#define IP_IRQ3(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ3)
- +#define IP_IRQ4(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ4)
- +#define IP_IRQ5(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ5)
- +#define IP_IRQ6(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ6)
- +#define IP_IRQ7(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ7)
- +
- +/* PA_BASE0~7 */
- +#define IP_PA_BASE0(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE0)
- +#define IP_PA_BASE1(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE1)
- +#define IP_PA_BASE2(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE2)
- +#define IP_PA_BASE3(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE3)
- +#define IP_PA_BASE4(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE4)
- +#define IP_PA_BASE5(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE5)
- +#define IP_PA_BASE6(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE6)
- +#define IP_PA_BASE7(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE7)
- +
- +/* PA_LIMIT0~7 */
- +#define IP_PA_LIMIT0(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT0)
- +#define IP_PA_LIMIT1(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT1)
- +#define IP_PA_LIMIT2(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT2)
- +#define IP_PA_LIMIT3(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT3)
- +#define IP_PA_LIMIT4(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT4)
- +#define IP_PA_LIMIT5(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT5)
- +#define IP_PA_LIMIT6(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT6)
- +#define IP_PA_LIMIT7(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT7)
- +
- +/* PA_SIZE0~7 */
- +#define IP_PA_SIZE0(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE0)
- +#define IP_PA_SIZE1(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE1)
- +#define IP_PA_SIZE2(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE2)
- +#define IP_PA_SIZE3(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE3)
- +#define IP_PA_SIZE4(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE4)
- +#define IP_PA_SIZE5(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE5)
- +#define IP_PA_SIZE6(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE6)
- +#define IP_PA_SIZE7(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE7)
- +
- +/* VA_BASE0~7 */
- +#define IP_VA_BASE0(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE0)
- +#define IP_VA_BASE1(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE1)
- +#define IP_VA_BASE2(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE2)
- +#define IP_VA_BASE3(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE3)
- +#define IP_VA_BASE4(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE4)
- +#define IP_VA_BASE5(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE5)
- +#define IP_VA_BASE6(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE6)
- +#define IP_VA_BASE7(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE7)
- +
- +/* VA_LIMIT0~7 */
- +#define IP_VA_LIMIT0(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT0)
- +#define IP_VA_LIMIT1(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT1)
- +#define IP_VA_LIMIT2(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT2)
- +#define IP_VA_LIMIT3(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT3)
- +#define IP_VA_LIMIT4(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT4)
- +#define IP_VA_LIMIT5(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT5)
- +#define IP_VA_LIMIT6(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT6)
- +#define IP_VA_LIMIT7(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT7)
- +
- +/* VA_SIZE0~7 */
- +#define IP_VA_SIZE0(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE0)
- +#define IP_VA_SIZE1(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE1)
- +#define IP_VA_SIZE2(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE2)
- +#define IP_VA_SIZE3(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE3)
- +#define IP_VA_SIZE4(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE4)
- +#define IP_VA_SIZE5(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE5)
- +#define IP_VA_SIZE6(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE6)
- +#define IP_VA_SIZE7(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE7)
- +
- +#endif /* __FARADAY_PLATFORM_INDEPENDENT_SPECIFICATION__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/spinlock.h linux-3.4.110/arch/nds32/include/asm/spinlock.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/spinlock.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/spinlock.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,183 @@
- +/*
- + * linux/arch/nds32/include/asm/spinlock.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __ASM_SPINLOCK_H
- +#define __ASM_SPINLOCK_H
- +
- +#include <asm/processor.h>
- +
- +#define arch_spin_is_locked(x) ((x)->lock != 0)
- +
- +#define arch_spin_unlock_wait(lock) \
- + do { while (arch_spin_is_locked(lock)) cpu_relax(); } while (0)
- +
- +#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
- +
- +static inline void arch_spin_lock(arch_spinlock_t *lock)
- +{
- + unsigned long tmp;
- +
- + __asm__ __volatile__(
- + "xor\t$r15, $r15, $r15\n"
- + "1:\n"
- + "\tllw\t%0, [%1+$r15]\n"
- + "\tbnez\t%0, 1b\n"
- + "\tmovi\t%0, #0x1\n"
- + "\tscw\t%0, [%1+$r15]\n"
- + "\tbeqz\t%0, 1b\n"
- + : "=&r" (tmp)
- + : "r" (&lock->lock)
- + : "memory");
- +}
- +
- +static inline int arch_spin_trylock(arch_spinlock_t *lock)
- +{
- + unsigned long ret, tmp;
- +
- + __asm__ __volatile__(
- + "xor\t$r15, $r15, $r15\n"
- + "1:\n"
- + "\tllw\t%0, [%2+$r15]\n"
- + "\tmovi\t%1, #0x1\n"
- + "\tscw\t%1, [%2+$r15]\n"
- + "\tbeqz\t%1, 1b\n"
- + : "=&r" (ret), "=&r" (tmp)
- + : "r" (&lock->lock)
- + : "memory");
- +
- + return ret == 0;
- +}
- +
- +static inline void arch_spin_unlock(arch_spinlock_t *lock)
- +{
- + __asm__ __volatile__(
- + "xor\t$r15, $r15, $r15\n"
- + "\tswi\t$r15, [%0]\n"
- + :
- + : "r" (&lock->lock)
- + : "memory");
- +}
- +
- +static inline void arch_write_lock(arch_rwlock_t *rw)
- +{
- + unsigned long tmp;
- +
- + __asm__ __volatile__(
- + "xor\t$r15, $r15, $r15\n"
- + "1:\n"
- + "\tllw\t%0, [%1+$r15]\n"
- + "\tbnez\t%0, 1b\n"
- + "\tsethi\t%0, 0x80000\n"
- + "\tscw\t%0, [%1+$r15]\n"
- + "\tbeqz\t%0, 1b\n"
- + : "=&r" (tmp)
- + : "r" (&rw->lock)
- + : "memory");
- +}
- +
- +static inline void arch_write_unlock(arch_rwlock_t *rw)
- +{
- + __asm__ __volatile__(
- + "xor\t$r15, $r15, $r15\n"
- + "\tswi\t$r15, [%0]\n"
- + :
- + : "r" (&rw->lock)
- + : "memory");
- +}
- +
- +#define arch_write_can_lock(x) ((x)->lock == 0)
- +static inline void arch_read_lock(arch_rwlock_t *rw)
- +{
- + int tmp;
- +
- + __asm__ __volatile__(
- + "xor\t$r15, $r15, $r15\n"
- + "1:\n"
- + "\tllw\t%0, [%1+$r15]\n"
- + "\tbltz\t%0, 1b\n"
- + "\taddi\t%0, %0, #1\n"
- + "\tscw\t%0, [%1+$r15]\n"
- + "\tbeqz\t%0, 1b\n"
- + : "=&r" (tmp)
- + : "r" (&rw->lock)
- + : "memory");
- +}
- +
- +static inline void arch_read_unlock(arch_rwlock_t *rw)
- +{
- + unsigned long tmp;
- +
- + __asm__ __volatile__(
- + "xor\t$r15, $r15, $r15\n"
- + "1:\n"
- + "\tllw\t%0, [%1+$r15]\n"
- + "\taddi\t%0, %0, #-1\n"
- + "\tscw\t%0, [%1+$r15]\n"
- + "\tbeqz\t%0, 1b\n"
- + : "=&r" (tmp)
- + : "r" (&rw->lock)
- + : "memory");
- +}
- +
- +static inline int arch_read_trylock(arch_rwlock_t *rw)
- +{
- + unsigned long ret, tmp;
- +
- + __asm__ __volatile__(
- + "xor\t$r15, $r15, $r15\n"
- + "\tmovi\t%0, #0x0\n"
- + "1:\n"
- + "\tllw\t%1, [%2+$r15]\n"
- + "\tbltz\t%1, 2f\n"
- + "\taddi\t%1, %1, #1\n"
- + "\tscw\t%1, [%2+$r15]\n"
- + "\tbeqz\t%1, 1b\n"
- + "\tmovi\t%0, #0x1\n"
- + "\tj\t3f\n"
- + "2:\n"
- + "\tscw\t%1, [%2+$r15]\n"
- + "3:\n"
- + : "=&r" (ret), "=&r" (tmp)
- + : "r" (&rw->lock)
- + : "memory");
- +
- + return ret;
- +}
- +
- +static inline int arch_write_trylock(arch_rwlock_t *rw)
- +{
- + unsigned long ret, tmp;
- +
- + __asm__ __volatile__(
- + "xor\t$r15, $r15, $r15\n"
- + "\tmovi\t%0, #0x0\n"
- + "1:\n"
- + "\tllw\t%1, [%2+$r15]\n"
- + "\tbnez\t%1, 2f\n"
- + "\tsethi\t%1, 0x80000\n"
- + "\tscw\t%1, [%2+$r15]\n"
- + "\tbeqz\t%1, 1b\n"
- + "\tmovi\t%0, #0x1\n"
- + "\tj\t3f\n"
- + "2:\n"
- + "\tscw\t%1, [%2+$r15]\n"
- + "3:\n"
- + : "=&r" (ret), "=&r" (tmp)
- + : "r" (&rw->lock)
- + : "memory");
- +
- + return ret;
- +}
- +
- +#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
- +#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
- +
- +#define arch_read_can_lock(x) ((x)->lock < 0x80000000)
- +
- +#define arch_spin_relax(lock) cpu_relax()
- +#define arch_read_relax(lock) cpu_relax()
- +#define arch_write_relax(lock) cpu_relax()
- +
- +#endif /* __ASM_SPINLOCK_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/spinlock_types.h linux-3.4.110/arch/nds32/include/asm/spinlock_types.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/spinlock_types.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/spinlock_types.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,25 @@
- +/*
- + * linux/arch/nds32/include/asm/spinlock_types.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASM_SPINLOCK_TYPES_H
- +#define _ASM_SPINLOCK_TYPES_H
- +
- +#ifndef __LINUX_SPINLOCK_TYPES_H
- +# error "please don't include this file directly"
- +#endif
- +
- +typedef struct {
- + volatile unsigned int lock;
- +} arch_spinlock_t;
- +
- +#define __ARCH_SPIN_LOCK_UNLOCKED { 0 }
- +
- +typedef struct {
- + volatile unsigned int lock;
- +} arch_rwlock_t;
- +
- +#define __ARCH_RW_LOCK_UNLOCKED { 0 }
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/statfs.h linux-3.4.110/arch/nds32/include/asm/statfs.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/statfs.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/statfs.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/statfs.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASMNDS32_STATFS_H
- +#define _ASMNDS32_STATFS_H
- +
- +#include <asm-generic/statfs.h>
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/stat.h linux-3.4.110/arch/nds32/include/asm/stat.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/stat.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/stat.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,101 @@
- +/*
- + * linux/arch/nds32/include/asm/stat.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASMNDS32_STAT_H
- +#define _ASMNDS32_STAT_H
- +
- +struct __old_kernel_stat {
- + unsigned short st_dev;
- + unsigned short st_ino;
- + unsigned short st_mode;
- + unsigned short st_nlink;
- + unsigned short st_uid;
- + unsigned short st_gid;
- + unsigned short st_rdev;
- + unsigned long st_size;
- + unsigned long st_atime;
- + unsigned long st_mtime;
- + unsigned long st_ctime;
- +};
- +
- +#define STAT_HAVE_NSEC
- +
- +struct stat {
- +#if defined(__NDS32_EB__)
- + unsigned short st_dev;
- + unsigned short __pad1;
- +#else
- + unsigned long st_dev;
- +#endif
- + unsigned long st_ino;
- + unsigned short st_mode;
- + unsigned short st_nlink;
- + unsigned short st_uid;
- + unsigned short st_gid;
- +#if defined(__NDS32_EB__)
- + unsigned short st_rdev;
- + unsigned short __pad2;
- +#else
- + unsigned long st_rdev;
- +#endif
- + unsigned long st_size;
- + unsigned long st_blksize;
- + unsigned long st_blocks;
- + unsigned long st_atime;
- + unsigned long st_atime_nsec;
- + unsigned long st_mtime;
- + unsigned long st_mtime_nsec;
- + unsigned long st_ctime;
- + unsigned long st_ctime_nsec;
- + unsigned long __unused4;
- + unsigned long __unused5;
- +};
- +
- +/* This matches struct stat64 in glibc2.1, hence the absolutely
- + * insane amounts of padding around dev_t's.
- + * Note: The kernel zero's the padded region because glibc might read them
- + * in the hope that the kernel has stretched to using larger sizes.
- + */
- +
- +struct stat64 {
- + unsigned long long st_dev;
- + unsigned long __pad0;
- +
- +#define STAT64_HAS_BROKEN_ST_INO 1
- + unsigned long __st_ino;
- + unsigned int st_mode;
- + unsigned int st_nlink;
- +
- + unsigned long st_uid;
- + unsigned long st_gid;
- +
- + unsigned long long st_rdev;
- + unsigned int __pad3;
- +
- + unsigned long long st_size;
- + unsigned long st_blksize;
- +
- +//#if defined(__NDS32EB__)
- +// unsigned long __pad4; // Future possible st_blocks hi bits
- + unsigned long long st_blocks; // Number 512-byte blocks allocated.
- +//#else // Must be little
- +// unsigned long st_blocks; // Number 512-byte blocks allocated.
- +// unsigned long __pad4; // Future possible st_blocks hi bits
- +//#endif
- +
- + unsigned long st_atime;
- + unsigned long st_atime_nsec;
- +
- + unsigned long st_mtime;
- + unsigned long st_mtime_nsec;
- +
- + unsigned long st_ctime;
- + unsigned long st_ctime_nsec;
- +
- + unsigned long long st_ino;
- +};
- +
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/string.h linux-3.4.110/arch/nds32/include/asm/string.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/string.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/string.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,45 @@
- +/*
- + * linux/arch/nds32/include/asm/string.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __ASM_NDS32_STRING_H
- +#define __ASM_NDS32_STRING_H
- +
- +/*
- + * We don't do inline string functions, since the
- + * optimised inline asm versions are not small.
- + */
- +
- +#define __HAVE_ARCH_STRRCHR
- +extern char * strrchr(const char * s, int c);
- +
- +#define __HAVE_ARCH_STRCHR
- +extern char * strchr(const char * s, int c);
- +
- +#define __HAVE_ARCH_MEMCPY
- +extern void * memcpy(void *, const void *, __kernel_size_t);
- +
- +#define __HAVE_ARCH_MEMMOVE
- +extern void * memmove(void *, const void *, __kernel_size_t);
- +
- +#define __HAVE_ARCH_MEMZERO
- +#define __HAVE_ARCH_MEMSET
- +extern void * memset(void *, int, __kernel_size_t);
- +
- +extern void __memzero(void *ptr, __kernel_size_t n);
- +
- +#define memset(p,v,n) \
- + ({ \
- + if ((n) != 0) { \
- + if (__builtin_constant_p((v)) && (v) == 0) \
- + __memzero((p),(n)); \
- + else \
- + memset((p),(v),(n)); \
- + } \
- + (p); \
- + })
- +
- +#define memzero(p,n) ({ if ((n) != 0) __memzero((p),(n)); (p); })
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/suspend.h linux-3.4.110/arch/nds32/include/asm/suspend.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/suspend.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/suspend.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,9 @@
- +/*
- + * linux/arch/nds32/include/asm/suspend.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASMNDS32_SUSPEND_H
- +#define _ASMNDS32_SUSPEND_H
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/swab.h linux-3.4.110/arch/nds32/include/asm/swab.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/swab.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/swab.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,34 @@
- +/*
- + * include/asm/byteorder.h
- + * Copyright (C) 2008 Andes Technology, Inc.
- + */
- +
- +#ifndef __NDS32_SWAB_H__
- +#define __NDS32_SWAB_H__
- +
- +#include <linux/types.h>
- +#include <linux/compiler.h>
- +
- +static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
- +{
- + __asm__("wsbh %0, %0\n\t" /* word swap byte within halfword */
- + "rotri %0, %0, #16\n"
- + : "=r" (x) : "0" (x));
- + return x;
- +}
- +
- +static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
- +{
- + __asm__("wsbh %0, %0\n" /* word swap byte within halfword */
- + : "=r" (x) : "0" (x));
- + return x;
- +}
- +#define __arch_swab32(x) ___arch__swab32(x)
- +#define __arch_swab16(x) ___arch__swab16(x)
- +
- +#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
- +# define __BYTEORDER_HAS_U64__
- +# define __SWAB_64_THRU_32__
- +#endif
- +
- +#endif /* __NDS32_SWAB_H__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/switch_to.h linux-3.4.110/arch/nds32/include/asm/switch_to.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/switch_to.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/switch_to.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,18 @@
- +#ifndef __ASM_NDS32_SWITCH_TO_H
- +#define __ASM_NDS32_SWITCH_TO_H
- +
- +#include <linux/thread_info.h>
- +
- +/*
- + * switch_to(prev, next) should switch from task `prev' to `next'
- + * `prev' will never be the same as `next'. schedule() itself
- + * contains the memory barrier to tell GCC not to cache `current'.
- + */
- +extern struct task_struct *__switch_to(struct task_struct *, struct thread_info *, struct thread_info *);
- +
- +#define switch_to( prev, next, last) \
- +do { \
- + last = __switch_to( prev, task_thread_info( prev), task_thread_info( next)); \
- +} while (0)
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/system.h linux-3.4.110/arch/nds32/include/asm/system.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/system.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/system.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,4 @@
- +/* FILE TO BE DELETED. DO NOT ADD STUFF HERE! */
- +#include <asm/barrier.h>
- +#include <asm/switch_to.h>
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/termbits.h linux-3.4.110/arch/nds32/include/asm/termbits.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/termbits.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/termbits.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,198 @@
- +#ifndef __ASM_NDS32_TERMBITS_H
- +#define __ASM_NDS32_TERMBITS_H
- +
- +typedef unsigned char cc_t;
- +typedef unsigned int speed_t;
- +typedef unsigned int tcflag_t;
- +
- +#define NCCS 19
- +struct termios {
- + tcflag_t c_iflag; /* input mode flags */
- + tcflag_t c_oflag; /* output mode flags */
- + tcflag_t c_cflag; /* control mode flags */
- + tcflag_t c_lflag; /* local mode flags */
- + cc_t c_line; /* line discipline */
- + cc_t c_cc[NCCS]; /* control characters */
- +};
- +
- +struct termios2 {
- + tcflag_t c_iflag; /* input mode flags */
- + tcflag_t c_oflag; /* output mode flags */
- + tcflag_t c_cflag; /* control mode flags */
- + tcflag_t c_lflag; /* local mode flags */
- + cc_t c_line; /* line discipline */
- + cc_t c_cc[NCCS]; /* control characters */
- + speed_t c_ispeed; /* input speed */
- + speed_t c_ospeed; /* output speed */
- +};
- +
- +struct ktermios {
- + tcflag_t c_iflag; /* input mode flags */
- + tcflag_t c_oflag; /* output mode flags */
- + tcflag_t c_cflag; /* control mode flags */
- + tcflag_t c_lflag; /* local mode flags */
- + cc_t c_line; /* line discipline */
- + cc_t c_cc[NCCS]; /* control characters */
- + speed_t c_ispeed; /* input speed */
- + speed_t c_ospeed; /* output speed */
- +};
- +
- +
- +/* c_cc characters */
- +#define VINTR 0
- +#define VQUIT 1
- +#define VERASE 2
- +#define VKILL 3
- +#define VEOF 4
- +#define VTIME 5
- +#define VMIN 6
- +#define VSWTC 7
- +#define VSTART 8
- +#define VSTOP 9
- +#define VSUSP 10
- +#define VEOL 11
- +#define VREPRINT 12
- +#define VDISCARD 13
- +#define VWERASE 14
- +#define VLNEXT 15
- +#define VEOL2 16
- +
- +/* c_iflag bits */
- +#define IGNBRK 0000001
- +#define BRKINT 0000002
- +#define IGNPAR 0000004
- +#define PARMRK 0000010
- +#define INPCK 0000020
- +#define ISTRIP 0000040
- +#define INLCR 0000100
- +#define IGNCR 0000200
- +#define ICRNL 0000400
- +#define IUCLC 0001000
- +#define IXON 0002000
- +#define IXANY 0004000
- +#define IXOFF 0010000
- +#define IMAXBEL 0020000
- +#define IUTF8 0040000
- +
- +/* c_oflag bits */
- +#define OPOST 0000001
- +#define OLCUC 0000002
- +#define ONLCR 0000004
- +#define OCRNL 0000010
- +#define ONOCR 0000020
- +#define ONLRET 0000040
- +#define OFILL 0000100
- +#define OFDEL 0000200
- +#define NLDLY 0000400
- +#define NL0 0000000
- +#define NL1 0000400
- +#define CRDLY 0003000
- +#define CR0 0000000
- +#define CR1 0001000
- +#define CR2 0002000
- +#define CR3 0003000
- +#define TABDLY 0014000
- +#define TAB0 0000000
- +#define TAB1 0004000
- +#define TAB2 0010000
- +#define TAB3 0014000
- +#define XTABS 0014000
- +#define BSDLY 0020000
- +#define BS0 0000000
- +#define BS1 0020000
- +#define VTDLY 0040000
- +#define VT0 0000000
- +#define VT1 0040000
- +#define FFDLY 0100000
- +#define FF0 0000000
- +#define FF1 0100000
- +
- +/* c_cflag bit meaning */
- +#define CBAUD 0010017
- +#define B0 0000000 /* hang up */
- +#define B50 0000001
- +#define B75 0000002
- +#define B110 0000003
- +#define B134 0000004
- +#define B150 0000005
- +#define B200 0000006
- +#define B300 0000007
- +#define B600 0000010
- +#define B1200 0000011
- +#define B1800 0000012
- +#define B2400 0000013
- +#define B4800 0000014
- +#define B9600 0000015
- +#define B19200 0000016
- +#define B38400 0000017
- +#define EXTA B19200
- +#define EXTB B38400
- +#define CSIZE 0000060
- +#define CS5 0000000
- +#define CS6 0000020
- +#define CS7 0000040
- +#define CS8 0000060
- +#define CSTOPB 0000100
- +#define CREAD 0000200
- +#define PARENB 0000400
- +#define PARODD 0001000
- +#define HUPCL 0002000
- +#define CLOCAL 0004000
- +#define CBAUDEX 0010000
- +#define BOTHER 0010000
- +#define B57600 0010001
- +#define B115200 0010002
- +#define B230400 0010003
- +#define B460800 0010004
- +#define B500000 0010005
- +#define B576000 0010006
- +#define B921600 0010007
- +#define B1000000 0010010
- +#define B1152000 0010011
- +#define B1500000 0010012
- +#define B2000000 0010013
- +#define B2500000 0010014
- +#define B3000000 0010015
- +#define B3500000 0010016
- +#define B4000000 0010017
- +#define CIBAUD 002003600000 /* input baud rate */
- +#define CMSPAR 010000000000 /* mark or space (stick) parity */
- +#define CRTSCTS 020000000000 /* flow control */
- +
- +#define IBSHIFT 16
- +
- +/* c_lflag bits */
- +#define ISIG 0000001
- +#define ICANON 0000002
- +#define XCASE 0000004
- +#define ECHO 0000010
- +#define ECHOE 0000020
- +#define ECHOK 0000040
- +#define ECHONL 0000100
- +#define NOFLSH 0000200
- +#define TOSTOP 0000400
- +#define ECHOCTL 0001000
- +#define ECHOPRT 0002000
- +#define ECHOKE 0004000
- +#define FLUSHO 0010000
- +#define PENDIN 0040000
- +#define IEXTEN 0100000
- +#define EXTPROC 0200000
- +
- +/* tcflow() and TCXONC use these */
- +#define TCOOFF 0
- +#define TCOON 1
- +#define TCIOFF 2
- +#define TCION 3
- +
- +/* tcflush() and TCFLSH use these */
- +#define TCIFLUSH 0
- +#define TCOFLUSH 1
- +#define TCIOFLUSH 2
- +
- +/* tcsetattr uses these */
- +#define TCSANOW 0
- +#define TCSADRAIN 1
- +#define TCSAFLUSH 2
- +
- +#endif /* __ASM_NDS32_TERMBITS_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/termios.h linux-3.4.110/arch/nds32/include/asm/termios.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/termios.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/termios.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,116 @@
- +/*
- + * linux/arch/nds32/include/asm/termios.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __ASM_NDS32_TERMIOS_H
- +#define __ASM_NDS32_TERMIOS_H
- +
- +#include <asm/termbits.h>
- +#include <asm/ioctls.h>
- +
- +struct winsize {
- + unsigned short ws_row;
- + unsigned short ws_col;
- + unsigned short ws_xpixel;
- + unsigned short ws_ypixel;
- +};
- +
- +#define NCC 8
- +struct termio {
- + unsigned short c_iflag; /* input mode flags */
- + unsigned short c_oflag; /* output mode flags */
- + unsigned short c_cflag; /* control mode flags */
- + unsigned short c_lflag; /* local mode flags */
- + unsigned char c_line; /* line discipline */
- + unsigned char c_cc[NCC]; /* control characters */
- +};
- +
- +#ifdef __KERNEL__
- +/* intr=^C quit=^| erase=del kill=^U
- + eof=^D vtime=\0 vmin=\1 sxtc=\0
- + start=^Q stop=^S susp=^Z eol=\0
- + reprint=^R discard=^U werase=^W lnext=^V
- + eol2=\0
- +*/
- +#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
- +#endif
- +
- +/* modem lines */
- +#define TIOCM_LE 0x001
- +#define TIOCM_DTR 0x002
- +#define TIOCM_RTS 0x004
- +#define TIOCM_ST 0x008
- +#define TIOCM_SR 0x010
- +#define TIOCM_CTS 0x020
- +#define TIOCM_CAR 0x040
- +#define TIOCM_RNG 0x080
- +#define TIOCM_DSR 0x100
- +#define TIOCM_CD TIOCM_CAR
- +#define TIOCM_RI TIOCM_RNG
- +#define TIOCM_OUT1 0x2000
- +#define TIOCM_OUT2 0x4000
- +#define TIOCM_LOOP 0x8000
- +
- +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
- +
- +/* line disciplines */
- +#define N_TTY 0
- +#define N_SLIP 1
- +#define N_MOUSE 2
- +#define N_PPP 3
- +#define N_STRIP 4
- +#define N_AX25 5
- +#define N_X25 6 /* X.25 async */
- +#define N_6PACK 7
- +#define N_MASC 8 /* Reserved for Mobitex module <kaz@cafe.net> */
- +#define N_R3964 9 /* Reserved for Simatic R3964 module */
- +#define N_PROFIBUS_FDL 10 /* Reserved for Profibus <Dave@mvhi.com> */
- +#define N_IRDA 11 /* Linux IrDa - http://irda.sourceforge.net/ */
- +#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */
- +#define N_HDLC 13 /* synchronous HDLC */
- +#define N_SYNC_PPP 14
- +#define N_HCI 15 /* Bluetooth HCI UART */
- +
- +#ifdef __KERNEL__
- +
- +/*
- + * Translate a "termio" structure into a "termios". Ugh.
- + */
- +#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
- + unsigned short __tmp; \
- + get_user(__tmp,&(termio)->x); \
- + *(unsigned short *) &(termios)->x = __tmp; \
- +}
- +
- +#define user_termio_to_kernel_termios(termios, termio) \
- +({ \
- + SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
- + SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
- + SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
- + SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
- + copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
- +})
- +
- +/*
- + * Translate a "termios" structure into a "termio". Ugh.
- + */
- +#define kernel_termios_to_user_termio(termio, termios) \
- +({ \
- + put_user((termios)->c_iflag, &(termio)->c_iflag); \
- + put_user((termios)->c_oflag, &(termio)->c_oflag); \
- + put_user((termios)->c_cflag, &(termio)->c_cflag); \
- + put_user((termios)->c_lflag, &(termio)->c_lflag); \
- + put_user((termios)->c_line, &(termio)->c_line); \
- + copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
- +})
- +
- +#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
- +#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
- +
- +#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
- +#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
- +
- +#endif /* __KERNEL__ */
- +
- +#endif /* __ASM_NDS32_TERMIOS_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/thread_info.h linux-3.4.110/arch/nds32/include/asm/thread_info.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/thread_info.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/thread_info.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,145 @@
- +/*
- + * linux/arch/nds32/include/asm/thread_info.h
- + *
- + * Copyright (C) 2002 Russell King.
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#ifndef __ASM_NDS32_THREAD_INFO_H
- +#define __ASM_NDS32_THREAD_INFO_H
- +
- +#ifdef __KERNEL__
- +
- +#define THREAD_SHIFT (13)
- +#define THREAD_SIZE (1 << THREAD_SHIFT)
- +
- +#ifndef __ASSEMBLY__
- +
- +struct task_struct;
- +struct exec_domain;
- +
- +#include <asm/ptrace.h>
- +#include <asm/types.h>
- +
- +
- +typedef struct {
- + unsigned long seg;
- +} mm_segment_t;
- +//typedef unsigned long mm_segment_t;
- +
- +struct cpu_context_save {
- + unsigned long r6;
- + unsigned long r7;
- + unsigned long r8;
- + unsigned long r9;
- + unsigned long r10;
- + unsigned long r11;
- + unsigned long r12;
- + unsigned long r13;
- + unsigned long r14;
- + unsigned long fp;
- + unsigned long pc;
- +};
- +
- +/*
- + * low level task data that entry.S needs immediate access to.
- + * __switch_to() assumes cpu_context follows immediately after cpu_domain.
- + */
- +struct thread_info {
- + unsigned long flags; /* low level flags */
- + __s32 preempt_count; /* 0 => preemptable, <0 => bug */
- + mm_segment_t addr_limit; /* address limit */
- + struct task_struct *task; /* main task structure */
- + struct exec_domain *exec_domain; /* execution domain */
- + __u32 cpu; /* cpu */
- + struct cpu_context_save* sp_save; /* cpu context */
- + struct restart_block restart_block;
- +};
- +
- +#define INIT_THREAD_INFO(tsk) \
- +{ \
- + .task = &tsk, \
- + .exec_domain = &default_exec_domain, \
- + .flags = 0, \
- + .cpu = 0, \
- + .preempt_count = 1, \
- + .addr_limit = KERNEL_DS, \
- + .restart_block = { \
- + .fn = do_no_restart_syscall, \
- + }, \
- +}
- +
- +#define init_thread_info (init_thread_union.thread_info)
- +#define init_stack (init_thread_union.stack)
- +
- +
- +/*
- + * how to get the thread information struct from C
- + */
- +static inline struct thread_info *current_thread_info(void) __attribute_const__;
- +
- +static inline struct thread_info *current_thread_info(void)
- +{
- + register unsigned long sp asm ("$sp"); //M Tom asm -> __asm__ __volatile__
- + return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
- +}
- +
- +#define get_thread_info(ti) get_task_struct((ti)->task)
- +#define put_thread_info(ti) put_task_struct((ti)->task)
- +
- +#define thread_saved_pc(tsk) \
- + ((unsigned long)(task_thread_info(tsk)->sp_save->pc))
- +#define thread_saved_fp(tsk) \
- + ((unsigned long)(task_thread_info(tsk)->sp_save->fp))
- +#endif
- +
- +#define THREAD_SIZE_ORDER (1)
- +/*
- + * We use bit 30 of the preempt_count to indicate that kernel
- + * preemption is occuring. See include/asm-arm/hardirq.h.
- + */
- +#define PREEMPT_ACTIVE 0x40000000
- +
- +/*
- + * thread information flags:
- + * TIF_SYSCALL_TRACE - syscall trace active
- + * TIF_NOTIFY_RESUME - resumption notification requested
- + * TIF_SIGPENDING - signal pending
- + * TIF_NEED_RESCHED - rescheduling necessary
- + * TIF_USEDFPU - FPU was used by this task this quantum (SMP)
- + * TIF_POLLING_NRFLAG - true if poll_idle() is polling TIF_NEED_RESCHED
- + * TIF_USEDAUDIO - Audio has been used by this task and no need to init the regs
- + */
- +#define TIF_SIGPENDING 1
- +#define TIF_NEED_RESCHED 2
- +#define TIF_SINGLESTEP 3
- +#define TIF_NOTIFY_RESUME 5
- +#define TIF_SYSCALL_TRACE 8
- +#define TIF_RESTORE_SIGMASK 9
- +#define TIF_USEDFPU 16
- +#define TIF_POLLING_NRFLAG 17
- +#define TIF_MEMDIE 18
- +#define TIF_FREEZE 19
- +#define TIF_USEDAUDIO 20
- +
- +#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
- +#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
- +#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
- +#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
- +#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
- +#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
- +#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
- +#define _TIF_FREEZE (1 << TIF_FREEZE)
- +
- +/*
- + * Change these and you break ASM code in entry-common.S
- + */
- +#define _TIF_WORK_MASK 0x000000ff
- +#define _TIF_WORK_SYSCALL_ENTRY (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP)
- +#define _TIF_WORK_SYSCALL_LEAVE (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP)
- +
- +#endif /* __KERNEL__ */
- +#endif /* __ASM_NDS32_THREAD_INFO_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/timer.h linux-3.4.110/arch/nds32/include/asm/timer.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/timer.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/timer.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,94 @@
- +/*
- + * include/arch/nds32/include/asm/timer.h
- + *
- + * Faraday FTTMR010 Timer Device Driver Interface
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * Note
- + *
- + * As IP_COUNT might be greater than one, timer ID is computed as follows:
- + * id=0~2 : Timer 1~3 of the first FTTMR010 IP
- + * id=3~5 : Timer 1~3 of the second FTTMR010 IP
- + * ...
- + * Therefore:
- + * (id / 3) : Compute which IP
- + * (id % 3) : Compute which timer in this IP
- + * Notice:
- + * For simplicity's sake, all code does not check for invalid timer id
- + *
- + * ChangeLog
- + *
- + * Luke Lee 09/14/2005 Created, heavily modified from Faraday CPE platform code.
- + */
- +
- +
- +#ifndef __FARADAY_TIMER_FTTMR010_HEADER__
- +#define __FARADAY_TIMER_FTTMR010_HEADER__
- +
- +/*
- + * Definition of register offsets
- + */
- +
- +#define TIMER1_COUNT 0x0
- +#define TIMER1_LOAD 0x4
- +#define TIMER1_MATCH1 0x8
- +#define TIMER1_MATCH2 0xC
- +
- +#define TIMER2_COUNT 0x10
- +#define TIMER2_LOAD 0x14
- +#define TIMER2_MATCH1 0x18
- +#define TIMER2_MATCH2 0x1C
- +
- +#define TIMER3_COUNT 0x20
- +#define TIMER3_LOAD 0x24
- +#define TIMER3_MATCH1 0x28
- +#define TIMER3_MATCH2 0x2C
- +
- +#define TIMER_TMCR 0x30
- +#define TIMER_INTRSTATE 0x34
- +#define TIMER_INTRMASK 0x38
- +
- +/* Each timer's register address is offset by 0x10 */
- +#define TIMER_OFFSET 0x10
- +
- +/*
- + * Definition of TMCR bits
- + */
- +
- +#define TM1ENABLE 1
- +#define TM1CLOCK (1<<1)
- +#define TM1OFENABLE (1<<2)
- +
- +#define TM2ENABLE (1<<3)
- +#define TM2CLOCK (1<<4)
- +#define TM2OFENABLE (1<<5)
- +
- +#define TM3ENABLE (1<<6)
- +#define TM3CLOCK (1<<7)
- +#define TM3OFENABLE (1<<8)
- +
- +#define TM1UPDOWN (1<<9)
- +#define TM2UPDOWN (1<<10)
- +#define TM3UPDOWN (1<<11)
- +
- +
- +#define TM1MATCH1 (1 << 0)
- +#define TM1MATCH2 (1 << 1)
- +#define TM1OVERFLOW (1 << 2)
- +#define TM2MATCH1 (1 << 3)
- +#define TM2MATCH2 (1 << 4)
- +#define TM2OVERFLOW (1 << 5)
- +#define TM3MATCH1 (1 << 6)
- +#define TM3MATCH2 (1 << 7)
- +#define TM3OVERFLOW (1 << 8)
- +
- +struct sys_timer;
- +extern struct sys_timer platform_timer;
- +
- +#endif // __FARADAY_TIMER_FTTMR010_HEADER__
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/timex.h linux-3.4.110/arch/nds32/include/asm/timex.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/timex.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/timex.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,36 @@
- +/*
- + * linux/arch/nds32/include/asm/timex.h
- + *
- + * Copyright (C) 1997,1998 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * Architecture Specific TIME specifications
- + */
- +#ifndef _ASMNDS32_TIMEX_H
- +#define _ASMNDS32_TIMEX_H
- +
- +#ifndef __FARADAY_PLATFORM_INDEPENDENT_TIMEX_HEADER__
- +#define __FARADAY_PLATFORM_INDEPENDENT_TIMEX_HEADER__
- +
- +#include <asm/spec.h>
- +
- +#ifndef CLOCK_TICK_RATE
- +#define CLOCK_TICK_RATE (TIMER_CLK_IN)
- +#endif
- +
- +#endif /* __FARADAY_PLATFORM_INDEPENDENT_TIMEX_HEADER__ */
- +
- +typedef unsigned long cycles_t;
- +
- +extern cycles_t cacheflush_time;
- +
- +static inline cycles_t get_cycles (void)
- +{
- + return 0;
- +}
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/tlbflush.h linux-3.4.110/arch/nds32/include/asm/tlbflush.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/tlbflush.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/tlbflush.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,80 @@
- +/*
- + * linux/arch/nds32/include/asm/tlbflush.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASMNDS32_TLBFLUSH_H
- +#define _ASMNDS32_TLBFLUSH_H
- +
- +#include <linux/spinlock.h>
- +#include <linux/mm.h>
- +#include <nds32_intrinsic.h>
- +
- +static inline void local_flush_tlb_all(void)
- +{
- + asm("tlbop FLUA\n");
- + __nds32__isb();
- +}
- +static inline void local_flush_tlb_mm(struct mm_struct *mm)
- +{
- + asm("tlbop FLUA\n");
- + __nds32__isb();
- +}
- +static inline void local_flush_tlb_kernel_range(unsigned long start,
- + unsigned long end)
- +{
- + while(start < end) {
- + asm("tlbop %0, INV"::"r" (start));
- + __nds32__isb();
- + start += PAGE_SIZE;
- + }
- +}
- +
- +#ifndef CONFIG_CPU_NO_CONTEXT_ID
- +void local_flush_tlb_range(struct vm_area_struct *vma,
- + unsigned long start, unsigned long end);
- +void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
- +#else
- +static inline void local_flush_tlb_range(struct vm_area_struct *vma,
- + unsigned long start, unsigned long end)
- +{
- + if ((end - start) > 0x400000) {
- + asm("tlbop FLUA");
- + __nds32__isb();
- + return ;
- + }
- + while(start < end) {
- + asm("tlbop %0, INV"::"r" (start));
- + __nds32__isb();
- + start += PAGE_SIZE;
- + }
- +}
- +
- +static inline void local_flush_tlb_page(struct vm_area_struct *vma,
- + unsigned long addr)
- +{
- + asm("tlbop %0, INV"::"r" (addr));
- + __nds32__isb();
- +}
- +#endif
- +
- +#ifndef CONFIG_SMP
- +#define flush_tlb_all local_flush_tlb_all
- +#define flush_tlb_mm local_flush_tlb_mm
- +#define flush_tlb_range local_flush_tlb_range
- +#define flush_tlb_page local_flush_tlb_page
- +#define flush_tlb_kernel_range local_flush_tlb_kernel_range
- +#else
- +void flush_tlb_all(void);
- +void flush_tlb_mm(struct mm_struct *mm);
- +void flush_tlb_range(struct vm_area_struct *vma,
- + unsigned long start, unsigned long end);
- +void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
- +void flush_tlb_kernel_range(unsigned long start, unsigned long end);
- +#endif
- +
- +void update_mmu_cache(struct vm_area_struct *vma,
- + unsigned long address, pte_t* pte);
- +void tlb_migrate_finish(struct mm_struct *mm);
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/tlb.h linux-3.4.110/arch/nds32/include/asm/tlb.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/tlb.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/tlb.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,30 @@
- +/*
- + * linux/arch/nds32/include/asm/tlb.h
- + * Copyright (C) 2009 Andes Technology Corporation
- + */
- +
- +#ifndef __ASMNDS32_TLB_H
- +#define __ASMNDS32_TLB_H
- +
- +#define tlb_start_vma(tlb,vma) \
- + do { \
- + if (!tlb->fullmm) \
- + flush_cache_range(vma, vma->vm_start, vma->vm_end); \
- + } while (0)
- +
- +#define tlb_end_vma(tlb,vma) \
- + do { \
- + if(!tlb->fullmm) \
- + flush_tlb_range(vma, vma->vm_start, vma->vm_end); \
- + } while (0)
- +
- +#define __tlb_remove_tlb_entry(tlb, pte, addr) do { } while (0)
- +
- +#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
- +
- +#include <asm-generic/tlb.h>
- +
- +#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte)
- +#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tln)->mm, pmd)
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/topology.h linux-3.4.110/arch/nds32/include/asm/topology.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/topology.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/topology.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,11 @@
- +/*
- + * linux/arch/nds32/include/asm/topology.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASM_NDS32_TOPOLOGY_H
- +#define _ASM_NDS32_TOPOLOGY_H
- +
- +#include <asm-generic/topology.h>
- +
- +#endif /* _ASM_NDS32_TOPOLOGY_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/traps.h linux-3.4.110/arch/nds32/include/asm/traps.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/traps.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/traps.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,25 @@
- +/*
- + * linux/arch/nds32/include/asm/traps.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASMNDS32_TRAP_H
- +#define _ASMNDS32_TRAP_H
- +
- +#include <linux/list.h>
- +
- +struct undef_hook {
- + struct list_head node;
- + u32 instr_mask;
- + u32 instr_val;
- + u32 cpsr_mask;
- + u32 cpsr_val;
- + int (*fn)(struct pt_regs *regs, unsigned int instr);
- +};
- +
- +void register_undef_hook(struct undef_hook *hook);
- +void unregister_undef_hook(struct undef_hook *hook);
- +
- +extern void __init early_trap_init(void);
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/types.h linux-3.4.110/arch/nds32/include/asm/types.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/types.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/types.h 2016-04-07 10:20:50.918080096 +0200
- @@ -0,0 +1,16 @@
- +#ifndef __ASM_NDS32_TYPES_H
- +#define __ASM_NDS32_TYPES_H
- +
- +#include <asm-generic/int-ll64.h>
- +
- +/*
- + * These aren't exported outside the kernel to avoid name space clashes
- + */
- +#ifdef __KERNEL__
- +
- +#define BITS_PER_LONG 32
- +
- +#endif /* __KERNEL__ */
- +
- +#endif
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/uaccess.h linux-3.4.110/arch/nds32/include/asm/uaccess.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/uaccess.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/uaccess.h 2016-04-07 10:20:50.934080715 +0200
- @@ -0,0 +1,428 @@
- +/*
- + * linux/arch/nds32/include/asm/uaccess.h
- + *
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#ifndef _ASMANDES_UACCESS_H
- +#define _ASMANDES_UACCESS_H
- +
- +/*
- + * User space memory access functions
- + */
- +#include <linux/sched.h>
- +#include <asm/errno.h>
- +#include <asm/memory.h>
- +#include <asm/system.h>
- +#include <asm/types.h>
- +#include <linux/mm.h>
- +
- +#define VERIFY_READ 0
- +#define VERIFY_WRITE 1
- +
- +/*
- + * The exception table consists of pairs of addresses: the first is the
- + * address of an instruction that is allowed to fault, and the second is
- + * the address at which the program should continue. No registers are
- + * modified, so it is entirely up to the continuation code to figure out
- + * what to do.
- + *
- + * All the routines below use bits of fixup code that are out of line
- + * with the main instruction path. This means when everything is well,
- + * we don't even have to jump over them. Further, they do not intrude
- + * on our cache or tlb entries.
- + */
- +
- +struct exception_table_entry
- +{
- + unsigned long insn, fixup;
- +};
- +
- +extern int fixup_exception(struct pt_regs *regs);
- +
- +#define KERNEL_DS ((mm_segment_t) { ~0UL })
- +#define USER_DS ((mm_segment_t) {TASK_SIZE - 1})
- +
- +#define get_ds() (KERNEL_DS)
- +#define get_fs() (current_thread_info()->addr_limit)
- +
- +static inline void set_fs (mm_segment_t fs)
- +{
- + current_thread_info()->addr_limit = fs;
- +}
- +
- +#define segment_eq(a, b) ((a.seg) == (b.seg))
- +
- +#define __range_ok(addr, size) (size <= get_fs().seg && addr <= (get_fs().seg -size))
- +
- +#define access_ok(type, addr, size) \
- + __range_ok((unsigned long)addr, (unsigned long)size)
- +/*
- + * Single-value transfer routines. They automatically use the right
- + * size if we just have the right pointer type. Note that the functions
- + * which read from user space (*get_*) need to take care not to leak
- + * kernel data even if the calling code is buggy and fails to check
- + * the return value. This means zeroing out the destination variable
- + * or buffer on error. Normally this is done out of line by the
- + * fixup code, but there are a few places where it intrudes on the
- + * main code path. When we only write to user space, there is no
- + * problem.
- + *
- + * The "__xxx" versions of the user access functions do not verify the
- + * address space - it must have been done previously with a separate
- + * "access_ok()" call.
- + *
- + * The "xxx_error" versions set the third argument to EFAULT if an
- + * error occurs, and leave it unchanged on success. Note that these
- + * versions are void (ie, don't return a value as such).
- + */
- +
- +extern int __get_user_1(void *);
- +extern int __get_user_2(void *);
- +extern int __get_user_4(void *);
- +extern int __get_user_8(void *);
- +extern int __get_user_bad(void);
- +
- +#define __get_user_x(__r2,__p,__e,__s,__i...) \
- + __asm__ __volatile__ ( \
- + __asmeq("%0", "$r0") __asmeq("%1", "$r2") \
- + "bal __get_user_" #__s \
- + : "=&r" (__e), "=r" (__r2) \
- + : "0" (__p) \
- + : __i, "cc")
- +
- +#define get_user(x,p) \
- + ({ \
- + const register typeof(*(p)) __user *__p asm("$r0") = (p);\
- + register unsigned long __r2 asm("$r2"); \
- + register int __e asm("$r0"); \
- + switch (sizeof(*(__p))) { \
- + case 1: \
- + __get_user_x(__r2, __p, __e, 1, "$lp"); \
- + break; \
- + case 2: \
- + __get_user_x(__r2, __p, __e, 2, "$r3", "$lp"); \
- + break; \
- + case 4: \
- + __get_user_x(__r2, __p, __e, 4, "$lp"); \
- + break; \
- + case 8: \
- + __get_user_x(__r2, __p, __e, 8, "$lp"); \
- + break; \
- + default: __e = __get_user_bad(); break; \
- + } \
- + x = (typeof(*(p))) __r2; \
- + __e; \
- + })
- +
- +#define __get_user(x,ptr) \
- +({ \
- + long __gu_err = 0; \
- + __get_user_err((x),(ptr),__gu_err); \
- + __gu_err; \
- +})
- +
- +#define __get_user_error(x,ptr,err) \
- +({ \
- + __get_user_err((x),(ptr),err); \
- + (void) 0; \
- +})
- +
- +#define __get_user_err(x,ptr,err) \
- +do { \
- + unsigned long __gu_addr = (unsigned long)(ptr); \
- + unsigned long __gu_val; \
- + __chk_user_ptr(ptr); \
- + switch (sizeof(*(ptr))) { \
- + case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \
- + case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \
- + case 4: __get_user_asm_word(__gu_val,__gu_addr,err); break; \
- + default: (__gu_val) = __get_user_bad(); \
- + } \
- + (x) = (__typeof__(*(ptr)))__gu_val; \
- +} while (0)
- +
- +#define __get_user_asm_byte(x,addr,err) \
- + __asm__ __volatile__( \
- + "1: lbi %1,[%2]\n" \
- + "2:\n" \
- + " .section .fixup,\"ax\"\n" \
- + " .align 2\n" \
- + "3: move %0, %3\n" \
- + " move %1, #0\n" \
- + " b 2b\n" \
- + " .previous\n" \
- + " .section __ex_table,\"a\"\n" \
- + " .align 3\n" \
- + " .long 1b, 3b\n" \
- + " .previous" \
- + : "+r" (err), "=&r" (x) \
- + : "r" (addr), "i" (-EFAULT) \
- + : "cc")
- +
- +#ifndef __NDS32_EB__
- +#define __get_user_asm_half(x,__gu_addr,err) \
- +({ \
- + unsigned long __b1, __b2; \
- + __get_user_asm_byte(__b1, __gu_addr, err); \
- + __get_user_asm_byte(__b2, __gu_addr + 1, err); \
- + (x) = __b1 | (__b2 << 8); \
- +})
- +#else
- +#define __get_user_asm_half(x,__gu_addr,err) \
- +({ \
- + unsigned long __b1, __b2; \
- + __get_user_asm_byte(__b1, __gu_addr, err); \
- + __get_user_asm_byte(__b2, __gu_addr + 1, err); \
- + (x) = (__b1 << 8) | __b2; \
- +})
- +#endif
- +
- +#define __get_user_asm_word(x,addr,err) \
- + __asm__ __volatile__( \
- + "1: lwi %1,[%2]\n" \
- + "2:\n" \
- + " .section .fixup,\"ax\"\n" \
- + " .align 2\n" \
- + "3: move %0, %3\n" \
- + " move %1, #0\n" \
- + " b 2b\n" \
- + " .previous\n" \
- + " .section __ex_table,\"a\"\n" \
- + " .align 3\n" \
- + " .long 1b, 3b\n" \
- + " .previous" \
- + : "+r" (err), "=&r" (x) \
- + : "r" (addr), "i" (-EFAULT) \
- + : "cc")
- +
- +extern int __put_user_1(void *, unsigned int);
- +extern int __put_user_2(void *, unsigned int);
- +extern int __put_user_4(void *, unsigned int);
- +extern int __put_user_8(void *, unsigned long long);
- +extern int __put_user_bad(void);
- +
- +#ifdef _GCC444
- +#define __put_user_x(__r2,__p,__e,__s) \
- + __asm__ __volatile__ ( \
- + __asmeq("%0", "$r0") __asmeq("%2", "$r2") \
- + "bal __put_user_" #__s \
- + : "=&r" (__e) \
- + : "0" (__p), "r" (__r2) \
- + : "$p0", "$lp", "cc")
- +#else
- +#define __put_user_x(__r2,__p,__e,__s) \
- + __asm__ __volatile__ ( \
- + __asmeq("%0", "$r0") __asmeq("%2", "$r2") \
- + "bal __put_user_" #__s \
- + : "=&r" (__e) \
- + : "0" (__p), "r" (__r2) \
- + : "$r26", "$lp", "cc")
- +#endif
- +
- +#define put_user(x,p) \
- + ({ \
- + const register typeof(*(p)) __r2 asm("$r2") = (x); \
- + const register typeof(*(p)) __user *__p asm("$r0") = (p);\
- + register int __e asm("$r0"); \
- + switch (sizeof(*(__p))) { \
- + case 1: \
- + __put_user_x(__r2, __p, __e, 1); \
- + break; \
- + case 2: \
- + __put_user_x(__r2, __p, __e, 2); \
- + break; \
- + case 4: \
- + __put_user_x(__r2, __p, __e, 4); \
- + break; \
- + case 8: \
- + __put_user_x(__r2, __p, __e, 8); \
- + break; \
- + default: __e = __put_user_bad(); break; \
- + } \
- + __e; \
- + })
- +
- +#define __put_user(x,ptr) \
- +({ \
- + long __pu_err = 0; \
- + __put_user_err((x),(ptr),__pu_err); \
- + __pu_err; \
- +})
- +
- +#define __put_user_error(x,ptr,err) \
- +({ \
- + __put_user_err((x),(ptr),err); \
- + (void) 0; \
- +})
- +
- +#define __put_user_err(x,ptr,err) \
- +do { \
- + unsigned long __pu_addr = (unsigned long)(ptr); \
- + __typeof__(*(ptr)) __pu_val = (x); \
- + __chk_user_ptr(ptr); \
- + switch (sizeof(*(ptr))) { \
- + case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \
- + case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \
- + case 4: __put_user_asm_word(__pu_val,__pu_addr,err); break; \
- + case 8: __put_user_asm_dword(__pu_val,__pu_addr,err); break; \
- + default: __put_user_bad(); \
- + } \
- +} while (0)
- +
- +#define __put_user_asm_byte(x,__pu_addr,err) \
- + __asm__ __volatile__( \
- + "1: sbi %1,[%2]\n" \
- + "2:\n" \
- + " .section .fixup,\"ax\"\n" \
- + " .align 2\n" \
- + "3: move %0, %3\n" \
- + " b 2b\n" \
- + " .previous\n" \
- + " .section __ex_table,\"a\"\n" \
- + " .align 3\n" \
- + " .long 1b, 3b\n" \
- + " .previous" \
- + : "+r" (err) \
- + : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \
- + : "cc")
- +
- +#ifndef __NDS32_EB__
- +#define __put_user_asm_half(x,__pu_addr,err) \
- +({ \
- + unsigned long __temp = (unsigned long)(x); \
- + __put_user_asm_byte(__temp, __pu_addr, err); \
- + __put_user_asm_byte(__temp >> 8, __pu_addr + 1, err); \
- +})
- +#else
- +#define __put_user_asm_half(x,__pu_addr,err) \
- +({ \
- + unsigned long __temp = (unsigned long)(x); \
- + __put_user_asm_byte(__temp >> 8, __pu_addr, err); \
- + __put_user_asm_byte(__temp, __pu_addr + 1, err); \
- +})
- +#endif
- +
- +#define __put_user_asm_word(x,__pu_addr,err) \
- + __asm__ __volatile__( \
- + "1: swi %1,[%2]\n" \
- + "2:\n" \
- + " .section .fixup,\"ax\"\n" \
- + " .align 2\n" \
- + "3: move %0, %3\n" \
- + " b 2b\n" \
- + " .previous\n" \
- + " .section __ex_table,\"a\"\n" \
- + " .align 3\n" \
- + " .long 1b, 3b\n" \
- + " .previous" \
- + : "+r" (err) \
- + : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \
- + : "cc")
- +
- +#ifdef __NDS32_EB__
- +#define __reg_oper0 "%H2"
- +#define __reg_oper1 "%L2"
- +#else
- +#define __reg_oper0 "%L2"
- +#define __reg_oper1 "%H2"
- +#endif
- +
- +#define __put_user_asm_dword(x, __pu_addr, __pu_err) \
- + __asm__ __volatile__ ( \
- + "\n1:\tswi " __reg_oper0 ",[%1]\n" \
- + "\n2:\tswi " __reg_oper1 ",[%1+4]\n" \
- + "3:\n" \
- + " .section .fixup,\"ax\"\n" \
- + " .align 2\n" \
- + "4: move %0, %3\n" \
- + " b 3b\n" \
- + " .previous\n" \
- + " .section __ex_table,\"a\"\n" \
- + " .align 3\n" \
- + " .long 1b, 4b\n" \
- + " .long 2b, 4b\n" \
- + " .previous" \
- + : "+r"(__pu_err) \
- + : "r"(__pu_addr), "r"(x), "i"(-EFAULT) \
- + : "cc")
- +extern unsigned long __arch_copy_from_user(void *to, const void __user *from, unsigned long n);
- +extern unsigned long __arch_copy_to_user(void __user *to, const void *from, unsigned long n);
- +extern unsigned long __arch_clear_user(void __user *addr, unsigned long n);
- +extern unsigned long __arch_strncpy_from_user(char *to, const char __user *from, unsigned long count);
- +extern unsigned long __arch_strnlen_user(const char __user *s, long n);
- +
- +static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
- +{
- + if (access_ok(VERIFY_READ, from, n))
- + n = __arch_copy_from_user(to, from, n);
- + else /* security hole - plug it */
- + memzero(to, n);
- + return n;
- +}
- +
- +static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n)
- +{
- + return __arch_copy_from_user(to, from, n);
- +}
- +
- +static inline unsigned long copy_to_user(void __user *to, const void *from, unsigned long n)
- +{
- + if (access_ok(VERIFY_WRITE, to, n))
- + n = __arch_copy_to_user(to, from, n);
- + return n;
- +}
- +
- +static inline unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n)
- +{
- + return __arch_copy_to_user(to, from, n);
- +}
- +
- +#define __copy_to_user_inatomic __copy_to_user
- +#define __copy_from_user_inatomic __copy_from_user
- +
- +static inline unsigned long clear_user (void __user *to, unsigned long n)
- +{
- + if (access_ok(VERIFY_WRITE, to, n))
- + n = __arch_clear_user(to, n);
- + return n;
- +}
- +
- +static inline unsigned long __clear_user (void __user *to, unsigned long n)
- +{
- + return __arch_clear_user(to, n);
- +}
- +
- +/*
- + * We check the flags of vma here before __arch_strncpy_from_user().
- + * An alternative way to do it is using lwup instruction in __arch_strncpy_from_user().
- + * TODO: Should perform performance evaluation of the two.
- + */
- +static inline long strncpy_from_user (char *dst, const char __user *src, long count)
- +{
- + long res = -EFAULT;
- + if (access_ok(VERIFY_READ, src, 1))
- + res = __arch_strncpy_from_user(dst, src, count);
- + return res;
- +}
- +
- +static inline long __strncpy_from_user (char *dst, const char __user *src, long count)
- +{
- + return __arch_strncpy_from_user(dst, src, count);
- +}
- +
- +#define strlen_user(s) strnlen_user(s, ~0UL >> 1)
- +
- +static inline long strnlen_user(const char __user *s, long n)
- +{
- + unsigned long res = 0;
- +
- + if (segment_eq(get_fs(),KERNEL_DS) || ((unsigned long)s < get_fs().seg))
- + res = __arch_strnlen_user(s, n);
- +
- + return res;
- +}
- +#endif /* _ASMNDS32_UACCESS_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/ucontext.h linux-3.4.110/arch/nds32/include/asm/ucontext.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/ucontext.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/ucontext.h 2016-04-07 10:20:50.934080715 +0200
- @@ -0,0 +1,17 @@
- +/*
- + * linux/arch/nds32/include/asm/ucontext.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _ASMNDS32_UCONTEXT_H
- +#define _ASMNDS32_UCONTEXT_H
- +
- +struct ucontext {
- + unsigned long uc_flags;
- + struct ucontext *uc_link;
- + stack_t uc_stack;
- + struct sigcontext uc_mcontext;
- + sigset_t uc_sigmask; /* mask last for extensibility */
- +};
- +
- +#endif /* !_ASMNDS32_UCONTEXT_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/unaligned.h linux-3.4.110/arch/nds32/include/asm/unaligned.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/unaligned.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/unaligned.h 2016-04-07 10:20:50.934080715 +0200
- @@ -0,0 +1,24 @@
- +/*
- + * linux/arch/nds32/include/asm/unaligned.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef __ASM_NDS32_UNALIGNED_H
- +#define __ASM_NDS32_UNALIGNED_H
- +
- +#include <linux/unaligned/le_byteshift.h>
- +#include <linux/unaligned/be_byteshift.h>
- +#include <linux/unaligned/generic.h>
- +
- +/*
- + * Select endianness
- + */
- +#if defined(__NDS32_EB__)
- +#define get_unaligned __get_unaligned_be
- +#define put_unaligned __put_unaligned_be
- +#else
- +#define get_unaligned __get_unaligned_le
- +#define put_unaligned __put_unaligned_le
- +#endif
- +
- +#endif /* __ASM_NDS32_UNALIGNED_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/uncompress.h linux-3.4.110/arch/nds32/include/asm/uncompress.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/uncompress.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/uncompress.h 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,65 @@
- +/*
- + * linux/arch/nds32/include/asm/uncompress.h
- + *
- + * Faraday Linux Boot Loader UART (FTUART010) Routines
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + * Note
- + *
- + * The first UART (FTUART010) in the system is used for dumping debug messages.
- + *
- + * ChangeLog
- + *
- + * Luke Lee 09/21/2005 Created. Heavily modified from Faraday CPE port.
- + */
- +
- +#include <asm/spec.h>
- +
- +#ifdef CONFIG_PLAT_AG102
- +#define UART_PA_BASE 0x94200000
- +#else
- +#define UART_PA_BASE 0x99600000
- +#endif
- +
- +#define arch_decomp_setup()
- +#define arch_decomp_wdog()
- +
- +#ifndef STANDALONE_DEBUG
- +#define putstr debug_puts
- +#endif
- +
- +#define SERIAL_THR 0x00
- +#define SERIAL_LSR 0x14
- +#define SERIAL_LSR_THRE 0x20
- +
- +static inline void uncompress_puts(const char *s)
- +{
- + volatile unsigned *status = (volatile unsigned *)(UART_PA_BASE+SERIAL_LSR);
- + while (*s) {
- + while ((*status & SERIAL_LSR_THRE)==0);
- +
- + *(volatile unsigned*)(UART_PA_BASE+SERIAL_THR) = (unsigned)*s;
- +
- + if (*s == '\n') {
- + while ((*status & SERIAL_LSR_THRE)==0);
- + *(volatile unsigned*)(UART_PA_BASE+SERIAL_THR) = '\r';
- + }
- + s++;
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/unistd.h linux-3.4.110/arch/nds32/include/asm/unistd.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/unistd.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/unistd.h 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,468 @@
- +/*
- + * linux/arch/nds32/include/asm/unistd.h
- + *
- + * Copyright (C) 2001-2003 Russell King
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * Please forward _all_ changes to this file to rmk@arm.linux.org.uk,
- + * no matter what the change is. Thanks!
- + */
- +/* ============================================================================
- + *
- + * linux/arch/nds32/include/asm/unistd.h
- + *
- + * Copyright (C) 2007 Andes Technology Corporation
- + * This file is part of Linux and should be licensed under the GPL.
- + * See the file COPYING for conditions for redistribution.
- + *
- + * Abstract:
- + *
- + * This program is syscall scheme for Andes NDS32 architecture.
- + *
- + * Revision History:
- + *
- + * Jul.07.2007 Original from Shawn and Tom, refined by Harry.
- + *
- + * Note:
- + *
- + * ============================================================================
- + */
- +
- +#ifndef __ASM_NDS32_UNISTD_H
- +#define __ASM_NDS32_UNISTD_H
- +
- +#define __NR_SYSCALL_BASE 0x5000
- +#define __NR_NDS32_BASE 0x7000
- +/*
- + * This file contains the system call numbers.
- + */
- +
- +#define __NR_restart_syscall (__NR_SYSCALL_BASE+ 0)
- +#define __NR_exit (__NR_SYSCALL_BASE+ 1)
- +#define __NR_fork (__NR_SYSCALL_BASE+ 2)
- +#define __NR_read (__NR_SYSCALL_BASE+ 3)
- +#define __NR_write (__NR_SYSCALL_BASE+ 4)
- +#define __NR_open (__NR_SYSCALL_BASE+ 5)
- +#define __NR_close (__NR_SYSCALL_BASE+ 6)
- +#define __NR_waitpid (__NR_SYSCALL_BASE+ 7)
- + /* 7 was sys_waitpid */
- +#define __NR_creat (__NR_SYSCALL_BASE+ 8)
- +#define __NR_link (__NR_SYSCALL_BASE+ 9)
- +#define __NR_unlink (__NR_SYSCALL_BASE+ 10)
- +#define __NR_execve (__NR_SYSCALL_BASE+ 11)
- +#define __NR_chdir (__NR_SYSCALL_BASE+ 12)
- +#define __NR_time (__NR_SYSCALL_BASE+ 13)
- +#define __NR_mknod (__NR_SYSCALL_BASE+ 14)
- +#define __NR_chmod (__NR_SYSCALL_BASE+ 15)
- +#define __NR_lchown (__NR_SYSCALL_BASE+ 16)
- + /* 17 was sys_break */
- + /* 18 was sys_oldstat */
- +#define __NR_lseek (__NR_SYSCALL_BASE+ 19)
- +#define __NR_getpid (__NR_SYSCALL_BASE+ 20)
- +#define __NR_mount (__NR_SYSCALL_BASE+ 21)
- +#define __NR_umount (__NR_SYSCALL_BASE+ 22)
- +#define __NR_setuid (__NR_SYSCALL_BASE+ 23)
- +#define __NR_getuid (__NR_SYSCALL_BASE+ 24)
- +#define __NR_stime (__NR_SYSCALL_BASE+ 25)
- +#define __NR_ptrace (__NR_SYSCALL_BASE+ 26)
- +#define __NR_alarm (__NR_SYSCALL_BASE+ 27)
- + /* 28 was sys_oldfstat */
- +#define __NR_pause (__NR_SYSCALL_BASE+ 29)
- +#define __NR_utime (__NR_SYSCALL_BASE+ 30)
- + /* 31 was sys_stty */
- + /* 32 was sys_gtty */
- +#define __NR_access (__NR_SYSCALL_BASE+ 33)
- +#define __NR_nice (__NR_SYSCALL_BASE+ 34)
- + /* 35 was sys_ftime */
- +#define __NR_sync (__NR_SYSCALL_BASE+ 36)
- +#define __NR_kill (__NR_SYSCALL_BASE+ 37)
- +#define __NR_rename (__NR_SYSCALL_BASE+ 38)
- +#define __NR_mkdir (__NR_SYSCALL_BASE+ 39)
- +#define __NR_rmdir (__NR_SYSCALL_BASE+ 40)
- +#define __NR_dup (__NR_SYSCALL_BASE+ 41)
- +#define __NR_pipe (__NR_SYSCALL_BASE+ 42)
- +#define __NR_times (__NR_SYSCALL_BASE+ 43)
- + /* 44 was sys_prof */
- +#define __NR_brk (__NR_SYSCALL_BASE+ 45)
- +#define __NR_setgid (__NR_SYSCALL_BASE+ 46)
- +#define __NR_getgid (__NR_SYSCALL_BASE+ 47)
- + /* 48 was sys_signal */
- +#define __NR_geteuid (__NR_SYSCALL_BASE+ 49)
- +#define __NR_getegid (__NR_SYSCALL_BASE+ 50)
- +#define __NR_acct (__NR_SYSCALL_BASE+ 51)
- +#define __NR_umount2 (__NR_SYSCALL_BASE+ 52)
- + /* 53 was sys_lock */
- +#define __NR_ioctl (__NR_SYSCALL_BASE+ 54)
- +#define __NR_fcntl (__NR_SYSCALL_BASE+ 55)
- + /* 56 was sys_mpx */
- +#define __NR_setpgid (__NR_SYSCALL_BASE+ 57)
- + /* 58 was sys_ulimit */
- + /* 59 was sys_olduname */
- +#define __NR_umask (__NR_SYSCALL_BASE+ 60)
- +#define __NR_chroot (__NR_SYSCALL_BASE+ 61)
- +#define __NR_ustat (__NR_SYSCALL_BASE+ 62)
- +#define __NR_dup2 (__NR_SYSCALL_BASE+ 63)
- +#define __NR_getppid (__NR_SYSCALL_BASE+ 64)
- +#define __NR_getpgrp (__NR_SYSCALL_BASE+ 65)
- +#define __NR_setsid (__NR_SYSCALL_BASE+ 66)
- +#define __NR_sigaction (__NR_SYSCALL_BASE+ 67)
- + /* 68 was sys_sgetmask */
- + /* 69 was sys_ssetmask */
- +#define __NR_setreuid (__NR_SYSCALL_BASE+ 70)
- +#define __NR_setregid (__NR_SYSCALL_BASE+ 71)
- +#define __NR_sigsuspend (__NR_SYSCALL_BASE+ 72)
- +#define __NR_sigpending (__NR_SYSCALL_BASE+ 73)
- +#define __NR_sethostname (__NR_SYSCALL_BASE+ 74)
- +#define __NR_setrlimit (__NR_SYSCALL_BASE+ 75)
- +#define __NR_getrlimit (__NR_SYSCALL_BASE+ 76) /* Back compat 2GB limited rlimit */
- +#define __NR_getrusage (__NR_SYSCALL_BASE+ 77)
- +#define __NR_gettimeofday (__NR_SYSCALL_BASE+ 78)
- +#define __NR_settimeofday (__NR_SYSCALL_BASE+ 79)
- +#define __NR_getgroups (__NR_SYSCALL_BASE+ 80)
- +#define __NR_setgroups (__NR_SYSCALL_BASE+ 81)
- +#define __NR_select (__NR_SYSCALL_BASE+ 82)
- +#define __NR_symlink (__NR_SYSCALL_BASE+ 83)
- + /* 84 was sys_lstat */
- +#define __NR_readlink (__NR_SYSCALL_BASE+ 85)
- +#define __NR_uselib (__NR_SYSCALL_BASE+ 86)
- +#define __NR_swapon (__NR_SYSCALL_BASE+ 87)
- +#define __NR_reboot (__NR_SYSCALL_BASE+ 88)
- +#define __NR_readdir (__NR_SYSCALL_BASE+ 89)
- +#define __NR_mmap (__NR_SYSCALL_BASE+ 90)
- +#define __NR_munmap (__NR_SYSCALL_BASE+ 91)
- +#define __NR_truncate (__NR_SYSCALL_BASE+ 92)
- +#define __NR_ftruncate (__NR_SYSCALL_BASE+ 93)
- +#define __NR_fchmod (__NR_SYSCALL_BASE+ 94)
- +#define __NR_fchown (__NR_SYSCALL_BASE+ 95)
- +#define __NR_getpriority (__NR_SYSCALL_BASE+ 96)
- +#define __NR_setpriority (__NR_SYSCALL_BASE+ 97)
- + /* 98 was sys_profil */
- +#define __NR_statfs (__NR_SYSCALL_BASE+ 99)
- +#define __NR_fstatfs (__NR_SYSCALL_BASE+100)
- + /* 101 was sys_ioperm */
- +#define __NR_socketcall (__NR_SYSCALL_BASE+102)
- +#define __NR_syslog (__NR_SYSCALL_BASE+103)
- +#define __NR_setitimer (__NR_SYSCALL_BASE+104)
- +#define __NR_getitimer (__NR_SYSCALL_BASE+105)
- +#define __NR_stat (__NR_SYSCALL_BASE+106)
- +#define __NR_lstat (__NR_SYSCALL_BASE+107)
- +#define __NR_fstat (__NR_SYSCALL_BASE+108)
- + /* 109 was sys_uname */
- + /* 110 was sys_iopl */
- +#define __NR_vhangup (__NR_SYSCALL_BASE+111)
- + /* 112 was sys_idle */
- +#define __NR_syscall (__NR_SYSCALL_BASE+113) /* syscall to call a syscall! */
- +#define __NR_wait4 (__NR_SYSCALL_BASE+114)
- +#define __NR_swapoff (__NR_SYSCALL_BASE+115)
- +#define __NR_sysinfo (__NR_SYSCALL_BASE+116)
- +#define __NR_ipc (__NR_SYSCALL_BASE+117)
- +#define __NR_fsync (__NR_SYSCALL_BASE+118)
- +#define __NR_sigreturn (__NR_SYSCALL_BASE+119)
- +#define __NR_clone (__NR_SYSCALL_BASE+120)
- +#define __NR_setdomainname (__NR_SYSCALL_BASE+121)
- +#define __NR_uname (__NR_SYSCALL_BASE+122)
- + /* 123 was sys_modify_ldt */
- +#define __NR_adjtimex (__NR_SYSCALL_BASE+124)
- +#define __NR_mprotect (__NR_SYSCALL_BASE+125)
- +#define __NR_sigprocmask (__NR_SYSCALL_BASE+126)
- + /* 127 was sys_create_module */
- +#define __NR_init_module (__NR_SYSCALL_BASE+128)
- +#define __NR_delete_module (__NR_SYSCALL_BASE+129)
- + /* 130 was sys_get_kernel_syms */
- +#define __NR_quotactl (__NR_SYSCALL_BASE+131)
- +#define __NR_getpgid (__NR_SYSCALL_BASE+132)
- +#define __NR_fchdir (__NR_SYSCALL_BASE+133)
- +#define __NR_bdflush (__NR_SYSCALL_BASE+134)
- +#define __NR_sysfs (__NR_SYSCALL_BASE+135)
- +#define __NR_personality (__NR_SYSCALL_BASE+136)
- + /* 137 was sys_afs_syscall */
- +#define __NR_setfsuid (__NR_SYSCALL_BASE+138)
- +#define __NR_setfsgid (__NR_SYSCALL_BASE+139)
- +#define __NR__llseek (__NR_SYSCALL_BASE+140)
- +#define __NR_getdents (__NR_SYSCALL_BASE+141)
- +#define __NR__newselect (__NR_SYSCALL_BASE+142)
- +#define __NR_flock (__NR_SYSCALL_BASE+143)
- +#define __NR_msync (__NR_SYSCALL_BASE+144)
- +#define __NR_readv (__NR_SYSCALL_BASE+145)
- +#define __NR_writev (__NR_SYSCALL_BASE+146)
- +#define __NR_getsid (__NR_SYSCALL_BASE+147)
- +#define __NR_fdatasync (__NR_SYSCALL_BASE+148)
- +#define __NR__sysctl (__NR_SYSCALL_BASE+149)
- +#define __NR_mlock (__NR_SYSCALL_BASE+150)
- +#define __NR_munlock (__NR_SYSCALL_BASE+151)
- +#define __NR_mlockall (__NR_SYSCALL_BASE+152)
- +#define __NR_munlockall (__NR_SYSCALL_BASE+153)
- +#define __NR_sched_setparam (__NR_SYSCALL_BASE+154)
- +#define __NR_sched_getparam (__NR_SYSCALL_BASE+155)
- +#define __NR_sched_setscheduler (__NR_SYSCALL_BASE+156)
- +#define __NR_sched_getscheduler (__NR_SYSCALL_BASE+157)
- +#define __NR_sched_yield (__NR_SYSCALL_BASE+158)
- +#define __NR_sched_get_priority_max (__NR_SYSCALL_BASE+159)
- +#define __NR_sched_get_priority_min (__NR_SYSCALL_BASE+160)
- +#define __NR_sched_rr_get_interval (__NR_SYSCALL_BASE+161)
- +#define __NR_nanosleep (__NR_SYSCALL_BASE+162)
- +#define __NR_mremap (__NR_SYSCALL_BASE+163)
- +#define __NR_setresuid (__NR_SYSCALL_BASE+164)
- +#define __NR_getresuid (__NR_SYSCALL_BASE+165)
- +#define __NR_getpagesize (__NR_SYSCALL_BASE+166)
- + /* 167 was sys_query_module */
- +#define __NR_poll (__NR_SYSCALL_BASE+168)
- +#define __NR_nfsservctl (__NR_SYSCALL_BASE+169)
- +#define __NR_setresgid (__NR_SYSCALL_BASE+170)
- +#define __NR_getresgid (__NR_SYSCALL_BASE+171)
- +#define __NR_prctl (__NR_SYSCALL_BASE+172)
- +#define __NR_rt_sigreturn (__NR_SYSCALL_BASE+173)
- +#define __NR_rt_sigaction (__NR_SYSCALL_BASE+174)
- +#define __NR_rt_sigprocmask (__NR_SYSCALL_BASE+175)
- +#define __NR_rt_sigpending (__NR_SYSCALL_BASE+176)
- +#define __NR_rt_sigtimedwait (__NR_SYSCALL_BASE+177)
- +#define __NR_rt_sigqueueinfo (__NR_SYSCALL_BASE+178)
- +#define __NR_rt_sigsuspend (__NR_SYSCALL_BASE+179)
- +#define __NR_pread64 (__NR_SYSCALL_BASE+180)
- +#define __NR_pwrite64 (__NR_SYSCALL_BASE+181)
- +#define __NR_chown (__NR_SYSCALL_BASE+182)
- +#define __NR_getcwd (__NR_SYSCALL_BASE+183)
- +#define __NR_capget (__NR_SYSCALL_BASE+184)
- +#define __NR_capset (__NR_SYSCALL_BASE+185)
- +#define __NR_sigaltstack (__NR_SYSCALL_BASE+186)
- +#define __NR_sendfile (__NR_SYSCALL_BASE+187)
- + /* 188 reserved */
- + /* 189 reserved */
- +#define __NR_vfork (__NR_SYSCALL_BASE+190)
- +#define __NR_ugetrlimit (__NR_SYSCALL_BASE+191) /* SuS compliant getrlimit */
- +#define __NR_mmap2 (__NR_SYSCALL_BASE+192)
- +#define __NR_truncate64 (__NR_SYSCALL_BASE+193)
- +#define __NR_ftruncate64 (__NR_SYSCALL_BASE+194)
- +#define __NR_stat64 (__NR_SYSCALL_BASE+195)
- +#define __NR_lstat64 (__NR_SYSCALL_BASE+196)
- +#define __NR_fstat64 (__NR_SYSCALL_BASE+197)
- +#define __NR_lchown32 (__NR_SYSCALL_BASE+198)
- +#define __NR_getuid32 (__NR_SYSCALL_BASE+199)
- +#define __NR_getgid32 (__NR_SYSCALL_BASE+200)
- +#define __NR_geteuid32 (__NR_SYSCALL_BASE+201)
- +#define __NR_getegid32 (__NR_SYSCALL_BASE+202)
- +#define __NR_setreuid32 (__NR_SYSCALL_BASE+203)
- +#define __NR_setregid32 (__NR_SYSCALL_BASE+204)
- +#define __NR_getgroups32 (__NR_SYSCALL_BASE+205)
- +#define __NR_setgroups32 (__NR_SYSCALL_BASE+206)
- +#define __NR_fchown32 (__NR_SYSCALL_BASE+207)
- +#define __NR_setresuid32 (__NR_SYSCALL_BASE+208)
- +#define __NR_getresuid32 (__NR_SYSCALL_BASE+209)
- +#define __NR_setresgid32 (__NR_SYSCALL_BASE+210)
- +#define __NR_getresgid32 (__NR_SYSCALL_BASE+211)
- +#define __NR_chown32 (__NR_SYSCALL_BASE+212)
- +#define __NR_setuid32 (__NR_SYSCALL_BASE+213)
- +#define __NR_setgid32 (__NR_SYSCALL_BASE+214)
- +#define __NR_setfsuid32 (__NR_SYSCALL_BASE+215)
- +#define __NR_setfsgid32 (__NR_SYSCALL_BASE+216)
- +#define __NR_getdents64 (__NR_SYSCALL_BASE+217)
- +#define __NR_pivot_root (__NR_SYSCALL_BASE+218)
- +#define __NR_mincore (__NR_SYSCALL_BASE+219)
- +#define __NR_madvise (__NR_SYSCALL_BASE+220)
- +#define __NR_fcntl64 (__NR_SYSCALL_BASE+221)
- + /* 222 for tux */
- + /* 223 is unused */
- +#define __NR_gettid (__NR_SYSCALL_BASE+224)
- +#define __NR_readahead (__NR_SYSCALL_BASE+225)
- +#define __NR_setxattr (__NR_SYSCALL_BASE+226)
- +#define __NR_lsetxattr (__NR_SYSCALL_BASE+227)
- +#define __NR_fsetxattr (__NR_SYSCALL_BASE+228)
- +#define __NR_getxattr (__NR_SYSCALL_BASE+229)
- +#define __NR_lgetxattr (__NR_SYSCALL_BASE+230)
- +#define __NR_fgetxattr (__NR_SYSCALL_BASE+231)
- +#define __NR_listxattr (__NR_SYSCALL_BASE+232)
- +#define __NR_llistxattr (__NR_SYSCALL_BASE+233)
- +#define __NR_flistxattr (__NR_SYSCALL_BASE+234)
- +#define __NR_removexattr (__NR_SYSCALL_BASE+235)
- +#define __NR_lremovexattr (__NR_SYSCALL_BASE+236)
- +#define __NR_fremovexattr (__NR_SYSCALL_BASE+237)
- +#define __NR_tkill (__NR_SYSCALL_BASE+238)
- +#define __NR_sendfile64 (__NR_SYSCALL_BASE+239)
- +#define __NR_futex (__NR_SYSCALL_BASE+240)
- +#define __NR_sched_setaffinity (__NR_SYSCALL_BASE+241)
- +#define __NR_sched_getaffinity (__NR_SYSCALL_BASE+242)
- +#define __NR_io_setup (__NR_SYSCALL_BASE+243)
- +#define __NR_io_destroy (__NR_SYSCALL_BASE+244)
- +#define __NR_io_getevents (__NR_SYSCALL_BASE+245)
- +#define __NR_io_submit (__NR_SYSCALL_BASE+246)
- +#define __NR_io_cancel (__NR_SYSCALL_BASE+247)
- +#define __NR_exit_group (__NR_SYSCALL_BASE+248)
- +#define __NR_lookup_dcookie (__NR_SYSCALL_BASE+249)
- +#define __NR_epoll_create (__NR_SYSCALL_BASE+250)
- +#define __NR_epoll_ctl (__NR_SYSCALL_BASE+251)
- +#define __NR_epoll_wait (__NR_SYSCALL_BASE+252)
- +#define __NR_remap_file_pages (__NR_SYSCALL_BASE+253)
- + /* 254 for set_thread_area */
- + /* 255 for get_thread_area */
- +#define __NR_set_tid_address (__NR_SYSCALL_BASE+256)
- +#define __NR_timer_create (__NR_SYSCALL_BASE+257)
- +#define __NR_timer_settime (__NR_SYSCALL_BASE+258)
- +#define __NR_timer_gettime (__NR_SYSCALL_BASE+259)
- +#define __NR_timer_getoverrun (__NR_SYSCALL_BASE+260)
- +#define __NR_timer_delete (__NR_SYSCALL_BASE+261)
- +#define __NR_clock_settime (__NR_SYSCALL_BASE+262)
- +#define __NR_clock_gettime (__NR_SYSCALL_BASE+263)
- +#define __NR_clock_getres (__NR_SYSCALL_BASE+264)
- +#define __NR_clock_nanosleep (__NR_SYSCALL_BASE+265)
- +#define __NR_statfs64 (__NR_SYSCALL_BASE+266)
- +#define __NR_fstatfs64 (__NR_SYSCALL_BASE+267)
- +#define __NR_tgkill (__NR_SYSCALL_BASE+268)
- +#define __NR_utimes (__NR_SYSCALL_BASE+269)
- +#define __NR_fadvise64_64 (__NR_SYSCALL_BASE+270)
- +#define __NR_pciconfig_iobase (__NR_SYSCALL_BASE+271)
- +#define __NR_pciconfig_read (__NR_SYSCALL_BASE+272)
- +#define __NR_pciconfig_write (__NR_SYSCALL_BASE+273)
- +#define __NR_mq_open (__NR_SYSCALL_BASE+274)
- +#define __NR_mq_unlink (__NR_SYSCALL_BASE+275)
- +#define __NR_mq_timedsend (__NR_SYSCALL_BASE+276)
- +#define __NR_mq_timedreceive (__NR_SYSCALL_BASE+277)
- +#define __NR_mq_notify (__NR_SYSCALL_BASE+278)
- +#define __NR_mq_getsetattr (__NR_SYSCALL_BASE+279)
- +#define __NR_waitid (__NR_SYSCALL_BASE+280)
- +#define __NR_add_key (__NR_SYSCALL_BASE+281)
- +#define __NR_request_key (__NR_SYSCALL_BASE+282)
- +#define __NR_keyctl (__NR_SYSCALL_BASE+283)
- +#define __NR_ioprio_set (__NR_SYSCALL_BASE+284)
- +#define __NR_ioprio_get (__NR_SYSCALL_BASE+285)
- +#define __NR_inotify_init (__NR_SYSCALL_BASE+286)
- +#define __NR_inotify_add_watch (__NR_SYSCALL_BASE+287)
- +#define __NR_inotify_rm_watch (__NR_SYSCALL_BASE+288)
- +#define __NR_migrate_pages (__NR_SYSCALL_BASE+289)
- +#define __NR_openat (__NR_SYSCALL_BASE+290)
- +#define __NR_mkdirat (__NR_SYSCALL_BASE+291)
- +#define __NR_mknodat (__NR_SYSCALL_BASE+292)
- +#define __NR_fchownat (__NR_SYSCALL_BASE+293)
- +#define __NR_futimesat (__NR_SYSCALL_BASE+294)
- +#define __NR_fstatat64 (__NR_SYSCALL_BASE+295)
- +#define __NR_unlinkat (__NR_SYSCALL_BASE+296)
- +#define __NR_renameat (__NR_SYSCALL_BASE+297)
- +#define __NR_linkat (__NR_SYSCALL_BASE+298)
- +#define __NR_symlinkat (__NR_SYSCALL_BASE+299)
- +#define __NR_readlinkat (__NR_SYSCALL_BASE+300)
- +#define __NR_fchmodat (__NR_SYSCALL_BASE+301)
- +#define __NR_faccessat (__NR_SYSCALL_BASE+302)
- +#define __NR_pselect6 (__NR_SYSCALL_BASE+303)
- +#define __NR_ppoll (__NR_SYSCALL_BASE+304)
- +#define __NR_unshare (__NR_SYSCALL_BASE+305)
- +#define __NR_set_robust_list (__NR_SYSCALL_BASE+306)
- +#define __NR_get_robust_list (__NR_SYSCALL_BASE+307)
- +#define __NR_splice (__NR_SYSCALL_BASE+308)
- +#define __NR_sync_file_range2 (__NR_SYSCALL_BASE+309)
- +#define __NR_tee (__NR_SYSCALL_BASE+310)
- +#define __NR_vmsplice (__NR_SYSCALL_BASE+311)
- +#define __NR_move_pages (__NR_SYSCALL_BASE+312)
- +#define __NR_fadvise64 (__NR_SYSCALL_BASE+313)
- +#define __NR_utimensat (__NR_SYSCALL_BASE+314)
- +#define __NR_signalfd (__NR_SYSCALL_BASE+315)
- +#define __NR_timerfd_create (__NR_SYSCALL_BASE+316)
- +#define __NR_eventfd (__NR_SYSCALL_BASE+317)
- +#define __NR_fallocate (__NR_SYSCALL_BASE+318)
- +#define __NR_timerfd_settime (__NR_SYSCALL_BASE+319)
- +#define __NR_timerfd_gettime (__NR_SYSCALL_BASE+320)
- +#define __NR_getcpu (__NR_SYSCALL_BASE+321)
- +#define __NR_signalfd4 (__NR_SYSCALL_BASE+322)
- +#define __NR_eventfd2 (__NR_SYSCALL_BASE+323)
- +#define __NR_epoll_create1 (__NR_SYSCALL_BASE+324)
- +#define __NR_dup3 (__NR_SYSCALL_BASE+325)
- +#define __NR_pipe2 (__NR_SYSCALL_BASE+326)
- +#define __NR_inotify_init1 (__NR_SYSCALL_BASE+327)
- +#define __NR_kexec_load (__NR_SYSCALL_BASE+328)
- +#define __NR_accept (__NR_SYSCALL_BASE+329)
- +#define __NR_bind (__NR_SYSCALL_BASE+330)
- +#define __NR_connect (__NR_SYSCALL_BASE+331)
- +#define __NR_getpeername (__NR_SYSCALL_BASE+332)
- +#define __NR_getsockname (__NR_SYSCALL_BASE+333)
- +#define __NR_getsockopt (__NR_SYSCALL_BASE+334)
- +#define __NR_listen (__NR_SYSCALL_BASE+335)
- +#define __NR_recv (__NR_SYSCALL_BASE+336)
- +#define __NR_recvfrom (__NR_SYSCALL_BASE+337)
- +#define __NR_recvmsg (__NR_SYSCALL_BASE+338)
- +#define __NR_send (__NR_SYSCALL_BASE+339)
- +#define __NR_sendmsg (__NR_SYSCALL_BASE+340)
- +#define __NR_sendto (__NR_SYSCALL_BASE+341)
- +#define __NR_setsockopt (__NR_SYSCALL_BASE+342)
- +#define __NR_shutdown (__NR_SYSCALL_BASE+343)
- +#define __NR_socket (__NR_SYSCALL_BASE+344)
- +#define __NR_socketpair (__NR_SYSCALL_BASE+345)
- +#define __NR_prlimit64 (__NR_SYSCALL_BASE+346)
- +#define __NR_accept4 (__NR_SYSCALL_BASE+347)
- +#define __NR_recvmmsg (__NR_SYSCALL_BASE+348)
- +#define __NR_sendmmsg (__NR_SYSCALL_BASE+349)
- +#define __NR_fanotify_init (__NR_SYSCALL_BASE+350)
- +#define __NR_fanotify_mark (__NR_SYSCALL_BASE+351)
- +#define __NR_msgget (__NR_SYSCALL_BASE+352)
- +#define __NR_msgctl (__NR_SYSCALL_BASE+353)
- +#define __NR_msgrcv (__NR_SYSCALL_BASE+354)
- +#define __NR_msgsnd (__NR_SYSCALL_BASE+355)
- +#define __NR_semget (__NR_SYSCALL_BASE+356)
- +#define __NR_semctl (__NR_SYSCALL_BASE+357)
- +#define __NR_semtimedop (__NR_SYSCALL_BASE+358)
- +#define __NR_semop (__NR_SYSCALL_BASE+359)
- +#define __NR_shmget (__NR_SYSCALL_BASE+360)
- +#define __NR_shmctl (__NR_SYSCALL_BASE+361)
- +#define __NR_shmat (__NR_SYSCALL_BASE+362)
- +#define __NR_shmdt (__NR_SYSCALL_BASE+363)
- +#define __NR_syncfs (__NR_SYSCALL_BASE+364)
- +#define __NR_setns (__NR_SYSCALL_BASE+365)
- +#define __NR_name_to_handle_at (__NR_SYSCALL_BASE+366)
- +#define __NR_open_by_handle_at (__NR_SYSCALL_BASE+367)
- +#define __NR_process_vm_readv (__NR_SYSCALL_BASE+368)
- +#define __NR_process_vm_writev (__NR_SYSCALL_BASE+369)
- +#define __NR_clock_adjtime (__NR_SYSCALL_BASE+370)
- +#define __NR_get_mempolicy (__NR_SYSCALL_BASE+371)
- +#define __NR_mbind (__NR_SYSCALL_BASE+372)
- +#define __NR_perf_event_open (__NR_SYSCALL_BASE+373)
- +#define __NR_preadv (__NR_SYSCALL_BASE+374)
- +#define __NR_pwritev (__NR_SYSCALL_BASE+375)
- +#define __NR_rt_tgsigqueueinfo (__NR_SYSCALL_BASE+376)
- +#define __NR_set_mempolicy (__NR_SYSCALL_BASE+377)
- +#define __NR_epoll_pwait (__NR_SYSCALL_BASE+378)
- +
- +
- +
- +
- +#define __NR_lmmap (__NR_NDS32_BASE+ 1)
- +#define __NR_lmunmap (__NR_NDS32_BASE+ 2)
- +#define __NR_lmdma (__NR_NDS32_BASE+ 3)
- +#define __NR_pfmctl (__NR_NDS32_BASE+ 4)
- +#define __NR_getpfm (__NR_NDS32_BASE+ 5)
- +#define __NR_setpfm (__NR_NDS32_BASE+ 6)
- +#define __NR_wbna (__NR_NDS32_BASE+ 7)
- +
- +
- +
- +#ifdef __KERNEL__
- +
- +#define __ARCH_WANT_IPC_PARSE_VERSION
- +#define __ARCH_WANT_OLD_READDIR
- +#define __ARCH_WANT_STAT64
- +#define __ARCH_WANT_SYS_ALARM
- +#define __ARCH_WANT_SYS_GETHOSTNAME
- +#define __ARCH_WANT_SYS_PAUSE
- +#define __ARCH_WANT_SYS_TIME
- +#define __ARCH_WANT_SYS_UTIME
- +#define __ARCH_WANT_SYS_SOCKETCALL
- +#define __ARCH_WANT_SYS_FADVISE64
- +#define __ARCH_WANT_SYS_GETPGRP
- +#define __ARCH_WANT_SYS_LLSEEK
- +#define __ARCH_WANT_SYS_NICE
- +#define __ARCH_WANT_SYS_OLD_GETRLIMIT
- +#define __ARCH_WANT_SYS_OLD_MMAP
- +#define __ARCH_WANT_SYS_OLDUMOUNT
- +#define __ARCH_WANT_SYS_SIGPENDING
- +#define __ARCH_WANT_SYS_SIGPROCMASK
- +#define __ARCH_WANT_SYS_RT_SIGACTION
- +
- +/*
- + * "Conditional" syscalls
- + *
- + * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- + * but it doesn't work on all toolchains, so we just do it by hand
- + */
- +#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
- +
- +#endif
- +#endif /* __ASM_NDS32_UNISTD_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/user.h linux-3.4.110/arch/nds32/include/asm/user.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/user.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/user.h 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,89 @@
- +/*
- + * linux/arch/nds32/include/asm/user.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef _NDS32_USER_H
- +#define _NDS32_USER_H
- +
- +#include <asm/page.h>
- +#include <asm/ptrace.h>
- +/* Core file format: The core file is written in such a way that gdb
- + can understand it and provide useful information to the user (under
- + linux we use the 'trad-core' bfd). There are quite a number of
- + obstacles to being able to view the contents of the floating point
- + registers, and until these are solved you will not be able to view the
- + contents of them. Actually, you can read in the core file and look at
- + the contents of the user struct to find out what the floating point
- + registers contain.
- + The actual file contents are as follows:
- + UPAGE: 1 page consisting of a user struct that tells gdb what is present
- + in the file. Directly after this is a copy of the task_struct, which
- + is currently not used by gdb, but it may come in useful at some point.
- + All of the registers are stored as part of the upage. The upage should
- + always be only one page.
- + DATA: The data area is stored. We use current->end_text to
- + current->brk to pick up all of the user variables, plus any memory
- + that may have been malloced. No attempt is made to determine if a page
- + is demand-zero or if a page is totally unused, we just cover the entire
- + range. All of the addresses are rounded in such a way that an integral
- + number of pages is written.
- + STACK: We need the stack information in order to get a meaningful
- + backtrace. We need to write the data from (esp) to
- + current->start_stack, so we round each of these off in order to be able
- + to write an integer number of pages.
- + The minimum core file size is 3 pages, or 12288 bytes.
- +*/
- +
- +struct user_fp {
- + struct fp_reg {
- + unsigned int sign1:1;
- + unsigned int unused:15;
- + unsigned int sign2:1;
- + unsigned int exponent:14;
- + unsigned int j:1;
- + unsigned int mantissa1:31;
- + unsigned int mantissa0:32;
- + } fpregs[8];
- + unsigned int fpsr:32;
- + unsigned int fpcr:32;
- + unsigned char ftype[8];
- + unsigned int init_flag;
- +};
- +
- +/* When the kernel dumps core, it starts by dumping the user struct -
- + this will be used by gdb to figure out where the data and stack segments
- + are within the file, and what virtual addresses to use. */
- +struct user{
- +/* We start with the registers, to mimic the way that "memory" is returned
- + from the ptrace(3,...) function. */
- + struct pt_regs regs; /* Where the registers are actually stored */
- +/* ptrace does not yet supply these. Someday.... */
- + int u_fpvalid; /* True if math co-processor being used. */
- + /* for this mess. Not yet used. */
- +/* The rest of this junk is to help gdb figure out what goes where */
- + unsigned long int u_tsize; /* Text segment size (pages). */
- + unsigned long int u_dsize; /* Data segment size (pages). */
- + unsigned long int u_ssize; /* Stack segment size (pages). */
- + unsigned long start_code; /* Starting virtual address of text. */
- + unsigned long start_stack; /* Starting virtual address of stack area.
- + This is actually the bottom of the stack,
- + the top of the stack is always found in the
- + esp register. */
- + long int signal; /* Signal that caused the core dump. */
- + int reserved; /* No longer used */
- + struct pt_regs * u_ar0; /* Used by gdb to help find the values for */
- + /* the registers. */
- + unsigned long magic; /* To uniquely identify a core file */
- + char u_comm[32]; /* User command that was responsible */
- + int u_debugreg[8];
- + struct user_fp u_fp; /* FP state */
- + struct user_fp_struct * u_fp0;/* Used by gdb to help find the values for */
- + /* the FP registers. */
- +};
- +#define NBPG PAGE_SIZE
- +#define UPAGES 1
- +#define HOST_TEXT_START_ADDR (u.start_code)
- +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
- +
- +#endif /* _NDS32_USER_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/vga.h linux-3.4.110/arch/nds32/include/asm/vga.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/vga.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/vga.h 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,17 @@
- +/*
- + * linux/arch/nds32/include/asm/vga.h
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#ifndef ASMNDS32_VGA_H
- +#define ASMNDS32_VGA_H
- +
- +#include <asm/hardware.h>
- +#include <asm/io.h>
- +
- +#define VGA_MAP_MEM(x) (PCIMEM_BASE + (x))
- +
- +#define vga_readb(x) (*((volatile unsigned char *)x))
- +#define vga_writeb(x,y) (*((volatile unsigned char *)y) = (x))
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/vmalloc.h linux-3.4.110/arch/nds32/include/asm/vmalloc.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/vmalloc.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/vmalloc.h 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,31 @@
- +/*
- + * linux/arch/nds32/include/asm/vmalloc.h
- + *
- + * Faraday Platform Independent Virtual Memory Configuration
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + * ChangeLog
- + *
- + * Luke Lee 09/16/2005 Copy from Faraday CPE codes.
- + */
- +
- +#ifndef __FARADAY_PLATFORM_INDEPENDENT_VMALLOC_HEADER__
- +#define __FARADAY_PLATFORM_INDEPENDENT_VMALLOC_HEADER__
- +
- +#endif /* __FARADAY_PLATFORM_INDEPENDENT_VMALLOC_HEADER__ */
- diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/xor.h linux-3.4.110/arch/nds32/include/asm/xor.h
- --- linux-3.4.110.orig/arch/nds32/include/asm/xor.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/include/asm/xor.h 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,157 @@
- +/*
- + * linux/arch/nds32/include/asm/xor.h
- + *
- + * Copyright (C) 2001 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#include <asm-generic/xor.h>
- +
- +#define __XOR(a1, a2) a1 ^= a2
- +
- +
- +#define GET_BLOCK_2(dst) \
- + __asm__( \
- + " lmw.bim %1, [%0], %2 \n"\
- + : "=r" (dst), "=r" (a1), "=r" (a2) \
- + : "0" (dst))
- +
- +#define GET_BLOCK_4(dst) \
- + __asm__( \
- + " lmw.bim %1, [%0], %1 \n" \ //ldmia %0, {%1, %2, %3, %4}
- + " lmw.bim %2, [%0], %2 \n" \
- + " lmw.bim %3, [%0], %3 \n" \
- + " lmw.bim %4, [%0], %4 \n" \
- + : "=r" (dst), "=r" (a1), "=r" (a2), "=r" (a3), "=r" (a4) \
- + : "0" (dst))
- +
- +#define XOR_BLOCK_2(src) \
- + __asm__(\
- + " lmw.bim %1, [%0], %2 \n " \
- + " lmw.bim %2, [%0], %2 \n" \
- + : "=r" (src), "=r" (b1), "=r" (b2) \
- + : "0" (src)); \
- + __XOR(a1, b1); __XOR(a2, b2);
- +
- +
- +#define XOR_BLOCK_4(src) \
- + __asm__(\
- + "lmw.bim %1, [%0], %1 \n " \ // ldmia %0!, {%1, %2, %3, %4}
- + "lmw.bim %2, [%0], %2 \n " \
- + "lmw.bim %3, [%0], %3 \n " \
- + "lmw.bim %4, [%0], %4 \n " \
- + : "=r" (src), "=r" (b1), "=r" (b2), "=r" (b3), "=r" (b4) \
- + : "0" (src)); \
- + __XOR(a1, b1); __XOR(a2, b2); __XOR(a3, b3); __XOR(a4, b4)
- +
- +#define PUT_BLOCK_2(dst) \
- + __asm__ __volatile__( \
- + " smw.bim %2, [%0], %3" \
- + : "=r" (dst) \
- + : "0" (dst), "r" (a1), "r" (a2))
- +
- +#define PUT_BLOCK_4(dst) \
- + __asm__ __volatile__( \
- + " smw.bim %2, [%0], %5 \n" \
- + : "=r" (dst) \
- + : "0" (dst), "r" (a1), "r" (a2), "r" (a3), "r" (a4))
- +
- +static void
- +xor_nds32regs_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
- +{
- + unsigned int lines = bytes / sizeof(unsigned long) / 4;
- + register unsigned int a1 __asm__("r4");
- + register unsigned int a2 __asm__("r5");
- + register unsigned int a3 __asm__("r6");
- + register unsigned int a4 __asm__("r7");
- + register unsigned int b1 __asm__("r8");
- + register unsigned int b2 __asm__("r9");
- + register unsigned int b3 __asm__("p0");
- + register unsigned int b4 __asm__("ra");
- +
- + do {
- + GET_BLOCK_4(p1);
- + XOR_BLOCK_4(p2);
- + PUT_BLOCK_4(p1);
- + } while (--lines);
- +}
- +
- +static void
- +xor_nds32regs_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
- + unsigned long *p3)
- +{
- + unsigned int lines = bytes / sizeof(unsigned long) / 4;
- + register unsigned int a1 __asm__("r4");
- + register unsigned int a2 __asm__("r5");
- + register unsigned int a3 __asm__("r6");
- + register unsigned int a4 __asm__("r7");
- + register unsigned int b1 __asm__("r8");
- + register unsigned int b2 __asm__("r9");
- + register unsigned int b3 __asm__("p0");
- + register unsigned int b4 __asm__("ra");
- +
- + do {
- + GET_BLOCK_4(p1);
- + XOR_BLOCK_4(p2);
- + XOR_BLOCK_4(p3);
- + PUT_BLOCK_4(p1);
- + } while (--lines);
- +}
- +
- +static void
- +xor_nds32regs_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
- + unsigned long *p3, unsigned long *p4)
- +{
- + unsigned int lines = bytes / sizeof(unsigned long) / 2;
- + register unsigned int a1 __asm__("r8");
- + register unsigned int a2 __asm__("r9");
- + register unsigned int b1 __asm__("p0");
- + register unsigned int b2 __asm__("ra");
- +
- + do {
- + GET_BLOCK_2(p1);
- + XOR_BLOCK_2(p2);
- + XOR_BLOCK_2(p3);
- + XOR_BLOCK_2(p4);
- + PUT_BLOCK_2(p1);
- + } while (--lines);
- +}
- +
- +static void
- +xor_nds32regs_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
- + unsigned long *p3, unsigned long *p4, unsigned long *p5)
- +{
- + unsigned int lines = bytes / sizeof(unsigned long) / 2;
- + register unsigned int a1 __asm__("r8");
- + register unsigned int a2 __asm__("r9");
- + register unsigned int b1 __asm__("p0");
- + register unsigned int b2 __asm__("ra");
- +
- + do {
- + GET_BLOCK_2(p1);
- + XOR_BLOCK_2(p2);
- + XOR_BLOCK_2(p3);
- + XOR_BLOCK_2(p4);
- + XOR_BLOCK_2(p5);
- + PUT_BLOCK_2(p1);
- + } while (--lines);
- +}
- +
- +static struct xor_block_template xor_block_nds32regs = {
- + .name = "nds32regs",
- + .do_2 = xor_nds32regs_2,
- + .do_3 = xor_nds32regs_3,
- + .do_4 = xor_nds32regs_4,
- + .do_5 = xor_nds32regs_5,
- +};
- +
- +#undef XOR_TRY_TEMPLATES
- +#define XOR_TRY_TEMPLATES \
- + do { \
- + xor_speed(&xor_block_nds32regs); \
- + xor_speed(&xor_block_8regs); \
- + xor_speed(&xor_block_32regs); \
- + } while (0)
- diff -Nur linux-3.4.110.orig/arch/nds32/Kconfig linux-3.4.110/arch/nds32/Kconfig
- --- linux-3.4.110.orig/arch/nds32/Kconfig 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/Kconfig 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,249 @@
- +#
- +# For a description of the syntax of this configuration file,
- +# see Documentation/kbuild/kconfig-language.txt.
- +#
- +
- +config NDS32
- + bool
- + default y
- + select RTC_LIB
- + select HAVE_OPROFILE
- + select HAVE_ARCH_KGDB
- + select HAVE_KPROBES
- + select HAVE_KRETPROBES
- + select HAVE_FUNCTION_TRACER
- + select HAVE_FUNCTION_GRAPH_TRACER
- + select HAVE_FUNCTION_TRACE_MCOUNT_TEST
- + select SYS_SUPPORTS_APM_EMULATION
- + select HAVE_IDE
- + select HAVE_MEMBLOCK
- + select HAVE_MEMBLOCK_NODE_MAP
- +
- +config GENERIC_GPIO
- + bool
- + default n
- +
- +config GENERIC_TIME
- + bool
- + default y
- +
- +config GENERIC_CLOCKEVENTS
- + bool
- + default y
- +
- +config NO_IOPORT
- + bool
- + default y
- +
- +config GENERIC_IOMAP
- + def_bool y
- +
- +config GENERIC_LOCKBREAK
- + bool
- + default y
- + depends on SMP && PREEMPT
- +
- +config RWSEM_GENERIC_SPINLOCK
- + bool
- + default y
- +
- +config RWSEM_XCHGADD_ALGORITHM
- + bool
- +
- +config GENERIC_HWEIGHT
- + bool
- + default y
- +
- +config GENERIC_FIND_NEXT_BIT
- + bool
- + default y
- +
- +config GENERIC_CALIBRATE_DELAY
- + bool
- + default y
- +
- +config GENERIC_BUST_SPINLOCK
- + bool
- +
- +config GENERIC_HARDIRQS
- + bool
- + default y
- +
- +config GENERIC_HARDIRQS_NO__DO_IRQ
- + def_bool y
- +
- +config LOCKDEP_SUPPORT
- + bool
- + default y
- +
- +config STACKTRACE_SUPPORT
- + bool
- + default y
- +
- +config HAVE_LATENCYTOP_SUPPORT
- + def_bool y
- +
- +source "init/Kconfig"
- +source "kernel/Kconfig.freezer"
- +
- +menu "System Type"
- +source "arch/nds32/platforms/Kconfig"
- +source "arch/nds32/Kconfig.cpu"
- +
- +config VECTORS_BASE
- + hex
- + default 0xfeff0000 if MMU || CPU_HIGH_VECTOR
- + default DRAM_BASE if REMAP_VECTORS_TO_RAM
- + default 0x00000000
- + help
- + The base address of exception vectors.
- +
- +config MMU
- + bool
- + default y
- +
- +endmenu
- +
- +menu "Kernel Features"
- +source "kernel/time/Kconfig"
- +
- +config SMP
- + bool "Symmetric Multi-Processing"
- + depends on PLATFORM_AMIC
- + select USE_GENERIC_SMP_HELPERS
- + help
- + This enables support for systems with more than one CPU. If you have
- + a system with only one CPU, like most personal computers, say N. If
- + you have a system with more than one CPU, say Y.
- +
- + If you say N here, the kernel will run on single and multiprocessor
- + machines, but will use only one CPU of a multiprocessor machine. If
- + you say Y here, the kernel will run on many, but not all, single
- + processor machines. On a single processor machine, the kernel will
- + run faster if you say N here.
- +
- + See also the <file:Documentation/smp.tex>,
- + <file:Documentation/smp.txt>, <file:Documentation/i386/IO-APIC.txt>,
- + <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
- + <http://www.linuxdoc.org/docs.html#howto>.
- +
- + If you don't know what to do here, say N.
- +
- +config NR_CPUS
- + int "Maximum number of CPUs (2-32)"
- + depends on SMP
- + default "4"
- +
- +source "kernel/Kconfig.preempt"
- +source "mm/Kconfig"
- +
- +config FORCE_MAX_ZONEORDER
- + int "MAX_ORDER for the Page Allocator"
- + default "11"
- +
- +source "kernel/Kconfig.hz"
- +
- +config CMDLINE
- + string "Default kernel command string"
- + default "mem=64M@0x0 initrd=0x800000,8M root=/dev/ram0 rw console=ttyS0,38400n8 rootfstype=ext2 init=/sbin/init -s"
- +
- +endmenu
- +
- +menu "Power management options"
- +
- +config SYS_SUPPORTS_APM_EMULATION
- + bool
- +
- +config ARCH_SUSPEND_POSSIBLE
- + def_bool y
- +
- +source "kernel/power/Kconfig"
- +
- +if PLAT_AG101 || PLAT_AG102
- +source "drivers/cpufreq/Kconfig"
- +
- +if PLAT_AG101
- +choice
- + prompt "Default CPUFreq Implementation"
- + depends on CPU_FREQ
- + default AG101_CPU_FREQ_SCALING_MODE
- + help
- + This option sets which CPUFreq governor shall be loaded at
- + startup. If in doubt, select 'performance'.
- +config AG101_CPU_FREQ_SCALING_MODE
- + bool "AG101 Frequency Scaling Mode"
- + help
- + Rescale CPU frequency and Bus clock without changing PLL.
- +
- +config AG101_CPU_FREQ_FCS
- + bool "AG101 Frequency Change Sequence (FCS)"
- + help
- + The Frequency Change Sequence (FCS) is used to change the system
- + clock frequency. While in the FCS, the system clocks stop. This
- + mode is intended for setting a different frequency to overwrite
- + the default value at initial boot-up. This can be used as a powr-
- + saving feature that allows the AG101 to run at the minimum required
- + frequency
- +endchoice
- +endif
- +
- +if PLAT_AG102
- +choice
- + prompt "Default CPUFreq Implementation"
- + depends on CPU_FREQ
- + default AG102_CPU_FREQ_SCALING_MODE
- + help
- + This option sets which CPUFreq governor shall be loaded at
- + startup. If in doubt, select 'performance'.
- +config AG102_CPU_FREQ_SCALING_MODE
- + bool "AG102 Frequency Scaling Mode"
- + help
- + Rescale CPU frequency and Bus clock without changing PLL.
- +
- +config AG102_CPU_FREQ_FCS
- + bool "AG102 Frequency Change Sequence (FCS)"
- + help
- + The Frequency Change Sequence (FCS) is used to change the system
- + clock frequency. While in the FCS, the system clocks stop. This
- + mode is intended for setting a different frequency to overwrite
- + the default value at initial boot-up. This can be used as a powr-
- + saving feature that allows the AG101 to run at the minimum required
- + frequency
- +endchoice
- +endif
- +
- +
- +endif
- +
- +endmenu
- +
- +menu "Bus options"
- +
- +config PCI
- + bool "PCI support"
- + help
- + Find out whether you have a PCI motherboard. PCI is the name of a
- + bus system, i.e. the way the CPU talks to the other stuff inside
- + your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
- + VESA. If you have PCI, say Y, otherwise N.
- +
- + The PCI-HOWTO, available from
- + <http://www.tldp.org/docs.html#howto>, contains valuable
- + information about which PCI hardware does work under Linux and which
- + doesn't.
- +
- +source "drivers/pci/Kconfig"
- +
- +endmenu
- +
- +menu "Executable file formats"
- +source "fs/Kconfig.binfmt"
- +endmenu
- +
- +source "net/Kconfig"
- +source "drivers/Kconfig"
- +source "fs/Kconfig"
- +source "arch/nds32/Kconfig.debug"
- +source "security/Kconfig"
- +source "crypto/Kconfig"
- +source "lib/Kconfig"
- diff -Nur linux-3.4.110.orig/arch/nds32/Kconfig.cpu linux-3.4.110/arch/nds32/Kconfig.cpu
- --- linux-3.4.110.orig/arch/nds32/Kconfig.cpu 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/Kconfig.cpu 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,148 @@
- +comment "Processor Features"
- +config CPU_N1213
- + bool
- +
- +config CPU_N1213_43U1HA0
- + bool
- +
- +config CPU_N1233F
- + bool
- +
- +config CPU_CUSTOM
- + bool
- +
- +config FPU
- + bool "fpu support"
- +
- +config UNLAZY_FPU
- + bool "Unlazy FPU support"
- + depends on FPU
- + help
- + Say Y here to enable unlazy FPU and disable lazy FPU.
- +
- +
- +config AUDIO
- + bool "audio support" if CPU_CUSTOM
- +
- +config HWZOL
- + bool "hardware zero overhead loop support"
- + default y
- +
- +config UNLAZY_AUDIO
- + bool "Unlazy audio support"
- + depends on AUDIO
- + help
- + Say Y here to enable unlazy audio and disable lazy audio.
- +choice
- + prompt "Vector Interrupt Controller mode"
- + default IVIC_INTC
- +config IVIC_INTC
- + bool "IVIC mode with Interrupt Controller"
- +config IVIC
- + bool "IVIC mode"
- +config EVIC
- + bool "EVIC mode"
- +endchoice
- +
- +config CPU_NO_CONTEXT_ID
- + def_bool CPU_N1213_43U1HA0 || SMP
- +
- +config CPU_CACHE_NONALIASING
- + bool "Non-aliasing cache"
- +
- +choice
- + prompt "Paging -- page size "
- + default ANDES_PAGE_SIZE_4KB
- +config ANDES_PAGE_SIZE_4KB
- + bool "use 4KB page size"
- +config ANDES_PAGE_SIZE_8KB
- + bool "use 8KB page size"
- +endchoice
- +
- +config NO_KERNEL_LARGE_PAGE
- + def_bool CPU_N1213_43U1HA0 || SMP
- +
- +config CPU_ICACHE_DISABLE
- + bool "Disable I-Cache"
- + help
- + Say Y here to disable the processor instruction cache. Unless
- + you have a reason not to or are unsure, say N.
- +
- +config CPU_DCACHE_DISABLE
- + bool "Disable D-Cache"
- + help
- + Say Y here to disable the processor data cache. Unless
- + you have a reason not to or are unsure, say N.
- +
- +config CPU_DCACHE_WRITETHROUGH
- + bool "Force write through D-cache"
- + depends on !CPU_DCACHE_DISABLE
- + help
- + Say Y here to use the data cache in writethrough mode. Unless you
- + specifically require this or are unsure, say N.
- +
- +config KEXEC
- + bool "Kexec system call (EXPERIMENTAL)"
- + depends on EXPERIMENTAL
- + help
- + kexec is a system call that implements the ability to shutdown your
- + current kernel, and to start another kernel. It is like a reboot
- + but it is independent of the system firmware. And like a reboot
- + you can start any kernel with it, not just Linux.
- +
- + It is an ongoing process to be certain the hardware in a machine
- + is properly shutdown, so do not be surprised if this code does not
- + initially work for you. It may help to enable device hotplugging
- + support.
- +
- +config ABI1
- + bool "Allow ABI 1 binaries to run with this kernel (EXPERIMENTAL)"
- + depends on EXPERIMENTAL
- + default n
- + help
- + This option preserves the old syscall interface of ABI 1. If
- + you know you'll be using ABI 2 or 2fp then you can say N here.
- + If this option is not selected and you attempt to execute a
- + legacy ABI binary then the result will be UNPREDICTABLE
- + (in fact it can be predicted that it won't work at all). If
- + in doubt say Y.
- +
- +config WBNA
- + bool "WBNA"
- + default n
- + help
- + Say Y here to enable write-back memory with no-write-allocation policy.
- +
- +config HSS
- + bool "Using Hardware Single-Step (HSS) instead of software breakpoint"
- + default y
- +
- +config ALIGNMENT_TRAP
- + tristate "Kernel support unaligned access handling"
- + depends on EXPERIMENTAL
- + default y
- + help
- + Andes processors cannot fetch/store information which is not
- + naturally aligned on the bus, i.e., a 4 byte fetch must start at an
- + address divisible by 4. On 32-bit Andes processors, these non-aligned
- + fetch/store instructions will be emulated in software if you say
- + here, which has a severe performance impact. This is necessary for
- + correct operation of some network protocols. With an IP-only
- + configuration it is safe to say N, otherwise say Y.
- +
- +config HIGHMEM
- + bool "High Memory Support"
- + depends on MMU
- + help
- + The address space of ARM processors is only 4 Gigabytes large
- + and it has to accommodate user address space, kernel address
- + space as well as some memory mapped IO. That means that, if you
- + have a large amount of physical memory and/or IO, not all of the
- + memory can be "permanently mapped" by the kernel. The physical
- + memory that is not permanently mapped is called "high memory".
- +
- + Depending on the selected kernel/user memory split, minimum
- + vmalloc space and actual amount of RAM, you may not need this
- + option which should result in a slightly faster kernel.
- +
- + If unsure, say n.
- diff -Nur linux-3.4.110.orig/arch/nds32/Kconfig.debug linux-3.4.110/arch/nds32/Kconfig.debug
- --- linux-3.4.110.orig/arch/nds32/Kconfig.debug 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/Kconfig.debug 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,82 @@
- +menu "Kernel hacking"
- +
- +config TRACE_IRQFLAGS_SUPPORT
- + bool
- + default y
- +
- +source "lib/Kconfig.debug"
- +
- +config FRAME_POINTER
- + bool
- + default y
- + help
- + If you say N here, the resulting kernel will be slightly smaller and
- + faster. However, when a problem occurs with the kernel, the
- + information that is reported is severely limited. Most people
- + should say Y here.
- +
- +config DEBUG_USER
- + bool "Verbose user fault messages"
- + help
- + When a user program crashes due to an exception, the kernel can
- + print a brief message explaining what the problem was. This is
- + sometimes helpful for debugging but serves no purpose on a
- + production system. Most people should say N here.
- +
- + In addition, you need to pass user_debug=N on the kernel command
- + line to enable this feature. N consists of the sum of:
- +
- + 1 - undefined instruction events
- + 2 - system calls
- + 4 - invalid data aborts
- + 8 - SIGSEGV faults
- + 16 - SIGBUS faults
- +
- +config DEBUG_ERRORS
- + bool "Verbose kernel error messages"
- + depends on DEBUG_KERNEL
- + help
- + This option controls verbose debugging information which can be
- + printed when the kernel detects an internal error. This debugging
- + information is useful to kernel hackers when tracking down problems,
- + but mostly meaningless to other people. It's safe to say Y unless
- + you are concerned with the code size or don't want to see these
- + messages.
- +
- +config DEBUG_LL
- + bool "Kernel low-level debugging functions"
- + depends on DEBUG_KERNEL
- + help
- + Say Y here to include definitions of printascii, printchar, printhex
- + in the kernel. This is helpful if you are debugging code that
- + executes before the console is initialized.
- +
- +config CCTL
- + tristate "User space cache control support (EXPERIMENTAL)"
- + depends on EXPERIMENTAL
- + help
- + export cache control to user space via /proc
- +
- + If unsure, say N.
- +
- +config ELFCHK_DEFAULT_ENABLE
- + bool "Enable ELF-Core Checking by default"
- + default n
- + select PROC_FS
- + help
- + ELF-Core Checking is a mechanism which prevents ELF binary from
- + being loaded if it requires any feature that the underlying platform
- + doesn't support.
- +
- + If you say Y here, the resulting kernel enables ELF-Core Checking
- + mechanism by default.
- +config EARLY_PRINTK
- + bool "Early printk support"
- + default y
- + help
- + Say Y here if you want to have an early console using the
- + earlyprintk=<name>[,<addr>][,<options>] kernel parameter. It
- + is assumed that the early console device has been initialised
- + by the boot loader prior to starting the Linux kernel.
- +
- +endmenu
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/asm-offsets.c linux-3.4.110/arch/nds32/kernel/asm-offsets.c
- --- linux-3.4.110.orig/arch/nds32/kernel/asm-offsets.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/asm-offsets.c 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,72 @@
- +/*
- + * Copyright (C) 1995-2003 Russell King
- + * 2001-2002 Keith Owens
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * Generate definitions needed by assembly language modules.
- + * This code generates raw asm output which is post-processed to extract
- + * and format the required data.
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#include <linux/sched.h>
- +#include <linux/mm.h>
- +#include <asm/mach/arch.h>
- +#include <asm/thread_info.h>
- +#include <asm/memory.h>
- +#include <asm/procinfo.h>
- +
- +/*
- + * Make sure that the compiler and target are compatible.
- + */
- +
- +#if __GNUC__ < 3 || \
- + (__GNUC__ == 3 && __GNUC_MINOR__ < 4) || \
- + (__GNUC__ == 3 && __GNUC_MINOR__ == 4 && __GNUC_PATCHLEVEL__ != 0 && \
- + __GNUC_PATCHLEVEL__ < 4) || \
- + (__GNUC__ == 4 && __GNUC_MINOR__ < 2)
- +#error Your compiler is too buggy; it is known to miscompile kernels.
- +#error Known good compilers: 3.4.4, 4.2
- +#endif
- +
- +/* Use marker if you need to separate the values later */
- +
- +#define DEFINE(sym, val) \
- + asm volatile("\n->" #sym " %0 " #val : : "i" (val))
- +
- +#define BLANK() asm volatile("\n->" : : )
- +
- +int main(void)
- +{
- + DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
- + BLANK();
- + DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
- + DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
- + DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit));
- + DEFINE(TI_TASK, offsetof(struct thread_info, task));
- + DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain));
- + DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
- +// DEFINE(TI_TP_VALUE, offsetof(struct thread_info, tp_value));
- + DEFINE(TI_SP_SAVE, offsetof(struct thread_info, sp_save));
- + BLANK();
- + DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs));
- + BLANK();
- + DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id));
- + BLANK();
- + DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm));
- + DEFINE(VMA_VM_FLAGS, offsetof(struct vm_area_struct, vm_flags));
- + BLANK();
- + DEFINE(VM_EXEC, VM_EXEC);
- + BLANK();
- + DEFINE(VIRT_OFFSET, PAGE_OFFSET);
- + BLANK();
- + DEFINE(SIZEOF_MACHINE_DESC, sizeof(struct machine_desc));
- + DEFINE(MACHINFO_TYPE, offsetof(struct machine_desc, nr));
- + DEFINE(MACHINFO_NAME, offsetof(struct machine_desc, name));
- + BLANK();
- + DEFINE(PROC_INFO_SZ, sizeof(struct proc_info_list));
- +
- + return 0;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/audio.c linux-3.4.110/arch/nds32/kernel/audio.c
- --- linux-3.4.110.orig/arch/nds32/kernel/audio.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/audio.c 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,218 @@
- +/*
- + * arch/nds32/kernel/audio.c
- + *
- + * Copyright (C) 2001 Manuela Cirronis, Paolo Alberelli
- + * Copyright (C) 2002 STMicroelectronics Limited
- + * Author : Stuart Menefy
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * Started from SH4 version:
- + * Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka
- + *
- + * This file is subject to the terms and conditions of the GNU General Public
- + * License. See the file "COPYING" in the main directory of this archive
- + * for more details.
- + */
- +#include <linux/sched.h>
- +#include <linux/signal.h>
- +#include <asm/processor.h>
- +#include <asm/user.h>
- +#include <asm/io.h>
- +#include <asm/bitfield.h>
- +#include <asm/audio.h>
- +#include "audio.h"
- +/*
- + * Initially load the audio with signalling NANS. This bit pattern
- + * has the property that no matter whether considered as single or as
- + * double precision, it still represents a signalling NAN.
- + */
- +
- +static struct audio_struct init_audioregs = {
- + .auregs = {[0...31] = NAN32}
- +};
- +
- +void save_audio(struct task_struct *tsk)
- +{
- + unsigned int tmp;
- + enable_audio();
- + asm volatile ("mfsr %0, $MSC_CFG\n\t"
- + "andi %0, %0, %2\n\t"
- + "srli %0, %0, %3\n\t"
- + "slti %0, %0, 2\n\t"
- + "bnez %0, 99f\n\t"
- + "amfar %0, $D0.L24\n\t"
- + "swi %0, [%1+0x0]\n\t"
- + "amfar %0, $D1.L24\n\t"
- + "swi %0, [%1+0x4]\n\t"
- + "99:\n\t"
- + "amfar %0, $I0\n\t"
- + "swi %0, [%1+0x8]\n\t"
- + "amfar %0, $I1\n\t"
- + "swi %0, [%1+0xc]\n\t"
- + "amfar %0, $I2\n\t"
- + "swi %0, [%1+0x10]\n\t"
- + "amfar %0, $I3\n\t"
- + "swi %0, [%1+0x14]\n\t"
- + "amfar %0, $I4\n\t"
- + "swi %0, [%1+0x18]\n\t"
- + "amfar %0, $I5\n\t"
- + "swi %0, [%1+0x1c]\n\t"
- + "amfar %0, $I6\n\t"
- + "swi %0, [%1+0x20]\n\t"
- + "amfar %0, $I7\n\t"
- + "swi %0, [%1+0x24]\n\t"
- + "amfar %0, $M1\n\t"
- + "swi %0, [%1+0x28]\n\t"
- + "amfar %0, $M2\n\t"
- + "swi %0, [%1+0x2c]\n\t"
- + "amfar %0, $M3\n\t"
- + "swi %0, [%1+0x30]\n\t"
- + "amfar %0, $M5\n\t"
- + "swi %0, [%1+0x34]\n\t"
- + "amfar %0, $M6\n\t"
- + "swi %0, [%1+0x38]\n\t"
- + "amfar %0, $M7\n\t"
- + "swi %0, [%1+0x3c]\n\t"
- + "amfar %0, $MOD\n\t"
- + "swi %0, [%1+0x40]\n\t"
- + "amfar %0, $LB\n\t"
- + "swi %0, [%1+0x44]\n\t"
- + "amfar %0, $LE\n\t"
- + "swi %0, [%1+0x48]\n\t"
- + "amfar %0, $LC\n\t"
- + "swi %0, [%1+0x4c]\n\t"
- + "amfar %0, $ADM_VBASE\n\t"
- + "swi %0, [%1+0x50]\n\t"
- + "amfar %0, $SHFT_CTL0\n\t"
- + "swi %0, [%1+0x54]\n\t"
- + "amfar %0, $SHFT_CTL1\n\t"
- + "swi %0, [%1+0x58]\n\t"
- + "amfar2 %0, $CB_CTL\n\t"
- + "swi %0, [%1+0x5c]\n\t"
- + "amfar2 %0, $CBB0\n\t"
- + "swi %0, [%1+0x60]\n\t"
- + "amfar2 %0, $CBB1\n\t"
- + "swi %0, [%1+0x64]\n\t"
- + "amfar2 %0, $CBB2\n\t"
- + "swi %0, [%1+0x68]\n\t"
- + "amfar2 %0, $CBB3\n\t"
- + "swi %0, [%1+0x6c]\n\t"
- + "amfar2 %0, $CBE0\n\t"
- + "swi %0, [%1+0x70]\n\t"
- + "amfar2 %0, $CBE1\n\t"
- + "swi %0, [%1+0x74]\n\t"
- + "amfar2 %0, $CBE2\n\t"
- + "swi %0, [%1+0x78]\n\t"
- + "amfar2 %0, $CBE3\n\t"
- + "swi %0, [%1+0x7c]\n\t":"=&r" (tmp)
- + :"r"(&tsk->thread.audio), "i"(MSC_CFG_mskAUDIO),
- + "i"(MSC_CFG_offAUDIO)
- + :"memory");
- + disable_audio();
- +}
- +
- +void audioload(struct audio_struct *audioregs)
- +{
- + unsigned int tmp;
- + enable_audio();
- + asm volatile ("mfsr %0, $MSC_CFG\n\t"
- + "andi %0, %0, %2\n\t"
- + "srli %0, %0, %3\n\t"
- + "slti %0, %0, 2\n\t"
- + "bnez %0, 98f\n\t"
- + "lwi %0, [%1+0x0]\n\t"
- + "amtar %0, $D0.L24\n\t"
- + "lwi %0, [%1+0x4]\n\t"
- + "amtar %0, $D1.L24\n\t"
- + "98:\n\t"
- + "lwi %0, [%1+0x8]\n\t"
- + "amtar %0, $I0\n\t"
- + "lwi %0, [%1+0xc]\n\t"
- + "amtar %0, $I1\n\t"
- + "lwi %0, [%1+0x10]\n\t"
- + "amtar %0, $I2\n\t"
- + "lwi %0, [%1+0x14]\n\t"
- + "amtar %0, $I3\n\t"
- + "lwi %0, [%1+0x18]\n\t"
- + "amtar %0, $I4\n\t"
- + "lwi %0, [%1+0x1c]\n\t"
- + "amtar %0, $I5\n\t"
- + "lwi %0, [%1+0x20]\n\t"
- + "amtar %0, $I6\n\t"
- + "lwi %0, [%1+0x24]\n\t"
- + "amtar %0, $I7\n\t"
- + "lwi %0, [%1+0x28]\n\t"
- + "amtar %0, $M1\n\t"
- + "lwi %0, [%1+0x2c]\n\t"
- + "amtar %0, $M2\n\t"
- + "lwi %0, [%1+0x30]\n\t"
- + "amtar %0, $M3\n\t"
- + "lwi %0, [%1+0x34]\n\t"
- + "amtar %0, $M5\n\t"
- + "lwi %0, [%1+0x38]\n\t"
- + "amtar %0, $M6\n\t"
- + "lwi %0, [%1+0x3c]\n\t"
- + "amtar %0, $M7\n\t"
- + "lwi %0, [%1+0x40]\n\t"
- + "amtar %0, $MOD\n\t"
- + "lwi %0, [%1+0x44]\n\t"
- + "amtar %0, $LB\n\t"
- + "lwi %0, [%1+0x48]\n\t"
- + "amtar %0, $LE\n\t"
- + "lwi %0, [%1+0x4c]\n\t"
- + "amtar %0, $LC\n\t"
- + "lwi %0, [%1+0x50]\n\t"
- + "amtar %0, $ADM_VBASE\n\t"
- + "lwi %0, [%1+0x54]\n\t"
- + "amtar %0, $SHFT_CTL0\n\t"
- + "lwi %0, [%1+0x58]\n\t"
- + "amtar %0, $SHFT_CTL1\n\t"
- + "lwi %0, [%1+0x5c]\n\t"
- + "amtar2 %0, $CB_CTL\n\t"
- + "lwi %0, [%1+0x60]\n\t"
- + "amtar2 %0, $CBB0\n\t"
- + "lwi %0, [%1+0x64]\n\t"
- + "amtar2 %0, $CBB1\n\t"
- + "lwi %0, [%1+0x68]\n\t"
- + "amtar2 %0, $CBB2\n\t"
- + "lwi %0, [%1+0x6c]\n\t"
- + "amtar2 %0, $CBB3\n\t"
- + "lwi %0, [%1+0x70]\n\t"
- + "amtar2 %0, $CBE0\n\t"
- + "lwi %0, [%1+0x74]\n\t"
- + "amtar2 %0, $CBE1\n\t"
- + "lwi %0, [%1+0x78]\n\t"
- + "amtar2 %0, $CBE2\n\t"
- + "lwi %0, [%1+0x7c]\n\t"
- + "amtar2 %0, $CBE3\n\t":"=&r" (tmp)
- + :"r"(audioregs), "i"(MSC_CFG_mskAUDIO),
- + "i"(MSC_CFG_offAUDIO));
- + disable_audio();
- +}
- +
- +void do_audio_context_switch(unsigned long error_code, struct pt_regs *regs)
- +{
- + struct task_struct *tsk = current;
- +
- + if (!user_mode(regs))
- + die("Audio used in kernel", regs, error_code);
- +
- + /* Enable to use audio. */
- + grab_audio(regs);
- +#ifndef CONFIG_UNLAZY_AUDIO //Lazy audio is used
- + if (last_task_used_audio == current)
- + return;
- +
- + if (last_task_used_audio != NULL)
- + /* Other processes audio state, save away */
- + save_audio(last_task_used_audio);
- + last_task_used_audio = current;
- +#endif
- + if (test_tsk_thread_flag(tsk, TIF_USEDAUDIO)) {
- + audioload(¤t->thread.audio);
- + } else {
- + /* First time audio user. */
- + audioload(&init_audioregs);
- + set_tsk_thread_flag(tsk, TIF_USEDAUDIO);
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/audio.h linux-3.4.110/arch/nds32/kernel/audio.h
- --- linux-3.4.110.orig/arch/nds32/kernel/audio.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/audio.h 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,2 @@
- +
- +#define NAN32 0x0UL
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/bios32.c linux-3.4.110/arch/nds32/kernel/bios32.c
- --- linux-3.4.110.orig/arch/nds32/kernel/bios32.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/bios32.c 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,711 @@
- +/*
- + * linux/arch/nds32/kernel/bios32.c
- + *
- + * PCI bios-type initialisation for PCI machines
- + *
- + * Bits taken from various places.
- + *
- + * Copyright (C) 2009 Andes Technology Corporation
- + */
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/pci.h>
- +#include <linux/slab.h>
- +#include <linux/init.h>
- +
- +#include <asm/io.h>
- +#include <asm/mach-types.h>
- +#include <asm/mach/pci.h>
- +
- +static int debug_pci;
- +static int use_firmware;
- +
- +/*
- + * We can't use pci_find_device() here since we are
- + * called from interrupt context.
- + */
- +static void pcibios_bus_report_status(struct pci_bus *bus, u_int status_mask,
- + int warn)
- +{
- + struct pci_dev *dev;
- +
- + list_for_each_entry(dev, &bus->devices, bus_list) {
- + u16 status;
- +
- + /*
- + * ignore host bridge - we handle
- + * that separately
- + */
- + if (dev->bus->number == 0 && dev->devfn == 0)
- + continue;
- +
- + pci_read_config_word(dev, PCI_STATUS, &status);
- + if (status == 0xffff)
- + continue;
- +
- + if ((status & status_mask) == 0)
- + continue;
- +
- + /* clear the status errors */
- + pci_write_config_word(dev, PCI_STATUS, status & status_mask);
- +
- + if (warn)
- + printk("(%s: %04X) ", pci_name(dev), status);
- + }
- +
- + list_for_each_entry(dev, &bus->devices, bus_list)
- + if (dev->subordinate)
- + pcibios_bus_report_status(dev->subordinate, status_mask, warn);
- +}
- +
- +void pcibios_report_status(u_int status_mask, int warn)
- +{
- + struct list_head *l;
- +
- + list_for_each(l, &pci_root_buses) {
- + struct pci_bus *bus = pci_bus_b(l);
- +
- + pcibios_bus_report_status(bus, status_mask, warn);
- + }
- +}
- +
- +/*
- + * We don't use this to fix the device, but initialisation of it.
- + * It's not the correct use for this, but it works.
- + * Note that the arbiter/ISA bridge appears to be buggy, specifically in
- + * the following area:
- + * 1. park on CPU
- + * 2. ISA bridge ping-pong
- + * 3. ISA bridge master handling of target RETRY
- + *
- + * Bug 3 is responsible for the sound DMA grinding to a halt. We now
- + * live with bug 2.
- + */
- +static void __devinit pci_fixup_83c553(struct pci_dev *dev)
- +{
- + /*
- + * Set memory region to start at address 0, and enable IO
- + */
- + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
- + PCI_BASE_ADDRESS_SPACE_MEMORY);
- + pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_IO);
- +
- + dev->resource[0].end -= dev->resource[0].start;
- + dev->resource[0].start = 0;
- +
- + /*
- + * All memory requests from ISA to be channelled to PCI
- + */
- + pci_write_config_byte(dev, 0x48, 0xff);
- +
- + /*
- + * Enable ping-pong on bus master to ISA bridge transactions.
- + * This improves the sound DMA substantially. The fixed
- + * priority arbiter also helps (see below).
- + */
- + pci_write_config_byte(dev, 0x42, 0x01);
- +
- + /*
- + * Enable PCI retry
- + */
- + pci_write_config_byte(dev, 0x40, 0x22);
- +
- + /*
- + * We used to set the arbiter to "park on last master" (bit
- + * 1 set), but unfortunately the CyberPro does not park the
- + * bus. We must therefore park on CPU. Unfortunately, this
- + * may trigger yet another bug in the 553.
- + */
- + pci_write_config_byte(dev, 0x83, 0x02);
- +
- + /*
- + * Make the ISA DMA request lowest priority, and disable
- + * rotating priorities completely.
- + */
- + pci_write_config_byte(dev, 0x80, 0x11);
- + pci_write_config_byte(dev, 0x81, 0x00);
- +
- + /*
- + * Route INTA input to IRQ 11, and set IRQ11 to be level
- + * sensitive.
- + */
- + pci_write_config_word(dev, 0x44, 0xb000);
- + outb(0x08, 0x4d1);
- +}
- +
- +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553,
- + pci_fixup_83c553);
- +
- +static void __devinit pci_fixup_unassign(struct pci_dev *dev)
- +{
- + dev->resource[0].end -= dev->resource[0].start;
- + dev->resource[0].start = 0;
- +}
- +
- +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940F,
- + pci_fixup_unassign);
- +
- +/*
- + * Prevent the PCI layer from seeing the resources allocated to this device
- + * if it is the host bridge by marking it as such. These resources are of
- + * no consequence to the PCI layer (they are handled elsewhere).
- + */
- +static void __devinit pci_fixup_dec21285(struct pci_dev *dev)
- +{
- + int i;
- +
- + if (dev->devfn == 0) {
- + dev->class &= 0xff;
- + dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
- + for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- + dev->resource[i].start = 0;
- + dev->resource[i].end = 0;
- + dev->resource[i].flags = 0;
- + }
- + }
- +}
- +
- +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285,
- + pci_fixup_dec21285);
- +
- +/*
- + * PCI IDE controllers use non-standard I/O port decoding, respect it.
- + */
- +static void __devinit pci_fixup_ide_bases(struct pci_dev *dev)
- +{
- + struct resource *r;
- + int i;
- +
- + if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
- + return;
- +
- + for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- + r = dev->resource + i;
- + if ((r->start & ~0x80) == 0x374) {
- + r->start |= 2;
- + r->end = r->start;
- + }
- + }
- +}
- +
- +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
- +
- +/*
- + * Put the DEC21142 to sleep
- + */
- +static void __devinit pci_fixup_dec21142(struct pci_dev *dev)
- +{
- + pci_write_config_dword(dev, 0x40, 0x80000000);
- +}
- +
- +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
- + pci_fixup_dec21142);
- +
- +/*
- + * The CY82C693 needs some rather major fixups to ensure that it does
- + * the right thing. Idea from the Alpha people, with a few additions.
- + *
- + * We ensure that the IDE base registers are set to 1f0/3f4 for the
- + * primary bus, and 170/374 for the secondary bus. Also, hide them
- + * from the PCI subsystem view as well so we won't try to perform
- + * our own auto-configuration on them.
- + *
- + * In addition, we ensure that the PCI IDE interrupts are routed to
- + * IRQ 14 and IRQ 15 respectively.
- + *
- + * The above gets us to a point where the IDE on this device is
- + * functional. However, The CY82C693U _does not work_ in bus
- + * master mode without locking the PCI bus solid.
- + */
- +static void __devinit pci_fixup_cy82c693(struct pci_dev *dev)
- +{
- + if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
- + u32 base0, base1;
- +
- + if (dev->class & 0x80) { /* primary */
- + base0 = 0x1f0;
- + base1 = 0x3f4;
- + } else { /* secondary */
- + base0 = 0x170;
- + base1 = 0x374;
- + }
- +
- + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
- + base0 | PCI_BASE_ADDRESS_SPACE_IO);
- + pci_write_config_dword(dev, PCI_BASE_ADDRESS_1,
- + base1 | PCI_BASE_ADDRESS_SPACE_IO);
- +
- + dev->resource[0].start = 0;
- + dev->resource[0].end = 0;
- + dev->resource[0].flags = 0;
- +
- + dev->resource[1].start = 0;
- + dev->resource[1].end = 0;
- + dev->resource[1].flags = 0;
- + } else if (PCI_FUNC(dev->devfn) == 0) {
- + /*
- + * Setup IDE IRQ routing.
- + */
- + pci_write_config_byte(dev, 0x4b, 14);
- + pci_write_config_byte(dev, 0x4c, 15);
- +
- + /*
- + * Disable FREQACK handshake, enable USB.
- + */
- + pci_write_config_byte(dev, 0x4d, 0x41);
- +
- + /*
- + * Enable PCI retry, and PCI post-write buffer.
- + */
- + pci_write_config_byte(dev, 0x44, 0x17);
- +
- + /*
- + * Enable ISA master and DMA post write buffering.
- + */
- + pci_write_config_byte(dev, 0x45, 0x03);
- + }
- +}
- +
- +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693,
- + pci_fixup_cy82c693);
- +
- +void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
- +{
- + if (debug_pci)
- + printk("PCI: Assigning IRQ %02d to %s\n", irq, pci_name(dev));
- + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
- +}
- +
- +/*
- + * If the bus contains any of these devices, then we must not turn on
- + * parity checking of any kind. Currently this is CyberPro 20x0 only.
- + */
- +static inline int pdev_bad_for_parity(struct pci_dev *dev)
- +{
- + return (dev->vendor == PCI_VENDOR_ID_INTERG &&
- + (dev->device == PCI_DEVICE_ID_INTERG_2000 ||
- + dev->device == PCI_DEVICE_ID_INTERG_2010));
- +}
- +
- +/*
- + * Adjust the device resources from bus-centric to Linux-centric.
- + */
- +static void __devinit
- +pdev_fixup_device_resources(struct pci_sys_data *root, struct pci_dev *dev)
- +{
- + resource_size_t offset;
- + int i;
- +
- + for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- + if (dev->resource[i].start == 0)
- + continue;
- + if (dev->resource[i].flags & IORESOURCE_MEM)
- + offset = root->mem_offset;
- + else
- + offset = root->io_offset;
- +
- + dev->resource[i].start += offset;
- + dev->resource[i].end += offset;
- + }
- +}
- +
- +static void __devinit
- +pbus_assign_bus_resources(struct pci_bus *bus, struct pci_sys_data *root)
- +{
- + struct pci_dev *dev = bus->self;
- + int i;
- +
- + if (!dev) {
- + /*
- + * Assign root bus resources.
- + */
- + for (i = 0; i < 3; i++)
- + bus->resource[i] = root->resource[i];
- + }
- +}
- +
- +/*
- + * pcibios_fixup_bus - Called after each bus is probed,
- + * but before its children are examined.
- + */
- +void __devinit pcibios_fixup_bus(struct pci_bus *bus)
- +{
- + struct pci_sys_data *root = bus->sysdata;
- + struct pci_dev *dev;
- + u16 features =
- + PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_FAST_BACK;
- +
- + pbus_assign_bus_resources(bus, root);
- +
- + /*
- + * Walk the devices on this bus, working out what we can
- + * and can't support.
- + */
- + list_for_each_entry(dev, &bus->devices, bus_list) {
- + u16 status;
- +
- + pdev_fixup_device_resources(root, dev);
- +
- + pci_read_config_word(dev, PCI_STATUS, &status);
- +
- + /*
- + * If any device on this bus does not support fast back
- + * to back transfers, then the bus as a whole is not able
- + * to support them. Having fast back to back transfers
- + * on saves us one PCI cycle per transaction.
- + */
- + if (!(status & PCI_STATUS_FAST_BACK))
- + features &= ~PCI_COMMAND_FAST_BACK;
- +
- + if (pdev_bad_for_parity(dev))
- + features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
- +
- + switch (dev->class >> 8) {
- +#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
- + case PCI_CLASS_BRIDGE_ISA:
- + case PCI_CLASS_BRIDGE_EISA:
- + /*
- + * If this device is an ISA bridge, set isa_bridge
- + * to point at this device. We will then go looking
- + * for things like keyboard, etc.
- + */
- + isa_bridge = dev;
- + break;
- +#endif
- + case PCI_CLASS_BRIDGE_PCI:
- + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &status);
- + status |=
- + PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_MASTER_ABORT;
- + status &=
- + ~(PCI_BRIDGE_CTL_BUS_RESET |
- + PCI_BRIDGE_CTL_FAST_BACK);
- + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, status);
- + break;
- +
- + case PCI_CLASS_BRIDGE_CARDBUS:
- + pci_read_config_word(dev, PCI_CB_BRIDGE_CONTROL,
- + &status);
- + status |=
- + PCI_CB_BRIDGE_CTL_PARITY |
- + PCI_CB_BRIDGE_CTL_MASTER_ABORT;
- + pci_write_config_word(dev, PCI_CB_BRIDGE_CONTROL,
- + status);
- + break;
- + }
- + }
- +
- + /*
- + * Now walk the devices again, this time setting them up.
- + */
- + list_for_each_entry(dev, &bus->devices, bus_list) {
- + u16 cmd;
- +
- + pci_read_config_word(dev, PCI_COMMAND, &cmd);
- + cmd |= features;
- + pci_write_config_word(dev, PCI_COMMAND, cmd);
- +
- + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
- + L1_CACHE_BYTES >> 2);
- + }
- +
- + /*
- + * Propagate the flags to the PCI bridge.
- + */
- + if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- + if (features & PCI_COMMAND_FAST_BACK)
- + bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
- + if (features & PCI_COMMAND_PARITY)
- + bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
- + }
- +
- + /*
- + * Report what we did for this bus
- + */
- + printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
- + bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
- +}
- +
- +/*
- + * Convert from Linux-centric to bus-centric addresses for bridge devices.
- + */
- +void
- +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
- + struct resource *res)
- +{
- + struct pci_sys_data *root = dev->sysdata;
- + unsigned long offset = 0;
- +
- + if (res->flags & IORESOURCE_IO)
- + offset = root->io_offset;
- + if (res->flags & IORESOURCE_MEM)
- + offset = root->mem_offset;
- +
- + region->start = res->start - offset;
- + region->end = res->end - offset;
- +}
- +
- +void __devinit
- +pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
- + struct pci_bus_region *region)
- +{
- + struct pci_sys_data *root = dev->sysdata;
- + unsigned long offset = 0;
- +
- + if (res->flags & IORESOURCE_IO)
- + offset = root->io_offset;
- + if (res->flags & IORESOURCE_MEM)
- + offset = root->mem_offset;
- +
- + res->start = region->start + offset;
- + res->end = region->end + offset;
- +}
- +
- +#ifdef CONFIG_HOTPLUG
- +EXPORT_SYMBOL(pcibios_fixup_bus);
- +EXPORT_SYMBOL(pcibios_resource_to_bus);
- +EXPORT_SYMBOL(pcibios_bus_to_resource);
- +#endif
- +
- +/*
- + * This is the standard PCI-PCI bridge swizzling algorithm:
- + *
- + * Dev: 0 1 2 3
- + * A A B C D
- + * B B C D A
- + * C C D A B
- + * D D A B C
- + * ^^^^^^^^^^ irq pin on bridge
- + */
- +u8 __devinit pci_std_swizzle(struct pci_dev *dev, u8 * pinp)
- +{
- + int pin = *pinp - 1;
- +
- + while (dev->bus->self) {
- + pin = (pin + PCI_SLOT(dev->devfn)) & 3;
- + /*
- + * move up the chain of bridges,
- + * swizzling as we go.
- + */
- + dev = dev->bus->self;
- + }
- + *pinp = pin + 1;
- +
- + return PCI_SLOT(dev->devfn);
- +}
- +
- +/*
- + * Swizzle the device pin each time we cross a bridge.
- + * This might update pin and returns the slot number.
- + */
- +static u8 __devinit pcibios_swizzle(struct pci_dev *dev, u8 * pin)
- +{
- + struct pci_sys_data *sys = dev->sysdata;
- + int slot = 0, oldpin = *pin;
- +
- + if (sys->swizzle)
- + slot = sys->swizzle(dev, pin);
- +
- + if (debug_pci)
- + printk("PCI: %s swizzling pin %d => pin %d slot %d\n",
- + pci_name(dev), oldpin, *pin, slot);
- +
- + return slot;
- +}
- +
- +/*
- + * Map a slot/pin to an IRQ.
- + */
- +static int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
- +{
- + struct pci_sys_data *sys = dev->sysdata;
- + int irq = -1;
- +
- + if (sys->map_irq)
- + irq = sys->map_irq(dev, slot, pin);
- +
- + if (debug_pci)
- + printk("PCI: %s mapping slot %d pin %d => irq %d\n",
- + pci_name(dev), slot, pin, irq);
- +
- + return irq;
- +}
- +
- +static void __init pcibios_init_hw(struct hw_pci *hw)
- +{
- + struct pci_sys_data *sys = NULL;
- + int ret;
- + int nr, busnr;
- +
- + for (nr = busnr = 0; nr < hw->nr_controllers; nr++) {
- + sys = kmalloc(sizeof(struct pci_sys_data), GFP_KERNEL);
- + if (!sys)
- + panic("PCI: unable to allocate sys data!");
- +
- + memset(sys, 0, sizeof(struct pci_sys_data));
- +
- + sys->hw = hw;
- + sys->busnr = busnr;
- + sys->swizzle = hw->swizzle;
- + sys->map_irq = hw->map_irq;
- + sys->resource[0] = &ioport_resource;
- + sys->resource[1] = &iomem_resource;
- +
- + ret = hw->setup(nr, sys);
- +
- + if (ret > 0) {
- + sys->bus = hw->scan(nr, sys);
- +
- + if (!sys->bus)
- + panic("PCI: unable to scan bus!");
- +
- + busnr = sys->bus->subordinate + 1;
- +
- + list_add(&sys->node, &hw->buses);
- + } else {
- + kfree(sys);
- + if (ret < 0)
- + break;
- + }
- + }
- +}
- +
- +void __init pci_common_init(struct hw_pci *hw)
- +{
- + struct pci_sys_data *sys;
- +
- + INIT_LIST_HEAD(&hw->buses);
- +
- + if (hw->preinit)
- + hw->preinit();
- + pcibios_init_hw(hw);
- + if (hw->postinit)
- + hw->postinit();
- +
- + pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
- +
- + list_for_each_entry(sys, &hw->buses, node) {
- + struct pci_bus *bus = sys->bus;
- +
- + if (!use_firmware) {
- + /*
- + * Size the bridge windows.
- + */
- + pci_bus_size_bridges(bus);
- +
- + /*
- + * Assign resources.
- + */
- + pci_bus_assign_resources(bus);
- + }
- +
- + /*
- + * Tell drivers about devices found.
- + */
- + pci_bus_add_devices(bus);
- + }
- +}
- +
- +char *__devinit pcibios_setup(char *str)
- +{
- + if (!strcmp(str, "debug")) {
- + debug_pci = 1;
- + return NULL;
- + } else if (!strcmp(str, "firmware")) {
- + use_firmware = 1;
- + return NULL;
- + }
- + return str;
- +}
- +
- +/*
- + * From arch/i386/kernel/pci-i386.c:
- + *
- + * We need to avoid collisions with `mirrored' VGA ports
- + * and other strange ISA hardware, so we always want the
- + * addresses to be allocated in the 0x000-0x0ff region
- + * modulo 0x400.
- + *
- + * Why? Because some silly external IO cards only decode
- + * the low 10 bits of the IO address. The 0x00-0xff region
- + * is reserved for motherboard devices that decode all 16
- + * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
- + * but we want to try to avoid allocating at 0x2900-0x2bff
- + * which might be mirrored at 0x0100-0x03ff..
- + */
- +void pcibios_align_resource(void *data, struct resource *res,
- + resource_size_t size, resource_size_t align)
- +{
- + resource_size_t start = res->start;
- +
- + if (res->flags & IORESOURCE_IO && start & 0x300)
- + start = (start + 0x3ff) & ~0x3ff;
- +
- + res->start = (start + align - 1) & ~(align - 1);
- +}
- +
- +/**
- + * pcibios_enable_device - Enable I/O and memory.
- + * @dev: PCI device to be enabled
- + */
- +int pcibios_enable_device(struct pci_dev *dev, int mask)
- +{
- + u16 cmd, old_cmd;
- + int idx;
- + struct resource *r;
- +
- + pci_read_config_word(dev, PCI_COMMAND, &cmd);
- + old_cmd = cmd;
- + for (idx = 0; idx < 6; idx++) {
- + /* Only set up the requested stuff */
- + if (!(mask & (1 << idx)))
- + continue;
- +
- + r = dev->resource + idx;
- + if (!r->start && r->end) {
- + printk(KERN_ERR "PCI: Device %s not available because"
- + " of resource collisions\n", pci_name(dev));
- + return -EINVAL;
- + }
- + if (r->flags & IORESOURCE_IO)
- + cmd |= PCI_COMMAND_IO;
- + if (r->flags & IORESOURCE_MEM)
- + cmd |= PCI_COMMAND_MEMORY;
- + }
- +
- + /*
- + * Bridges (eg, cardbus bridges) need to be fully enabled
- + */
- + if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
- + cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
- +
- + if (cmd != old_cmd) {
- + printk("PCI: enabling device %s (%04x -> %04x)\n",
- + pci_name(dev), old_cmd, cmd);
- + pci_write_config_word(dev, PCI_COMMAND, cmd);
- + }
- + return 0;
- +}
- +
- +int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
- + enum pci_mmap_state mmap_state, int write_combine)
- +{
- + struct pci_sys_data *root = dev->sysdata;
- + unsigned long phys;
- +
- + if (mmap_state == pci_mmap_io) {
- + return -EINVAL;
- + } else {
- + phys = vma->vm_pgoff + (root->mem_offset >> PAGE_SHIFT);
- + }
- +
- + /*
- + * Mark this as IO
- + */
- + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- +
- + if (remap_pfn_range(vma, vma->vm_start, phys,
- + vma->vm_end - vma->vm_start, vma->vm_page_prot))
- + return -EAGAIN;
- +
- + return 0;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/calls.S linux-3.4.110/arch/nds32/kernel/calls.S
- --- linux-3.4.110.orig/arch/nds32/kernel/calls.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/calls.S 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,400 @@
- +/*
- + * linux/arch/nds32/kernel/calls.S
- + *
- + * Copyright (C) 1995-2004 Russell King
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * This file is included twice in entry-common.S
- + */
- +
- +/* 0 */ CALL(sys_restart_syscall)
- + CALL(sys_exit)
- + CALL(sys_fork_wrapper)
- + CALL(sys_read)
- + CALL(sys_write)
- +/* 5 */ CALL(sys_open)
- + CALL(sys_close)
- + CALL(sys_waitpid)
- + CALL(sys_creat)
- + CALL(sys_link)
- +/* 10 */ CALL(sys_unlink)
- + CALL(sys_execve_wrapper)
- + CALL(sys_chdir)
- + CALL(sys_time) /* used by libc4 */
- + CALL(sys_mknod)
- +/* 15 */ CALL(sys_chmod)
- + CALL(sys_lchown16)
- + CALL(sys_ni_syscall) /* was sys_break */
- + CALL(sys_ni_syscall) /* was sys_stat */
- + CALL(sys_lseek)
- +/* 20 */ CALL(sys_getpid)
- + CALL(sys_mount)
- + CALL(sys_oldumount) /* used by libc4 */
- + CALL(sys_setuid16)
- + CALL(sys_getuid16)
- +/* 25 */ CALL(sys_stime)
- + CALL(sys_ptrace)
- + CALL(sys_alarm) /* used by libc4 */
- + CALL(sys_ni_syscall) /* was sys_fstat */
- + CALL(sys_pause)
- +/* 30 */ CALL(sys_utime) /* used by libc4 */
- + CALL(sys_ni_syscall) /* was sys_stty */
- + CALL(sys_ni_syscall) /* was sys_getty */
- + CALL(sys_access)
- + CALL(sys_nice)
- +/* 35 */ CALL(sys_ni_syscall) /* was sys_ftime */
- + CALL(sys_sync)
- + CALL(sys_kill)
- + CALL(sys_rename)
- + CALL(sys_mkdir)
- +/* 40 */ CALL(sys_rmdir)
- + CALL(sys_dup)
- + CALL(sys_pipe)
- + CALL(sys_times)
- + CALL(sys_ni_syscall) /* was sys_prof */
- +/* 45 */ CALL(sys_brk)
- + CALL(sys_setgid16)
- + CALL(sys_getgid16)
- + CALL(sys_ni_syscall) /* was sys_signal */
- + CALL(sys_geteuid16)
- +/* 50 */ CALL(sys_getegid16)
- + CALL(sys_acct)
- + CALL(sys_umount)
- + CALL(sys_ni_syscall) /* was sys_lock */
- + CALL(sys_ioctl)
- +/* 55 */ CALL(sys_fcntl)
- + CALL(sys_ni_syscall) /* was sys_mpx */
- + CALL(sys_setpgid)
- + CALL(sys_ni_syscall) /* was sys_ulimit */
- + CALL(sys_cacheflush) /* was sys_olduname */
- +/* 60 */ CALL(sys_umask)
- + CALL(sys_chroot)
- + CALL(sys_ustat)
- + CALL(sys_dup2)
- + CALL(sys_getppid)
- +/* 65 */ CALL(sys_getpgrp)
- + CALL(sys_setsid)
- + CALL(sys_sigaction)
- + CALL(sys_ni_syscall) /* was sys_sgetmask */
- + CALL(sys_ni_syscall) /* was sys_ssetmask */
- +/* 70 */ CALL(sys_setreuid16)
- + CALL(sys_setregid16)
- + CALL(sys_sigsuspend_wrapper)
- + CALL(sys_sigpending)
- + CALL(sys_sethostname)
- +/* 75 */ CALL(sys_setrlimit)
- + CALL(sys_old_getrlimit) /* used by libc4 */
- + CALL(sys_getrusage)
- + CALL(sys_gettimeofday)
- + CALL(sys_settimeofday)
- +/* 80 */ CALL(sys_getgroups16)
- + CALL(sys_setgroups16)
- + CALL(old_select) /* used by libc4 */
- + CALL(sys_symlink)
- + CALL(sys_ni_syscall) /* was sys_lstat */
- +/* 85 */ CALL(sys_readlink)
- + CALL(sys_uselib)
- + CALL(sys_swapon)
- + CALL(sys_reboot)
- + CALL(sys_old_readdir) /* used by libc4 */
- +/* 90 */ CALL(sys_old_mmap) /* used by libc4 */
- + CALL(sys_munmap)
- + CALL(sys_truncate)
- + CALL(sys_ftruncate)
- + CALL(sys_fchmod)
- +/* 95 */ CALL(sys_fchown16)
- + CALL(sys_getpriority)
- + CALL(sys_setpriority)
- + CALL(sys_ni_syscall) /* was sys_profil */
- + CALL(sys_statfs)
- +/* 100 */ CALL(sys_fstatfs)
- + CALL(sys_ni_syscall)
- + CALL(sys_socketcall)
- + CALL(sys_syslog)
- + CALL(sys_setitimer)
- +/* 105 */ CALL(sys_getitimer)
- + CALL(sys_newstat)
- + CALL(sys_newlstat)
- + CALL(sys_newfstat)
- + CALL(sys_ni_syscall) /* was sys_uname */
- +/* 110 */ CALL(sys_ni_syscall) /* was sys_iopl */
- + CALL(sys_vhangup)
- + CALL(sys_ni_syscall)
- + CALL(sys_syscall) /* call a syscall */
- + CALL(sys_wait4)
- +/* 115 */ CALL(sys_swapoff)
- + CALL(sys_sysinfo)
- + CALL(sys_ipc)
- + CALL(sys_fsync)
- + CALL(sys_sigreturn_wrapper)
- +/* 120 */ CALL(sys_clone_wrapper)
- + CALL(sys_setdomainname)
- + CALL(sys_newuname)
- + CALL(sys_ni_syscall)
- + CALL(sys_adjtimex)
- +/* 125 */ CALL(sys_mprotect)
- + CALL(sys_sigprocmask)
- + CALL(sys_ni_syscall) /* was sys_create_module */
- + CALL(sys_init_module)
- + CALL(sys_delete_module)
- +/* 130 */ CALL(sys_ni_syscall) /* was sys_get_kernel_syms */
- + CALL(sys_quotactl)
- + CALL(sys_getpgid)
- + CALL(sys_fchdir)
- + CALL(sys_bdflush)
- +/* 135 */ CALL(sys_sysfs)
- + CALL(sys_personality)
- + CALL(sys_ni_syscall) /* was _sys_afs_syscall */
- + CALL(sys_setfsuid16)
- + CALL(sys_setfsgid16)
- +/* 140 */ CALL(sys_llseek)
- + CALL(sys_getdents)
- + CALL(sys_select)
- + CALL(sys_flock)
- + CALL(sys_msync)
- +/* 145 */ CALL(sys_readv)
- + CALL(sys_writev)
- + CALL(sys_getsid)
- + CALL(sys_fdatasync)
- + CALL(sys_sysctl)
- +/* 150 */ CALL(sys_mlock)
- + CALL(sys_munlock)
- + CALL(sys_mlockall)
- + CALL(sys_munlockall)
- + CALL(sys_sched_setparam)
- +/* 155 */ CALL(sys_sched_getparam)
- + CALL(sys_sched_setscheduler)
- + CALL(sys_sched_getscheduler)
- + CALL(sys_sched_yield)
- + CALL(sys_sched_get_priority_max)
- +/* 160 */ CALL(sys_sched_get_priority_min)
- + CALL(sys_sched_rr_get_interval)
- + CALL(sys_nanosleep)
- + CALL(sys_nds32_mremap)
- + CALL(sys_setresuid16)
- +/* 165 */ CALL(sys_getresuid16)
- + CALL(sys_getpagesize)
- + CALL(sys_ni_syscall) /* was sys_query_module */
- + CALL(sys_poll)
- + CALL(sys_ni_syscall) /* was nfsservctl */
- +/* 170 */ CALL(sys_setresgid16)
- + CALL(sys_getresgid16)
- + CALL(sys_prctl)
- + CALL(sys_rt_sigreturn_wrapper)
- + CALL(sys_rt_sigaction)
- +/* 175 */ CALL(sys_rt_sigprocmask)
- + CALL(sys_rt_sigpending)
- + CALL(sys_rt_sigtimedwait)
- + CALL(sys_rt_sigqueueinfo)
- + CALL(sys_rt_sigsuspend_wrapper)
- +/* 180 */ CALL(sys_pread64)
- + CALL(sys_pwrite64)
- + CALL(sys_chown16)
- + CALL(sys_getcwd)
- + CALL(sys_capget)
- +/* 185 */ CALL(sys_capset)
- + CALL(sys_sigaltstack_wrapper)
- + CALL(sys_sendfile)
- + CALL(sys_ni_syscall)
- + CALL(sys_ni_syscall)
- +/* 190 */ CALL(sys_vfork_wrapper)
- + CALL(sys_getrlimit)
- + CALL(sys_mmap2)
- + CALL(sys_truncate64)
- + CALL(sys_ftruncate64)
- +/* 195 */ CALL(sys_stat64)
- + CALL(sys_lstat64)
- + CALL(sys_fstat64)
- + CALL(sys_lchown)
- + CALL(sys_getuid)
- +/* 200 */ CALL(sys_getgid)
- + CALL(sys_geteuid)
- + CALL(sys_getegid)
- + CALL(sys_setreuid)
- + CALL(sys_setregid)
- +/* 205 */ CALL(sys_getgroups)
- + CALL(sys_setgroups)
- + CALL(sys_fchown)
- + CALL(sys_setresuid)
- + CALL(sys_getresuid)
- +/* 210 */ CALL(sys_setresgid)
- + CALL(sys_getresgid)
- + CALL(sys_chown)
- + CALL(sys_setuid)
- + CALL(sys_setgid)
- +/* 215 */ CALL(sys_setfsuid)
- + CALL(sys_setfsgid)
- + CALL(sys_getdents64)
- + CALL(sys_pivot_root)
- + CALL(sys_mincore)
- +/* 220 */ CALL(sys_madvise)
- + CALL(sys_fcntl64)
- + CALL(sys_ni_syscall) /* TUX */
- + CALL(sys_ni_syscall)
- + CALL(sys_gettid)
- +/* 225 */ CALL(sys_readahead)
- + CALL(sys_setxattr)
- + CALL(sys_lsetxattr)
- + CALL(sys_fsetxattr)
- + CALL(sys_getxattr)
- +/* 230 */ CALL(sys_lgetxattr)
- + CALL(sys_fgetxattr)
- + CALL(sys_listxattr)
- + CALL(sys_llistxattr)
- + CALL(sys_flistxattr)
- +/* 235 */ CALL(sys_removexattr)
- + CALL(sys_lremovexattr)
- + CALL(sys_fremovexattr)
- + CALL(sys_tkill)
- + CALL(sys_sendfile64)
- +/* 240 */ CALL(sys_futex_wrapper)
- + CALL(sys_sched_setaffinity)
- + CALL(sys_sched_getaffinity)
- + CALL(sys_io_setup)
- + CALL(sys_io_destroy)
- +/* 245 */ CALL(sys_io_getevents)
- + CALL(sys_io_submit)
- + CALL(sys_io_cancel)
- + CALL(sys_exit_group)
- + CALL(sys_lookup_dcookie)
- +/* 250 */ CALL(sys_epoll_create)
- + CALL(sys_epoll_ctl)
- + CALL(sys_epoll_wait)
- + CALL(sys_remap_file_pages)
- + CALL(sys_ni_syscall) /* sys_set_thread_area */
- +/* 255 */ CALL(sys_ni_syscall) /* sys_get_thread_area */
- + CALL(sys_set_tid_address)
- + CALL(sys_timer_create)
- + CALL(sys_timer_settime)
- + CALL(sys_timer_gettime)
- +/* 260 */ CALL(sys_timer_getoverrun)
- + CALL(sys_timer_delete)
- + CALL(sys_clock_settime)
- + CALL(sys_clock_gettime)
- + CALL(sys_clock_getres)
- +/* 265 */ CALL(sys_clock_nanosleep)
- + CALL(sys_statfs64)
- + CALL(sys_fstatfs64)
- + CALL(sys_tgkill)
- + CALL(sys_utimes)
- +/* 270 */ CALL(sys_fadvise64_64_wrapper)
- + CALL(sys_pciconfig_iobase)
- + CALL(sys_pciconfig_read)
- + CALL(sys_pciconfig_write)
- + CALL(sys_mq_open)
- +/* 275 */ CALL(sys_mq_unlink)
- + CALL(sys_mq_timedsend)
- + CALL(sys_mq_timedreceive)
- + CALL(sys_mq_notify)
- + CALL(sys_mq_getsetattr)
- +/* 280 */ CALL(sys_waitid)
- + CALL(sys_add_key)
- + CALL(sys_request_key)
- + CALL(sys_keyctl)
- + CALL(sys_ioprio_set)
- +/* 285 */ CALL(sys_ioprio_get)
- + CALL(sys_inotify_init)
- + CALL(sys_inotify_add_watch)
- + CALL(sys_inotify_rm_watch)
- + CALL(sys_migrate_pages)
- +/* 290 */ CALL(sys_openat)
- + CALL(sys_mkdirat)
- + CALL(sys_mknodat)
- + CALL(sys_fchownat)
- + CALL(sys_futimesat)
- +/* 295 */ CALL(sys_fstatat64)
- + CALL(sys_unlinkat)
- + CALL(sys_renameat)
- + CALL(sys_linkat)
- + CALL(sys_symlinkat)
- +/* 300 */ CALL(sys_readlinkat)
- + CALL(sys_fchmodat)
- + CALL(sys_faccessat)
- + CALL(sys_pselect6) /* sys_pselect6 */
- + CALL(sys_ppoll) /* sys_ppoll */
- +/* 305 */ CALL(sys_unshare)
- + CALL(sys_set_robust_list)
- + CALL(sys_get_robust_list)
- + CALL(sys_splice)
- + CALL(sys_sync_file_range2)
- +/* 310 */ CALL(sys_tee)
- + CALL(sys_vmsplice)
- + CALL(sys_move_pages)
- + CALL(sys_fadvise64)
- + CALL(sys_utimensat)
- +/* 315 */ CALL(sys_signalfd)
- + CALL(sys_timerfd_create)
- + CALL(sys_eventfd)
- + CALL(sys_fallocate)
- + CALL(sys_timerfd_settime)
- +/* 320 */ CALL(sys_timerfd_gettime)
- + CALL(sys_getcpu)
- + CALL(sys_signalfd4)
- + CALL(sys_eventfd2)
- + CALL(sys_epoll_create1)
- +/* 325 */ CALL(sys_dup3)
- + CALL(sys_pipe2)
- + CALL(sys_inotify_init1)
- + CALL(sys_kexec_load)
- + CALL(sys_accept)
- +/* 330 */ CALL(sys_bind)
- + CALL(sys_connect)
- + CALL(sys_getpeername)
- + CALL(sys_getsockname)
- + CALL(sys_getsockopt)
- +/* 335 */ CALL(sys_listen)
- + CALL(sys_recv)
- + CALL(sys_recvfrom)
- + CALL(sys_recvmsg)
- + CALL(sys_send)
- +/* 340 */ CALL(sys_sendmsg)
- + CALL(sys_sendto)
- + CALL(sys_setsockopt)
- + CALL(sys_shutdown)
- + CALL(sys_socket)
- +/* 345 */ CALL(sys_socketpair)
- + CALL(sys_prlimit64)
- + CALL(sys_accept4)
- + CALL(sys_recvmmsg)
- + CALL(sys_sendmmsg)
- +/* 350 */ CALL(sys_fanotify_init)
- + CALL(sys_fanotify_mark)
- + CALL(sys_msgget)
- + CALL(sys_msgctl)
- + CALL(sys_msgrcv)
- +/* 355 */ CALL(sys_msgsnd)
- + CALL(sys_semget)
- + CALL(sys_semctl)
- + CALL(sys_semtimedop)
- + CALL(sys_semop)
- +/* 360 */ CALL(sys_shmget)
- + CALL(sys_shmctl)
- + CALL(sys_shmat)
- + CALL(sys_shmdt)
- + CALL(sys_syncfs)
- +/* 365 */ CALL(sys_setns)
- + CALL(sys_name_to_handle_at)
- + CALL(sys_open_by_handle_at)
- + CALL(sys_process_vm_readv)
- + CALL(sys_process_vm_writev)
- +/* 370 */ CALL(sys_clock_adjtime)
- + CALL(sys_get_mempolicy)
- + CALL(sys_mbind)
- + CALL(sys_perf_event_open)
- + CALL(sys_preadv)
- +/* 375 */ CALL(sys_pwritev)
- + CALL(sys_rt_tgsigqueueinfo)
- + CALL(sys_set_mempolicy)
- + CALL(sys_epoll_pwait)
- +
- +#ifndef syscalls_counted
- +.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
- +#define syscalls_counted
- +#endif
- + .rept syscalls_padding
- + CALL(sys_ni_syscall)
- + .endr
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/early_printk.c linux-3.4.110/arch/nds32/kernel/early_printk.c
- --- linux-3.4.110.orig/arch/nds32/kernel/early_printk.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/early_printk.c 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,126 @@
- +/*
- + * Earlyprintk support.
- + *
- + * Copyright (C) 2012 ARM Ltd.
- + * Author: Catalin Marinas <catalin.marinas@arm.com>
- + *
- + * This program is free software: you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program. If not, see <http://www.gnu.org/licenses/>.
- + */
- +#include <linux/kernel.h>
- +#include <linux/console.h>
- +#include <linux/init.h>
- +#include <linux/string.h>
- +#include <linux/mm.h>
- +#include <linux/io.h>
- +
- +#include <linux/serial_reg.h>
- +#include <asm/setup.h>
- +
- +extern void __iomem *early_io_map(phys_addr_t phys);
- +static void __iomem *early_base;
- +static void (*printch) (char ch);
- +
- +/*
- + * 8250/16550 (8-bit aligned registers) single character TX.
- + */
- +static void uart8250_8bit_printch(char ch)
- +{
- + while (!(readb(early_base + UART_LSR) & UART_LSR_THRE)) ;
- + writeb(ch, early_base + UART_TX);
- +}
- +
- +/*
- + * 8250/16550 (32-bit aligned registers) single character TX.
- + */
- +static void uart8250_32bit_printch(char ch)
- +{
- + while (!(readl(early_base + (UART_LSR << 2)) & UART_LSR_THRE)) ;
- + writel(ch, early_base + (UART_TX << 2));
- +}
- +
- +struct earlycon_match {
- + const char *name;
- + void (*printch) (char ch);
- +};
- +
- +static const struct earlycon_match earlycon_match[] __initconst = {
- + {.name = "uart8250-8bit",.printch = uart8250_8bit_printch,},
- + {.name = "uart8250-32bit",.printch = uart8250_32bit_printch,},
- + {}
- +};
- +
- +static void early_write(struct console *con, const char *s, unsigned n)
- +{
- + while (n-- > 0) {
- + if (*s == '\n')
- + printch('\r');
- + printch(*s);
- + s++;
- + }
- +}
- +
- +static struct console early_console_dev = {
- + .name = "earlycon",
- + .write = early_write,
- + .flags = CON_PRINTBUFFER | CON_BOOT,
- + .index = -1,
- +};
- +
- +/*
- + * Parse earlyprintk=... parameter in the format:
- + *
- + * <name>[,<addr>][,<options>]
- + *
- + * and register the early console. It is assumed that the UART has been
- + * initialised by the bootloader already.
- + */
- +static int __init setup_early_printk(char *buf)
- +{
- + const struct earlycon_match *match = earlycon_match;
- + phys_addr_t paddr = 0;
- +
- + if (!buf) {
- + pr_warning("No earlyprintk arguments passed.\n");
- + return 0;
- + }
- +
- + while (match->name) {
- + size_t len = strlen(match->name);
- + if (!strncmp(buf, match->name, len)) {
- + buf += len;
- + break;
- + }
- + match++;
- + }
- + if (!match->name) {
- + pr_warning("Unknown earlyprintk arguments: %s\n", buf);
- + return 0;
- + }
- +
- + /* I/O address */
- + if (!strncmp(buf, ",0x", 3)) {
- + char *e;
- + paddr = simple_strtoul(buf + 1, &e, 16);
- + buf = e;
- + }
- +
- + if (paddr)
- + early_base = early_io_map(paddr);
- + printch = match->printch;
- + //early_console = &early_console_dev;
- + register_console(&early_console_dev);
- +
- + return 0;
- +}
- +
- +early_param("earlyprintk", setup_early_printk);
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/elfchk.c linux-3.4.110/arch/nds32/kernel/elfchk.c
- --- linux-3.4.110.orig/arch/nds32/kernel/elfchk.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/elfchk.c 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,190 @@
- +#include <linux/module.h>
- +#include <linux/kallsyms.h>
- +#include <asm/hardware.h>
- +#include <asm/uaccess.h>
- +#include <asm/elf.h>
- +#include <asm/fpu.h>
- +#include <asm/audio.h>
- +#include <linux/elf.h>
- +#include <linux/proc_fs.h>
- +
- +#define ELF_CHECKING_OS
- +#include "nds32-elf.h"
- +
- +extern struct proc_dir_entry *proc_dir_cpu;
- +
- +#ifdef CONFIG_ELFCHK_DEFAULT_ENABLE
- +static int elf_check_en = 1;
- +#else
- +static int elf_check_en = 0;
- +#endif
- +
- +struct reg_struct {
- +
- + const char *name;
- + int idx;
- +};
- +
- +static struct reg_struct regs[] = {
- +
- + {"cpu_ver", CPU_SR_INDEX(0, 0, 0)},
- + {"icm_cfg", CPU_SR_INDEX(0, 1, 0)},
- + {"dcm_cfg", CPU_SR_INDEX(0, 2, 0)},
- + {"mmu_cfg", CPU_SR_INDEX(0, 3, 0)},
- + {"msc_cfg", CPU_SR_INDEX(0, 4, 0)},
- +#ifdef CONFIG_FPU
- + {"fucop_exist", CPU_SR_INDEX(0, 5, 0)}
- +#endif
- +};
- +
- +#ifdef CONFIG_FPU
- +static unsigned int read_fpu_fpcfg(void)
- +{
- + unsigned int fpcfg = 0;
- +
- + enable_fpu();
- + asm volatile ("fmfcfg %0\n\t":"=&r" (fpcfg));
- + disable_fpu();
- +
- + return fpcfg;
- +}
- +#endif
- +
- +static unsigned int read_cpu_sr(unsigned int idx)
- +{
- + switch (idx) {
- +
- + case CPU_SR_INDEX(0, 0, 0):
- + return GET_CPU_VER();
- + case CPU_SR_INDEX(0, 1, 0):
- + return GET_ICM_CFG();
- + case CPU_SR_INDEX(0, 2, 0):
- + return GET_DCM_CFG();
- + case CPU_SR_INDEX(0, 3, 0):
- + return GET_MMU_CFG();
- + case CPU_SR_INDEX(0, 4, 0):
- + return GET_MSC_CFG();
- + case CPU_SR_INDEX(0, 5, 0):
- + return GET_FUCOP_EXIST();
- +
- + default:
- + printk(KERN_ERR
- + "%s: invalid system register index (%d, %d, %d)\n",
- + __func__, (idx >> 7) & 0x7, (idx >> 3) & 0xf, idx & 0x7);
- +
- + return SR_NOT_EXIST;
- + }
- +}
- +
- +static unsigned int reg_read_callback(unsigned int idx)
- +{
- + if (HW_IS_CPU(idx)) {
- +
- + return read_cpu_sr(SR_INDEX(idx));
- + } else if (HW_IS_FPU(idx)) {
- +
- +#ifdef CONFIG_FPU
- + if (SR_FPU_FPCFG == SR_INDEX(idx))
- + return read_fpu_fpcfg();
- + else
- + return SR_NOT_EXIST;
- +#endif
- + } else if (HW_IS_AUDIO(idx)) {
- +
- + return SR_NOT_EXIST;
- + }
- +
- + return SR_NOT_EXIST;
- +}
- +
- +#define BUFLEN 1024
- +
- +int do_elf_check_arch(const struct elf32_hdr *hdr)
- +{
- + static char msg_buf[BUFLEN];
- + unsigned int err;
- + int buf_status = 0;
- +
- + if (!elf_check_en)
- + return 1;
- +
- + err =
- + elf_check((void *)hdr, reg_read_callback, msg_buf, BUFLEN,
- + &buf_status);
- +
- + if (err)
- + printk(KERN_WARNING "%s", msg_buf);
- +
- + return !err;
- +}
- +
- +static int proc_elf_check_read(char *page, char **start, off_t off, int count,
- + int *eof, void *data)
- +{
- + return sprintf(page, "%d\n", elf_check_en);
- +}
- +
- +#define INPUTLEN 10
- +static int proc_elf_check_write(struct file *file, const char __user * buffer,
- + unsigned long count, void *data)
- +{
- + unsigned long en;
- + char inbuf[INPUTLEN];
- +
- + if (count > INPUTLEN - 1)
- + count = INPUTLEN - 1;
- +
- + if (copy_from_user(inbuf, buffer, count))
- + return -EFAULT;
- +
- + inbuf[count] = '\0';
- +
- + if (!sscanf(inbuf, "%lu", &en) || en > 3)
- + return -EFAULT;
- +
- + elf_check_en = en & 0x01;
- +
- + return count;
- +}
- +
- +static int proc_elf_check_read_reg(char *page, char **start,
- + off_t off, int count, int *eof, void *data)
- +{
- + unsigned long val = read_cpu_sr(*(int *)data);
- +
- + return sprintf(page, "0x%08lx\n", val);
- +}
- +
- +int __init elf_check_init(void)
- +{
- + static struct proc_dir_entry *res_elf_check;
- + int i;
- +
- + if (!proc_dir_cpu) {
- + if (!(proc_dir_cpu = proc_mkdir("cpu", NULL)))
- + return -ENOMEM;
- + }
- +
- + res_elf_check =
- + create_proc_entry("elf_core_checking", S_IWUSR | S_IRUGO,
- + proc_dir_cpu);
- + if (!res_elf_check)
- + return -ENOMEM;
- +
- + res_elf_check->read_proc = proc_elf_check_read;
- + res_elf_check->write_proc = proc_elf_check_write;
- +
- + for (i = 0; i < ARRAY_SIZE(regs); i++) {
- +
- + if (!create_proc_read_entry(regs[i].name, S_IWUSR | S_IRUGO,
- + proc_dir_cpu,
- + proc_elf_check_read_reg,
- + ®s[i].idx))
- +
- + return -ENOMEM;
- + }
- +
- + return 0;
- +}
- +
- +module_init(elf_check_init);
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/ex-entry.S linux-3.4.110/arch/nds32/kernel/ex-entry.S
- --- linux-3.4.110.orig/arch/nds32/kernel/ex-entry.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/ex-entry.S 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,294 @@
- +#include <linux/linkage.h>
- +#include <asm/memory.h>
- +#include <asm/nds32.h>
- +#include <asm/assembler.h>
- +#include <asm/errno.h>
- +#include <asm/asm-offsets.h>
- +#include <asm/page.h>
- +
- + .macro push_zol
- +#ifdef CONFIG_HWZOL
- + mfusr $r10, $LB
- + mfusr $r11, $LE
- + mfusr $r12, $LC
- +#endif
- + .endm
- + .macro save_user_regs
- + /* $p1 is VA of percpu data */
- + sethi $p0, hi20(PAGE_OFFSET - PHYS_OFFSET)
- + add $p1, $p1, $p0
- +
- + /* change to kernel stack */
- + mfsr $p0, $IPSW
- + andi $p0, $p0, #PSW_mskPOM
- + cmovz $sp, $r25, $p0
- +
- + /* 8 byte aligned */
- + movi $r25, #~7
- + and $r25, $sp, $r25
- + smw.adm $sp, [$r25], $sp, #0x1
- + move $sp, $r25
- +
- +#if defined(CONFIG_FPU) || defined(CONFIG_AUDIO)
- + mfsr $r25, $FUCOP_CTL
- + push $r25
- + bclr $r25, $r25, #FUCOP_CTL_offCP0EN
- + mtsr $r25, $FUCOP_CTL
- +#else
- + addi $sp, $sp, -4
- +#endif
- + pushm $r28, $r30
- +
- + /* zero fp if user mode*/
- + movi $r25, #0x0
- + cmovz $fp, $r25, $p0
- +
- + lwi $r25, [$p1+#0x0]
- + pushm $r0, $r25
- +#ifdef CONFIG_HWZOL
- + push_zol
- +#endif
- + mfsr $r9, $P_P1
- + mfsr $r8, $P_P0
- + mfsr $r7, $P_IPC
- + mfsr $r6, $P_IPSW
- + mfsr $r18, $IPC
- + mfsr $r17, $IPSW
- + mfsr $r16, $PSW
- + pushm $r6, $r13
- + push $r0
- + lwi $p0, [$p1+#0x8]
- + push $p0
- + pushm $r16, $r18
- +
- + andi $r19, $r16, #PSW_mskINTL
- + slti $r20, $r19, #4
- + bnez $r20, 1f
- + addi $r21, $r16, #-2
- + mtsr $r21, $PSW
- + isb
- +1:
- + addi $sp, $sp, -S_OFF
- + .endm
- +
- + .text
- +
- +/*
- + * Exception Vector
- + */
- +exception_handlers:
- + .long unhandled_exceptions !Reset/NMI
- + .long unhandled_exceptions !TLB fill
- + .long do_page_fault !PTE not present
- + .long do_dispatch_tlb_misc !TLB misc
- + .long unhandled_exceptions !TLB VLPT
- + .long unhandled_exceptions !Machine Error
- + .long do_debug_trap !Debug related
- + .long do_dispatch_general !General exception
- + .long eh_syscall !Syscall
- + .long asm_do_IRQ !IRQ
- +
- +common_exception_handler:
- + save_user_regs
- + lwi $p0, [$p1+#0x4]
- + andi $p1, $p0, #0x78
- + bnez $p1, 1f
- + sethi $lp, hi20(ret_from_exception)
- + ori $lp, $lp, lo12(ret_from_exception)
- + sethi $p1, hi20(exception_handlers)
- + ori $p1, $p1, lo12(exception_handlers)
- + lw $p1, [$p1+$p0<<2]
- + move $r0, $p0
- + mfsr $r1, $EVA
- + mfsr $r2, $ITYPE
- + move $r3, $sp
- + mfsr $r4, $OIPC
- + /* enable gie if it is enabled in IPSW. */
- + mfsr $r21, $PSW
- + andi $r17, $r17, #0x1
- + or $r21, $r21, $r17
- + mtsr $r21, $PSW
- + dsb
- + jr $p1
- +
- + /* syscall */
- +1:
- + addi $p1, $p0, #-8
- + bnez $p1, 2f
- + sethi $lp, hi20(ret_from_exception)
- + ori $lp, $lp, lo12(ret_from_exception)
- + sethi $p1, hi20(exception_handlers)
- + ori $p1, $p1, lo12(exception_handlers)
- + lwi $p1, [$p1+#0x8<<2]
- + jr $p1
- +
- + /* interrupt */
- +2:
- +#ifdef CONFIG_TRACE_IRQFLAGS
- + jal arch_trace_hardirqs_off
- +#endif
- +#if defined(CONFIG_EVIC) || defined(CONFIG_IVIC)
- + addi $r0, $p0, #-9
- +#else
- +# ifdef CONFIG_IVIC_INTC
- + jal get_IntSrc
- +# else
- +# error "Not configure Vector Interrupt Controller mode"
- +# endif
- +#endif
- + move $r1, $sp
- + sethi $lp, hi20(ret_from_intr)
- + ori $lp, $lp, lo12(ret_from_intr)
- + sethi $p0, hi20(exception_handlers)
- + ori $p0, $p0, lo12(exception_handlers)
- + lwi $p0, [$p0+#0x9<<2]
- + jr $p0
- +
- + .macro EXCEPTION_VECTOR, num
- + .align 6
- + .ifc \num, 6
- + mfsr $p0, $EDM_CTL
- + andi $p0, $p0, EDM_CTL_mskV3_EDM_MODE
- + tnez $p0, 0x1a
- + .endif
- + /* $p1 is PA of percpu data */
- +#ifdef CONFIG_CPU_N1213_43U1HA0
- + movi $p1, #0x0
- +#else
- + mfsr $p1, $CORE_ID
- +#endif
- + slli $p1, $p1, #0x9
- + li $p0, #(PHYS_OFFSET+0x6000)
- + or $p1, $p1, $p0
- +
- + /*
- + * 0x0 saved $r25
- + * 0x4 vector number
- + * 0x8 user stack pointer
- + * 0xc kernel stack pointer
- + */
- + swi $r25, [$p1+0x0]
- + movi $p0, \num
- + swi $p0, [$p1+#0x4]
- + swi $sp, [$p1+#0x8]
- + lwi $r25, [$p1+#0xc]
- + sethi $p0, hi20(common_exception_handler)
- + ori $p0, $p0, lo12(common_exception_handler)
- + jral.ton $p0, $p0
- + .endm
- +
- + .macro IPI_VECTOR, num
- + .align 6
- +#ifdef CONFIG_CPU_N1213_43U1HA0
- + movi $p1, #0x0
- +#else
- + mfsr $p1, $CORE_ID
- +#endif
- + slli $p1, $p1, #0x9
- + li $p0, #(PHYS_OFFSET+0x6000)
- + or $p1, $p1, $p0
- +
- + /*
- + * 0x10 indicator of CPU is initialized
- + * 0x14 CPU init function
- + */
- + swi $r25, [$p1+0x0]
- + movi $p0, \num
- + swi $p0, [$p1+#0x4]
- + swi $sp, [$p1+#0x8]
- + lwi $r25, [$p1+#0xc]
- + lwi $p0, [$p1+#0x10]
- + beqz $p0, 1f
- + sethi $p0, hi20(common_exception_handler)
- + ori $p0, $p0, lo12(common_exception_handler)
- + jral.ton $p0, $p0
- +1:
- + lwi $p0, [$p1+#0x14]
- + jr $p0
- +
- + .endm
- +
- + .section ".text.init", #alloc, #execinstr
- + .global exception_vector
- +exception_vector:
- + EXCEPTION_VECTOR 0
- + EXCEPTION_VECTOR 1
- + EXCEPTION_VECTOR 2
- + EXCEPTION_VECTOR 3
- + EXCEPTION_VECTOR 4
- + EXCEPTION_VECTOR 5
- + EXCEPTION_VECTOR 6
- + EXCEPTION_VECTOR 7
- + EXCEPTION_VECTOR 8
- +#ifdef CONFIG_EVIC
- + EXCEPTION_VECTOR 9
- +#else
- + IPI_VECTOR 9
- +#endif
- + EXCEPTION_VECTOR 10
- + EXCEPTION_VECTOR 11
- + EXCEPTION_VECTOR 12
- + EXCEPTION_VECTOR 13
- + EXCEPTION_VECTOR 14
- + EXCEPTION_VECTOR 15
- + EXCEPTION_VECTOR 16
- + EXCEPTION_VECTOR 17
- + EXCEPTION_VECTOR 18
- + EXCEPTION_VECTOR 19
- + EXCEPTION_VECTOR 20
- + EXCEPTION_VECTOR 21
- + EXCEPTION_VECTOR 22
- + EXCEPTION_VECTOR 23
- + EXCEPTION_VECTOR 24
- + EXCEPTION_VECTOR 25
- + EXCEPTION_VECTOR 26
- + EXCEPTION_VECTOR 27
- + EXCEPTION_VECTOR 28
- + EXCEPTION_VECTOR 29
- + EXCEPTION_VECTOR 30
- + EXCEPTION_VECTOR 31
- + EXCEPTION_VECTOR 32
- + EXCEPTION_VECTOR 33
- + EXCEPTION_VECTOR 34
- + EXCEPTION_VECTOR 35
- + EXCEPTION_VECTOR 36
- + EXCEPTION_VECTOR 37
- + EXCEPTION_VECTOR 38
- + EXCEPTION_VECTOR 39
- + EXCEPTION_VECTOR 40
- +#ifdef CONFIG_EVIC
- + IPI_VECTOR 41
- +#else
- + EXCEPTION_VECTOR 41
- +#endif
- + EXCEPTION_VECTOR 42
- + EXCEPTION_VECTOR 43
- + EXCEPTION_VECTOR 44
- + EXCEPTION_VECTOR 45
- + EXCEPTION_VECTOR 46
- + EXCEPTION_VECTOR 47
- + EXCEPTION_VECTOR 48
- + EXCEPTION_VECTOR 49
- + EXCEPTION_VECTOR 50
- + EXCEPTION_VECTOR 51
- + EXCEPTION_VECTOR 52
- + EXCEPTION_VECTOR 53
- + EXCEPTION_VECTOR 54
- + EXCEPTION_VECTOR 55
- + EXCEPTION_VECTOR 56
- + EXCEPTION_VECTOR 57
- + EXCEPTION_VECTOR 58
- + EXCEPTION_VECTOR 59
- + EXCEPTION_VECTOR 60
- + EXCEPTION_VECTOR 61
- + EXCEPTION_VECTOR 62
- + EXCEPTION_VECTOR 63
- + EXCEPTION_VECTOR 64
- + EXCEPTION_VECTOR 65
- + EXCEPTION_VECTOR 66
- + EXCEPTION_VECTOR 67
- + EXCEPTION_VECTOR 68
- + EXCEPTION_VECTOR 69
- + EXCEPTION_VECTOR 70
- + EXCEPTION_VECTOR 71
- + EXCEPTION_VECTOR 72
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/ex-exit.S linux-3.4.110/arch/nds32/kernel/ex-exit.S
- --- linux-3.4.110.orig/arch/nds32/kernel/ex-exit.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/ex-exit.S 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,220 @@
- +#include <linux/linkage.h>
- +#include <asm/unistd.h>
- +#include <asm/assembler.h>
- +#include <asm/nds32.h>
- +#include <asm/asm-offsets.h>
- +#include <asm/thread_info.h>
- +
- +#define why $r8 // Linux syscall (!= 0)
- +#define tsk $r9 // current thread_info
- +
- +
- + .macro pop_zol
- +#ifdef CONFIG_HWZOL
- + mtusr $r10, $LB
- + mtusr $r11, $LE
- + mtusr $r12, $LC
- +#endif
- + .endm
- +
- + .macro restore_user_regs_first
- + setgie.d
- + isb
- + /* $p1 is VA of percpu data */
- +#ifdef CONFIG_CPU_N1213_43U1HA0
- + movi $p1, #0x0
- +#else
- + mfsr $p1, $CORE_ID
- +#endif
- + andi $p1, $p1, #0x3
- + slli $p1, $p1, #0x9
- + sethi $p0, #0xc0006
- + or $p1, $p1, $p0
- +
- + addi $sp, $sp, S_OFF
- + popm $r16, $r18
- + mtsr $r16, $PSW
- + pop $r16
- + swi $r16, [$p1+#0x8]
- + addi $sp, $sp, #4 !pop $r0
- + popm $r6, $r13
- + mtsr $r17, $IPSW
- + mtsr $r18, $IPC
- + mtsr $r6, $P_IPSW
- + mtsr $r7, $P_IPC
- + mtsr $r8, $P_P0
- + mtsr $r9, $P_P1
- +#ifdef CONFIG_HWZOL
- + pop_zol
- +#endif
- + .endm
- +
- + .macro restore_user_regs_last
- + popm $r28, $r30
- +#if defined(CONFIG_FPU) || defined(CONFIG_AUDIO)
- + pop $p0
- + mtsr $p0, $FUCOP_CTL
- +#else
- + addi $sp, $sp, 4
- +#endif
- +
- + pop $p0
- + cmovn $sp, $p0, $p0
- +
- + mfsr $p0, $IPSW
- + andi $p0, $p0, #PSW_mskPOM
- + bnez $p0, 1f
- + swi $sp, [$p1+#0xc]
- + lwi $sp, [$p1+#0x8]
- +1:
- + // This is SW workaround for Bug #6294
- + li $p0, 0xc0000000
- + cctl $p0, L1D_VA_INVAL
- + lwi $p1, [$p0]
- +
- + iret
- + nop
- +
- + .endm
- +
- + .macro restore_user_regs
- + restore_user_regs_first
- + popm $r0, $r25
- + restore_user_regs_last
- + .endm
- +
- + .macro fast_restore_user_regs
- + restore_user_regs_first
- + addi $sp, $sp, #4
- + popm $r1, $r25
- + restore_user_regs_last
- + .endm
- +
- +#ifdef CONFIG_PREEMPT
- + .macro preempt_stop
- + .endm
- +#else
- + .macro preempt_stop
- + setgie.d
- + isb
- + .endm
- +#define resume_kernel no_work_pending
- +#endif
- +
- +ENTRY(ret_from_exception)
- + preempt_stop
- +ENTRY(ret_from_intr)
- + get_thread_info tsk
- + move why, #0 ! not system call
- +
- +/*
- + * judge Kernel or user mode
- + *
- + */
- + lwi $p0, [$sp+(#S_IPSW+#S_OFF)]
- +! mfsr $p0, $IPSW ! Check if in nested interrupt
- + andi $p0, $p0, #PSW_mskINTL
- + bnez $p0, resume_kernel ! done with iret
- + j resume_userspace
- +
- +
- +/*
- + * This is the fast syscall return path. We do as little as
- + * possible here, and this includes saving $r0 back into the SVC
- + * stack.
- + * fixed: tsk - $r9, why - $r8, $r7 - syscall #, $r8 - syscall table pointer
- + */
- +ENTRY(ret_fast_syscall)
- + gie_disable
- + lwi $r1, [tsk+#TI_FLAGS]
- + andi $p1, $r1, #_TIF_WORK_MASK
- + bnez $p1, fast_work_pending
- + fast_restore_user_regs ! iret
- +
- +/*
- + * Ok, we need to do extra processing,
- + * enter the slow path returning from syscall, while pending work.
- + */
- +fast_work_pending:
- + swi $r0, [$sp+(#S_R0+#S_OFF)] ! what is different from ret_from_exception
- + ! addi $sp, $sp, S_OFF
- + move why, #1 ! come from a syscall
- +work_pending:
- + andi $p1, $r1, #_TIF_NEED_RESCHED
- + bnez $p1, work_resched
- +
- + andi $p1, $r1, #_TIF_SIGPENDING|#_TIF_NOTIFY_RESUME
- + beqz $p1, no_work_pending
- +
- + move $r0, $sp ! 'regs'
- + move $r2, why
- + gie_enable
- + bal do_notify_resume
- +
- + b ret_slow_syscall ! return from slow_restore_user_regs
- +
- +work_resched:
- + bal schedule ! path, return to user mode
- +
- +/*
- + * "slow" syscall return path.
- + * "why" tells us if this was a real syscall.
- + */
- +ENTRY(resume_userspace)
- +ENTRY(ret_slow_syscall)
- + gie_disable
- + lwi $p0, [$sp+(#S_IPSW+#S_OFF)]
- +! mfsr $p0, $IPSW ! Check if in nested interrupt
- + andi $p0, $p0, #PSW_mskINTL
- + bnez $p0, no_work_pending ! done with iret
- + lwi $r1, [tsk+#TI_FLAGS]
- + andi $p1, $r1, #_TIF_WORK_MASK
- + bnez $p1, work_pending ! handle work_resched, sig_pend
- +
- +no_work_pending:
- +#ifdef CONFIG_TRACE_IRQFLAGS
- + lwi $p0, [$sp+(#S_IPSW+#S_OFF)]
- + andi $p0, $p0, #0x1
- + la $r10, arch_trace_hardirqs_off
- + la $r9, arch_trace_hardirqs_on
- + cmovz $r9, $p0, $r10
- + jral $r9
- +#endif
- + restore_user_regs ! return from iret
- +
- +
- +/*
- + * preemptive kernel
- + */
- +#ifdef CONFIG_PREEMPT
- +resume_kernel:
- + gie_disable
- + lwi $t0, [tsk+#TI_PREEMPT]
- + bnez $t0, no_work_pending
- +need_resched:
- + lwi $t0, [tsk+#TI_FLAGS]
- + andi $p1, $t0, #_TIF_NEED_RESCHED
- + beqz $p1, no_work_pending
- +
- + lwi $t0, [$sp+(#S_IPSW+#S_OFF)] ! Interrupts off?
- + andi $t0, $t0, #1
- + beqz $t0, no_work_pending
- +
- + jal preempt_schedule_irq
- + b need_resched
- +#endif
- +
- +/*
- + * This is how we return from a fork.
- + */
- +ENTRY(ret_from_fork)
- + bal schedule_tail
- + get_thread_info tsk
- + lwi $r1, [tsk+#TI_FLAGS] ! check for syscall tracing
- + move why, #1
- + andi $p1, $r1, #_TIF_WORK_SYSCALL_LEAVE ! are we tracing syscalls?
- + beqz $p1, ret_slow_syscall
- + move $r0, $sp
- + bal syscall_trace_leave
- + b ret_slow_syscall
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/ex-scall.S linux-3.4.110/arch/nds32/kernel/ex-scall.S
- --- linux-3.4.110.orig/arch/nds32/kernel/ex-scall.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/ex-scall.S 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,288 @@
- +#include <linux/linkage.h>
- +#include <asm/unistd.h>
- +#include <asm/assembler.h>
- +#include <asm/nds32.h>
- +#include <asm/asm-offsets.h>
- +#include <asm/thread_info.h>
- +
- +/*
- + * $r0 = previous task_struct,
- + * $r1 = previous thread_info,
- + * $r2 = next thread_info
- + * previous and next are guaranteed not to be the same.
- + */
- +
- +ENTRY(_switch)
- + smw.adm $r6, [$sp], $r14, #0xa
- + swi $sp, [$r1+ TI_SP_SAVE] /* Save $sp to task structure */
- + lwi $sp, [$r2+ TI_SP_SAVE] /* Get $sp from task structure */
- + lmw.bim $r6, [$sp], $r14, #0xa
- + ret
- +
- +/*
- + * These are the registers used in the syscall handler, and allow us
- + * to have in theory up to 6 arguments to a function - $r0 to $r5.
- + * $r7 is reserved for the system call number for Andes architecture.
- + *
- + * Note that tbl == why is intentional.
- + * We must set at least "tsk" and "why" when calling ret_with_reschedule.
- + */
- +#define tbl $r8 // syscall table pointer
- +#define why $r8 // Linux syscall (!= 0)
- +#define tsk $r9 // current thread_info
- +
- +/*
- + * Get the system call number. let $r7 take a system call nr.
- + *
- + * if it is called from library function, $r7 is filled by library call
- + * when user program make a system call. and swid bitfield of $ir6 will
- + * always be encoded as 0x7fff.
- + *
- + * if it is called from kernel code, $r7 will be writen as syscall nr
- + * by retrieving from $ir6 'swid' bitfiled
- + */
- + .macro get_scno
- + mfsr $r7, $ITYPE
- +#ifdef CONFIG_PLAT_QEMU
- + slli $r7, $r7, #1
- + srli $r7, $r7, #ITYPE_offSWID+1
- +#else
- + srli $r7, $r7, #ITYPE_offSWID
- +#endif
- + .endm
- +
- + .macro updateipc
- + addi $r17, $r18, #4
- + swi $r17, [$sp + S_OFF + S_IPC]
- + .endm
- +
- + .equ NR_syscalls,0
- +#define CALL(x) .equ NR_syscalls,NR_syscalls+1
- +#include "calls.S"
- +#undef CALL
- +#define CALL(x) .long x
- +
- +ENTRY(eh_syscall)
- + updateipc
- +
- + get_scno
- + gie_enable
- + get_thread_info tsk
- + lwi $p0, [tsk+#TI_FLAGS] ! check for syscall tracing
- +
- + andi $p1, $p0, #_TIF_WORK_SYSCALL_ENTRY ! are we tracing syscalls?
- + bnez $p1, __sys_trace
- +
- + la $lp, ret_fast_syscall ! return address
- +
- + li $p0, __NR_NDS32_BASE
- + addi $p0, $p0, -1
- + slt $p0, $p0, $r7
- + beqz $p0, 1f
- + addi $r1, $SP, #0
- + move $r0, $r7
- + b nds32_syscall
- +1:
- + ! check upper syscall limit,
- + andi $r7, $r7, #0xfff
- + addi $p1, $r7, #-NR_syscalls ! syscall number of syscall instruction is guarded by addembler
- + bgez $p1, _SCNO_EXCEED ! call sys_* routine
- + la tbl, sys_call_table ! load syscall table pointer
- + slli $p1, $r7, #2
- + add $p1, tbl, $p1
- + lwi $p1, [$p1]
- + jr $p1 ! no return
- +
- +_SCNO_EXCEED:
- + ori $r0, $r7, #0
- + ori $r1, $sp, #0
- + b bad_syscall
- +
- +/*
- + * This is the really slow path. We're going to be doing
- + * context switches, and waiting for our parent to respond.
- + */
- +__sys_trace:
- + move $r1, $sp
- + move $r0, $r7 ! trace entry [IP = 0]
- + bal syscall_trace_enter
- + move $r7, $r0
- + la $lp, __sys_trace_return ! return address
- +
- + li $p0, __NR_NDS32_BASE
- + addi $p0, $p0, -1
- + slt $p0, $p0, $r7
- + beqz $p0, 1f
- + addi $r1, $SP, #0
- + b nds32_syscall
- +1:
- + andi $r7, $r7, #0xfff
- + addi $p1, $sp, #S_R0+S_OFF ! pointer to regs
- + addi $p0, $r7, -#NR_syscalls ! check upper syscall limit
- + bgez $p0, _SCNO_EXCEED
- + lmw.bi $r0, [$p1], $r5 ! have to reload $r0 - $r5
- +
- + slli $p0, $r7, #2 ! call sys_* routine
- + la tbl, sys_call_table ! load syscall table pointer
- + add $p0, tbl, $p0
- + lwi $p0, [$p0]
- + jr $p0
- +
- +__sys_trace_return:
- + swi $r0, [$sp+(#S_R0+S_OFF)] ! T: save returned $r0
- + bal syscall_trace_leave
- + b ret_slow_syscall
- +
- + .type sys_call_table, #object
- +ENTRY(sys_call_table)
- +#include "calls.S"
- +
- +/*
- + * Special system call wrappers
- + *
- + * $r0 = syscall number
- + * $r8 = syscall table
- + */
- + .type sys_syscall, #function
- +sys_syscall:
- +
- + li $p0, __NR_NDS32_BASE
- + addi $p0, $p0, -1
- + slt $p0, $p0, $r0
- + beqz $p0, 1f
- + addi $r1, $SP, #0
- + b nds32_syscall
- +1:
- + bltz $r0, 3f ! Guard whether syscall number is between 0~0x7fff.
- + andi $r0, $r0, #0xfff
- + addi $p1, $r0, #-NR_syscalls
- + bgtz $p1, 3f
- + move $p1, $r0
- + move $r0, $r1
- + move $r1, $r2
- + move $r2, $r3
- + move $r3, $r4
- + move $r4, $r5
- +! add for syscall 6 args
- + lwi $r5, [$sp + (#S_SP + #S_OFF) ]
- + lwi $r5, [$r5 + #S_OFF]
- +! ~add for syscall 6 args
- +
- + lw $p1, [tbl+$p1<<2]
- + jr $p1
- +3: b sys_ni_syscall
- +
- +sys_fork_wrapper:
- + addi $r0, $sp, #0
- + b sys_fork
- +
- +sys_vfork_wrapper:
- + addi $r0, $sp, #0
- + b sys_vfork
- +
- +sys_execve_wrapper:
- + addi $r3, $sp, #0
- + b sys_execve
- +
- +sys_clone_wrapper:
- + addi $r5, $SP, #0
- + b sys_clone
- +
- +sys_sigsuspend_wrapper:
- + addi $r3, $sp, #0
- + b sys_sigsuspend
- +
- +sys_rt_sigsuspend_wrapper:
- + addi $r2, $sp, #0
- + b sys_rt_sigsuspend
- +
- +sys_sigreturn_wrapper:
- + addi $r0, $sp, #0
- + b sys_sigreturn
- +
- +sys_rt_sigreturn_wrapper:
- + addi $r0, $sp, #0
- + b sys_rt_sigreturn
- +
- +sys_sigaltstack_wrapper:
- + lwi $r2, [$sp+(#S_OFF + S_SP)]
- + b do_sigaltstack
- +
- +sys_futex_wrapper:
- + b sys_futex
- +
- +#ifdef CONFIG_FUNCTION_TRACER
- + .global _mcount
- + .global ftrace_stub
- +_mcount:
- + sethi $r15, hi20(function_trace_stop)
- + lwi $r15, [$r15 + lo12(function_trace_stop)]
- + bnez $r15, _ftrace_stub
- +
- + sethi $r15, hi20(ftrace_trace_function)
- + lwi $p0, [$r15 + lo12(ftrace_trace_function)]
- + sethi $r15, hi20(ftrace_stub)
- + ori $r15, $r15, lo12(ftrace_stub)
- + bne $r15, $p0, trace
- +
- +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- + sethi $p0, hi20(ftrace_graph_return)
- + lwi $p0, [$p0 + lo12(ftrace_graph_return)]
- + bne $r15, $p0, _ftrace_graph_caller
- +
- + sethi $r15, hi20(ftrace_graph_entry)
- + lwi $r15, [$r15 + lo12(ftrace_graph_entry)]
- + sethi $p0, hi20(ftrace_graph_entry_stub)
- + ori $p0, $p0, lo12(ftrace_graph_entry_stub)
- + bne $r15, $p0, _ftrace_graph_caller
- +#endif
- +
- +_ftrace_stub:
- +ftrace_stub:
- + ret
- +
- +trace:
- + smw.adm $r0, [$sp], $r5, #10
- + move $r0, $lp
- + sethi $r15, hi20(get_selfpc)
- + ori $r15, $r15, lo12(get_selfpc)
- + jral $r15
- + move $r1, $r0
- + lwi $r0, [$sp+36]
- + jral $p0
- + lmw.bim $r0, [$sp], $r5, #10
- + ret
- +#endif
- +
- +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- + .global ftrace_graph_caller
- + .global return_to_handler
- +_ftrace_graph_caller:
- +ftrace_graph_caller:
- + sethi $p1, hi20(function_trace_stop)
- + lwi $p1, [$p1 + lo12(function_trace_stop)]
- + bnez $p1, ftrace_stub
- +
- + sethi $p1, hi20(prepare_ftrace_return)
- + ori $p1, $p1, lo12(prepare_ftrace_return)
- +
- + smw.adm $r0, [$sp], $r5, #10
- + move $r0, $lp
- + sethi $p0, hi20(get_selfpc)
- + ori $p0, $p0, lo12(get_selfpc)
- + jral $p0
- + move $r1, $r0
- + addi $r0, $sp, #36
- + jral $p1
- + lmw.bim $r0, [$sp], $r5, #10
- + ret
- +
- +return_to_handler:
- + smw.adm $r0, [$sp], $r5, #10
- + sethi $r15, hi20(ftrace_return_to_handler)
- + ori $r15, $r15, lo12(ftrace_return_to_handler)
- + jral $r15
- + move $r15, $r0
- + lmw.bim $r0, [$sp], $r5, #10
- + jr $r15
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/fpu.c linux-3.4.110/arch/nds32/kernel/fpu.c
- --- linux-3.4.110.orig/arch/nds32/kernel/fpu.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/fpu.c 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,306 @@
- +/*
- + * arch/nds32/kernel/fpu.c
- + *
- + * Copyright (C) 2001 Manuela Cirronis, Paolo Alberelli
- + * Copyright (C) 2002 STMicroelectronics Limited
- + * Author : Stuart Menefy
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * Started from SH4 version:
- + * Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka
- + *
- + * This file is subject to the terms and conditions of the GNU General Public
- + * License. See the file "COPYING" in the main directory of this archive
- + * for more details.
- + */
- +#include <linux/sched.h>
- +#include <linux/signal.h>
- +#include <asm/processor.h>
- +#include <asm/user.h>
- +#include <asm/io.h>
- +#include <asm/bitfield.h>
- +#include <asm/fpu.h>
- +#include "fpu.h"
- +
- +extern void do_revinsn(struct pt_regs *regs);
- +extern int do_fpu_denorm(struct pt_regs *regs, struct fpu_struct *fpu);
- +
- +static struct fpu_struct init_fpuregs = {
- + .fs_regs = {[0 ... 31] = sNAN32},
- + .fd_regs = {[0 ... 15] = sNAN64},
- + .fpcsr = FPCSR_INIT
- +};
- +
- +void save_fpu(struct task_struct *tsk)
- +{
- + unsigned int fpcfg, fpcsr;
- + enable_fpu();
- + asm volatile ("fmfcfg %0\n\t":"=&r" (fpcfg));
- + fpcfg = ((fpcfg & FPCFG_mskFREG) >> FPCFG_offFREG);
- +
- + switch (fpcfg) {
- + case 3:
- + asm volatile ("fsdi $fd31, [%0+0xf8]\n\t"
- + "fsdi $fd30, [%0+0xf0]\n\t"
- + "fsdi $fd29, [%0+0xe8]\n\t"
- + "fsdi $fd28, [%0+0xe0]\n\t"
- + "fsdi $fd27, [%0+0xd8]\n\t"
- + "fsdi $fd26, [%0+0xd0]\n\t"
- + "fsdi $fd25, [%0+0xc8]\n\t"
- + "fsdi $fd24, [%0+0xc0]\n\t"
- + "fsdi $fd23, [%0+0xb8]\n\t"
- + "fsdi $fd22, [%0+0xb0]\n\t"
- + "fsdi $fd21, [%0+0xa8]\n\t"
- + "fsdi $fd20, [%0+0xa0]\n\t"
- + "fsdi $fd19, [%0+0x98]\n\t"
- + "fsdi $fd18, [%0+0x90]\n\t"
- + "fsdi $fd17, [%0+0x88]\n\t"
- + "fsdi $fd16, [%0+0x80]\n\t"
- + : /* no output */
- + :"r" (&tsk->thread.fpu)
- + :"memory");
- + /* fall through */
- + case 2:
- + asm volatile ("fssi $fs31, [%0+0x7c]\n\t"
- + "fssi $fs30, [%0+0x78]\n\t"
- + "fssi $fs29, [%0+0x74]\n\t"
- + "fssi $fs28, [%0+0x70]\n\t"
- + "fssi $fs27, [%0+0x6c]\n\t"
- + "fssi $fs26, [%0+0x68]\n\t"
- + "fssi $fs25, [%0+0x64]\n\t"
- + "fssi $fs24, [%0+0x60]\n\t"
- + "fssi $fs23, [%0+0x5c]\n\t"
- + "fssi $fs22, [%0+0x58]\n\t"
- + "fssi $fs21, [%0+0x54]\n\t"
- + "fssi $fs20, [%0+0x50]\n\t"
- + "fssi $fs19, [%0+0x4c]\n\t"
- + "fssi $fs18, [%0+0x48]\n\t"
- + "fssi $fs17, [%0+0x44]\n\t"
- + "fssi $fs16, [%0+0x40]\n\t"
- + : /* no output */
- + :"r" (&tsk->thread.fpu)
- + :"memory");
- + /* fall through */
- + case 1:
- + asm volatile ("fssi $fs15, [%0+0x3c]\n\t"
- + "fssi $fs14, [%0+0x38]\n\t"
- + "fssi $fs13, [%0+0x34]\n\t"
- + "fssi $fs12, [%0+0x30]\n\t"
- + "fssi $fs11, [%0+0x2c]\n\t"
- + "fssi $fs10, [%0+0x28]\n\t"
- + "fssi $fs9, [%0+0x24]\n\t"
- + "fssi $fs8, [%0+0x20]\n\t"
- + : /* no output */
- + :"r" (&tsk->thread.fpu)
- + :"memory");
- + /* fall through */
- + case 0:
- + asm volatile ("fssi $fs7, [%1+0x1c]\n\t"
- + "fssi $fs6, [%1+0x18]\n\t"
- + "fssi $fs5, [%1+0x14]\n\t"
- + "fssi $fs4, [%1+0x10]\n\t"
- + "fssi $fs3, [%1+0xc]\n\t"
- + "fssi $fs2, [%1+0x8]\n\t"
- + "fssi $fs1, [%1+0x4]\n\t"
- + "fssi $fs0, [%1+0x0]\n\t"
- + "fmfcsr %0\n\t"
- + "swi %0, [%1+0x100]\n\t"
- + :"=&r" (fpcsr)
- + :"r"(&tsk->thread.fpu)
- + :"memory");
- + }
- + disable_fpu();
- +}
- +
- +void fpload(struct fpu_struct *fpregs)
- +{
- + unsigned int fpcfg, fpcsr;
- + enable_fpu();
- +
- + asm volatile ("fmfcfg %0\n\t":"=&r" (fpcfg));
- + fpcfg = ((fpcfg & FPCFG_mskFREG) >> FPCFG_offFREG);
- +
- + switch (fpcfg) {
- + case 3:
- + asm volatile ("fldi $fd31, [%0+0xf8]\n\t"
- + "fldi $fd30, [%0+0xf0]\n\t"
- + "fldi $fd29, [%0+0xe8]\n\t"
- + "fldi $fd28, [%0+0xe0]\n\t"
- + "fldi $fd27, [%0+0xd8]\n\t"
- + "fldi $fd26, [%0+0xd0]\n\t"
- + "fldi $fd25, [%0+0xc8]\n\t"
- + "fldi $fd24, [%0+0xc0]\n\t"
- + "fldi $fd23, [%0+0xb8]\n\t"
- + "fldi $fd22, [%0+0xb0]\n\t"
- + "fldi $fd21, [%0+0xa8]\n\t"
- + "fldi $fd20, [%0+0xa0]\n\t"
- + "fldi $fd19, [%0+0x98]\n\t"
- + "fldi $fd18, [%0+0x90]\n\t"
- + "fldi $fd17, [%0+0x88]\n\t"
- + "fldi $fd16, [%0+0x80]\n\t"
- + : /* no output */
- + :"r" (fpregs));
- + /* fall through */
- + case 2:
- + asm volatile ("flsi $fs31, [%0+0x7c]\n\t"
- + "flsi $fs30, [%0+0x78]\n\t"
- + "flsi $fs29, [%0+0x74]\n\t"
- + "flsi $fs28, [%0+0x70]\n\t"
- + "flsi $fs27, [%0+0x6c]\n\t"
- + "flsi $fs26, [%0+0x68]\n\t"
- + "flsi $fs25, [%0+0x64]\n\t"
- + "flsi $fs24, [%0+0x60]\n\t"
- + "flsi $fs23, [%0+0x5c]\n\t"
- + "flsi $fs22, [%0+0x58]\n\t"
- + "flsi $fs21, [%0+0x54]\n\t"
- + "flsi $fs20, [%0+0x50]\n\t"
- + "flsi $fs19, [%0+0x4c]\n\t"
- + "flsi $fs18, [%0+0x48]\n\t"
- + "flsi $fs17, [%0+0x44]\n\t"
- + "flsi $fs16, [%0+0x40]\n\t"
- + : /* no output */
- + :"r" (fpregs));
- + /* fall through */
- + case 1:
- + asm volatile ("flsi $fs15, [%0+0x3c]\n\t"
- + "flsi $fs14, [%0+0x38]\n\t"
- + "flsi $fs13, [%0+0x34]\n\t"
- + "flsi $fs12, [%0+0x30]\n\t"
- + "flsi $fs11, [%0+0x2c]\n\t"
- + "flsi $fs10, [%0+0x28]\n\t"
- + "flsi $fs9, [%0+0x24]\n\t"
- + "flsi $fs8, [%0+0x20]\n\t"
- + : /* no output */
- + :"r" (fpregs));
- + /* fall through */
- + case 0:
- + asm volatile ("flsi $fs7, [%1+0x1c]\n\t"
- + "flsi $fs6, [%1+0x18]\n\t"
- + "flsi $fs5, [%1+0x14]\n\t"
- + "flsi $fs4, [%1+0x10]\n\t"
- + "flsi $fs3, [%1+0xc]\n\t"
- + "flsi $fs2, [%1+0x8]\n\t"
- + "flsi $fs1, [%1+0x4]\n\t"
- + "flsi $fs0, [%1+0x0]\n\t"
- + "lwi %0, [%1+0x100]\n\t"
- + "fmtcsr %0\n\t":"=&r" (fpcsr)
- + :"r"(fpregs));
- + }
- + disable_fpu();
- +}
- +
- +void do_fpu_context_switch(unsigned long error_code, struct pt_regs *regs)
- +{
- + /* Enable to use FPU. */
- +
- + if (!user_mode(regs)) {
- + printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
- + BUG();
- + return;
- + }
- +
- + grab_fpu(regs);
- +#ifndef CONFIG_UNLAZY_FPU //Lazy FPU is used
- + if (last_task_used_math == current)
- + return;
- + if (last_task_used_math != NULL)
- + /* Other processes fpu state, save away */
- + save_fpu(last_task_used_math);
- + last_task_used_math = current;
- +#endif
- + if (used_math()) {
- + fpload(¤t->thread.fpu);
- + } else {
- + /* First time FPU user. */
- + fpload(&init_fpuregs);
- + set_used_math();
- + }
- +
- +}
- +
- +void do_fpu_exception(unsigned long error_code, struct pt_regs *regs)
- +{
- + unsigned int subtype =
- + ((GET_ITYPE() & ITYPE_mskSTYPE) >> ITYPE_offSTYPE);
- + unsigned int cpid = ((GET_ITYPE() & ITYPE_mskCPID) >> ITYPE_offCPID);
- +
- + /* FPU */
- + if ((cpid == 0) && (GET_FUCOP_EXIST() & FUCOP_EXIST_mskCP0ISFPU)) {
- + /* Coprocessor disabled exception */
- + if (subtype == 1) {
- + preempt_disable();
- + do_fpu_context_switch(error_code, regs);
- + preempt_enable();
- + }
- + /* Coprocessor exception */
- + else if (subtype == 2) {
- + siginfo_t si = { 0 };
- + unsigned int fpcsr;
- + enable_fpu();
- + asm volatile ("fmfcsr %0\n\t":"=&r" (fpcsr));
- + disable_fpu();
- +
- + if (fpcsr & FPCSR_mskALLT) {
- + si.si_signo = SIGFPE;
- + /* Exception handling, denorm input, UDF and OVF */
- + if (fpcsr & FPCSR_mskDNIT) {
- + unsigned int rfpcsr;
- + lose_fpu(1);
- + si.si_signo =
- + do_fpu_denorm(regs,
- + ¤t->thread.fpu);
- + own_fpu(1);
- +
- + if (si.si_signo == SIGFPE) {
- + rfpcsr =
- + current->thread.fpu.fpcsr;
- +
- + if (rfpcsr & FPCSR_mskIVO)
- + si.si_code = FPE_FLTINV;
- + if (rfpcsr & FPCSR_mskDBZ)
- + si.si_code = FPE_FLTDIV;
- + if (rfpcsr & FPCSR_mskOVF)
- + si.si_code = FPE_FLTOVF;
- + if (rfpcsr & FPCSR_mskUDF)
- + si.si_code = FPE_FLTUND;
- + if (rfpcsr & FPCSR_mskIEX)
- + si.si_code = FPE_FLTRES;
- + } else if (si.si_code == SIGILL)
- + show_regs(regs);
- + else if (si.si_code == SIGBUS)
- + si.si_code = BUS_ADRERR;
- + } else if (fpcsr & FPCSR_mskRIT) {
- + printk("Reserved Instruction\n");
- + show_regs(regs);
- + if (!user_mode(regs))
- + do_exit(SIGILL);
- + si.si_signo = SIGILL;
- + } else if (fpcsr & FPCSR_mskUDFT)
- + si.si_code = FPE_FLTUND;
- + else if (fpcsr & FPCSR_mskOVFT)
- + si.si_code = FPE_FLTOVF;
- + else if (fpcsr & FPCSR_mskIVOT)
- + si.si_code = FPE_FLTINV;
- + else if (fpcsr & FPCSR_mskDBZT)
- + si.si_code = FPE_FLTDIV;
- + else if (fpcsr & FPCSR_mskIEXT)
- + si.si_code = FPE_FLTRES;
- + /* If something went wrong, signal */
- + if (si.si_signo) {
- + if (si.si_code == SIGILL) {
- + force_sig(si.si_signo, current);
- + } else {
- + si.si_addr =
- + (void __user *)
- + instruction_pointer(regs);
- + force_sig_info(si.si_signo, &si,
- + current);
- + }
- + }
- + } else {
- + printk("Bad FPU exception\n");
- + BUG();
- + }
- + }
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/fpu.h linux-3.4.110/arch/nds32/kernel/fpu.h
- --- linux-3.4.110.orig/arch/nds32/kernel/fpu.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/fpu.h 2016-04-07 10:20:50.938080870 +0200
- @@ -0,0 +1,13 @@
- +
- +
- +/*
- + * Initially load the FPU with signalling NANS. This bit pattern
- + * has the property that no matter whether considered as single or as
- + * double precision, it still represents a signalling NAN.
- + */
- +
- + #define sNAN64 0xFFFFFFFFFFFFFFFFULL
- + #define sNAN32 0xFFFFFFFFUL
- +
- + #define FPCSR_INIT 0x0 /* Hardware reset value */
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/ftrace.c linux-3.4.110/arch/nds32/kernel/ftrace.c
- --- linux-3.4.110.orig/arch/nds32/kernel/ftrace.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/ftrace.c 2016-04-07 10:20:50.942081024 +0200
- @@ -0,0 +1,219 @@
- +/*
- + * Code for replacing ftrace calls with jumps.
- + *
- + * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
- + *
- + * Thanks goes out to P.A. Semi, Inc for supplying me with a PPC64 box.
- + *
- + * Added function graph tracer code, taken from x86 that was written
- + * by Frederic Weisbecker, and ported to PPC by Steven Rostedt.
- + *
- + */
- +
- +#include <linux/spinlock.h>
- +#include <linux/hardirq.h>
- +#include <linux/uaccess.h>
- +#include <linux/module.h>
- +#include <linux/ftrace.h>
- +#include <linux/percpu.h>
- +#include <linux/init.h>
- +#include <linux/list.h>
- +
- +#include <asm/cacheflush.h>
- +#include <asm/ftrace.h>
- +
- +# define GET_ADDR(addr) (*(unsigned long *)addr)
- +
- +#ifdef CONFIG_DYNAMIC_FTRACE
- +static unsigned int ftrace_nop_replace(void)
- +{
- +// return PPC_INST_NOP;
- + return 0;
- +}
- +
- +static unsigned int
- +ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
- +{
- + unsigned int op;
- +
- + addr = GET_ADDR(addr);
- +
- + /* if (link) set op to 'bl' else 'b' */
- +// op = create_branch((unsigned int *)ip, addr, link ? 1 : 0);
- +
- + return op;
- +}
- +
- +static int
- +ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
- +{
- + unsigned int replaced;
- +
- + /*
- + * Note: Due to modules and __init, code can
- + * disappear and change, we need to protect against faulting
- + * as well as code changing. We do this by using the
- + * probe_kernel_* functions.
- + *
- + * No real locking needed, this code is run through
- + * kstop_machine, or before SMP starts.
- + */
- +
- + /* read the text we want to modify */
- + if (probe_kernel_read(&replaced, (void *)ip, MCOUNT_INSN_SIZE))
- + return -EFAULT;
- +
- + /* Make sure it is what we expect it to be */
- + if (replaced != old)
- + return -EINVAL;
- +
- + /* replace the text with the new text */
- + if (probe_kernel_write((void *)ip, &new, MCOUNT_INSN_SIZE))
- + return -EPERM;
- +
- + flush_icache_range(ip, ip + 8);
- +
- + return 0;
- +}
- +
- +int ftrace_make_nop(struct module *mod,
- + struct dyn_ftrace *rec, unsigned long addr)
- +{
- + unsigned long ip = rec->ip;
- + unsigned int old, new;
- +
- + old = ftrace_call_replace(ip, addr, 1);
- + new = ftrace_nop_replace();
- + return ftrace_modify_code(ip, old, new);
- +}
- +
- +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
- +{
- + unsigned long ip = rec->ip;
- + unsigned int old, new;
- +
- + old = ftrace_nop_replace();
- + new = ftrace_call_replace(ip, addr, 1);
- + return ftrace_modify_code(ip, old, new);
- +}
- +
- +int ftrace_update_ftrace_func(ftrace_func_t func)
- +{
- + unsigned long ip = (unsigned long)(&ftrace_call);
- + unsigned int old, new;
- + int ret;
- +
- + old = *(unsigned int *)&ftrace_call;
- + new = ftrace_call_replace(ip, (unsigned long)func, 1);
- + ret = ftrace_modify_code(ip, old, new);
- +
- + return ret;
- +}
- +
- +int __init ftrace_dyn_arch_init(void *data)
- +{
- + /* caller expects data to be zero */
- + unsigned long *p = data;
- +
- + *p = 0;
- +
- + return 0;
- +}
- +#endif /* CONFIG_DYNAMIC_FTRACE */
- +
- +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- +
- +#ifdef CONFIG_DYNAMIC_FTRACE
- +extern void ftrace_graph_call(void);
- +extern void ftrace_graph_stub(void);
- +
- +int ftrace_enable_ftrace_graph_caller(void)
- +{
- + unsigned long ip = (unsigned long)(&ftrace_graph_call);
- + unsigned long addr = (unsigned long)(&ftrace_graph_caller);
- + unsigned long stub = (unsigned long)(&ftrace_graph_stub);
- + unsigned int old, new;
- +
- + old = ftrace_call_replace(ip, stub, 0);
- + new = ftrace_call_replace(ip, addr, 0);
- +
- + return ftrace_modify_code(ip, old, new);
- +}
- +
- +int ftrace_disable_ftrace_graph_caller(void)
- +{
- + unsigned long ip = (unsigned long)(&ftrace_graph_call);
- + unsigned long addr = (unsigned long)(&ftrace_graph_caller);
- + unsigned long stub = (unsigned long)(&ftrace_graph_stub);
- + unsigned int old, new;
- +
- + old = ftrace_call_replace(ip, addr, 0);
- + new = ftrace_call_replace(ip, stub, 0);
- +
- + return ftrace_modify_code(ip, old, new);
- +}
- +#endif /* CONFIG_DYNAMIC_FTRACE */
- +int get_selfpc(unsigned long mcount_lp)
- +{
- + unsigned long symbol_size, offset;
- + kallsyms_lookup_size_offset(mcount_lp, &symbol_size, &offset);
- + return mcount_lp - offset;
- +}
- +
- +/*
- + * Hook the return address and push it in the stack of return addrs
- + * in current thread info.
- + */
- +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
- +{
- + unsigned long old;
- + int faulted;
- + struct ftrace_graph_ent trace;
- + unsigned long return_hooker = (unsigned long)&return_to_handler;
- +
- + if (unlikely(atomic_read(¤t->tracing_graph_pause)))
- + return;
- +
- + /*
- + * Protect against fault, even if it shouldn't
- + * happen. This tool is too much intrusive to
- + * ignore such a protection.
- + */
- + asm volatile ("1: lwi %[old], [%[parent]]\n"
- + "2: swi %[return_hooker], [%[parent]]\n"
- + " movi %[faulted], 0\n"
- + "3:\n"
- + ".section .fixup, \"ax\"\n"
- + ".align 2 \n"
- + "4: movi %[faulted], 1\n"
- + " b 3b\n"
- + ".previous\n"
- + ".section __ex_table,\"a\"\n"
- + ".align 3 \n"
- + ".long 1b,4b\n"
- + ".long 2b,4b\n"
- + ".previous":[old] "=&r"(old),[faulted] "=r"(faulted)
- + :[parent] "r"(parent),[return_hooker] "r"(return_hooker)
- + :"memory");
- +
- + if (unlikely(faulted)) {
- + ftrace_graph_stop();
- + WARN_ON(1);
- + return;
- + }
- +
- + trace.func = self_addr;
- + trace.depth = current->curr_ret_stack + 1;
- +
- + /* Only trace if the calling function expects to */
- + if (!ftrace_graph_entry(&trace)) {
- + *parent = old;
- + return;
- + }
- +
- + if (ftrace_push_return_trace(old, self_addr, &trace.depth, 0) == -EBUSY) {
- + *parent = old;
- + return;
- + }
- +}
- +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/head.S linux-3.4.110/arch/nds32/kernel/head.S
- --- linux-3.4.110.orig/arch/nds32/kernel/head.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/head.S 2016-04-07 10:20:50.942081024 +0200
- @@ -0,0 +1,350 @@
- +/*
- + * arch/nds32/kernel/head.S
- + *
- + * NDS32 Kernel startup code
- + *
- + * Copyright (C) 2007 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + */
- +#include <linux/linkage.h>
- +#include <linux/init.h>
- +#include <asm/assembler.h>
- +#include <asm/mach-types.h>
- +#include <asm/procinfo.h>
- +#include <asm/ptrace.h>
- +#include <asm/asm-offsets.h>
- +//#include <asm/system.h>
- +#include <asm/page.h>
- +#include <asm/pgtable.h>
- +#include <asm/l2_cache.h>
- +#include <asm/sizes.h>
- +
- +/*
- + * We place the page tables 16K below TEXTADDR. Therefore, we must make sure
- + * that TEXTADDR is correctly set. Currently, we expect the least significant
- + * 16 bits to be 0x8000, but we could probably relax this restriction to
- + * TEXTADDR >= PAGE_OFFSET + 0x4000
- + *
- + * Note that swapper_pg_dir is the virtual address of the page tables, and
- + * pgtbl gives us a position-independent reference to these tables. We can
- + * do this because _stext == TEXTADDR
- + */
- +
- + .globl swapper_pg_dir
- + .equ swapper_pg_dir, TEXTADDR - 0x4000
- +
- +/*
- + * Kernel startup entry point.
- + * ---------------------------
- + *
- + * This is normally called from the decompressor code. The requirements
- + * are: MMU = off, D-cache = off, I-cache = dont care, $r0 = 0,
- + * $r1 = machine nr.
- + *
- + * This code is mostly position independent, so if you link the kernel at
- + * 0xc0008000, you call this at __pa(0xc0008000).
- + *
- + * See linux/arch/nds32/tools/mach-types for the complete list of machine
- + * numbers for $r1.
- + *
- + * We're trying to keep crap to a minimum; DO NOT add any machine specific
- + * crap here - that's what the boot loader (or in extreme, well justified
- + * circumstances, zImage) is for.
- + */
- + .section ".head.text", "ax"
- + .type _stext, %function
- +ENTRY(_stext)
- + setgie.d ! Disable interrupt
- + isb
- + move $r1, #MACH_TYPE_FARADAY ! Note: as far, we are in the Superuser mode
- + jal __lookup_processor_type ! get processor id, $r5=procinfo, $r9=cpuid, invalid processor $r5=0
- + li $r2, 'p'
- + beqz $r5, __error ! yes, error 'p'
- + jal __lookup_machine_type ! $r5=machinfo
- + li $r2, 'a'
- + beqz $r5, __error
- +
- +/*
- + * Create a temporary mapping area for booting, before start_kernel
- + */
- + sethi $r4, hi20(swapper_pg_dir)
- + li $p0, (PAGE_OFFSET - PHYS_OFFSET)
- + sub $r4, $r4, $p0
- + tlbop FlushAll ! invalidate TLB\n"
- + isb
- + mtsr $r4, $L1_PPTB ! load page table pointer\n"
- +
- +/* set NTC0 cacheable/writeback, mutliple page size in use */
- + mfsr $r3, $MMU_CTL
- + li $r0, ~0x6
- + and $r3, $r3, $r0
- + ori $r3, $r3, 0x404
- + mtsr $r3, $MMU_CTL
- + isb
- +
- +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
- + li $r2, #(PHYS_OFFSET + 0x7bf)
- +#else
- + li $r2, #(PHYS_OFFSET + 0x6bf) ! to remember here
- +#endif
- + movi $r3, #0x5
- + mtsr $r3, $TLB_MISC
- +
- + sethi $r3, hi20(PAGE_OFFSET)
- + li $r0, #PHYS_OFFSET
- + sethi $r5, hi20(SZ_1M) ! Use 1MB pages
- + sethi $r6, hi20(PHYS_OFFSET+SZ_32M) ! Create 32MB first, leave the rest in paging_init()
- +_tlb:
- + mtsr $r3, $TLB_VPN
- + dsb
- + tlbop $r2, RWR
- + isb
- + add $r0, $r0, $r5
- + add $r3, $r3, $r5
- + add $r2, $r2, $r5
- + bne $r0, $r6, _tlb
- +
- + mtsr $r3, $TLB_MISC ! setup access page size
- + li $r2, #~0xf
- + and $r3, $r3, $r2
- +#ifdef CONFIG_ANDES_PAGE_SIZE_8KB
- + ori $r3, $r3, #0x1
- +#endif
- + mtsr $r3, $TLB_MISC
- +
- + mfsr $r0, $MISC_CTL ! Enable BTB and RTP
- + li $r1, #~0x3
- + and $r0, $r0, $r1
- + mtsr $r0, $MISC_CTL
- +
- +/*
- + * Disable L2CC and wait until L2CC registers are mapped into memory to use L2$.
- + */
- +#ifdef CONFIG_CACHE_L2
- + li $p0, L2CC_PA_BASE
- + li $p1, 0
- + swi $p1, [$p0 + L2CC_CTRL_OFF]
- +#endif
- +
- +#ifdef CONFIG_PLAT_AG102
- +/*
- + * Set GPUBA to 0x0c000006. GPUB 0x1c000000, FB size 64MB.
- + */
- + li $p0, DDR2C_PA_BASE + 0x02a4
- + li $p1, 0x0c000006
- + swi $p1, [$p0]
- +#endif
- +
- + mfsr $p1, $PSW
- + li $r15, #~0x43df ! clear WBNA|DME|IME|DT|IT|POM|INTL|GIE
- + and $p1, $p1, $r15
- +#ifdef __NDS32_EB__
- + #ifdef CONFIG_WBNA
- + ori $p1, $p1, #0x40ea ! set WBNA|DT|IT|BE|POM:super|INTL:1
- + #else
- + ori $p1, $p1, #0xea ! set ----|DT|IT|BE|POM:super|INTL:1
- + #endif
- +#else
- + #ifdef CONFIG_WBNA
- + ori $p1, $p1, #0x40ca ! set WBNA|DT|IT|--|POM:super|INTL:1
- + #else
- + ori $p1, $p1, #0xca ! set ----|DT|IT|--|POM:super|INTL:1
- + #endif
- +#endif
- +
- + mtsr $p1, $IPSW ! when iret, it will automatically enable MMU
- + la $lp, __mmap_switched
- + mtsr $lp, $IPC
- + iret
- + nop
- +
- + .type __switch_data, %object
- +__switch_data:
- + .long __mmap_switched
- + .long _sdata ! $r5
- + .long __bss_start ! $r6
- + .long _end ! $r7
- + .long __machine_arch_type ! $r5
- + .long init_thread_union + 8192 ! $sp
- +
- +
- +/*
- + * The following fragment of code is executed with the MMU on in MMU mode,
- + * and uses absolute addresses; this is not position independent.
- + *
- + * $r0
- + * $r10 = points to proc info
- + * $r8 = points to machine info,
- + * $r1 = machine ID, 0x2c8 for Andes AG101 board
- + * $r9 = processor ID of value in version register
- + */
- + .align
- + .type __mmap_switched, %function
- +__mmap_switched:
- + la $r3, __switch_data + 4
- + lmw.bim $r5, [$r3], $r7
- +
- + move $fp, #0 ! Clear BSS (and zero $fp)
- + beq $r7, $r6, _RRT
- +1: swi.bi $fp, [$r6], #4
- + bne $r7, $r6, 1b
- +
- +_RRT:
- + lmw.bim $r4, [$r3], $r4, #0b0001
- + sw $r1, [$r4] ! Save machine type to memory
- + b start_kernel
- +
- +
- +/*
- + * Read processor ID register (CP#15, $CR0), and look up in the linker-built
- + * supported processor list. Note that we can't use the absolute addresses
- + * for the __proc_info lists since we aren't running with the MMU on
- + * (and therefore, we are not in the correct address space). We have to
- + * calculate the offset.
- + *
- + * $r9 = cpuid, get from $CPU_VER
- + * Returns:
- + * $r3, $r4, $r6 corrupted
- + * $r5 = proc_info pointer in physical address space
- + * $r9 = cpuid
- + */
- +
- + .type __lookup_processor_type, %function
- +__lookup_processor_type:
- + la $r5, __proc_info_begin
- + la $r6, __proc_info_end
- + mfsr $r9, $CPU_VER ! get cpu version
- + li $p0, (PAGE_OFFSET - PHYS_OFFSET)
- +1:
- + sub $p1, $r5, $p0
- + lmw.bi $r3, [$p1], $r4 ! value, mask
- + and $r4, $r4, $r9 ! mask wanted bits
- + xor $p1, $r3, $r4
- + beqz $p1, 2f
- + addi $r5, $r5, #PROC_INFO_SZ ! sizeof(proc_info_list)
- + bne $r5, $r6, 1b
- +
- + move $r5, #0 ! unknown processor -> exit
- +2: ret
- +
- +
- +
- +/*
- + * Lookup machine architecture in the linker-build list of architectures.
- + * Note that we can't use the absolute addresses for the __arch_info
- + * lists since we aren't running with the MMU on (and therefore, we are
- + * not in the correct address space). We have to calculate the offset.
- + *
- + * $r1 = machine architecture number
- + * Returns:
- + * $r3, $r4, $r6 corrupted
- + * $r5 = mach_info pointer in physical address space
- + */
- + .type __lookup_machine_type, %function
- +__lookup_machine_type:
- + la $r5, __arch_info_begin
- + la $r6, __arch_info_end
- +1:
- + li $p0, (PAGE_OFFSET - PHYS_OFFSET)
- + sub $p1, $r5, $p0
- + lwi $r3, [$p1] ! use PA to get machine type
- + xor $p1, $r3, $r1 ! matches loader number?
- + beqz $p1, 2f ! found
- + addi $r5, $r5, #SIZEOF_MACHINE_DESC ! next machine_desc
- + bne $r5, $r6, 1b
- + move $r5, #0 ! unknown machine
- +2: ret
- +
- +
- +/*
- + * Exception handling. Something went wrong and we can't proceed. We
- + * ought to tell the user, but since we don't have any guarantee that
- + * we're even running on the right architecture, we do virtually nothing.
- + *
- + * a = invalid architecture
- + * p = invalid processor
- + *
- + * Generally, only serious errors cause this.
- + */
- +__error:
- + li $r1, UART0_PA_BASE
- + sw $r2, [$r1]
- +die: b die
- +
- +
- +
- +#ifdef CONFIG_SMP
- +
- + .type secondary_startup, %function
- +ENTRY(secondary_startup)
- + /*
- + * Common entry point for secondary CPUs.
- + *
- + * Lookup the processor type - there is no need to check the
- + * machine type as it has already been validated by the
- + * primary processor.
- + */
- + mfsr $r0, $MMU_CTL
- + ori $r0, $r0, #4
- +#ifndef CONFIG_NO_KERNEL_LARGE_PAGE
- + ori $r0, $r0, #0x400
- +#endif
- + mtsr $r0, $MMU_CTL
- +
- + movi $r15, #0x01
- + swi $r15, [$p1+#0x10]
- + lwi $sp, [$p1+#0x18]
- +
- + /*
- + * Set stack, L1_PPTB, and enable mmu
- + */
- + sethi $r4, hi20(swapper_pg_dir)
- + li $p0, (PAGE_OFFSET - PHYS_OFFSET)
- + sub $r4, $r4, $p0
- +
- + tlbop FlushAll
- + isb
- + mtsr $r4, $L1_PPTB
- +
- +#ifdef CONFIG_CACHE_L2
- + li $r0, #0x1801
- + mtsr $r0, $HSMP_SADDR
- + isb
- + li $r0, #(L2CC_PA_BASE+0x10) ! L2CC Control
- + lwi $r1, [$r0]
- + li $r2, #~(0xf << 28)
- + and $r1, $r1, $r2
- + bset $r1, $r1, #29
- + bset $r1, $r1, #31
- + swi $r1, [$r0]
- +#endif
- +
- + move $fp, #0
- +
- + mfsr $p1, $PSW
- + li $r15, #~0x43df ! clear WBNA|DME|IME|DT|IT|POM|INTL|GIE
- + and $p1, $p1, $r15
- +#ifdef __NDS32_EB__
- + #ifdef CONFIG_WBNA
- + ori $p1, $p1, #0x40ea ! set WBNA|DT|IT|BE|POM:super|INTL:1
- + #else
- + ori $p1, $p1, #0xea ! set ----|DT|IT|BE|POM:super|INTL:1
- + #endif
- +#else
- + #ifdef CONFIG_WBNA
- + ori $p1, $p1, #0x40ca ! set WBNA|DT|IT|--|POM:super|INTL:1
- + #else
- + ori $p1, $p1, #0xca ! set ----|DT|IT|--|POM:super|INTL:1
- + #endif
- +#endif
- +
- + mtsr $p1, $IPSW ! when iret, it will automatically enable MMU
- + la $lp, secondary_start_kernel
- + mtsr $lp, $IPC
- + iret
- + nop
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/init_task.c linux-3.4.110/arch/nds32/kernel/init_task.c
- --- linux-3.4.110.orig/arch/nds32/kernel/init_task.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/init_task.c 2016-04-07 10:20:50.942081024 +0200
- @@ -0,0 +1,25 @@
- +/*
- + * linux/arch/nds32/kernel/init_task.c
- + *
- + * Copyright (C) 2009 Andes Technology Corporation
- + */
- +#include <linux/module.h>
- +#include <linux/init_task.h>
- +#include <linux/mqueue.h>
- +#include <linux/fs.h>
- +
- +#include <asm/uaccess.h>
- +
- +static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
- +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
- +
- +/* Initial task structure */
- +struct task_struct init_task = INIT_TASK(init_task);
- +EXPORT_SYMBOL(init_task);
- +
- +/*
- + * Initial thread structure. Alignment of this is handled by a special
- + * linker map entry.
- + */
- +union thread_union init_thread_union __init_task_data =
- + { INIT_THREAD_INFO(init_task) };
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/io.c linux-3.4.110/arch/nds32/kernel/io.c
- --- linux-3.4.110.orig/arch/nds32/kernel/io.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/io.c 2016-04-07 10:20:50.942081024 +0200
- @@ -0,0 +1,51 @@
- +#include <linux/module.h>
- +#include <linux/types.h>
- +
- +#include <asm/io.h>
- +
- +/*
- + * Copy data from IO memory space to "real" memory space.
- + * This needs to be optimized.
- + */
- +void _memcpy_fromio(void *to, const volatile void __iomem * from, size_t count)
- +{
- + unsigned char *t = to;
- + while (count) {
- + count--;
- + *t = readb(from);
- + t++;
- + from++;
- + }
- +}
- +
- +/*
- + * Copy data from "real" memory space to IO memory space.
- + * This needs to be optimized.
- + */
- +void _memcpy_toio(volatile void __iomem * to, const void *from, size_t count)
- +{
- + const unsigned char *f = from;
- + while (count) {
- + count--;
- + writeb(*f, to);
- + f++;
- + to++;
- + }
- +}
- +
- +/*
- + * "memset" on IO memory space.
- + * This needs to be optimized.
- + */
- +void _memset_io(volatile void __iomem * dst, int c, size_t count)
- +{
- + while (count) {
- + count--;
- + writeb(c, dst);
- + dst++;
- + }
- +}
- +
- +EXPORT_SYMBOL(_memcpy_fromio);
- +EXPORT_SYMBOL(_memcpy_toio);
- +EXPORT_SYMBOL(_memset_io);
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/irq.c linux-3.4.110/arch/nds32/kernel/irq.c
- --- linux-3.4.110.orig/arch/nds32/kernel/irq.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/irq.c 2016-04-07 10:20:50.942081024 +0200
- @@ -0,0 +1,122 @@
- +/*
- + * linux/arch/nds32/kernel/irq.c
- + *
- + * Copyright (C) 1992 Linus Torvalds
- + * Modifications for ARM processor Copyright (C) 1995-2000 Russell King.
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * This file contains the code used by various IRQ handling routines:
- + * asking for different IRQ's should be done through these routines
- + * instead of just grabbing them. Thus setups with different IRQ numbers
- + * shouldn't result in any weird surprises, and installing new handlers
- + * should be easier.
- + *
- + * IRQ's are in fact implemented a bit like signal handlers for the kernel.
- + * Naturally it's not a 1:1 relation, but there are similarities.
- + */
- +#include <linux/kernel_stat.h>
- +#include <linux/module.h>
- +#include <linux/interrupt.h>
- +#include <linux/irq.h>
- +#include <linux/slab.h>
- +#include <linux/random.h>
- +#include <linux/seq_file.h>
- +#include <linux/kallsyms.h>
- +
- +void (*init_arch_irq) (void)__initdata = NULL;
- +unsigned long irq_err_count;
- +
- +void ack_bad_irq(unsigned int irq)
- +{
- + printk("bad IRQ %d\n", irq);
- +}
- +
- +int show_interrupts(struct seq_file *p, void *v)
- +{
- + int i = *(loff_t *) v, cpu;
- + struct irqaction *action;
- + unsigned long flags;
- +
- + if (i == 0) {
- + char cpuname[12];
- +
- + seq_printf(p, " ");
- + for_each_present_cpu(cpu) {
- + sprintf(cpuname, "CPU%d", cpu);
- + seq_printf(p, " %10s", cpuname);
- + }
- + seq_putc(p, '\n');
- + }
- +
- + if (i < NR_IRQS) {
- + raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
- + action = irq_desc[i].action;
- + if (!action)
- + goto unlock;
- +
- + seq_printf(p, "%3d: ", i);
- + for_each_present_cpu(cpu)
- + seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
- + seq_printf(p, " %s", action->name);
- + for (action = action->next; action; action = action->next)
- + seq_printf(p, ", %s", action->name);
- +
- + seq_putc(p, '\n');
- +unlock:
- + raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
- + } else if (i == NR_IRQS) {
- + seq_printf(p, "Err: %10lu\n", irq_err_count);
- + }
- + return 0;
- +}
- +
- +/*
- + * do_IRQ handles all hardware IRQ's. Decoded IRQs should not
- + * come via this function. Instead, they should provide their
- + * own 'handler'
- + */
- +asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
- +{
- + struct pt_regs *old_regs = set_irq_regs(regs);
- +
- + /*
- + * Some hardware gives randomly wrong interrupts. Rather
- + * than crashing, do something sensible.
- + */
- + if (unlikely(irq >= NR_IRQS)) {
- + printk(KERN_EMERG "IRQ exceeds NR_IRQS\n");
- + BUG();
- + }
- +
- + irq_enter();
- + generic_handle_irq(irq);
- + irq_exit();
- + set_irq_regs(old_regs);
- +
- +}
- +
- +void __init init_IRQ(void)
- +{
- + int irq;
- +
- + for (irq = 0; irq < NR_IRQS; irq++)
- + irq_set_noprobe(irq);
- +
- + init_arch_irq();
- +}
- +
- +#ifdef CONFIG_TRACE_IRQFLAGS
- +void notrace arch_trace_hardirqs_on(void)
- +{
- + trace_hardirqs_on();
- +}
- +
- +void notrace arch_trace_hardirqs_off(void)
- +{
- + trace_hardirqs_off();
- +}
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/kgdb.c linux-3.4.110/arch/nds32/kernel/kgdb.c
- --- linux-3.4.110.orig/arch/nds32/kernel/kgdb.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/kgdb.c 2016-04-07 10:20:50.942081024 +0200
- @@ -0,0 +1,291 @@
- +/* ============================================================================
- + *
- + * arch/nds32/kernel/kgdb.c
- + *
- + * Copyright (C) 2007 Andes Technology Corporation
- + * This file is part of Linux and should be licensed under the GPL.
- + * See the file COPYING for conditions for redistribution.
- + *
- + * Abstract:
- + *
- + * This program is for NDS32 KGDB support.
- + *
- + * Author: Harry Pan
- + *
- + * Revision History:
- + *
- + * Nov.23.2007 Initial ported by Harry,
- + * inherited from the KGDB in 2.6.11 and 2.4.35.
- + *
- + * Note:
- + *
- + * ============================================================================
- + */
- +#include <linux/types.h>
- +#include <linux/kernel.h>
- +#include <linux/signal.h>
- +#include <linux/sched.h>
- +#include <linux/mm.h>
- +#include <linux/spinlock.h>
- +#include <linux/personality.h>
- +#include <linux/ptrace.h>
- +#include <linux/elf.h>
- +#include <linux/interrupt.h>
- +#include <linux/init.h>
- +#include <linux/kgdb.h>
- +#include <linux/kdebug.h>
- +
- +#include <asm/atomic.h>
- +#include <asm/io.h>
- +#include <asm/pgtable.h>
- +#include <asm/system.h>
- +#include <asm/uaccess.h>
- +#include <asm/unistd.h>
- +#include <asm/ptrace.h>
- +#include <asm/traps.h>
- +
- +// ============================================================================
- +// regs_to_gdb_regs()
- +//
- +// Make a local copy of the registers passed into the handler (bletch).
- +// ============================================================================
- +void pt_regs_to_gdb_regs(unsigned long *gregs, struct pt_regs *kregs)
- +{
- + int regno;
- +
- + /* Initialize all to zero (??) */
- + for (regno = 0; regno < NDS32_NUM_REGS; regno++)
- + gregs[regno] = 0;
- +
- + gregs[0] = kregs->NDS32_r0;
- + gregs[1] = kregs->NDS32_r1;
- + gregs[2] = kregs->NDS32_r2;
- + gregs[3] = kregs->NDS32_r3;
- + gregs[4] = kregs->NDS32_r4;
- + gregs[5] = kregs->NDS32_r5;
- + gregs[6] = kregs->NDS32_r6;
- + gregs[7] = kregs->NDS32_r7;
- + gregs[8] = kregs->NDS32_r8;
- + gregs[9] = kregs->NDS32_r9;
- + gregs[10] = kregs->NDS32_r10;
- + gregs[11] = kregs->NDS32_r11;
- + gregs[12] = kregs->NDS32_r12;
- + gregs[13] = kregs->NDS32_r13;
- + gregs[14] = kregs->NDS32_r14;
- + gregs[15] = kregs->NDS32_r15;
- + gregs[16] = kregs->NDS32_r16;
- + gregs[17] = kregs->NDS32_r17;
- + gregs[18] = kregs->NDS32_r18;
- + gregs[19] = kregs->NDS32_r19;
- + gregs[20] = kregs->NDS32_r20;
- + gregs[21] = kregs->NDS32_r21;
- + gregs[22] = kregs->NDS32_r22;
- + gregs[23] = kregs->NDS32_r23;
- + gregs[24] = kregs->NDS32_r24;
- + gregs[25] = kregs->NDS32_r25;
- + gregs[26] = kregs->NDS32_pp0;
- + gregs[27] = kregs->NDS32_pp1;
- + gregs[28] = kregs->NDS32_fp;
- + gregs[29] = kregs->NDS32_gp;
- + gregs[30] = kregs->NDS32_lp;
- + gregs[31] = kregs->NDS32_sp;
- + gregs[32] = kregs->NDS32_ipc;
- + gregs[33] = kregs->NDS32_d0lo;
- + gregs[34] = kregs->NDS32_d0hi;
- + gregs[35] = kregs->NDS32_d1lo;
- + gregs[36] = kregs->NDS32_d1hi;
- + gregs[NDS32_IR0_REGNUM] = kregs->NDS32_ipsw;
- +}
- +
- +// ============================================================================
- +// gdb_regs_to_regs()
- +//
- +// Copy local gdb registers back to kgdb regs, for later copy to kernel.
- +// ============================================================================
- +void gdb_regs_to_pt_regs(unsigned long *gregs, struct pt_regs *kregs)
- +{
- + kregs->NDS32_r0 = gregs[0];
- + kregs->NDS32_r1 = gregs[1];
- + kregs->NDS32_r2 = gregs[2];
- + kregs->NDS32_r3 = gregs[3];
- + kregs->NDS32_r4 = gregs[4];
- + kregs->NDS32_r5 = gregs[5];
- + kregs->NDS32_r6 = gregs[6];
- + kregs->NDS32_r7 = gregs[7];
- + kregs->NDS32_r8 = gregs[8];
- + kregs->NDS32_r9 = gregs[9];
- + kregs->NDS32_r10 = gregs[10];
- + kregs->NDS32_r11 = gregs[11];
- + kregs->NDS32_r12 = gregs[12];
- + kregs->NDS32_r13 = gregs[13];
- + kregs->NDS32_r14 = gregs[14];
- + kregs->NDS32_r15 = gregs[15];
- + kregs->NDS32_r16 = gregs[16];
- + kregs->NDS32_r17 = gregs[17];
- + kregs->NDS32_r18 = gregs[18];
- + kregs->NDS32_r19 = gregs[19];
- + kregs->NDS32_r20 = gregs[20];
- + kregs->NDS32_r21 = gregs[21];
- + kregs->NDS32_r22 = gregs[22];
- + kregs->NDS32_r23 = gregs[23];
- + kregs->NDS32_r24 = gregs[24];
- + kregs->NDS32_r25 = gregs[25];
- + kregs->NDS32_pp0 = gregs[26];
- + kregs->NDS32_pp1 = gregs[27];
- + kregs->NDS32_fp = gregs[28];
- + kregs->NDS32_gp = gregs[29];
- + kregs->NDS32_lp = gregs[30];
- + kregs->NDS32_sp = gregs[31];
- + kregs->NDS32_ipc = gregs[32];
- + kregs->NDS32_d0lo = gregs[33];
- + kregs->NDS32_d0hi = gregs[34];
- + kregs->NDS32_d1lo = gregs[35];
- + kregs->NDS32_d1hi = gregs[36];
- + kregs->NDS32_ipsw = gregs[NDS32_IR0_REGNUM];
- +}
- +
- +// ----------------------------------------------------------------------------
- +// kgdb_get_user_regs()
- +//
- +// Get user process registers.
- +// ----------------------------------------------------------------------------
- +static inline struct pt_regs *kgdb_get_user_regs(struct task_struct *task)
- +{
- + return (struct pt_regs *)
- + ((unsigned long)task_thread_info(task) + THREAD_SIZE -
- + 8 - sizeof(struct pt_regs));
- +}
- +
- +// ============================================================================
- +// sleeping_thread_to_gdb_regs()
- +//
- +// ============================================================================
- +void sleeping_thread_to_gdb_regs(unsigned long *gregs, struct task_struct *task)
- +{
- + int regno;
- + struct pt_regs *tregs;
- +
- + /* Just making sure... */
- + if (task == NULL)
- + return;
- +
- + /* Initialize to zero */
- + for (regno = 0; regno < NDS32_NUM_REGS; regno++)
- + gregs[regno] = 0;
- +
- + /* Otherwise, we have only some registers from switch_to() */
- + tregs = kgdb_get_user_regs(task);
- +
- + gregs[0] = tregs->NDS32_r0;
- + gregs[1] = tregs->NDS32_r1;
- + gregs[2] = tregs->NDS32_r2;
- + gregs[3] = tregs->NDS32_r3;
- + gregs[4] = tregs->NDS32_r4;
- + gregs[5] = tregs->NDS32_r5;
- + gregs[6] = tregs->NDS32_r6;
- + gregs[7] = tregs->NDS32_r7;
- + gregs[8] = tregs->NDS32_r8;
- + gregs[9] = tregs->NDS32_r9;
- + gregs[10] = tregs->NDS32_r10;
- + gregs[11] = tregs->NDS32_r11;
- + gregs[12] = tregs->NDS32_r12;
- + gregs[13] = tregs->NDS32_r13;
- + gregs[14] = tregs->NDS32_r14;
- + gregs[15] = tregs->NDS32_r15;
- + gregs[16] = tregs->NDS32_r16;
- + gregs[17] = tregs->NDS32_r17;
- + gregs[18] = tregs->NDS32_r18;
- + gregs[19] = tregs->NDS32_r19;
- + gregs[20] = tregs->NDS32_r20;
- + gregs[21] = tregs->NDS32_r21;
- + gregs[22] = tregs->NDS32_r22;
- + gregs[23] = tregs->NDS32_r23;
- + gregs[24] = tregs->NDS32_r24;
- + gregs[25] = tregs->NDS32_r25;
- + gregs[26] = tregs->NDS32_pp0;
- + gregs[27] = tregs->NDS32_pp1;
- + gregs[28] = tregs->NDS32_fp;
- + gregs[29] = tregs->NDS32_gp;
- + gregs[30] = tregs->NDS32_lp;
- + gregs[31] = tregs->NDS32_sp;
- + gregs[32] = tregs->NDS32_ipc;
- + gregs[33] = tregs->NDS32_d0lo;
- + gregs[34] = tregs->NDS32_d0hi;
- + gregs[35] = tregs->NDS32_d1lo;
- + gregs[36] = tregs->NDS32_d1hi;
- + gregs[NDS32_IR0_REGNUM] = tregs->NDS32_ipsw;
- +}
- +
- +int kgdb_arch_handle_exception(int exception_vector, int signo,
- + int err_code, char *remcom_in_buffer,
- + char *remcom_out_buffer,
- + struct pt_regs *linux_regs)
- +{
- + long addr;
- + char *ptr;
- +
- + if (0 == atomic_dec_if_positive(&kgdb_setting_breakpoint))
- + linux_regs->NDS32_ipc += 2;
- +
- + switch (remcom_in_buffer[0]) {
- + case 'k':
- + case 'D':
- + case 'c':
- + case 's':
- + kgdb_contthread = NULL;
- +
- + /*
- + * Try to read optional parameter, pc unchanged if no parm.
- + * If this was a compiled breakpoint, we need to move
- + * to the next instruction or we will just breakpoint
- + * over and over again.
- + */
- + ptr = &remcom_in_buffer[1];
- + if (kgdb_hex2long(&ptr, &addr)) {
- + linux_regs->NDS32_ipc = addr;
- + }
- + linux_regs->NDS32_ipsw &= ~0x800;
- + if (remcom_in_buffer[0] == 's') {
- + linux_regs->NDS32_ipsw |= 0x800;
- + }
- +
- + return 0;
- + }
- +
- + return -1;
- +}
- +
- +static int kgdb_notify(struct notifier_block *self,
- + unsigned long cmd, void *ptr)
- +{
- + struct die_args *args = ptr;
- + unsigned long addr = args->err;
- + if (addr > TASK_SIZE) {
- + kgdb_handle_exception(args->trapnr, args->signr,
- + args->err, args->regs);
- + return NOTIFY_STOP;
- + }
- + return NOTIFY_DONE;
- +}
- +
- +static struct notifier_block kgdb_notifier = {
- + .notifier_call = kgdb_notify,
- +};
- +
- +int kgdb_arch_init(void)
- +{
- + register_die_notifier(&kgdb_notifier);
- +}
- +
- +void kgdb_arch_exit(void)
- +{
- + unregister_die_notifier(&kgdb_notifier);
- +}
- +
- +struct kgdb_arch arch_kgdb_ops = {
- +#ifdef __NDS32_EL__
- + .gdb_bpt_instr = {0xeb, 0xff}
- +#else
- + .gdb_bpt_instr = {0xff, 0xeb}
- +#endif
- +};
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/kprobes.c linux-3.4.110/arch/nds32/kernel/kprobes.c
- --- linux-3.4.110.orig/arch/nds32/kernel/kprobes.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/kprobes.c 2016-04-07 10:20:50.942081024 +0200
- @@ -0,0 +1,869 @@
- +/*
- + * Kernel Probes (KProbes)
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- + *
- + * Copyright (C) IBM Corporation, 2002, 2004
- + *
- + * 2002-Oct Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel
- + * Probes initial implementation ( includes contributions from
- + * Rusty Russell).
- + * 2004-July Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
- + * interface to access function arguments.
- + * 2004-Oct Jim Keniston <jkenisto@us.ibm.com> and Prasanna S Panchamukhi
- + * <prasanna@in.ibm.com> adapted for x86_64 from i386.
- + * 2005-Mar Roland McGrath <roland@redhat.com>
- + * Fixed to handle %rip-relative addressing mode correctly.
- + * 2005-May Hien Nguyen <hien@us.ibm.com>, Jim Keniston
- + * <jkenisto@us.ibm.com> and Prasanna S Panchamukhi
- + * <prasanna@in.ibm.com> added function-return probes.
- + * 2005-May Rusty Lynch <rusty.lynch@intel.com>
- + * Added function return probes functionality
- + * 2006-Feb Masami Hiramatsu <hiramatu@sdl.hitachi.co.jp> added
- + * kprobe-booster and kretprobe-booster for i386.
- + * 2007-Dec Masami Hiramatsu <mhiramat@redhat.com> added kprobe-booster
- + * and kretprobe-booster for x86-64
- + * 2007-Dec Masami Hiramatsu <mhiramat@redhat.com>, Arjan van de Ven
- + * <arjan@infradead.org> and Jim Keniston <jkenisto@us.ibm.com>
- + * unified x86 kprobes code.
- + */
- +
- +#include <linux/kprobes.h>
- +#include <linux/ptrace.h>
- +#include <linux/string.h>
- +#include <linux/slab.h>
- +#include <linux/hardirq.h>
- +#include <linux/preempt.h>
- +#include <linux/module.h>
- +#include <linux/kdebug.h>
- +
- +#include <asm/cacheflush.h>
- +#include <asm/uaccess.h>
- +
- +#ifdef __NDS32_EL__
- +#define SZINSN(insn) (((insn & 0x00000080) == 0) ? 4 : 2)
- +#define BREAK16_1FE 0xFEEB
- +#else
- +#define SZINSN(insn) (((insn & 0x80000000) == 0) ? 4 : 2)
- +#define BREAK16_1FE 0xEBFE
- +#endif
- +
- +void jprobe_return_point(void);
- +
- +DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
- +DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
- +
- +#if 0
- +/* Insert a jump instruction at address 'from', which jumps to address 'to'.*/
- +static void __kprobes set_jmp_op(void *from, void *to)
- +{
- + struct __arch_jmp_op {
- + char op;
- + s32 raddr;
- + } __attribute__ ((packed)) * jop;
- + jop = (struct __arch_jmp_op *)from;
- + jop->raddr = (s32) ((long)(to) - ((long)(from) + 5));
- + jop->op = RELATIVEJUMP_INSTRUCTION;
- +}
- +
- +/*
- + * Check for the REX prefix which can only exist on X86_64
- + * X86_32 always returns 0
- + */
- +static int __kprobes is_REX_prefix(kprobe_opcode_t * insn)
- +{
- +#ifdef CONFIG_X86_64
- + if ((*insn & 0xf0) == 0x40)
- + return 1;
- +#endif
- + return 0;
- +}
- +
- +/*
- + * Returns non-zero if opcode is boostable.
- + * RIP relative instructions are adjusted at copying time in 64 bits mode
- + */
- +static int __kprobes can_boost(kprobe_opcode_t * opcodes)
- +{
- + kprobe_opcode_t opcode;
- + kprobe_opcode_t *orig_opcodes = opcodes;
- +
- + if (search_exception_tables(opcodes))
- + return 0; /* Page fault may occur on this address. */
- +
- +retry:
- + if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1)
- + return 0;
- + opcode = *(opcodes++);
- +
- + /* 2nd-byte opcode */
- + if (opcode == 0x0f) {
- + if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1)
- + return 0;
- + return test_bit(*opcodes,
- + (unsigned long *)twobyte_is_boostable);
- + }
- +
- + switch (opcode & 0xf0) {
- +#ifdef CONFIG_X86_64
- + case 0x40:
- + goto retry; /* REX prefix is boostable */
- +#endif
- + case 0x60:
- + if (0x63 < opcode && opcode < 0x67)
- + goto retry; /* prefixes */
- + /* can't boost Address-size override and bound */
- + return (opcode != 0x62 && opcode != 0x67);
- + case 0x70:
- + return 0; /* can't boost conditional jump */
- + case 0xc0:
- + /* can't boost software-interruptions */
- + return (0xc1 < opcode && opcode < 0xcc) || opcode == 0xcf;
- + case 0xd0:
- + /* can boost AA* and XLAT */
- + return (opcode == 0xd4 || opcode == 0xd5 || opcode == 0xd7);
- + case 0xe0:
- + /* can boost in/out and absolute jmps */
- + return ((opcode & 0x04) || opcode == 0xea);
- + case 0xf0:
- + if ((opcode & 0x0c) == 0 && opcode != 0xf1)
- + goto retry; /* lock/rep(ne) prefix */
- + /* clear and set flags are boostable */
- + return (opcode == 0xf5 || (0xf7 < opcode && opcode < 0xfe));
- + default:
- + /* segment override prefixes are boostable */
- + if (opcode == 0x26 || opcode == 0x36 || opcode == 0x3e)
- + goto retry; /* prefixes */
- + /* CS override prefix and call are not boostable */
- + return (opcode != 0x2e && opcode != 0x9a);
- + }
- +}
- +
- +/*
- + * Returns non-zero if opcode modifies the interrupt flag.
- + */
- +static int __kprobes is_IF_modifier(kprobe_opcode_t * insn)
- +{
- + switch (*insn) {
- + case 0xfa: /* cli */
- + case 0xfb: /* sti */
- + case 0xcf: /* iret/iretd */
- + case 0x9d: /* popf/popfd */
- + return 1;
- + }
- +
- + /*
- + * on X86_64, 0x40-0x4f are REX prefixes so we need to look
- + * at the next byte instead.. but of course not recurse infinitely
- + */
- + if (is_REX_prefix(insn))
- + return is_IF_modifier(++insn);
- +
- + return 0;
- +}
- +
- +/*
- + * Adjust the displacement if the instruction uses the %rip-relative
- + * addressing mode.
- + * If it does, Return the address of the 32-bit displacement word.
- + * If not, return null.
- + * Only applicable to 64-bit x86.
- + */
- +static void __kprobes fix_riprel(struct kprobe *p)
- +{
- +#ifdef CONFIG_X86_64
- + u8 *insn = p->ainsn.insn;
- + s64 disp;
- + int need_modrm;
- +
- + /* Skip legacy instruction prefixes. */
- + while (1) {
- + switch (*insn) {
- + case 0x66:
- + case 0x67:
- + case 0x2e:
- + case 0x3e:
- + case 0x26:
- + case 0x64:
- + case 0x65:
- + case 0x36:
- + case 0xf0:
- + case 0xf3:
- + case 0xf2:
- + ++insn;
- + continue;
- + }
- + break;
- + }
- +
- + /* Skip REX instruction prefix. */
- + if (is_REX_prefix(insn))
- + ++insn;
- +
- + if (*insn == 0x0f) {
- + /* Two-byte opcode. */
- + ++insn;
- + need_modrm = test_bit(*insn,
- + (unsigned long *)twobyte_has_modrm);
- + } else
- + /* One-byte opcode. */
- + need_modrm = test_bit(*insn,
- + (unsigned long *)onebyte_has_modrm);
- +
- + if (need_modrm) {
- + u8 modrm = *++insn;
- + if ((modrm & 0xc7) == 0x05) {
- + /* %rip+disp32 addressing mode */
- + /* Displacement follows ModRM byte. */
- + ++insn;
- + /*
- + * The copied instruction uses the %rip-relative
- + * addressing mode. Adjust the displacement for the
- + * difference between the original location of this
- + * instruction and the location of the copy that will
- + * actually be run. The tricky bit here is making sure
- + * that the sign extension happens correctly in this
- + * calculation, since we need a signed 32-bit result to
- + * be sign-extended to 64 bits when it's added to the
- + * %rip value and yield the same 64-bit result that the
- + * sign-extension of the original signed 32-bit
- + * displacement would have given.
- + */
- + disp = (u8 *) p->addr + *((s32 *) insn) -
- + (u8 *) p->ainsn.insn;
- + BUG_ON((s64) (s32) disp != disp); /* Sanity check. */
- + *(s32 *) insn = (s32) disp;
- + }
- + }
- +#endif
- +}
- +#endif
- +
- +static void __kprobes arch_copy_kprobe(struct kprobe *p)
- +{
- + memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
- + flush_icache_range((unsigned long)p->ainsn.insn,
- + (unsigned long)p->ainsn.insn +
- + MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
- +
- +// fix_riprel(p);
- +
- +// if (can_boost(p->addr))
- +// p->ainsn.boostable = 0;
- +// else
- + p->ainsn.boostable = -1;
- +
- + p->opcode = *p->addr;
- +}
- +
- +int __kprobes arch_prepare_kprobe(struct kprobe *p)
- +{
- + /* insn: must be on special executable page on x86. */
- + p->ainsn.insn = get_insn_slot();
- + if (!p->ainsn.insn)
- + return -ENOMEM;
- + arch_copy_kprobe(p);
- + return 0;
- +}
- +
- +void __kprobes arch_arm_kprobe(struct kprobe *p)
- +{
- + *p->addr = BREAK16_1FE;
- + flush_icache_range((unsigned long)p->addr,
- + (unsigned long)p->addr + sizeof(kprobe_opcode_t));
- +}
- +
- +void __kprobes arch_disarm_kprobe(struct kprobe *p)
- +{
- + *p->addr = p->opcode;
- + flush_icache_range((unsigned long)p->addr,
- + (unsigned long)p->addr + sizeof(kprobe_opcode_t));
- +}
- +
- +void __kprobes arch_remove_kprobe(struct kprobe *p)
- +{
- + if (p->ainsn.insn) {
- + free_insn_slot(p->ainsn.insn, (p->ainsn.boostable == 1));
- + p->ainsn.insn = NULL;
- + }
- +}
- +
- +static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
- +{
- + kcb->prev_kprobe.kp = kprobe_running();
- + kcb->prev_kprobe.status = kcb->kprobe_status;
- + kcb->prev_kprobe.old_flags = kcb->kprobe_old_flags;
- + kcb->prev_kprobe.saved_flags = kcb->kprobe_saved_flags;
- +}
- +
- +static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
- +{
- + __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
- + kcb->kprobe_status = kcb->prev_kprobe.status;
- + kcb->kprobe_old_flags = kcb->prev_kprobe.old_flags;
- + kcb->kprobe_saved_flags = kcb->prev_kprobe.saved_flags;
- +}
- +
- +static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
- + struct kprobe_ctlblk *kcb)
- +{
- + __get_cpu_var(current_kprobe) = p;
- +// kcb->kprobe_saved_flags = kcb->kprobe_old_flags
- +// = regs->NDS32_ipsw & PSW_mskHSS;
- +}
- +
- +static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
- +{
- + regs->NDS32_ipsw |= PSW_mskHSS;
- + /* single step inline if the instruction is an int3 */
- +// if (p->opcode == BREAK16_1FE)
- +// regs->NDS32_ipc = (unsigned long)p->addr;
- +// else
- + regs->NDS32_ipc = (unsigned long)p->ainsn.insn;
- +}
- +
- +void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
- + struct pt_regs *regs)
- +{
- + ri->ret_addr = (kprobe_opcode_t *) regs->NDS32_lp;
- + regs->NDS32_lp = (unsigned long)&kretprobe_trampoline;
- +}
- +
- +static void __kprobes setup_singlestep(struct kprobe *p, struct pt_regs *regs,
- + struct kprobe_ctlblk *kcb)
- +{
- +#if !defined(CONFIG_PREEMPT) || defined(CONFIG_FREEZER)
- + if (p->ainsn.boostable == 1 && !p->post_handler) {
- + /* Boost up -- we can execute copied instructions directly */
- + reset_current_kprobe();
- + regs->NDS32_ipc = (unsigned long)p->ainsn.insn;
- + preempt_enable_no_resched();
- + return;
- + }
- +#endif
- + prepare_singlestep(p, regs);
- + kcb->kprobe_status = KPROBE_HIT_SS;
- +}
- +
- +/*
- + * We have reentered the kprobe_handler(), since another probe was hit while
- + * within the handler. We save the original kprobes variables and just single
- + * step on the instruction of the new probe without calling any user handlers.
- + */
- +static int __kprobes reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
- + struct kprobe_ctlblk *kcb)
- +{
- + switch (kcb->kprobe_status) {
- +#if 0
- + case KPROBE_HIT_SSDONE:
- +#ifdef CONFIG_X86_64
- + /* TODO: Provide re-entrancy from post_kprobes_handler() and
- + * avoid exception stack corruption while single-stepping on
- + * the instruction of the new probe.
- + */
- + arch_disarm_kprobe(p);
- + regs->ip = (unsigned long)p->addr;
- + reset_current_kprobe();
- + preempt_enable_no_resched();
- + break;
- +#endif
- +#endif
- + case KPROBE_HIT_ACTIVE:
- + save_previous_kprobe(kcb);
- + set_current_kprobe(p, regs, kcb);
- + kprobes_inc_nmissed_count(p);
- + prepare_singlestep(p, regs);
- + kcb->kprobe_status = KPROBE_REENTER;
- + break;
- + case KPROBE_HIT_SS:
- + if (p == kprobe_running()) {
- + regs->NDS32_ipc &= ~PSW_mskHSS;
- +// regs->NDS32_ipc |= kcb->kprobe_saved_flags;
- + return 0;
- + } else {
- + /* A probe has been hit in the codepath leading up
- + * to, or just after, single-stepping of a probed
- + * instruction. This entire codepath should strictly
- + * reside in .kprobes.text section. Raise a warning
- + * to highlight this peculiar case.
- + */
- + }
- + default:
- + /* impossible cases */
- + WARN_ON(1);
- + return 0;
- + }
- +
- + return 1;
- +}
- +
- +/*
- + * Interrupts are disabled on entry as trap3 is an interrupt gate and they
- + * remain disabled thorough out this function.
- + */
- +static int __kprobes kprobe_handler(struct pt_regs *regs)
- +{
- + kprobe_opcode_t *addr;
- + struct kprobe *p;
- + struct kprobe_ctlblk *kcb;
- +
- + addr = (kprobe_opcode_t *) regs->NDS32_ipc;
- + if (*addr != BREAK16_1FE) {
- + /*
- + * The breakpoint instruction was removed right
- + * after we hit it. Another cpu has removed
- + * either a probepoint or a debugger breakpoint
- + * at this address. In either case, no further
- + * handling of this interrupt is appropriate.
- + * Back up over the (now missing) int3 and run
- + * the original instruction.
- + */
- + return 1;
- + }
- +
- + /*
- + * We don't want to be preempted for the entire
- + * duration of kprobe processing. We conditionally
- + * re-enable preemption at the end of this function,
- + * and also in reenter_kprobe() and setup_singlestep().
- + */
- + preempt_disable();
- +
- + kcb = get_kprobe_ctlblk();
- + p = get_kprobe(addr);
- +
- + if (p) {
- + if (kprobe_running()) {
- + if (reenter_kprobe(p, regs, kcb))
- + return 1;
- + } else {
- + set_current_kprobe(p, regs, kcb);
- + kcb->kprobe_status = KPROBE_HIT_ACTIVE;
- +
- + /*
- + * If we have no pre-handler or it returned 0, we
- + * continue with normal processing. If we have a
- + * pre-handler and it returned non-zero, it prepped
- + * for calling the break_handler below on re-entry
- + * for jprobe processing, so get out doing nothing
- + * more here.
- + */
- + if (!p->pre_handler || !p->pre_handler(p, regs))
- + setup_singlestep(p, regs, kcb);
- + return 1;
- + }
- + } else if (kprobe_running()) {
- + p = __get_cpu_var(current_kprobe);
- + if (p->break_handler && p->break_handler(p, regs)) {
- + setup_singlestep(p, regs, kcb);
- + return 1;
- + }
- + }
- + /* else: not a kprobe fault; let the kernel handle it */
- + preempt_enable_no_resched();
- + return 0;
- +}
- +
- +/*
- + * When a retprobed function returns, this code saves registers and
- + * calls trampoline_handler() runs, which calls the kretprobe's handler.
- + */
- +static void __used __kprobes kretprobe_trampoline_holder(void)
- +{
- + asm volatile (".global kretprobe_trampoline \n"
- + "kretprobe_trampoline: \n"
- + "smw.adm $r15, [$sp], $r15, #0x0\n"
- + "smw.adm $r0, [$sp], $r5, #0x1 \n"
- + "addi $r0, $sp, #-76 \n"
- + "bal trampoline_handler \n"
- + "move $lp, $r0 \n"
- + "lmw.bim $r0, [$sp], $r5, #0x1 \n"
- + "lmw.bim $r15, [$sp], $r15, #0x0\n"
- + "ret \n");
- +}
- +
- +/*
- + * Called from kretprobe_trampoline
- + */
- +static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
- +{
- + struct kretprobe_instance *ri = NULL;
- + struct hlist_head *head, empty_rp;
- + struct hlist_node *node, *tmp;
- + unsigned long flags, orig_ret_address = 0;
- + unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
- +
- + INIT_HLIST_HEAD(&empty_rp);
- + kretprobe_hash_lock(current, &head, &flags);
- +
- + /*
- + * It is possible to have multiple instances associated with a given
- + * task either because multiple functions in the call path have
- + * return probes installed on them, and/or more than one
- + * return probe was registered for a target function.
- + *
- + * We can handle this because:
- + * - instances are always pushed into the head of the list
- + * - when multiple return probes are registered for the same
- + * function, the (chronologically) first instance's ret_addr
- + * will be the real return address, and all the rest will
- + * point to kretprobe_trampoline.
- + */
- + hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
- + if (ri->task != current)
- + /* another task is sharing our hash bucket */
- + continue;
- +
- + if (ri->rp && ri->rp->handler) {
- + __get_cpu_var(current_kprobe) = &ri->rp->kp;
- + get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE;
- + ri->rp->handler(ri, regs);
- + __get_cpu_var(current_kprobe) = NULL;
- + }
- +
- + orig_ret_address = (unsigned long)ri->ret_addr;
- + recycle_rp_inst(ri, &empty_rp);
- +
- + if (orig_ret_address != trampoline_address)
- + /*
- + * This is the real return address. Any other
- + * instances associated with this task are for
- + * other calls deeper on the call stack
- + */
- + break;
- + }
- +
- + kretprobe_assert(ri, orig_ret_address, trampoline_address);
- +
- + kretprobe_hash_unlock(current, &flags);
- +
- + hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
- + hlist_del(&ri->hlist);
- + kfree(ri);
- + }
- + return (void *)orig_ret_address;
- +}
- +
- +/*
- + * Called after single-stepping. p->addr is the address of the
- + * instruction whose first byte has been replaced by the "int 3"
- + * instruction. To avoid the SMP problems that can occur when we
- + * temporarily put back the original opcode to single-step, we
- + * single-stepped a copy of the instruction. The address of this
- + * copy is p->ainsn.insn.
- + *
- + * This function prepares to return from the post-single-step
- + * interrupt. We have to fix up the stack as follows:
- + *
- + * 0) Except in the case of absolute or indirect jump or call instructions,
- + * the new ip is relative to the copied instruction. We need to make
- + * it relative to the original instruction.
- + *
- + * 1) If the single-stepped instruction was pushfl, then the TF and IF
- + * flags are set in the just-pushed flags, and may need to be cleared.
- + *
- + * 2) If the single-stepped instruction was a call, the return address
- + * that is atop the stack is the address following the copied instruction.
- + * We need to make it the address following the original instruction.
- + *
- + * If this is the first time we've single-stepped the instruction at
- + * this probepoint, and the instruction is boostable, boost it: add a
- + * jump instruction after the copied instruction, that jumps to the next
- + * instruction after the probepoint.
- + */
- +static void __kprobes resume_execution(struct kprobe *p,
- + struct pt_regs *regs,
- + struct kprobe_ctlblk *kcb)
- +{
- +// unsigned long *tos = stack_addr(regs);
- +// unsigned long copy_ip = (unsigned long)p->ainsn.insn;
- +// unsigned long orig_ip = (unsigned long)p->addr;
- + kprobe_opcode_t *insn = p->ainsn.insn;
- + unsigned long rawinsn = *(unsigned long *)insn;
- + int size = SZINSN(rawinsn);
- + regs->NDS32_ipc = (unsigned long)p->addr + size;
- + regs->NDS32_ipsw &= ~PSW_mskHSS;
- +#if 0
- +
- + /*skip the REX prefix */
- + if (is_REX_prefix(insn))
- + insn++;
- +
- + regs->flags &= ~X86_EFLAGS_TF;
- + switch (*insn) {
- + case 0x9c: /* pushfl */
- + *tos &= ~(X86_EFLAGS_TF | X86_EFLAGS_IF);
- + *tos |= kcb->kprobe_old_flags;
- + break;
- + case 0xc2: /* iret/ret/lret */
- + case 0xc3:
- + case 0xca:
- + case 0xcb:
- + case 0xcf:
- + case 0xea: /* jmp absolute -- ip is correct */
- + /* ip is already adjusted, no more changes required */
- + p->ainsn.boostable = 1;
- + goto no_change;
- + case 0xe8: /* call relative - Fix return addr */
- + *tos = orig_ip + (*tos - copy_ip);
- + break;
- +#ifdef CONFIG_X86_32
- + case 0x9a: /* call absolute -- same as call absolute, indirect */
- + *tos = orig_ip + (*tos - copy_ip);
- + goto no_change;
- +#endif
- + case 0xff:
- + if ((insn[1] & 0x30) == 0x10) {
- + /*
- + * call absolute, indirect
- + * Fix return addr; ip is correct.
- + * But this is not boostable
- + */
- + *tos = orig_ip + (*tos - copy_ip);
- + goto no_change;
- + } else if (((insn[1] & 0x31) == 0x20) ||
- + ((insn[1] & 0x31) == 0x21)) {
- + /*
- + * jmp near and far, absolute indirect
- + * ip is correct. And this is boostable
- + */
- + p->ainsn.boostable = 1;
- + goto no_change;
- + }
- + default:
- + break;
- + }
- +
- + if (p->ainsn.boostable == 0) {
- + if ((regs->ip > copy_ip) &&
- + (regs->ip - copy_ip) + 5 < MAX_INSN_SIZE) {
- + /*
- + * These instructions can be executed directly if it
- + * jumps back to correct address.
- + */
- + set_jmp_op((void *)regs->ip,
- + (void *)orig_ip + (regs->ip - copy_ip));
- + p->ainsn.boostable = 1;
- + } else {
- + p->ainsn.boostable = -1;
- + }
- + }
- +
- + regs->ip += orig_ip - copy_ip;
- +
- +no_change:
- + restore_btf();
- +#endif
- +}
- +
- +/*
- + * Interrupts are disabled on entry as trap1 is an interrupt gate and they
- + * remain disabled thoroughout this function.
- + */
- +static int __kprobes post_kprobe_handler(struct pt_regs *regs)
- +{
- + struct kprobe *cur = kprobe_running();
- + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
- +
- + if (!cur)
- + return 0;
- +
- + resume_execution(cur, regs, kcb);
- + regs->NDS32_ipsw |= kcb->kprobe_saved_flags;
- +
- + if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
- + kcb->kprobe_status = KPROBE_HIT_SSDONE;
- + cur->post_handler(cur, regs, 0);
- + }
- +
- + /* Restore back the original saved kprobes variables and continue. */
- + if (kcb->kprobe_status == KPROBE_REENTER) {
- + restore_previous_kprobe(kcb);
- + goto out;
- + }
- + reset_current_kprobe();
- +out:
- + preempt_enable_no_resched();
- +
- + /*
- + * if somebody else is singlestepping across a probe point, flags
- + * will have TF set, in which case, continue the remaining processing
- + * of do_debug, as if this is not a probe hit.
- + */
- + if (regs->NDS32_ipsw & PSW_mskHSS)
- + return 0;
- +
- + return 1;
- +}
- +
- +int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
- +{
- + struct kprobe *cur = kprobe_running();
- + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
- +
- + switch (kcb->kprobe_status) {
- + case KPROBE_HIT_SS:
- + case KPROBE_REENTER:
- + /*
- + * We are here because the instruction being single
- + * stepped caused a page fault. We reset the current
- + * kprobe and the ip points back to the probe address
- + * and allow the page fault handler to continue as a
- + * normal page fault.
- + */
- + regs->NDS32_ipc = (unsigned long)cur->addr;
- + regs->NDS32_ipsw |= kcb->kprobe_old_flags;
- + if (kcb->kprobe_status == KPROBE_REENTER)
- + restore_previous_kprobe(kcb);
- + else
- + reset_current_kprobe();
- + preempt_enable_no_resched();
- + break;
- + case KPROBE_HIT_ACTIVE:
- + case KPROBE_HIT_SSDONE:
- + /*
- + * We increment the nmissed count for accounting,
- + * we can also use npre/npostfault count for accounting
- + * these specific fault cases.
- + */
- + kprobes_inc_nmissed_count(cur);
- +
- + /*
- + * We come here because instructions in the pre/post
- + * handler caused the page_fault, this could happen
- + * if handler tries to access user space by
- + * copy_from_user(), get_user() etc. Let the
- + * user-specified handler try to fix it first.
- + */
- + if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
- + return 1;
- +
- + /*
- + * In case the user-specified fault handler returned
- + * zero, try to fix up.
- + */
- + if (fixup_exception(regs))
- + return 1;
- +
- + /*
- + * fixup routine could not handle it,
- + * Let do_page_fault() fix it.
- + */
- + break;
- + default:
- + break;
- + }
- + return 0;
- +}
- +
- +/*
- + * Wrapper routine for handling exceptions.
- + */
- +int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
- + unsigned long val, void *data)
- +{
- + struct die_args *args = data;
- + int ret = NOTIFY_DONE;
- + int why = args->trapnr & 0xf;
- +
- + if (args->regs && user_mode(args->regs))
- + return ret;
- +
- + switch (why) {
- + case 1:
- + if (kprobe_handler(args->regs))
- + ret = NOTIFY_STOP;
- + break;
- + case 7:
- + if (post_kprobe_handler(args->regs))
- + ret = NOTIFY_STOP;
- + break;
- + default:
- + break;
- + }
- + return ret;
- +}
- +
- +int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
- +{
- + struct jprobe *jp = container_of(p, struct jprobe, kp);
- + unsigned long addr;
- + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
- +
- + kcb->jprobe_saved_regs = *regs;
- + kcb->jprobe_saved_sp = regs->NDS32_sp;
- + addr = (unsigned long)(kcb->jprobe_saved_sp);
- +
- + /*
- + * As Linus pointed out, gcc assumes that the callee
- + * owns the argument space and could overwrite it, e.g.
- + * tailcall optimization. So, to be absolutely safe
- + * we also save and restore enough stack bytes to cover
- + * the argument area.
- + */
- + memcpy(kcb->jprobes_stack, (kprobe_opcode_t *) addr,
- + MIN_STACK_SIZE(addr));
- + regs->NDS32_ipsw &= ~PSW_mskGIE;
- + trace_hardirqs_off();
- + regs->NDS32_ipc = (unsigned long)(jp->entry);
- + return 1;
- +}
- +
- +void __kprobes jprobe_return(void)
- +{
- + struct kprobe_ctlblk *kcd = get_kprobe_ctlblk();
- + asm volatile (" move $sp, %0\n"
- + " .globl jprobe_return_point\n"
- + " jprobe_return_point: \n"
- + " break #0x1fe \n"::"r" (kcd->
- + jprobe_saved_sp));
- +}
- +
- +int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
- +{
- + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
- + struct jprobe *jp = container_of(p, struct jprobe, kp);
- +
- + if (regs->NDS32_ipc == jprobe_return_point) {
- + if (regs->NDS32_sp != kcb->jprobe_saved_sp) {
- + struct pt_regs *saved_regs = &kcb->jprobe_saved_regs;
- + printk(KERN_ERR
- + "current sp %p does not match saved sp %p\n",
- + regs->NDS32_sp, kcb->jprobe_saved_sp);
- + printk(KERN_ERR "Saved registers for jprobe %p\n", jp);
- + show_regs(saved_regs);
- + printk(KERN_ERR "Current registers\n");
- + show_regs(regs);
- + BUG();
- + }
- + *regs = kcb->jprobe_saved_regs;
- + memcpy((kprobe_opcode_t *) (kcb->jprobe_saved_sp),
- + kcb->jprobes_stack,
- + MIN_STACK_SIZE(kcb->jprobe_saved_sp));
- + preempt_enable_no_resched();
- + return 1;
- + }
- + return 0;
- +}
- +
- +int __init arch_init_kprobes(void)
- +{
- + return 0;
- +}
- +
- +int __kprobes arch_trampoline_kprobe(struct kprobe *p)
- +{
- + return 0;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/machine_kexec.c linux-3.4.110/arch/nds32/kernel/machine_kexec.c
- --- linux-3.4.110.orig/arch/nds32/kernel/machine_kexec.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/machine_kexec.c 2016-04-07 10:20:50.942081024 +0200
- @@ -0,0 +1,80 @@
- +/*
- + * machine_kexec.c - handle transition of Linux booting another kernel
- + */
- +
- +#include <linux/mm.h>
- +#include <linux/kexec.h>
- +#include <linux/delay.h>
- +#include <linux/reboot.h>
- +#include <linux/io.h>
- +#include <asm/pgtable.h>
- +#include <asm/pgalloc.h>
- +#include <asm/mmu_context.h>
- +#include <asm/cacheflush.h>
- +#include <asm/mach-types.h>
- +
- +extern const unsigned char relocate_new_kernel[];
- +extern const unsigned int relocate_new_kernel_size;
- +
- +extern void setup_mm_for_reboot(char mode);
- +
- +extern unsigned long kexec_start_address;
- +extern unsigned long kexec_indirection_page;
- +extern unsigned long kexec_mach_type;
- +extern unsigned long kexec_boot_atags;
- +
- +/*
- + * Provide a dummy crash_notes definition while crash dump arrives to nds32.
- + * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
- + */
- +
- +int machine_kexec_prepare(struct kimage *image)
- +{
- + return 0;
- +}
- +
- +void machine_kexec_cleanup(struct kimage *image)
- +{
- +}
- +
- +void machine_shutdown(void)
- +{
- +}
- +
- +void machine_crash_shutdown(struct pt_regs *regs)
- +{
- +}
- +
- +void machine_kexec(struct kimage *image)
- +{
- + unsigned long page_list;
- + unsigned long reboot_code_buffer_phys;
- + void *reboot_code_buffer;
- +
- + page_list = image->head & PAGE_MASK;
- +
- + /* we need both effective and real address here */
- + reboot_code_buffer_phys =
- + page_to_pfn(image->control_code_page) << PAGE_SHIFT;
- + reboot_code_buffer = page_address(image->control_code_page);
- +
- + /* Prepare parameters for reboot_code_buffer */
- + kexec_start_address = image->start;
- + kexec_indirection_page = page_list;
- + kexec_mach_type = machine_arch_type;
- + kexec_boot_atags =
- + image->start - KEXEC_NDS32_ZIMAGE_OFFSET + KEXEC_NDS32_ATAGS_OFFSET;
- +
- + /* copy our kernel relocation code to the control code page */
- + memcpy(reboot_code_buffer,
- + relocate_new_kernel, relocate_new_kernel_size);
- +
- + flush_icache_range((unsigned long)reboot_code_buffer,
- + (unsigned long)reboot_code_buffer +
- + KEXEC_CONTROL_PAGE_SIZE);
- + printk(KERN_INFO "Bye!\n");
- +
- + cpu_proc_fin();
- + setup_mm_for_reboot(0); /* mode is not used, so just pass 0 */
- + cpu_reset(reboot_code_buffer_phys);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/Makefile linux-3.4.110/arch/nds32/kernel/Makefile
- --- linux-3.4.110.orig/arch/nds32/kernel/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/Makefile 2016-04-07 10:20:50.942081024 +0200
- @@ -0,0 +1,45 @@
- +#
- +# Makefile for the linux kernel.
- +#
- +
- +CPPFLAGS_vmlinux.lds +=-DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
- +AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
- +
- +# Object file lists.
- +
- +obj-y := ex-entry.o ex-exit.o ex-scall.o irq.o \
- + process.o ptrace.o setup.o signal.o \
- + sys_nds32.o time.o traps.o io.o proc.o \
- + elfchk.o
- +ifdef CONFIG_FUNCTION_TRACER
- +CFLAGS_REMOVE_ftrace.o = -pg
- +CFLAGS_REMOVE_ex-entry.o = -pg
- +CFLAGS_REMOVE_ex-exit.o = -pg
- +CFLAGS_REMOVE_ex-scall.o = -pg
- +CFLAGS_REMOVE_stacktrace.o = -pg
- +CFLAGS_REMOVE_traps.o = -pg
- +endif
- +
- +obj-$(CONFIG_MODULES) += nds32_ksyms.o module.o
- +obj-$(CONFIG_ISA_DMA) += dma-isa.o
- +obj-$(CONFIG_PCI) += bios32.o
- +obj-$(CONFIG_SMP) += smp.o
- +obj-$(CONFIG_KGDB) += kgdb.o
- +obj-$(CONFIG_STACKTRACE) += stacktrace.o
- +obj-$(CONFIG_KPROBES) += kprobes.o
- +obj-$(CONFIG_FPU) += fpu.o
- +obj-$(CONFIG_AUDIO) += audio.o
- +obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
- +obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
- +obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
- +
- +extra-y := head.o init_task.o vmlinux.lds
- +
- +CFLAGS_fpu.o += \
- + $(shell $(CC) -E -dM -xc /dev/null | grep -o -m1 NDS32_EXT_FPU_SP | sed -e 's/NDS32_EXT_FPU_SP/-mext-fpu-sp/') \
- + $(shell $(CC) -E -dM -xc /dev/null | grep -o -m1 NDS32_EXT_FPU_DP | sed -e 's/NDS32_EXT_FPU_DP/-mext-fpu-dp/')
- +ifdef CONFIG_FPU
- +CFLAGS_elfchk.o += \
- + $(shell $(CC) -E -dM -xc /dev/null | grep -o -m1 NDS32_EXT_FPU_SP | sed -e 's/NDS32_EXT_FPU_SP/-mext-fpu-sp/') \
- + $(shell $(CC) -E -dM -xc /dev/null | grep -o -m1 NDS32_EXT_FPU_DP | sed -e 's/NDS32_EXT_FPU_DP/-mext-fpu-dp/')
- +endif
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/module.c linux-3.4.110/arch/nds32/kernel/module.c
- --- linux-3.4.110.orig/arch/nds32/kernel/module.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/module.c 2016-04-07 10:20:50.942081024 +0200
- @@ -0,0 +1,314 @@
- +/*
- + * linux/arch/nds32/kernel/module.c
- + *
- + * Copyright (C) 2002 Russell King.
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * Module allocation method suggested by Andi Kleen.
- + */
- +#include <linux/module.h>
- +#include <linux/elf.h>
- +#include <linux/vmalloc.h>
- +#include <linux/slab.h>
- +#include <linux/mm.h>
- +
- +#include <asm/pgtable.h>
- +
- +#define DEBUG 0
- +#if DEBUG
- +#define PRINTK printk
- +#else
- +#define PRINTK(x...)
- +#endif
- +
- +void *module_alloc(unsigned long size)
- +{
- +#ifdef CONFIG_KPROBES
- + if (size == 0)
- + return NULL;
- + return vmalloc_exec(size);
- +#else
- + return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
- + GFP_KERNEL, PAGE_KERNEL, -1,
- + __builtin_return_address(0));
- +#endif
- +}
- +
- +void module_free(struct module *module, void *region)
- +{
- + vfree(region);
- +}
- +
- +int module_frob_arch_sections(Elf_Ehdr * hdr,
- + Elf_Shdr * sechdrs,
- + char *secstrings, struct module *mod)
- +{
- + return 0;
- +}
- +
- +void do_reloc16(unsigned int val, unsigned int *loc, unsigned int val_mask,
- + unsigned int val_shift, unsigned int loc_mask,
- + unsigned int partial_in_place, unsigned int swap)
- +{
- + unsigned int tmp = 0, tmp2 = 0;
- +
- + __asm__ __volatile__("\tlhi.bi\t%0, [%2], 0\n"
- + "\tbeqz\t%3, 1f\n"
- + "\twsbh\t%0, %1\n"
- + "1:\n":"=r"(tmp):"0"(tmp), "r"(loc), "r"(swap)
- + );
- +
- + tmp2 = tmp & loc_mask;
- + if (partial_in_place) {
- + tmp &= (!loc_mask);
- + tmp =
- + tmp2 | ((tmp + ((val & val_mask) >> val_shift)) & val_mask);
- + } else {
- + tmp = tmp2 | ((val & val_mask) >> val_shift);
- + }
- +
- + __asm__ __volatile__("\tbeqz\t%3, 2f\n"
- + "\twsbh\t%0, %1\n"
- + "2:\n"
- + "\tshi.bi\t%0, [%2], 0\n":"=r"(tmp):"0"(tmp),
- + "r"(loc), "r"(swap)
- + );
- +}
- +
- +void do_reloc32(unsigned int val, unsigned int *loc, unsigned int val_mask,
- + unsigned int val_shift, unsigned int loc_mask,
- + unsigned int partial_in_place, unsigned int swap)
- +{
- + unsigned int tmp = 0, tmp2 = 0;
- +
- + __asm__ __volatile__("\tlmw.bi\t%0, [%2], %0, 0\n"
- + "\tbeqz\t%3, 1f\n"
- + "\twsbh\t%0, %1\n"
- + "\trotri\t%0, %1, 16\n"
- + "1:\n":"=r"(tmp):"0"(tmp), "r"(loc), "r"(swap)
- + );
- +
- + tmp2 = tmp & loc_mask;
- + if (partial_in_place) {
- + tmp &= (!loc_mask);
- + tmp =
- + tmp2 | ((tmp + ((val & val_mask) >> val_shift)) & val_mask);
- + } else {
- + tmp = tmp2 | ((val & val_mask) >> val_shift);
- + }
- +
- + __asm__ __volatile__("\tbeqz\t%3, 2f\n"
- + "\twsbh\t%0, %1\n"
- + "\trotri\t%0, %1, 16\n"
- + "2:\n"
- + "\tsmw.bi\t%0, [%2], %0, 0\n":"=r"(tmp):"0"(tmp),
- + "r"(loc), "r"(swap)
- + );
- +}
- +
- +static inline int exceed_limit(int offset, unsigned int val_mask,
- + struct module *module, Elf32_Rela * rel,
- + unsigned int relindex, unsigned int reloc_order)
- +{
- + int abs_off = offset < 0 ? ~offset : offset;
- +
- + if (abs_off & (~val_mask)) {
- + printk(KERN_ERR "\n%s: relocation type %d out of range.\n"
- + "please rebuild the kernel module with gcc option \"-Wa,-mno-small-text\".\n",
- + module->name, ELF32_R_TYPE(rel->r_info));
- + PRINTK("section %d reloc %d offset 0x%x relative 0x%x.\n"
- + relindex, reloc_order, rel->r_offset, offset);
- + return true;
- + }
- + return false;
- +}
- +
- +#ifdef __NDS32_EL__
- +#define NEED_SWAP 1
- +#else
- +#define NEED_SWAP 0
- +#endif
- +
- +int
- +apply_relocate_add(Elf32_Shdr * sechdrs, const char *strtab,
- + unsigned int symindex, unsigned int relindex,
- + struct module *module)
- +{
- + Elf32_Shdr *symsec = sechdrs + symindex;
- + Elf32_Shdr *relsec = sechdrs + relindex;
- + Elf32_Shdr *dstsec = sechdrs + relsec->sh_info;
- + Elf32_Rela *rel = (void *)relsec->sh_addr;
- + unsigned int i;
- +
- + for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rela); i++, rel++) {
- + Elf32_Addr *loc;
- + Elf32_Sym *sym;
- + Elf32_Addr v;
- + s32 offset;
- +
- + offset = ELF32_R_SYM(rel->r_info);
- + if (offset < 0
- + || offset > (symsec->sh_size / sizeof(Elf32_Sym))) {
- + printk(KERN_ERR "%s: bad relocation\n", module->name);
- + PRINTK("section %d reloc %d\n", module->name, relindex,
- + i);
- + return -ENOEXEC;
- + }
- +
- + sym = ((Elf32_Sym *) symsec->sh_addr) + offset;
- +
- + if (rel->r_offset < 0
- + || rel->r_offset > dstsec->sh_size - sizeof(u16)) {
- + printk(KERN_ERR "%s: out of bounds relocation\n",
- + module->name);
- + PRINTK("section %d reloc %d offset 0x%0x size %d\n",
- + relindex, i, rel->r_offset, dstsec->sh_size);
- + return -ENOEXEC;
- + }
- +
- + loc = (Elf32_Addr *) (dstsec->sh_addr + rel->r_offset);
- + v = sym->st_value + rel->r_addend;
- +
- + switch (ELF32_R_TYPE(rel->r_info)) {
- + case R_NDS32_NONE:
- + case R_NDS32_INSN16:
- + case R_NDS32_LABEL:
- + case R_NDS32_LONGCALL1:
- + case R_NDS32_LONGCALL2:
- + case R_NDS32_LONGCALL3:
- + case R_NDS32_LONGCALL4:
- + case R_NDS32_LONGJUMP1:
- + case R_NDS32_LONGJUMP2:
- + case R_NDS32_LONGJUMP3:
- + case R_NDS32_9_FIXED_RELA:
- + case R_NDS32_15_FIXED_RELA:
- + case R_NDS32_17_FIXED_RELA:
- + case R_NDS32_25_FIXED_RELA:
- + case R_NDS32_LOADSTORE:
- + case R_NDS32_DWARF2_OP1_RELA:
- + case R_NDS32_DWARF2_OP2_RELA:
- + case R_NDS32_DWARF2_LEB_RELA:
- + case R_NDS32_RELA_NOP_MIX...R_NDS32_RELA_NOP_MAX:
- + break;
- +
- + case R_NDS32_32_RELA:
- + do_reloc32(v, loc, 0xffffffff, 0, 0, 0, 0);
- + break;
- +
- + case R_NDS32_HI20_RELA:
- + do_reloc32(v, loc, 0xfffff000, 12, 0xfff00000, 0,
- + NEED_SWAP);
- + break;
- +
- + case R_NDS32_LO12S3_RELA:
- + do_reloc32(v, loc, 0x00000fff, 3, 0xfffff000, 0,
- + NEED_SWAP);
- + break;
- +
- + case R_NDS32_LO12S2_RELA:
- + do_reloc32(v, loc, 0x00000fff, 2, 0xfffff000, 0,
- + NEED_SWAP);
- + break;
- +
- + case R_NDS32_LO12S1_RELA:
- + do_reloc32(v, loc, 0x00000fff, 1, 0xfffff000, 0,
- + NEED_SWAP);
- + break;
- +
- + case R_NDS32_LO12S0_RELA:
- + case R_NDS32_LO12S0_ORI_RELA:
- + do_reloc32(v, loc, 0x00000fff, 0, 0xfffff000, 0,
- + NEED_SWAP);
- + break;
- +
- + case R_NDS32_9_PCREL_RELA:
- + if (exceed_limit
- + ((v - (Elf32_Addr) loc), 0x000000ff, module, rel,
- + relindex, i))
- + return -ENOEXEC;
- + do_reloc16(v - (Elf32_Addr) loc, loc, 0x000001ff, 1,
- + 0xffffff00, 0, NEED_SWAP);
- + break;
- +
- + case R_NDS32_15_PCREL_RELA:
- + if (exceed_limit
- + ((v - (Elf32_Addr) loc), 0x00003fff, module, rel,
- + relindex, i))
- + return -ENOEXEC;
- + do_reloc32(v - (Elf32_Addr) loc, loc, 0x00007fff, 1,
- + 0xffffc000, 0, NEED_SWAP);
- + break;
- +
- + case R_NDS32_17_PCREL_RELA:
- + if (exceed_limit
- + ((v - (Elf32_Addr) loc), 0x0000ffff, module, rel,
- + relindex, i))
- + return -ENOEXEC;
- + do_reloc32(v - (Elf32_Addr) loc, loc, 0x0001ffff, 1,
- + 0xffff0000, 0, NEED_SWAP);
- + break;
- +
- + case R_NDS32_25_PCREL_RELA:
- + if (exceed_limit
- + ((v - (Elf32_Addr) loc), 0x00ffffff, module, rel,
- + relindex, i))
- + return -ENOEXEC;
- + do_reloc32(v - (Elf32_Addr) loc, loc, 0x01ffffff, 1,
- + 0xff000000, 0, NEED_SWAP);
- + break;
- + case R_NDS32_WORD_9_PCREL_RELA:
- + if (exceed_limit
- + ((v - (Elf32_Addr) loc), 0x000000ff, module, rel,
- + relindex, i))
- + return -ENOEXEC;
- + do_reloc32(v - (Elf32_Addr) loc, loc, 0x000001ff, 1,
- + 0xffffff00, 0, NEED_SWAP);
- + break;
- +
- + case R_NDS32_SDA15S3_RELA:
- + case R_NDS32_SDA15S2_RELA:
- + case R_NDS32_SDA15S1_RELA:
- + case R_NDS32_SDA15S0_RELA:
- + printk(KERN_ERR "%s: unsupported relocation type %d.\n",
- + module->name, ELF32_R_TYPE(rel->r_info));
- + printk(KERN_ERR
- + "Small data section access doesn't work in the kernel space; "
- + "please rebuild the kernel module with gcc option -G0.\n");
- + PRINTK("section %d reloc %d offset 0x%x size %d\n",
- + relindex, i, rel->r_offset, dstsec->sh_size);
- + break;
- +
- + default:
- + printk(KERN_ERR "%s: unsupported relocation type %d.\n",
- + module->name, ELF32_R_TYPE(rel->r_info));
- + PRINTK("section %d reloc %d offset 0x%x size %d\n",
- + relindex, i, rel->r_offset, dstsec->sh_size);
- + }
- + }
- + return 0;
- +}
- +
- +int
- +apply_relocate(Elf32_Shdr * sechdrs, const char *strtab,
- + unsigned int symindex, unsigned int relsec,
- + struct module *module)
- +{
- +// printk(KERN_ERR "module %s: non-ADD RELOCATION unsupported\n", module->name);
- +// return -ENOEXEC;
- + return 0;
- +}
- +
- +int
- +module_finalize(const Elf32_Ehdr * hdr, const Elf_Shdr * sechdrs,
- + struct module *module)
- +{
- + return 0;
- +}
- +
- +void module_arch_cleanup(struct module *mod)
- +{
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/nds32-elf.h linux-3.4.110/arch/nds32/kernel/nds32-elf.h
- --- linux-3.4.110.orig/arch/nds32/kernel/nds32-elf.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/nds32-elf.h 2016-04-07 10:20:50.942081024 +0200
- @@ -0,0 +1,855 @@
- +#ifndef _NDS32_ELF_CHECK
- +#define _NDS32_ELF_CHECK
- +
- +//#define TEST_ELF_CHECK_FUNC
- +#ifdef TEST_ELF_CHECK_FUNC
- +#include <stdio.h>
- +#include <stdlib.h>
- +#endif
- +
- +//#include <stdio.h>
- +//#include <stdarg.h>
- +
- +#ifdef __cplusplus
- +extern "C"
- +{
- +#else
- +#include <stdbool.h>
- +#endif //#ifdef __cplusplus
- +
- +
- + enum ELF_HEADER_FLAG_FIELD
- + {
- + EHFF_ARCH_VER = 0xF0000000, EHFF_ARCH_VER_SHIFT = 28,
- + //EHFF_RESERVED = 0x08000000,
- + EHFF_HAS_ZOL = 0x04000000,
- + EHFF_ISA_DSP = 0x02000000,
- + EHFF_ISA_FPU_MAC = 0x01000000,
- + EHFF_FPU_REG = 0x00C00000, EHFF_FPU_REG_SHIFT = 22,
- + EHFF_ISA_L2C = 0x00200000,
- + EHFF_ISA_NO_MAC = 0x00100000,
- + EHFF_ISA_MAC_DX = 0x00100000,
- + EHFF_ISA_FPU_DP = 0x00080000,
- + //EHFF_RESERVED = 0x00040000,
- + EHFF_ISA_SATURATION = 0x00020000,
- + EHFF_REDUCED_REGS = 0x00010000,
- + EHFF_ISA_STRING = 0x00008000,
- + EHFF_ISA_16BIT = 0x00004000,
- + EHFF_ISA_IFC = 0x00004000,
- + EHFF_ISA_DIV = 0x00002000,
- + EHFF_ISA_DIV_DX = 0x00002000,
- + EHFF_ISA_AUDIO = 0x00001000,
- + EHFF_ISA_FPU_SP = 0x00000800,
- + EHFF_ISA_EXT2 = 0x00000400,
- + EHFF_ISA_EXT = 0x00000200,
- + EHFF_ISA_EIT = 0x00000100,
- + EHFF_ISA_MFUSR_PC = 0x00000100,
- + EHFF_ABI_VER = 0x000000F0,
- + EHFF_ELF_VER = 0x0000000F, EHFF_ELF_VER_SHIFT = 0,
- + };
- +
- +
- + enum ELF_HEADER_FLAG_FIELD_ARCH_VER
- + {
- + EHFF_ARCH_VER_RESERVED = 0x0,
- + EHFF_ARCH_VER_V1 = 0x1,
- + EHFF_ARCH_VER_V2 = 0x2,
- + EHFF_ARCH_VER_V3 = 0x3,
- + EHFF_ARCH_VER_V3M = 0x4,
- + };
- +
- + static const char *EHFF_ARCH_VER_MSG[] =
- + {
- + "RESERVED",
- + "BASE V1",
- + "BASE V2",
- + "BASE V3",
- + "BASE V3M",
- + };
- +
- +
- +
- +
- + /* ----------------------------------------------------------- */
- + /* 4-bit for ABI signature, allow up to 16 ABIs */
- + /* 0 : for OLD ABI V0, phase out
- + * 1 : for V1 , starting with V0 toolchain
- + * 2 : for V2
- + * 3 : for V2FP (fs0, fs1 as function parameter)
- + * 4 : for AABI */
- + /* only old N1213HC use V0 */
- + /* New ABI is used due to return register is changed to r0 from r5 */
- + /* ----------------------------------------------------------- */
- +#define E_NDS_ABI_V0 0x00000000
- +#define E_NDS_ABI_V1 0x00000010
- +#define E_NDS_ABI_V2 0x00000020
- +#define E_NDS_ABI_V2FP 0x00000030
- +#define E_NDS_ABI_AABI 0x00000040
- +#define E_NDS_ABI_V2FP_PLUS 0x00000050
- +
- + /* ---------------------------------------------------------------------------- */
- + /* This flag signifies the version of Andes ELF */
- + /* note : */
- + /* 1. v1.3.1 and beyond is accompanying with Baseline ISA 1.0b/2.0/... in ELF. */
- + /* 2. v1.3.1 is accompanying with Baseline ISA 1.0b in ELF. */
- + /* ... | MAC | ... | DIV | ... */
- + /* 3. v1.3.1 is accompanying with Baseline ISA 2.0 and beyond in ELF. */
- + /* ... | MAC_DX | ... | DIV_DX | ... */
- + /* ---------------------------------------------------------------------------- */
- +
- + enum ELF_HEADER_FLAG_FIELD_ELF_VER
- + {
- + EHFF_ELF_VER_1_3_0 = 0x0,
- + EHFF_ELF_VER_1_3_1 = 0x1,
- + EHFF_ELF_VER_1_4_0 = 0x2,
- + };
- +
- + static const char *EHFF_ELF_VER_MSG[] =
- + {
- + "1.3.0",
- + "1.3.1",
- + "1.4.0",
- + };
- + /* */
- + /* sr layout : */
- + /* sr[14..10] : hardware components */
- + /* cpu / fpu / audio / ... */
- + /* sr[9..0] : sr index number dedicated for sr[14..10] */
- + /* */
- +
- + //
- + // sr[14..10] definition:
- + // 0 : cpu
- + // 1 : fpu
- + // 2 : audio
- +#define INDEX_HW_MASK 0x00007c00
- +#define INDEX_HW_CPU 0x00000000
- +#define INDEX_HW_FPU 0x00000400
- +#define INDEX_HW_AUDIO 0x00000800
- +#define HW_IS_CPU(sr) ((sr & INDEX_HW_MASK) == INDEX_HW_CPU)
- +#define HW_IS_FPU(sr) ((sr & INDEX_HW_MASK) == INDEX_HW_FPU)
- +#define HW_IS_AUDIO(sr) ((sr & INDEX_HW_MASK) == INDEX_HW_AUDIO)
- +
- + //
- + // sr[9..0] definition:
- + // if (HW_IS_CPU(sr)) // cpu score
- + // sr[9..0] defined in chap 9 of Andes-Privilege-Architecture spec.
- + // else if (HW_IS_FPU(sr)) // fpu score
- + // sr[9..0] == SR_FPU_FPCFG, FPCFG defined in FPU_ISA_EXT spec.
- + // else if (HW_IS_AUDIO(sr)) // audio score
- + // //none register is used in loader checking mechanism
- + //
- +#define SR_INDEX_MASK 0x000003ff
- +#define SR_INDEX(sr) (sr & SR_INDEX_MASK)
- +#define CPU_SR_INDEX(x,y,z) ((x << 7) + (y << 3) + z)
- +#define FPU_SR_FPCFG() (INDEX_HW_FPU)
- +
- + //FPU-belonged system registers
- +#define SR_FPU_FPCFG 0x00
- +
- +#define SR_NOT_EXIST 0xffffffff
- +
- + typedef unsigned int (* CALLBACK_FUNC) (unsigned int index);
- +
- +
- + static const char *NEC_MSG_FPU_reg[5] =
- + {
- + "N/A",
- + " 8SP/ 4DP",
- + "16SP/ 8DP",
- + "32SP/16DP",
- + "32SP/32DP"
- + };
- + static const char *NEC_MSG_endian[2] =
- + {
- + "little",
- + "big"
- + };
- +
- +#define EM_NDS32 167
- +#if defined elf_check_swap_2 || defined elf_check_swap_4
- +#error "ERROR : elf_check_swap_2 and elf_check_swap_4 are multiple defined"
- +#endif
- +#define elf_check_swap_2(data) (((data&0x0000ff00)>>8) | ((data&0x000000ff)<<8))
- +#define elf_check_swap_4(data) (((data&0xff000000)>>24) | \
- + ((data&0x00ff0000)>>8) | \
- + ((data&0x0000ff00)<<8) | \
- + ((data&0x000000ff)<<24))
- +
- +#define MSC_CFG_BASEV 0x0000e000
- +
- +#define CPU_VER_EXT 0x00000001
- +#define CPU_VER_A16 0x00000002
- +#define CPU_VER_EXT2 0x00000004
- +#define CPU_VER_FPU 0x00000008
- +#define CPU_VER_STRING 0x00000010
- +#define CPU_VER_SATURATION 0x00000020
- +
- +#define MSC_CFG_DIV 0x00000020
- +#define MSC_CFG_MAC 0x00000040
- +#define MSC_CFG_L2C 0x00000200
- +#define MSC_CFG_REDUCED_REG 0x00000400
- +#define MSC_CFG_NOD 0x00010000
- +#define MSC_CFG_AUDIO 0x00000180
- +#define MSC_CFG_AUDIO_NONE 0x00000000
- +#define MSC_CFG_IFC 0x00080000
- +#define MSC_CFG_MCU 0x00100000
- +#define MSC_CFG_EX9IT 0x01000000
- +#define MSC_CFG_MSC_EXT 0xc0000000
- +
- +#define MSC_CFG2_DSPPF 0x00000018
- +#define MSC_CFG2_ZOL 0x00000020
- +
- +#define MMU_CFG_DE 0x04000000
- +
- + typedef struct nds32_elfinfo_s
- + {
- + unsigned int endian; // 1.local-used constant definition
- + // 0 : little , 1 : big
- + // 2.system-used constant definition
- + // little / big depends on system definition
- + unsigned int machine; //magic number (167 for nds32 machine)
- + unsigned int mfusr_pc; //reclaim in baseline v2
- + unsigned int abi; // abi version
- + unsigned int base16; // 0 : not support , 1 : support
- + unsigned int pex1;
- + unsigned int div; //reclaim in baseline v2
- + unsigned int pex2;
- + unsigned int fpu; //fpu single precision
- + unsigned int audio;
- + unsigned int string;
- + unsigned int reduced_regs;
- + unsigned int saturation;
- + unsigned int ifc;
- + unsigned int elf_ver; //elf version number, 0 for v1.3.0, 1 for v1.3.1
- + unsigned int l2c;
- + unsigned int mac; //reclaim in baseline v2
- + //unsigned int isa_ver;//0x0, baseline = baseline V1 - 16 bit ISA
- + //0x1, baseline = baseline V1
- + //0x2, baseline = baseline V1 + V2 extension ISA
- + //unsigned int fpu_sp; //fpu double precision
- + //unsigned int fpu_reg; //fpu registers capacity
- + } nds32_elfinfo_t;
- +
- + typedef enum nds32_elfchk_e
- + {
- + endian_chk = 0,
- + machine_chk,
- + isa_chk,
- + abi_chk
- + } nds32_elfchk_t;
- +
- + typedef enum ELF_Fail_Type
- + {
- + EFT_NONE,
- + EFT_WARNING,
- + EFT_ERROR
- + }ELF_Fail_Type;
- +
- + static inline void NEC_itoa(unsigned int value, char *buf, const unsigned int base)
- + {
- + char temp[10] = "\0", ch;
- + int len = 1, index;
- +
- + while(value > 0)
- + {
- + ch = value%base;
- + value = value/base;
- + if(ch >= 10)
- + ch = ch+'a'-10;
- + else
- + ch = ch+'0';
- + temp[len++] = ch;
- + }
- + len--;
- +
- + index = len;
- + while(index >= 0)
- + {
- + buf[index] = temp[len-index];
- + index--;
- + }
- + }
- +
- + static inline void NEC_format(char *buf, unsigned int width)
- + {
- + unsigned int len = strlen(buf);
- + memmove(buf+(width-len), buf, len+1);
- + memset(buf, ' ', (width-len));
- + }
- +
- + static void NEC_sprintf(char *buf, const char *str, ...)
- + {
- + int width, len = 0;
- + va_list ap;
- + char token, temp[100];
- + buf[0] = '\0';
- +
- +
- + va_start(ap, str);
- + while(*str != '\0')
- + {
- + if(*str != '%')
- + buf[len++] = *str;
- + else //*str == '%'
- + {
- + token = *(++str);
- +
- + width = 0;
- + while(token >= '0' && token <= '9')
- + {
- + width *= 10;
- + width += token-'0';
- + token = *(++str);
- + }
- +
- + switch(token)
- + {
- + case 'd':
- + NEC_itoa(va_arg(ap, unsigned int), temp, 10);
- + break;
- + case 'x':
- + NEC_itoa(va_arg(ap, unsigned int), temp, 16);
- + break;
- + case 's':
- + strcpy(temp, va_arg(ap, char *));
- + break;
- + }
- +
- + if(width != 0)
- + NEC_format(temp, width);
- +
- + buf[len++] = '\0';
- + strcat(buf, temp);
- + len = strlen(buf);
- + }
- +
- + str++;
- + }
- + buf[len] = '\0';
- + }
- +
- + //NDS32 strcat for avoiding buf overflow
- + static inline void NEC_strcat_safety(char *destination, unsigned int destination_size, char *source)
- + {
- + strncat(destination, source, destination_size - strlen(destination) - 1);
- + }
- +
- + //NDS32 Elf Check print
- + static inline void NEC_print(char *buf, unsigned int len, ELF_Fail_Type type, const char *name, const char *cpu, const char *elf, const char *error_message)
- + {
- + char temp[100];
- + switch(type)
- + {
- + case EFT_NONE:
- + NEC_sprintf(temp, "\t | %9s | %9s | %14s\n", cpu, elf, name);
- + break;
- + case EFT_WARNING:
- + NEC_sprintf(temp, "\t?| %9s | %9s | %14s Warning: %s\n", cpu, elf, name, error_message);
- + break;
- + case EFT_ERROR:
- + NEC_sprintf(temp, "\t!| %9s | %9s | %14s Error: %s\n", cpu, elf, name, error_message);
- + break;
- + }
- + NEC_strcat_safety(buf, len, temp);
- + }
- +
- + static inline bool NEC_check_bool(char *buf, unsigned int len, ELF_Fail_Type type, const char *isa, bool cpu, bool elf)
- + {
- + bool code;
- + const char *NEC_MSG_ISA[2] = { "OFF", "ON" };
- + if(!cpu && elf)
- + code = 1;
- + else
- + {
- + code = 0;
- + type = EFT_NONE;
- + }
- + NEC_print(buf, len, type, isa, NEC_MSG_ISA[cpu], NEC_MSG_ISA[elf], "Not supported by CPU");
- + return code;
- + }
- +
- + static inline ELF_Fail_Type elf_ver_and_arch_ver_compatibility_check(unsigned int elf_ver, unsigned int arch_ver)
- + {
- + switch(elf_ver)
- + {
- + case EHFF_ELF_VER_1_3_0:
- + switch(arch_ver)
- + {
- + case EHFF_ARCH_VER_V1:
- + return EFT_NONE;
- + default:
- + return EFT_ERROR;
- + }
- + case EHFF_ELF_VER_1_3_1:
- + switch(arch_ver)
- + {
- + case EHFF_ARCH_VER_V1:
- + case EHFF_ARCH_VER_V2:
- + case EHFF_ARCH_VER_V3M:
- + return EFT_NONE;
- + default:
- + return EFT_ERROR;
- + }
- + case EHFF_ELF_VER_1_4_0:
- + switch(arch_ver)
- + {
- + case EHFF_ARCH_VER_V1:
- + case EHFF_ARCH_VER_V2:
- + case EHFF_ARCH_VER_V3:
- + case EHFF_ARCH_VER_V3M:
- + return EFT_NONE;
- + default:
- + return EFT_ERROR;
- + }
- + }
- + return EFT_ERROR;
- + }
- +
- +
- + static inline ELF_Fail_Type arch_ver_check(unsigned int CPU, unsigned int ELF)
- + {
- + switch(CPU)
- + {
- + case EHFF_ARCH_VER_V1:
- + switch(ELF)
- + {
- + case EHFF_ARCH_VER_V1:
- + return EFT_NONE;
- + default:
- + return EFT_ERROR;
- + }
- + case EHFF_ARCH_VER_V2:
- + switch(ELF)
- + {
- + case EHFF_ARCH_VER_V1:
- + case EHFF_ARCH_VER_V2:
- + return EFT_NONE;
- + default:
- + return EFT_ERROR;
- + }
- + case EHFF_ARCH_VER_V3:
- + switch(ELF)
- + {
- + case EHFF_ARCH_VER_V1:
- + case EHFF_ARCH_VER_V2:
- + case EHFF_ARCH_VER_V3:
- + case EHFF_ARCH_VER_V3M:
- + return EFT_NONE;
- + default:
- + return EFT_ERROR;
- + }
- + case EHFF_ARCH_VER_V3M:
- + switch(ELF)
- + {
- + case EHFF_ARCH_VER_V3M:
- + return EFT_NONE;
- + default:
- + return EFT_ERROR;
- + }
- + }
- + return EFT_ERROR;
- + }
- +
- + // buf : buffer of char*, put Target Isa Info into *buf
- + // len : length of buffer (at least 300 chars in length)
- + // buf_status : status of buffer
- + // 0 : ok
- + // 1 : overflow
- +#define TARGET_ISA_INFO_LEN 2000
- + static inline unsigned int elf_check (unsigned char *ehdr, CALLBACK_FUNC reg_read_callback, char *buf, unsigned int len, unsigned int *buf_status)
- + {
- + unsigned int SR_msc_cfg, SR_msc_cfg2 = 0, SR_cpu_ver, SR_mmu_cfg, fpcfg, fucop_exist, fpu_mount;
- + unsigned int CPU_DIV_DX_ISA, CPU_MAC_DX_ISA;
- + unsigned int eflag, ELF_arch_ver, ELF_elf_ver, CPU_arch_ver;
- + unsigned short machine;
- + unsigned char big_endian_elf = 0, big_endian_cpu;
- +
- + char temp[100];
- + char temp_cpu[10];
- + char temp_elf[10];
- + int n_error, n_warning;
- + int CPU_support;
- + unsigned char FPU_reg_elf, FPU_reg_cpu;
- + ELF_Fail_Type error_type;
- +
- +
- +
- + n_error = 0;
- + n_warning = 0;
- +
- + buf[0] = '\0';
- + *buf_status = 0;
- +
- + SR_cpu_ver = reg_read_callback(CPU_SR_INDEX(0,0,0));
- + SR_msc_cfg = reg_read_callback(CPU_SR_INDEX(0,4,0));
- + SR_mmu_cfg = reg_read_callback(CPU_SR_INDEX(0,3,0));
- +
- + if (SR_msc_cfg & MSC_CFG_MSC_EXT)
- + SR_msc_cfg2 = reg_read_callback(CPU_SR_INDEX(0,4,1));
- +
- + switch(*((char*)(ehdr+5)))
- + {
- + case 1:
- + big_endian_elf = 0;
- + break;
- + case 2:
- + big_endian_elf = 1;
- + break;
- + }
- +
- + if(SR_mmu_cfg & MMU_CFG_DE)
- + big_endian_cpu = 1;
- + else
- + big_endian_cpu = 0;
- +
- +
- + /* 20091106 note :
- + * 1. In term of OS, elf_check() would be used in OS kernel and ld.so
- + * 2. Since OS is running on SID, eflag/machine did not need endian conversion for big endian format.
- + * 3. Later, elf_check interface is going to cover "OS" case by adding a new parameter.
- + *
- + */
- +#ifdef ELF_CHECKING_OS
- + eflag = *((unsigned int *)(ehdr+36));
- + machine = *((unsigned short*)(ehdr+18));
- +#else // GDB loader / SID loader
- + eflag = (big_endian_elf == 0)? *((unsigned int *)(ehdr+36)) : elf_check_swap_4(*((unsigned int *)(ehdr+36)));
- + machine = (big_endian_elf == 0)? *((unsigned short*)(ehdr+18)) : elf_check_swap_2(*((unsigned short*)(ehdr+18)));
- +#endif
- +
- + ELF_arch_ver = (eflag & EHFF_ARCH_VER) >> EHFF_ARCH_VER_SHIFT;
- + ELF_elf_ver = (eflag & EHFF_ELF_VER) >> EHFF_ELF_VER_SHIFT;
- +
- + CPU_arch_ver = ((SR_msc_cfg & MSC_CFG_BASEV) >> 13) + 1;
- + if(CPU_arch_ver == 3)
- + if(SR_msc_cfg & MSC_CFG_MCU)
- + CPU_arch_ver = 4;
- +
- + /*Basic version check
- +
- + 1.ELF version check
- + 2.Architecture version check
- + 3.Machine check
- + */
- + if(ELF_elf_ver > EHFF_ELF_VER_1_4_0)
- + {
- + NEC_sprintf(temp, "Error: unsupport ELF version: 0x%x\n", ELF_elf_ver);
- + NEC_strcat_safety(buf, len, temp);
- + return 1;
- + }
- + NEC_sprintf(temp, "ELF version: %s\n", EHFF_ELF_VER_MSG[ELF_elf_ver]);
- + NEC_strcat_safety(buf, len, temp);
- +
- +
- + if(elf_ver_and_arch_ver_compatibility_check(ELF_elf_ver, ELF_arch_ver) == EFT_ERROR)
- + {
- + NEC_sprintf(temp, "Error: architecture version is not supported in this ELF version: %s\n", EHFF_ARCH_VER_MSG[ELF_arch_ver]);
- + NEC_strcat_safety(buf, len, temp);
- + return 1;
- + }
- +
- + NEC_sprintf(temp, "\t %9s %9s \n", "CPU", "ELF");
- + NEC_strcat_safety(buf, len, temp);
- + if(big_endian_cpu != big_endian_elf)
- + {
- + error_type = EFT_ERROR;
- + n_error++;
- + }
- + else
- + error_type = EFT_NONE;
- + NEC_print(buf, len, error_type, "endianess", NEC_MSG_endian[big_endian_cpu], NEC_MSG_endian[big_endian_elf], "endianess mismatch");
- +
- +
- +
- +
- + if (EM_NDS32 != machine)
- + {
- + error_type = EFT_ERROR;
- + n_error++;
- + }
- + else
- + error_type = EFT_NONE;
- + NEC_sprintf(temp_cpu, "%d", EM_NDS32);
- + NEC_sprintf(temp_elf, "%d", machine);
- + NEC_print(buf, len, error_type, "machine", temp_cpu, temp_elf, "wrong machine");
- +
- +
- + error_type = arch_ver_check(CPU_arch_ver, ELF_arch_ver);
- + if(error_type == EFT_ERROR)
- + n_error++;
- + NEC_print(buf, len, error_type, "BASELINE ISA", EHFF_ARCH_VER_MSG[CPU_arch_ver], EHFF_ARCH_VER_MSG[ELF_arch_ver], "BASELINE ISA mismatch");
- +
- + /*Prepare reference variables
- +
- + 1.DIV, MAC, DX
- + 2.FPU
- + */
- +
- + CPU_MAC_DX_ISA = 0;
- + CPU_DIV_DX_ISA = 0;
- + switch(CPU_arch_ver)
- + {
- + case EHFF_ARCH_VER_V1:
- + if (SR_msc_cfg & MSC_CFG_MAC)
- + CPU_MAC_DX_ISA = 1;
- + if (SR_msc_cfg & MSC_CFG_DIV)
- + CPU_DIV_DX_ISA = 1;
- + break;
- + case EHFF_ARCH_VER_V2:
- + case EHFF_ARCH_VER_V3:
- + case EHFF_ARCH_VER_V3M:
- + if (!(SR_msc_cfg & MSC_CFG_NOD))
- + {
- + CPU_MAC_DX_ISA = 1;
- + CPU_DIV_DX_ISA = 1;
- + }
- + break;
- + }
- + fpu_mount = 0;
- + if (SR_cpu_ver & CPU_VER_FPU)
- + {
- + fucop_exist = reg_read_callback(CPU_SR_INDEX(0,5,0));
- + if (fucop_exist & 0x80000000)
- + {
- + fpu_mount = 1;
- + fpcfg = reg_read_callback(FPU_SR_FPCFG());
- + }
- + else
- + fpu_mount = 0;
- + }
- +
- + //Parse Configuration field (bit 27~8)
- +
- + //bit 27 Reserved
- + //bit 26 ZOL
- + CPU_support = 0;
- + if ((SR_msc_cfg & MSC_CFG_MSC_EXT) && (SR_msc_cfg2 & MSC_CFG2_ZOL))
- + CPU_support = 1;
- + if (ELF_elf_ver == EHFF_ELF_VER_1_4_0)
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "ZOL", CPU_support, eflag & EHFF_HAS_ZOL);
- +
- + //bit 25 DSP
- + CPU_support = 0;
- + if ((SR_msc_cfg & MSC_CFG_MSC_EXT) && (SR_msc_cfg2 & MSC_CFG2_DSPPF))
- + CPU_support = 1;
- + if (ELF_elf_ver == EHFF_ELF_VER_1_4_0)
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "DSP ISA", CPU_support, eflag & EHFF_ISA_DSP);
- +
- + //bit 24
- + CPU_support = 0;
- + if(fpu_mount)
- + if(fpcfg & 0x00000010)
- + CPU_support = 1;
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "FPU MAC ISA", CPU_support, eflag & EHFF_ISA_FPU_MAC);
- +
- + //bit 23~22
- + if(fpu_mount)
- + FPU_reg_cpu = ((fpcfg >> 2) & 0x3) + 1;
- + else
- + FPU_reg_cpu = 0;
- +
- + if(eflag & (EHFF_ISA_FPU_SP | EHFF_ISA_FPU_DP | EHFF_ISA_FPU_MAC))
- + FPU_reg_elf = ((eflag & EHFF_FPU_REG) >> EHFF_FPU_REG_SHIFT) + 1;
- + else
- + FPU_reg_elf = 0;
- + if(FPU_reg_elf > FPU_reg_cpu)
- + {
- + error_type = EFT_ERROR;
- + n_error++;
- + }
- + else
- + error_type = EFT_NONE;
- + NEC_print(buf, len, error_type, "FPU REGISTER", NEC_MSG_FPU_reg[FPU_reg_cpu], NEC_MSG_FPU_reg[FPU_reg_elf],
- + "FPU REGISTERS not supported by CPU");
- + //bit 21
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "L2C ISA", SR_msc_cfg & MSC_CFG_L2C, eflag & EHFF_ISA_L2C);
- +
- + //bit 20
- + //MAC_DX check
- + // Target Machine certainly has MAC_DX under the following conditions:
- + // 1. Baseline V1 ISA && MSC_CFG.MAC (softcore version)
- + // 2. Baseline V2 ISA && D0/D1 support
- + // 3. Baseline V3 ISA && D0/D1 support
- +
- + switch(ELF_arch_ver)
- + {
- + case EHFF_ARCH_VER_V1:
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "MAC/MAC DX ISA", CPU_MAC_DX_ISA, !(eflag & EHFF_ISA_NO_MAC));
- + break;
- + case EHFF_ARCH_VER_V2:
- + case EHFF_ARCH_VER_V3:
- + case EHFF_ARCH_VER_V3M:
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "MAC DX ISA", CPU_MAC_DX_ISA, eflag & EHFF_ISA_MAC_DX);
- + break;
- + }
- + //bit 19
- + CPU_support = 0;
- + if(fpu_mount)
- + if(fpcfg & 0x00000002)
- + CPU_support = 1;
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "FPU DP ISA", CPU_support, eflag & EHFF_ISA_FPU_DP);
- +
- +
- + //bit 18 Reserved
- + //bit 17
- + switch(ELF_elf_ver)
- + {
- + case EHFF_ELF_VER_1_3_0:
- + case EHFF_ELF_VER_1_3_1:
- + break;
- + case EHFF_ELF_VER_1_4_0:
- + switch(ELF_arch_ver)
- + {
- + case EHFF_ARCH_VER_V3:
- + case EHFF_ARCH_VER_V3M:
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "SATURATION ISA", SR_cpu_ver & CPU_VER_SATURATION, eflag & EHFF_ISA_SATURATION);
- + break;
- + }
- + break;
- + }
- + //bit 16
- + if(SR_msc_cfg & MSC_CFG_REDUCED_REG)
- + CPU_support = 0;
- + else
- + CPU_support = 1;
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "32 GPR", CPU_support, (eflag & EHFF_REDUCED_REGS) == 0);
- +
- + //bit 15
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "STRING ISA", SR_cpu_ver & CPU_VER_STRING, eflag & EHFF_ISA_STRING);
- +
- + //bit 14
- + switch(ELF_elf_ver)
- + {
- + case EHFF_ELF_VER_1_3_0:
- + case EHFF_ELF_VER_1_3_1:
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "16-BIT ISA", SR_cpu_ver & CPU_VER_A16, eflag & EHFF_ISA_16BIT);
- + break;
- + case EHFF_ELF_VER_1_4_0:
- + switch(ELF_arch_ver)
- + {
- + case EHFF_ARCH_VER_V1:
- + case EHFF_ARCH_VER_V2:
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "16-BIT ISA", SR_cpu_ver & CPU_VER_A16, eflag & EHFF_ISA_16BIT);
- + break;
- + case EHFF_ARCH_VER_V3:
- + case EHFF_ARCH_VER_V3M:
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "IFC ISA", SR_msc_cfg & MSC_CFG_IFC, eflag & EHFF_ISA_IFC);
- + break;
- + }
- + break;
- + }
- +
- + //bit 13
- + switch(ELF_arch_ver)
- + {
- + case EHFF_ARCH_VER_V1:
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "DIV DX ISA", CPU_DIV_DX_ISA, eflag & EHFF_ISA_DIV);
- + break;
- + case EHFF_ARCH_VER_V2:
- + case EHFF_ARCH_VER_V3:
- + case EHFF_ARCH_VER_V3M:
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "DIV DX ISA", CPU_DIV_DX_ISA, eflag & EHFF_ISA_DIV_DX);
- + break;
- + }
- + //bit 12
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "AUDIO/DSP ISA", SR_msc_cfg & MSC_CFG_AUDIO, eflag & EHFF_ISA_AUDIO);
- + //bit 11
- + CPU_support = 0;
- + if(fpu_mount)
- + if(fpcfg & 0x00000001)
- + CPU_support = 1;
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "FPU SP ISA", CPU_support, eflag & EHFF_ISA_FPU_SP);
- +
- + //bit 10
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "PEX2 ISA", SR_cpu_ver & CPU_VER_EXT2, eflag & EHFF_ISA_EXT2);
- +
- + //bit 9
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "PEX1 ISA", SR_cpu_ver & CPU_VER_EXT, eflag & EHFF_ISA_EXT);
- +
- + //bit 8
- + CPU_support = 0;
- + if(CPU_arch_ver == EHFF_ARCH_VER_V3M)
- + CPU_support = 1;
- + switch(ELF_elf_ver)
- + {
- + case EHFF_ELF_VER_1_3_0:
- + case EHFF_ELF_VER_1_3_1:
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "MFUSR_PC ISA", CPU_support, eflag & EHFF_ISA_MFUSR_PC);
- + break;
- + case EHFF_ELF_VER_1_4_0:
- + switch(ELF_arch_ver)
- + {
- + case EHFF_ARCH_VER_V1:
- + case EHFF_ARCH_VER_V2:
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "MFUSR_PC ISA", CPU_support, eflag & EHFF_ISA_MFUSR_PC);
- + break;
- + case EHFF_ARCH_VER_V3:
- + case EHFF_ARCH_VER_V3M:
- + n_error += NEC_check_bool(buf, len, EFT_ERROR, "EIT ISA", SR_msc_cfg & MSC_CFG_EX9IT, eflag & EHFF_ISA_EIT);
- + break;
- + }
- + break;
- + }
- +
- + if(n_error)
- + {
- + NEC_strcat_safety(buf, len, (char*)"Error: ELF and CPU mismatch\n");
- + NEC_sprintf(temp, "Total Error: %d\n", n_error);
- + NEC_strcat_safety(buf, len, temp);
- +
- + NEC_strcat_safety(buf, len, (char*)"Usage error, Consult Andes Toolchains and their compatible Andes cores for the Toolchain-CPU compatibility.\n");
- + NEC_strcat_safety(buf, len, (char*)"The Loader Checking can be disabled under Debug Configuration.\n");
- + }
- + else
- + NEC_strcat_safety(buf, len, (char*)"NDS32 ELF checking pass\n");
- +
- + if(n_warning)
- + {
- + NEC_sprintf(temp, "Total Warning: %d\n", n_warning);
- + NEC_strcat_safety(buf, len, temp);
- + }
- +
- +
- + // checking buf overflow
- + if(strlen(buf) >= len)
- + *buf_status = 1;
- +
- + return n_error;
- + } //end of elf_check
- +
- +#undef elf_check_swap_2
- +#undef elf_check_swap_4
- +
- +#undef MSC_CFG_BASEV
- +
- +#undef CPU_VER_STRING
- +#undef CPU_VER_EXT
- +#undef CPU_VER_A16
- +#undef CPU_VER_EXT2
- +#undef CPU_VER_FPU
- +#undef CPU_VER_SATURATION
- +
- +#undef MSC_CFG_DIV
- +#undef MSC_CFG_MAC
- +#undef MSC_CFG_L2C
- +#undef MSC_CFG_REDUCED_REG
- +#undef MSC_CFG_NOD
- +#undef MSC_CFG_AUDIO
- +#undef MSC_CFG_AUDIO_NONE
- +#undef MSC_CFG_IFC
- +#undef MSC_CFG_MCU
- +#undef MSC_CFG_EX9IT
- +#undef MSC_CFG_MSC_EXT
- +
- +#undef MSC_CFG2_DSPPF
- +#undef MSC_CFG2_ZOL
- +
- +#undef MMU_CFG_DE
- +
- +#ifdef __cplusplus
- +}
- +#endif //#ifdef __cplusplus
- +
- +#endif //end of _NDS32_ELF_CHECK
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/nds32_ksyms.c linux-3.4.110/arch/nds32/kernel/nds32_ksyms.c
- --- linux-3.4.110.orig/arch/nds32/kernel/nds32_ksyms.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/nds32_ksyms.c 2016-04-07 10:20:50.942081024 +0200
- @@ -0,0 +1,103 @@
- +/*
- + * arch/nds32/kernel/nds32_ksyms.c
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +
- +#include <linux/module.h>
- +#include <linux/string.h>
- +#include <linux/delay.h>
- +#include <linux/in6.h>
- +#include <linux/syscalls.h>
- +
- +#include <asm/checksum.h>
- +#include <asm/io.h>
- +#include <asm/system.h>
- +#include <asm/uaccess.h>
- +
- +/*
- + * libgcc functions - functions that are used internally by the
- + * compiler... (prototypes are not correct though, but that
- + * doesn't really matter since they're not versioned).
- + */
- +extern void __ashldi3(void);
- +extern void __ashrdi3(void);
- +extern void __divsi3(void);
- +extern void __lshrdi3(void);
- +extern void __modsi3(void);
- +extern void __muldi3(void);
- +extern void __ucmpdi2(void);
- +extern void __udivdi3(void);
- +extern void __umoddi3(void);
- +extern void __udivmoddi4(void);
- +extern void __udivsi3(void);
- +extern void __umodsi3(void);
- +
- +/*
- + * This has a special calling convention; it doesn't
- + * modify any of the usual registers, except for LR.
- + */
- +#define EXPORT_SYMBOL_ALIAS(sym,orig) \
- + const struct kernel_symbol __ksymtab_##sym \
- + __attribute__((section("__ksymtab"))) = \
- + { (unsigned long)&orig, #sym };
- +
- +/*
- + * floating point math emulator support.
- + * These symbols will never change their calling convention...
- + */
- +
- +/* networking */
- +EXPORT_SYMBOL(csum_partial);
- +EXPORT_SYMBOL(csum_partial_copy_nocheck);
- +
- +/* string / mem functions */
- +EXPORT_SYMBOL(strchr);
- +EXPORT_SYMBOL(strrchr);
- +EXPORT_SYMBOL(memset);
- +EXPORT_SYMBOL(memcpy);
- +EXPORT_SYMBOL(memmove);
- +EXPORT_SYMBOL(__memzero);
- +
- +/* user mem (segment) */
- +EXPORT_SYMBOL(__arch_copy_from_user);
- +EXPORT_SYMBOL(__arch_copy_to_user);
- +EXPORT_SYMBOL(__arch_clear_user);
- +EXPORT_SYMBOL(__arch_strnlen_user);
- +EXPORT_SYMBOL(__arch_strncpy_from_user);
- +
- +EXPORT_SYMBOL(__get_user_1);
- +EXPORT_SYMBOL(__get_user_2);
- +EXPORT_SYMBOL(__get_user_4);
- +EXPORT_SYMBOL(__get_user_8);
- +
- +EXPORT_SYMBOL(__put_user_1);
- +EXPORT_SYMBOL(__put_user_2);
- +EXPORT_SYMBOL(__put_user_4);
- +EXPORT_SYMBOL(__put_user_8);
- +
- +/* gcc lib functions */
- +EXPORT_SYMBOL(__ashldi3);
- +EXPORT_SYMBOL(__ashrdi3);
- +EXPORT_SYMBOL(__divsi3);
- +EXPORT_SYMBOL(__lshrdi3);
- +EXPORT_SYMBOL(__modsi3);
- +EXPORT_SYMBOL(__muldi3);
- +EXPORT_SYMBOL(__ucmpdi2);
- +EXPORT_SYMBOL(__udivdi3);
- +EXPORT_SYMBOL(__umoddi3);
- +EXPORT_SYMBOL(__udivmoddi4);
- +EXPORT_SYMBOL(__udivsi3);
- +EXPORT_SYMBOL(__umodsi3);
- +
- +/* syscalls */
- +EXPORT_SYMBOL(sys_write);
- +EXPORT_SYMBOL(sys_lseek);
- +EXPORT_SYMBOL(sys_exit);
- +EXPORT_SYMBOL(sys_wait4);
- +
- +/* cache handling */
- +
- +EXPORT_SYMBOL(cpu_icache_inval_all);
- +EXPORT_SYMBOL(cpu_dcache_wbinval_all);
- +EXPORT_SYMBOL(cpu_dma_inval_range);
- +EXPORT_SYMBOL(cpu_dma_wb_range);
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/proc.c linux-3.4.110/arch/nds32/kernel/proc.c
- --- linux-3.4.110.orig/arch/nds32/kernel/proc.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/proc.c 2016-04-07 10:20:50.942081024 +0200
- @@ -0,0 +1,81 @@
- +/*
- + * linux/arch/nds32/kernel/setup.c
- + *
- + * Copyright (C) 1995-2001 Russell King
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +/* ============================================================================
- + * Copyright (C) 2007 Andes Technology Corporation
- + * This file is part of Linux and should be licensed under the GPL.
- + * See the file COPYING for conditions for redistribution.
- + *
- + * Abstract:
- + *
- + * This program is for Andes NDS32 architecture.
- + *
- + * Revision History:
- + *
- + * Jul.05.2007 Initial ported by Tom, revised and patched for KGDB
- + * by Harry.
- + *
- + * Note:
- + *
- + * ============================================================================
- + */
- +
- +#include <asm/procinfo.h>
- +
- +struct proc_info_item info_item = {
- + "AndesCore",
- +#ifndef CONFIG_CPU_ICACHE_DISABLE
- + "I"
- +#endif
- +#ifndef CONFIG_CPU_DCACHE_DISABLE
- + "D"
- +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
- + "(wt)"
- +#else
- + "(wb)"
- +#endif
- +#endif
- +};
- +
- +struct proc_info_list n10_proc_info
- + __attribute__ ((section(".proc.info.init"))) = {
- +.cpu_val = 0x0a000000,.cpu_mask = 0xff000000,.arch_name =
- + "NDS32 N10",.elf_name = "NDS32 ELF",.elf_hwcap = 0,.info =
- + &info_item,};
- +
- +struct proc_info_list n12_proc_info
- + __attribute__ ((section(".proc.info.init"))) = {
- +.cpu_val = 0x0c000000,.cpu_mask = 0xff000000,.arch_name =
- + "NDS32 N12",.elf_name = "NDS32 ELF",.elf_hwcap = 0,.info =
- + &info_item,};
- +
- +struct proc_info_list n13_proc_info
- + __attribute__ ((section(".proc.info.init"))) = {
- +.cpu_val = 0x0d000000,.cpu_mask = 0xff000000,.arch_name =
- + "NDS32 N13",.elf_name = "NDS32 ELF",.elf_hwcap = 0,.info =
- + &info_item,};
- +
- +struct proc_info_list n968_proc_info
- + __attribute__ ((section(".proc.info.init"))) = {
- +.cpu_val = 0x19000000,.cpu_mask = 0xff000000,.arch_name =
- + "NDS32 N968",.elf_name = "NDS32 ELF",.elf_hwcap = 0,.info =
- + &info_item,};
- +
- +struct proc_info_list n1068_proc_info
- + __attribute__ ((section(".proc.info.init"))) = {
- +.cpu_val = 0x1a000000,.cpu_mask = 0xff000000,.arch_name =
- + "NDS32 N1068",.elf_name = "NDS32 ELF",.elf_hwcap = 0,.info =
- + &info_item,};
- +
- +// the last one (a roust way to do so)
- +struct proc_info_list nXX_proc_info
- + __attribute__ ((section(".proc.info.init"))) = {
- +.cpu_val = 0x00000000,.cpu_mask = 0x00000000,.arch_name =
- + "NDS32 N??",.elf_name = "NDS32 ELF",.elf_hwcap = 0,.info =
- + &info_item,};
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/process.c linux-3.4.110/arch/nds32/kernel/process.c
- --- linux-3.4.110.orig/arch/nds32/kernel/process.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/process.c 2016-04-07 10:20:50.942081024 +0200
- @@ -0,0 +1,630 @@
- +/*
- + * linux/arch/nds32/kernel/process.c
- + */
- +/* Copyright (C) 1996-2000 Russell King - Converted to ARM.
- + * Original Copyright (C) 1995 Linus Torvalds
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +/* ============================================================================
- + * Copyright (C) 2007 Andes Technology Corporation
- + * This file is part of Linux and should be licensed under the GPL.
- + * See the file COPYING for conditions for redistribution.
- + *
- + * Abstract:
- + *
- + * This program is process implementation for NDS32 architecture, and it
- + * is original referred from ARM.
- + *
- + * Revision History:
- + *
- + * Oct.02.2007 Initial ported by Tom, Shawn, Steven, and Harry.
- + * Oct.03.2007 Updated get_wchan() for info under /proc.
- + *
- + * Note:
- + *
- + * ============================================================================
- + */
- +#include <linux/module.h>
- +#include <linux/sched.h>
- +#include <linux/delay.h>
- +#include <linux/kallsyms.h>
- +#include <asm/hardware.h>
- +#include <asm/leds.h>
- +#include <asm/uaccess.h>
- +#include <asm/elf.h>
- +#include <asm/fpu.h>
- +#include <asm/audio.h>
- +#include <linux/elf.h>
- +#include <linux/tick.h>
- +#include <linux/proc_fs.h>
- +
- +extern const char *processor_modes[];
- +extern void setup_mm_for_reboot(char mode);
- +extern struct task_struct *_switch(struct task_struct *last,
- + struct thread_info *prev,
- + struct thread_info *next);
- +
- +#ifndef CONFIG_UNLAZY_FPU
- +struct task_struct *last_task_used_math = NULL;
- +#endif
- +#ifndef CONFIG_UNLAZY_AUDIO
- +struct task_struct *last_task_used_audio = NULL;
- +#endif
- +static volatile int hlt_counter;
- +
- +#ifdef CONFIG_PROC_FS
- +struct proc_dir_entry *proc_dir_cpu;
- +EXPORT_SYMBOL(proc_dir_cpu);
- +#endif
- +
- +extern inline void arch_reset(char mode)
- +{
- + if (mode == 's') {
- + /* Use cpu handler, jump to 0 */
- + cpu_reset(0);
- + } else {
- + /*
- + * Suppose there should be HW function.
- + * Here we used one tick watchdog as a trick.
- + * It is not very good idea in the view of SoC
- + * design, but smart in firmware functionality.
- + * Harry@Jan,08.2008
- + */
- + REG32(WDT_FTWDT010_0_VA_BASE + 0x0C) = 0; // WdCR
- + REG32(WDT_FTWDT010_0_VA_BASE + 0x04) = 1; // WdLoad
- + REG32(WDT_FTWDT010_0_VA_BASE + 0x08) = 0x5AB9; // WdRestart
- + REG32(WDT_FTWDT010_0_VA_BASE + 0x0C) = 0x13; // Go...
- + }
- +}
- +
- +#ifndef arch_idle
- +static inline void arch_idle(void)
- +{
- + cpu_do_idle();
- +}
- +#endif
- +
- +void disable_hlt(void)
- +{
- + hlt_counter++;
- +}
- +
- +EXPORT_SYMBOL(disable_hlt);
- +
- +void enable_hlt(void)
- +{
- + hlt_counter--;
- +}
- +
- +EXPORT_SYMBOL(enable_hlt);
- +
- +static int __init nohlt_setup(char *__unused)
- +{
- + hlt_counter = 1;
- + return 1;
- +}
- +
- +static int __init hlt_setup(char *__unused)
- +{
- + hlt_counter = 0;
- + return 1;
- +}
- +
- +__setup("nohlt", nohlt_setup);
- +__setup("hlt", hlt_setup);
- +
- +/*
- + * The following aren't currently used.
- + */
- +
- +void (*pm_idle) (void) = NULL;
- +EXPORT_SYMBOL(pm_idle);
- +
- +void (*pm_power_off) (void);
- +EXPORT_SYMBOL(pm_power_off);
- +
- +/*
- + * This is our default idle handler. We need to disable
- + * interrupts here to ensure we don't miss a wakeup call.
- + */
- +void default_idle(void)
- +{
- + local_irq_disable();
- + if (!need_resched() && !hlt_counter)
- + arch_idle();
- + local_irq_enable();
- +}
- +
- +/*
- + * The idle thread. We try to conserve power, while trying to keep
- + * overall latency low. The architecture specific idle is passed
- + * a value to indicate the level of "idleness" of the system.
- + */
- +void cpu_idle(void)
- +{
- +
- + /* endless idle loop with no priority at all */
- + while (1) {
- + void (*idle) (void) = pm_idle;
- +
- + if (!idle)
- + idle = default_idle;
- + tick_nohz_idle_enter();
- + leds_event(led_idle_start);
- + while (!need_resched())
- + idle();
- + leds_event(led_idle_end);
- + tick_nohz_idle_exit();
- + preempt_enable_no_resched();
- + schedule();
- + preempt_disable();
- + }
- +}
- +
- +static char reboot_mode = 'h';
- +
- +int __init reboot_setup(char *str)
- +{
- + reboot_mode = str[0];
- + return 1;
- +}
- +
- +#ifdef CONFIG_PLAT_AG102
- +static int cpub_pwroff(void)
- +{
- + //PCU_SET_REG(PCS9_PARA,
- + // PCU_PREPARE(PCS9_PARA, IE, 0x0) |
- + // PCU_PREPARE(PCS9_PARA, CMD, PCS_CMD_SCALING) |
- + // PCU_PREPARE(PCS9_PARA, SYNC, PCS_SYNC_SRC) |
- + // PCU_PREPARE(PCS9_PARA, NXTPAR, 0x1b) // turn off cpub power
- + //);
- + //printk("cpub Power off: ok!!!OKOKOK\n");
- + //REG32(PCU_VA_BASE + 0x1A4) = (0x0000001B & 0x00FFFFFF)| ((0x2 << 24) & 0x0F000000) | ((0x1 << 28) & 0x70000000) | 0x00000000;
- + //__asm__ volatile ("standby wait_done\n");
- + //PCU_SET_REG(PCS9_ST1, 0x0); // clear status
- + //REG32(PCU_VA_BASE + 0x1A8) = 0x0;
- +
- + //par = PCS_POWER_CPUB;
- + //PCU_SET_REG(PCS9_PARA,
- + //PCU_PREPARE(PCS9_PARA, IE, 0x1) |
- + //PCU_PREPARE(PCS9_PARA, CMD, PCS_CMD_PW_DOWN) |
- + //PCU_PREPARE(PCS9_PARA, SYNC, PCS_SYNC_SRC) |
- + //PCU_PREPARE(PCS9_PARA, NXTPAR, 0x6) // turn off all power
- +
- + //printk("cpua Power off: ok!!!YAYAYA\n");
- + //printk("The value = 0x%08x\n", (0x00000006 & 0x00FFFFFF)| ((0x1 << 24) & 0x0F000000) | ((0x2 << 28) & 0x70000000) | 0x80000000);
- + REG32(PCU_VA_BASE + 0x1A4) =
- + (0x00000006 & 0x00FFFFFF) | ((0x1 << 24) & 0x0F000000) |
- + ((0x2 << 28) & 0x70000000) | 0x80000000;
- + __asm__ volatile ("standby wake_grant\n");
- + return (0);
- +}
- +#else
- +static int cpub_pwroff(void)
- +{
- + return 0;
- +}
- +
- +#endif
- +
- +__setup("reboot=", reboot_setup);
- +
- +void machine_halt(void)
- +{
- + //ADD by river 2011.04.14
- + cpub_pwroff();
- +}
- +
- +EXPORT_SYMBOL(machine_halt);
- +
- +void machine_power_off(void)
- +{
- + if (pm_power_off)
- + pm_power_off();
- +}
- +
- +EXPORT_SYMBOL(machine_power_off);
- +
- +void machine_restart(char *__unused)
- +{
- + /*
- + * Clean and disable cache, and turn off interrupts
- + */
- + cpu_proc_fin();
- +
- + /*
- + * Tell the mm system that we are going to reboot -
- + * we may need it to insert some 1:1 mappings so that
- + * soft boot works.
- + */
- + setup_mm_for_reboot(reboot_mode);
- +
- + /*
- + * Now call the architecture specific reboot code.
- + */
- + arch_reset(reboot_mode);
- +
- + /*
- + * Whoops - the architecture was unable to reboot.
- + * Tell the user!
- + */
- + mdelay(1000);
- + printk("Reboot failed -- System halted\n");
- + while (1) ;
- +}
- +
- +EXPORT_SYMBOL(machine_restart);
- +
- +void show_regs(struct pt_regs *regs)
- +{
- + print_symbol("PC is at %s\n", instruction_pointer(regs));
- + print_symbol("LR is at %s\n", regs->NDS32_lp);
- + printk("pc : [<%08lx>] lp : [<%08lx>] %s\n"
- + "sp : %08lx fp : %08lx gp : %08lx\n",
- + instruction_pointer(regs),
- + regs->NDS32_lp, print_tainted(), regs->NDS32_sp,
- + regs->NDS32_fp, regs->NDS32_gp);
- + printk("r25: %08lx r24 : %08lx\n", regs->NDS32_r25, regs->NDS32_r24);
- +
- + printk("r23: %08lx r22: %08lx r21: %08lx r20: %08lx\n",
- + regs->NDS32_r23, regs->NDS32_r22,
- + regs->NDS32_r21, regs->NDS32_r20);
- + printk("r19: %08lx r18: %08lx r17: %08lx r16: %08lx\n",
- + regs->NDS32_r19, regs->NDS32_r18,
- + regs->NDS32_r17, regs->NDS32_r16);
- + printk("r15: %08lx r14: %08lx r13: %08lx r12: %08lx\n",
- + regs->NDS32_r15, regs->NDS32_r14,
- + regs->NDS32_r13, regs->NDS32_r12);
- + printk("r11: %08lx r10: %08lx r9 : %08lx r8 : %08lx\n",
- + regs->NDS32_r11, regs->NDS32_r10,
- + regs->NDS32_r9, regs->NDS32_r8);
- + printk("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n",
- + regs->NDS32_r7, regs->NDS32_r6, regs->NDS32_r5, regs->NDS32_r4);
- + printk("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
- + regs->NDS32_r3, regs->NDS32_r2, regs->NDS32_r1, regs->NDS32_r0);
- + printk(" IRQs o%s Segment %s\n",
- + interrupts_enabled(regs) ? "n" : "ff",
- + segment_eq(get_fs(), get_ds())? "kernel" : "user");
- +}
- +
- +void show_fpregs(struct user_fp *regs)
- +{
- + int i;
- +
- + for (i = 0; i < 8; i++) {
- + unsigned long *p;
- + char type;
- +
- + p = (unsigned long *)(regs->fpregs + i);
- +
- + switch (regs->ftype[i]) {
- + case 1:
- + type = 'f';
- + break;
- + case 2:
- + type = 'd';
- + break;
- + case 3:
- + type = 'e';
- + break;
- + default:
- + type = '?';
- + break;
- + }
- + if (regs->init_flag)
- + type = '?';
- +
- + printk(" f%d(%c): %08lx %08lx %08lx%c",
- + i, type, p[0], p[1], p[2], i & 1 ? '\n' : ' ');
- + }
- +
- + printk("FPSR: %08lx FPCR: %08lx\n",
- + (unsigned long)regs->fpsr, (unsigned long)regs->fpcr);
- +}
- +
- +/*
- + * Task structure and kernel stack allocation.
- + */
- +static unsigned long *thread_info_head;
- +static unsigned int nr_thread_info;
- +
- +#define EXTRA_TASK_STRUCT 4
- +#define ll_alloc_task_struct() ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
- +#define ll_free_task_struct(p) free_pages((unsigned long)(p),1)
- +
- +struct thread_info *alloc_thread_info(struct task_struct *task)
- +{
- + struct thread_info *thread = NULL;
- +
- + if (EXTRA_TASK_STRUCT) {
- + unsigned long *p = thread_info_head;
- +
- + if (p) {
- + thread_info_head = (unsigned long *)p[0];
- + nr_thread_info -= 1;
- + }
- + thread = (struct thread_info *)p;
- + }
- +
- + if (!thread)
- + thread = ll_alloc_task_struct();
- +
- +#ifdef CONFIG_MAGIC_SYSRQ
- + /*
- + * The stack must be cleared if you want SYSRQ-T to
- + * give sensible stack usage information
- + */
- + if (thread) {
- + char *p = (char *)thread;
- + memzero(p + KERNEL_STACK_SIZE, KERNEL_STACK_SIZE);
- + }
- +#endif
- + return thread;
- +}
- +
- +void free_thread_info(struct thread_info *thread)
- +{
- + if (EXTRA_TASK_STRUCT && nr_thread_info < EXTRA_TASK_STRUCT) {
- + unsigned long *p = (unsigned long *)thread;
- + p[0] = (unsigned long)thread_info_head;
- + thread_info_head = p;
- + nr_thread_info += 1;
- + } else
- + ll_free_task_struct(thread);
- +}
- +
- +/*
- + * Free current thread data structures etc..
- + */
- +void exit_thread(void)
- +{
- +#if defined(CONFIG_FPU)
- +# ifndef CONFIG_UNLAZY_FPU
- + if (last_task_used_math == current) {
- + last_task_used_math = NULL;
- + }
- +# endif
- +#endif
- +#if defined(CONFIG_AUDIO)
- +# ifndef CONFIG_UNLAZY_AUDIO
- + if (last_task_used_audio == current) {
- + last_task_used_audio = NULL;
- + }
- +# endif
- +#endif
- +}
- +
- +void flush_thread(void)
- +{
- + struct task_struct *tsk = current;
- +
- + memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
- +#if defined(CONFIG_FPU)
- + clear_fpu(task_pt_regs(tsk));
- + clear_used_math();
- +# ifndef CONFIG_UNLAZY_FPU
- + if (last_task_used_math == current) {
- + last_task_used_math = NULL;
- + }
- +# endif
- +#endif
- +
- +#if defined(CONFIG_AUDIO)
- + clear_audio(task_pt_regs(tsk));
- + clear_tsk_thread_flag(tsk, TIF_USEDAUDIO);
- +# ifndef CONFIG_UNLAZY_AUDIO
- + if (last_task_used_audio == current) {
- + last_task_used_audio = NULL;
- + }
- +# endif
- +#endif
- +
- +}
- +
- +void release_thread(struct task_struct *dead_task)
- +{
- +}
- +
- +asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
- +
- +/*
- + * Shuffle the argument into the correct register before calling the
- + * thread function. $r1 is the thread argument, $r2 is the pointer to
- + * the thread function, and $r3 points to the exit function.
- + */
- +extern void kernel_thread_helper(void);
- +asm(".section .text\n"
- + " .align\n"
- + " .type kernel_thread_helper, #function\n"
- + "kernel_thread_helper:\n"
- + " move $r2, $lp\n"
- + " move $r0, $r1\n"
- + " move $lp, $r3\n"
- + " jr $r2 \n"
- + " .size kernel_thread_helper, . - kernel_thread_helper\n"
- + " .previous");
- +
- +pid_t kernel_thread(int (*fn) (void *), void *arg, unsigned long flags)
- +{
- + struct pt_regs regs;
- +
- + memset(®s, 0, sizeof(regs));
- +
- + regs.NDS32_r1 = (unsigned long)arg;
- + regs.NDS32_r2 = (unsigned long)fn;
- + /* to apply right path */
- + regs.NDS32_lp = regs.NDS32_r2;
- + regs.NDS32_r3 = (unsigned long)do_exit;
- + regs.NDS32_ipc = (unsigned long)kernel_thread_helper;
- +
- +#ifdef __NDS32_EB__
- +#define PSW_DE PSW_mskBE
- +#else
- +#define PSW_DE 0x0
- +#endif
- +
- +#ifdef CONFIG_WBNA
- +#define PSW_valWBNA PSW_mskWBNA
- +#else
- +#define PSW_valWBNA 0x0
- +#endif
- +
- + regs.NDS32_ipsw =
- + (PSW_CPL_ANY | PSW_valWBNA | PSW_mskDT | PSW_mskIT | PSW_DE |
- + PSW_SYSTEM | PSW_INTL_1 | PSW_mskGIE);
- + regs.NDS32_ir0 =
- + (PSW_CPL_ANY | PSW_valWBNA | PSW_mskDT | PSW_mskIT | PSW_DE |
- + PSW_SYSTEM | PSW_INTL_1);
- +
- + return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL,
- + NULL);
- +}
- +
- +EXPORT_SYMBOL(kernel_thread);
- +
- +int
- +copy_thread(unsigned long clone_flags, unsigned long stack_start,
- + unsigned long stk_sz, struct task_struct *p, struct pt_regs *regs)
- +{
- + struct thread_info *thread = task_thread_info(p);
- + struct pt_regs *childregs;
- +
- + childregs =
- + ((struct pt_regs *)((unsigned long)thread + THREAD_SIZE - 8)) - 1;
- +
- + *childregs = *regs;
- + childregs->NDS32_r0 = 0; /* child get zero as ret. */
- + childregs->NDS32_sp = stack_start;
- + childregs->NDS32_osp = 0;
- +
- + thread->sp_save = ((struct cpu_context_save *)(childregs)) - 1;
- + /* cpu context switching */
- + thread->sp_save->pc = (unsigned long)ret_from_fork;
- + if (clone_flags & CLONE_SETTLS)
- + childregs->NDS32_r25 = regs->NDS32_r3;
- +
- +#ifdef CONFIG_FPU
- + if (used_math()) {
- +# ifdef CONFIG_UNLAZY_FPU
- + unlazy_fpu(current);
- +# else
- + preempt_disable();
- + if (last_task_used_math == current)
- + save_fpu(current);
- + preempt_enable();
- +# endif
- + p->thread.fpu = current->thread.fpu;
- + clear_fpu(task_pt_regs(p));
- + set_stopped_child_used_math(p);
- + }
- +#endif
- +
- +#ifdef CONFIG_AUDIO
- + if (test_tsk_thread_flag(current, TIF_USEDAUDIO)) {
- +# ifdef CONFIG_UNLAZY_AUDIO
- + unlazy_audio(current);
- +# else
- + preempt_disable();
- + if (last_task_used_audio == current)
- + save_audio(current);
- + preempt_enable();
- +# endif
- + p->thread.audio = current->thread.audio;
- + clear_audio(childregs);
- + set_tsk_thread_flag(p, TIF_USEDAUDIO);
- + }
- +#endif
- +
- +#ifdef CONFIG_HWZOL
- + childregs->NDS32_lb = 0;
- + childregs->NDS32_le = 0;
- + childregs->NDS32_lc = 0;
- +#endif
- +
- + return 0;
- +}
- +
- +struct task_struct *__switch_to(struct task_struct *last,
- + struct thread_info *prev,
- + struct thread_info *next)
- +{
- +#if defined(CONFIG_FPU) || defined(CONFIG_AUDIO)
- +# ifdef CONFIG_UNLAZY_FPU
- + unlazy_fpu(prev->task);
- +# endif
- +# ifdef CONFIG_UNLAZY_AUDIO
- + unlazy_audio(prev->task);
- +# endif
- + if (!(next->task->flags & PF_KTHREAD)) {
- +#ifdef CONFIG_FPU
- + clear_fpu(task_pt_regs(next->task));
- +#endif
- +#ifdef CONFIG_AUDIO
- + clear_audio(task_pt_regs(next->task));
- +#endif
- + }
- +#endif
- + return _switch(last, prev, next);
- +}
- +
- +/*
- + * fill in the fpe structure for a core dump...
- + */
- +int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpu)
- +{
- + int fpvalid = 0;
- +
- +#if 0 // XXX defined(CONFIG_FPU)
- + struct task_struct *tsk = current;
- +
- + fpvalid = !!tsk_used_math(tsk);
- + if (fpvalid) {
- + unlazy_fpu(tsk, regs);
- + memcpy(fpu, &tsk->thread.fpu, sizeof(*fpu));
- + }
- +#endif
- +
- + return fpvalid;
- +}
- +
- +EXPORT_SYMBOL(dump_fpu);
- +
- +unsigned long get_wchan(struct task_struct *p)
- +{
- + unsigned long fp, lr;
- + unsigned long stack_start, stack_end;
- + int count = 0;
- +
- + if (!p || p == current || p->state == TASK_RUNNING)
- + return 0;
- +
- +#ifdef CONFIG_FRAME_POINTER
- + stack_start = (unsigned long)end_of_stack(p);
- + stack_end = (unsigned long)task_stack_page(p) + THREAD_SIZE;
- +
- + fp = thread_saved_fp(p);
- + do {
- + if (fp < stack_start || fp > stack_end)
- + return 0;
- + lr = ((unsigned long *)fp)[0];
- + if (!in_sched_functions(lr))
- + return lr;
- + fp = *(unsigned long *)(fp + 4);
- + } while (count++ < 16);
- + return 0;
- +#else
- + return 0;
- +#endif
- +}
- +
- +EXPORT_SYMBOL(get_wchan);
- +
- +extern int do_elf_check_arch(const struct elf32_hdr *hdr);
- +
- +int elf_check_arch(const struct elf32_hdr *hdr)
- +{
- + return do_elf_check_arch(hdr);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/ptrace.c linux-3.4.110/arch/nds32/kernel/ptrace.c
- --- linux-3.4.110.orig/arch/nds32/kernel/ptrace.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/ptrace.c 2016-04-07 10:22:02.056831821 +0200
- @@ -0,0 +1,919 @@
- +/*
- + * linux/arch/nds32/kernel/ptrace.c
- + */
- +/* By Ross Biro 1/23/92
- + * edited by Linus Torvalds
- + * ARM modifications Copyright (C) 2000 Russell King
- + * NDS32 modifications Copyright (C) 2007 Harry Pan
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +/* ============================================================================
- + * Copyright (C) 2007 Andes Technology Corporation
- + * This file is part of Linux and should be licensed under the GPL.
- + * See the file COPYING for conditions for redistribution.
- + *
- + * Abstract:
- + *
- + * This program is for Andes NDS32 architecture.
- + *
- + * Revision History:
- + *
- + * Jul.31.2007 Initial ported by Tom, Shawn, and Steven,
- + * revised by Harry.
- + * Current implmentation is based on Andes Instruction
- + * Set Architecture Specification (AS-0001-0001)
- + * version:3.7 date:7-20-2007.
- + * It is original taken from ARM, then fit to NDS32.
- + * Aug.15.2007 Mainly updated breakpoint handling base on NDS32 ISA.
- + * I also did code revise.
- + * Nov.14.2007 Fixed up ptrace_set_bpt() while handling 16-bit insn.
- + * Nov.27.2007 Added checking duplicate breakpoints in
- + * add_breakpoint(), based on Shawn's idea.
- + * Dec.06.2007 Added get_user_gpr().
- + * Apr.17.2009 Added support for FPU and Audio regs.
- + * Added support for PTRACE_GETFPREGS, PTRACE_SETFPREGS,
- + * PTRACE_GETAUREGS, PTRACE_SETAUREGS
- + *
- + * Note:
- + *
- + * Current layout: 0-31 GR, 32-34 SPR, 35-... SR, index start from zero.
- + *
- + * +----------+-----+--------------+---+--------+
- + * | GR | SPR | SR |...| Audio |
- + * +----------+-----+--------------+---+--------+
- + * 0 32 35 ...500 531
- + *
- + * ============================================================================
- + */
- +#include <linux/kernel.h>
- +#include <linux/sched.h>
- +#include <linux/mm.h>
- +#include <linux/smp.h>
- +#include <linux/ptrace.h>
- +#include <linux/user.h>
- +#include <linux/security.h>
- +#include <linux/init.h>
- +
- +#include <asm/uaccess.h>
- +#include <asm/pgtable.h>
- +#include <asm/system.h>
- +#include <asm/traps.h>
- +#include <asm/fpu.h>
- +#include <asm/audio.h>
- +
- +#include "ptrace.h"
- +
- +#ifdef __NDS32_EL__
- +#define BREAKINST 0x01EA
- +#else
- +#define BREAKINST 0xEA01
- +#endif
- +
- +/* get_user_reg()
- + *
- + * This routine will get a word off of the processes privileged stack.
- + * the offset is how far from the base addr as stored in the THREAD.
- + * this routine assumes that all the privileged stacks are in our
- + * data space.
- + */
- +static inline unsigned int get_user_reg(struct task_struct *task, int offset)
- +{
- + return task_pt_regs(task)->uregs[offset];
- +}
- +
- +#if !defined(CONFIG_HSS)
- +/* get_user_gpr()
- + *
- + */
- +static unsigned int get_user_gpr(struct task_struct *task, int idx)
- +{
- + unsigned int ret;
- +
- + if (idx < 26) // r0 to r25
- + ret = get_user_reg(task, idx + 13);
- + else if (idx == 26 || idx == 27) // p0, p1
- + ret = get_user_reg(task, idx - 26 + 7);
- + else if (idx > 27 && idx < 31) // fp, gp, lp
- + ret = get_user_reg(task, idx + 11);
- + else if (idx == 31) // sp
- + ret = get_user_reg(task, 3);
- + else
- + ret = 0;
- +
- + return ret;
- +}
- +#endif
- +
- +/* put_user_reg()
- + *
- + * this routine will put a word on the processes privileged stack.
- + * the offset is how far from the base addr as stored in the THREAD.
- + * this routine assumes that all the privileged stacks are in our
- + * data space.
- + */
- +static inline int put_user_reg(struct task_struct *task, int offset, long data)
- +{
- + struct pt_regs newregs, *regs = task_pt_regs(task);
- + int ret = -EINVAL;
- +
- + newregs = *regs;
- + newregs.uregs[offset] = data;
- +
- + if (valid_user_regs(&newregs)) {
- + regs->uregs[offset] = data;
- + ret = 0;
- + }
- +
- + return ret;
- +}
- +
- +#if !defined(CONFIG_HSS)
- +/*
- + * Read instruction.
- + */
- +static inline int
- +read_insn(struct task_struct *task, unsigned long addr, u32 * res)
- +{
- + int ret;
- + *res = 0;
- + ret = access_process_vm(task, addr, res, 2, 0);
- + if (ret != 2)
- + return 0;
- +#ifdef __NDS32_EL__
- + *res = swab16(*res);
- +#endif
- + if ((*res) & 0x8000)
- + return 2;
- +
- + ret = access_process_vm(task, addr, res, 4, 0);
- + if (ret != 4)
- + return 0;
- +#ifdef __NDS32_EL__
- + *res = swab32(*res);
- +#endif
- + return 4;
- +}
- +
- +/* get_branch_address()
- + *
- + * Decode branch instructions and destination.
- + */
- +static unsigned long
- +get_branch_address(struct task_struct *child,
- + unsigned long pc, unsigned long insn, unsigned int size)
- +{
- + unsigned int tpc = 0;
- +
- + /*
- + * TODO: COLE
- + * would it be simpler if we use two BREAKs,
- + * one for take, one for not
- + */
- +
- + if (size == 4) {
- + /* 32-bit instruction */
- + if ((insn & 0x7e000000) == 0x4c000000) // BR1
- + {
- + int cond, imm14s;
- + unsigned int rt, ra;
- +
- + rt = (insn >> 20) & 0x1f;
- + ra = (insn >> 15) & 0x1f;
- + cond = (insn >> 14) & 0x01;
- + imm14s = insn & 0x00003fff;
- +
- + if (imm14s & 0x00002000) // sign extend
- + imm14s -= (0x00002000 << 1);
- +
- + rt = get_user_gpr(child, rt);
- + ra = get_user_gpr(child, ra);
- +
- + if (((cond == 1) && (rt != ra)) || // bne
- + ((cond == 0) && (rt == ra))) // beq
- + tpc = pc + (imm14s << 1);
- + } else if ((insn & 0x7e000000) == 0x4e000000) // BR2
- + {
- + int cond, imm16s, taken = 0;
- + int rt;
- +
- + rt = (insn >> 20) & 0x1f;
- + cond = (insn >> 16) & 0x0f;
- + imm16s = insn & 0x0000ffff;
- +
- + if (imm16s & 0x00008000) // sign extend
- + imm16s -= (0x00008000 << 1);
- +
- + rt = get_user_gpr(child, rt);
- +
- + switch (cond) {
- + case 0x02: // beqz
- + if (rt == 0)
- + taken = 1;
- + break;
- + case 0x03: // bnez
- + if (rt != 0)
- + taken = 1;
- + break;
- + case 0x06: // bgtz
- + if (rt > 0)
- + taken = 1;
- + break;
- + case 0x07: // blez
- + if (rt <= 0)
- + taken = 1;
- + break;
- + case 0x04: // bgez
- + case 0x0c: // bgezal
- + if (rt >= 0)
- + taken = 1;
- + break;
- + case 0x05: // bltz
- + case 0x0d: // bltzal
- + if (rt < 0)
- + taken = 1;
- + break;
- + default:
- + printk(KERN_WARNING
- + "ptrace: unknown conditional branch.\n");
- + break;
- + }
- +
- + if (taken)
- + tpc = pc + (imm16s << 1);
- + } else if ((insn & 0x7e000000) == 0x48000000) // JI
- + {
- + int imm24s;
- +
- + imm24s = insn & 0x00ffffff;
- +
- + if (imm24s & 0x00800000) // sign extend
- + imm24s -= (0x00800000 << 1);
- +
- + tpc = pc + (imm24s << 1);
- + } else if ((insn & 0x7e000000) == 0x4a000000) // JREG
- + {
- + unsigned int rb = (insn >> 10) & 0x1f;
- +
- + tpc = get_user_gpr(child, rb);
- + }
- +
- + } else {
- + /* 16-bit instruction */
- +
- + if ((insn & 0xf800) == 0xc000) // beqz38
- + {
- + unsigned int rt3;
- +
- + rt3 = (insn >> 8) & 0x07;
- +
- + rt3 = get_user_gpr(child, rt3);
- +
- + if (rt3 == 0) {
- + int imm8s;
- +
- + imm8s = insn & 0x00ff;
- +
- + if (imm8s & 0x0080) // sign extend
- + imm8s -= (0x0080 << 1);
- +
- + tpc = pc + (imm8s << 1);
- + }
- + }
- +
- + if ((insn & 0xf800) == 0xc800) // bnez38
- + {
- + unsigned int rt3;
- +
- + rt3 = (insn >> 8) & 0x07;
- +
- + rt3 = get_user_gpr(child, rt3);
- +
- + if (rt3 != 0) {
- + int imm8s;
- +
- + imm8s = insn & 0x00ff;
- +
- + if (imm8s & 0x0080) // sign extend
- + imm8s -= (0x0080 << 1);
- +
- + tpc = pc + (imm8s << 1);
- + }
- + }
- +
- + if ((insn & 0xf800) == 0xd000) // beqs38, j8
- + {
- + unsigned int rt3, r5;
- +
- + rt3 = (insn >> 8) & 0x07;
- +
- + rt3 = get_user_gpr(child, rt3);
- + r5 = get_user_gpr(child, 5);
- +
- + if (r5 == rt3) {
- + int imm8s;
- + imm8s = insn & 0x00ff;
- +
- + if (imm8s & 0x0080) // sign extend
- + imm8s -= (0x0080 << 1);
- +
- + tpc = pc + (imm8s << 1);
- + }
- + }
- +
- + if ((insn & 0xf800) == 0xd800) // bnes38
- + {
- + unsigned int rt3, r5;
- +
- + rt3 = (insn >> 8) & 0x07;
- +
- + r5 = get_user_gpr(child, 5);
- + rt3 = get_user_gpr(child, rt3);
- +
- + if (r5 != rt3) {
- + int imm8s;
- +
- + imm8s = insn & 0x00ff;
- +
- + if (imm8s & 0x0080) // sign extend
- + imm8s -= (0x0080 << 1);
- +
- + tpc = pc + (imm8s << 1);
- + }
- + }
- +
- + if ((insn & 0xffe0) == 0xdd00 || // jr5
- + (insn & 0xffe0) == 0xdd80 || // ret5
- + (insn & 0xffe0) == 0xdd20) // jral5
- + {
- + unsigned int rb5;
- +
- + rb5 = insn & 0x1f;
- +
- + tpc = get_user_gpr(child, rb5);
- + }
- +
- + if ((insn & 0xfe00) == 0xe800) {
- + int taken = 0;
- + unsigned int r15;
- +
- + r15 = get_user_gpr(child, 15);
- +
- + if (insn & 0x0100) // bnezs8
- + {
- + if (r15 != 0)
- + taken = 1;
- + } else // beqzs8
- + {
- + if (r15 == 0)
- + taken = 1;
- + }
- +
- + if (taken) {
- + int imm8s;
- +
- + imm8s = insn & 0x00ff;
- +
- + if (imm8s & 0x0080) // sign extend
- + imm8s -= (0x0080 << 1);
- +
- + tpc = pc + (imm8s << 1);
- + }
- + }
- + }
- +
- + return tpc;
- +}
- +
- +/*
- + * Swap instructions in the user program.
- + * swap in new_insn. save orignal value in old_insn
- + * assume new_insn is 2-bytes long
- + */
- +static int
- +swap_insn(struct task_struct *task, unsigned long addr,
- + u16 * old_insn, u16 * new_insn)
- +{
- + int ret;
- +
- + ret = access_process_vm(task, addr, old_insn, 2, 0);
- + if (ret == 2)
- + ret = access_process_vm(task, addr, new_insn, 2, 1);
- +
- + return ret;
- +}
- +
- +/*
- + * Add one breakpoint in the user program.
- + */
- +static void
- +add_breakpoint(struct task_struct *task, struct debug_info *dbg,
- + unsigned long addr)
- +{
- + u16 new_insn = BREAKINST;
- + int res;
- +
- + if (dbg->valid) {
- + printk(KERN_ERR "ptrace: too many breakpoints\n");
- + return;
- + }
- +
- + dbg->address = addr;
- + res = swap_insn(task, addr, &dbg->insn, &new_insn);
- + if (res == 2)
- + dbg->valid = 1;
- + if (!dbg->valid)
- + printk(KERN_ERR "ptrace: fail to add breakpoint\n");
- +}
- +
- +/*
- + * Clear one software breakpoint in the user program.
- + */
- +static void clear_breakpoint(struct task_struct *task, struct debug_info *dbg)
- +{
- + int ret;
- + unsigned int addr = dbg->address;
- + u16 old_insn;
- +
- + if (!dbg->valid) {
- + return;
- + }
- + dbg->valid = 0;
- +
- + ret = swap_insn(task, addr, &old_insn, &dbg->insn);
- +
- + if (ret != 2 || old_insn != BREAKINST) {
- + printk(KERN_ERR "ptrace: %s:%d: corrupted NDS16 breakpoint at "
- + "0x%08x (0x%04x)\n", task->comm, task->pid,
- + addr, old_insn);
- + }
- +}
- +
- +/*
- + * ptrace_set_swbk
- + * Set breakpoint in user program.
- + */
- +void ptrace_set_swbk(struct task_struct *child)
- +{
- + struct pt_regs *regs;
- + unsigned long pc;
- + unsigned int size;
- + u32 insn;
- +
- + /*
- + * always clear before set,
- + * since in some sepcial case, it may fail to hit
- + */
- + ptrace_cancel_swbk(child);
- + regs = task_pt_regs(child);
- + pc = instruction_pointer(regs);
- + size = read_insn(child, pc, &insn);
- +
- + printk(KERN_DEBUG " STEP.size=%d\n", size);
- +
- + if (size > 0) {
- + struct debug_info *dbg = &child->thread.debug;
- + unsigned int tpc;
- +
- + /* Predict next PC. */
- + tpc = get_branch_address(child, pc, insn, size);
- +
- + if (tpc) {
- + printk(KERN_DEBUG " STEP.addr=0x%x\n", tpc);
- + add_breakpoint(child, dbg, tpc);
- + } else {
- + if (size == 4) {
- + printk(KERN_DEBUG " STEP.addr=0x%x\n",
- + (unsigned int)(pc + 4));
- + add_breakpoint(child, dbg, pc + 4);
- + } else if (size == 2) {
- + printk(KERN_DEBUG " STEP.addr=0x%x\n",
- + (unsigned int)(pc + 2));
- + add_breakpoint(child, dbg, pc + 2);
- + } else {
- + printk(KERN_ERR
- + "ptrace: bad step address, pc + %d\n",
- + size);
- + }
- + }
- + }
- +}
- +
- +/*
- + * Ensure no single-step breakpoint is pending. Returns non-zero
- + * value if child was being single-stepped.
- + */
- +void ptrace_cancel_swbk(struct task_struct *child)
- +{
- + if (!child->thread.debug.valid) {
- + return;
- + }
- +
- + clear_breakpoint(child, &child->thread.debug);
- +}
- +#endif /* end of !defined (CONFIG_HSS) */
- +
- +/*
- + * Called by kernel/ptrace.c when detaching..
- + *
- + * Make sure the single step bit is not set.
- + */
- +void ptrace_disable(struct task_struct *child)
- +{
- + user_disable_single_step(child);
- +}
- +
- +/*
- + * Handle hitting a breakpoint.
- + */
- +void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
- + int error_code, int si_code)
- +{
- + struct siginfo info;
- +
- +#if !defined (CONFIG_HSS)
- + /* clear the swbk; otherwise the user will see it */
- + ptrace_cancel_swbk(tsk);
- +#endif
- +
- + tsk->thread.trap_no = 1;
- + tsk->thread.error_code = error_code;
- +
- + memset(&info, 0, sizeof(info));
- + info.si_signo = SIGTRAP;
- + info.si_code = si_code;
- +
- + info.si_addr = (void __user *)instruction_pointer(regs);
- +
- + /* Send us the fake SIGTRAP */
- + force_sig_info(SIGTRAP, &info, tsk);
- +}
- +
- +/* ptrace_read_user()
- + *
- + * Read the word at offset "off" into the "struct user". We
- + * actually access the pt_regs stored on the kernel stack.
- + */
- +static int
- +ptrace_read_user(struct task_struct *tsk, unsigned long off,
- + unsigned long __user * ret)
- +{
- + unsigned long tmp = 0;
- +
- + if (off < 500) {
- + if (off & 3 || off >= sizeof(struct user))
- + return -EIO;
- +
- + if (off < sizeof(struct pt_regs))
- + tmp = get_user_reg(tsk, off >> 2);
- +
- + return put_user(tmp, ret);
- + } else if (off < 532) {
- +#ifdef CONFIG_AUDIO
- + off -= 500;
- + if (test_tsk_thread_flag(tsk, TIF_USEDAUDIO)) {
- +#ifdef CONFIG_UNLAZY_AUDIO
- + unlazy_audio(tsk);
- +#else
- + preempt_disable();
- + if (last_task_used_audio == tsk)
- + save_audio(tsk);
- + preempt_enable();
- +#endif
- + tmp = tsk->thread.audio.auregs[off];
- + }
- +#endif
- + return put_user(tmp, ret);
- + } else
- + return -EIO;
- +}
- +
- +/* ptrace_write_user()
- + *
- + * Write the word at offset "off" into "struct user". We
- + * actually access the pt_regs stored on the kernel stack.
- + */
- +static int
- +ptrace_write_user(struct task_struct *tsk, unsigned long off, unsigned long val)
- +{
- + if (off < 500) {
- + if (off & 3 || off >= sizeof(struct user))
- + return -EIO;
- +
- + if (off >= sizeof(struct pt_regs))
- + return 0;
- +
- + return put_user_reg(tsk, off >> 2, val);
- + } else if (off < 532) {
- +#ifdef CONFIG_AUDIO
- + off -= 500;
- + if (!test_tsk_thread_flag(tsk, TIF_USEDAUDIO)) {
- + /* First time Audio user. */
- + memset(&tsk->thread.audio, 0,
- + sizeof(struct audio_struct));
- + set_tsk_thread_flag(tsk, TIF_USEDAUDIO);
- + } else {
- +#ifdef CONFIG_UNLAZY_AUDIO
- + unlazy_audio(tsk);
- +#else
- + if (last_task_used_audio == tsk) {
- + preempt_disable();
- + save_audio(tsk);
- + preempt_enable();
- + }
- +#endif
- + /* Let the lazy mechanism do the restore. */
- + clear_audio(task_pt_regs(tsk));
- + }
- + tsk->thread.audio.auregs[off] = val;
- +#endif
- + return 0;
- + } else
- + return -EIO;
- +}
- +
- +/* ptrace_getregs()
- + *
- + * Get all user integer registers.
- + */
- +static int ptrace_getregs(struct task_struct *tsk, void __user * uregs)
- +{
- + struct pt_regs *regs = task_pt_regs(tsk);
- +
- + return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
- +}
- +
- +/* ptrace_setregs()
- + *
- + * Set all user integer registers.
- + */
- +static int ptrace_setregs(struct task_struct *tsk, void __user * uregs)
- +{
- + struct pt_regs newregs;
- + int ret;
- +
- + ret = -EFAULT;
- + if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) {
- + struct pt_regs *regs = task_pt_regs(tsk);
- +
- + ret = -EINVAL;
- + if (valid_user_regs(&newregs)) {
- + *regs = newregs;
- + ret = 0;
- + }
- + }
- +
- + return ret;
- +}
- +
- +/* ptrace_getfpregs()
- + *
- + * Get the child FPU state.
- + */
- +static int ptrace_getfpregs(struct task_struct *tsk, void __user * ufpregs)
- +{
- +#ifdef CONFIG_FPU
- + if (used_math()) {
- +# ifdef CONFIG_UNLAZY_FPU
- + unlazy_fpu(tsk);
- +# else
- + preempt_disable();
- + if (last_task_used_math == tsk)
- + save_fpu(tsk);
- + preempt_enable();
- +# endif
- + return copy_to_user(ufpregs, &tsk->thread.fpu,
- + sizeof(struct fpu_struct)) ? -EFAULT : 0;
- + } else {
- + /* First time FPU user. */
- + memset(ufpregs, -1, sizeof(struct fpu_struct));
- + return 0;
- + }
- +
- +#else
- + return -EFAULT;
- +#endif
- +}
- +
- +/*
- + * Set the child FPU state.
- + */
- +static int ptrace_setfpregs(struct task_struct *tsk, void __user * ufpregs)
- +{
- +#ifdef CONFIG_FPU
- + int ret;
- +
- +# ifndef CONFIG_UNLAZY_FPU
- + if (last_task_used_math == tsk)
- +# endif
- + clear_fpu(task_pt_regs(tsk));
- +
- + ret =
- + copy_from_user(&tsk->thread.fpu, ufpregs,
- + sizeof(struct fpu_struct)) ? -EFAULT : 0;
- +
- + if (!ret && !used_math()) {
- + /* First time Audio user. */
- + set_used_math();
- + }
- +
- + return ret;
- +#else
- + return -EFAULT;
- +#endif
- +}
- +
- +/* ptrace_getauregs()
- + *
- + * Get the child Audio state.
- + */
- +static int ptrace_getauregs(struct task_struct *tsk, void __user * uauregs)
- +{
- +#ifdef CONFIG_AUDIO
- + if (test_tsk_thread_flag(tsk, TIF_USEDAUDIO)) {
- +#ifdef CONFIG_UNLAZY_AUDIO
- + unlazy_audio(tsk);
- +#else
- + preempt_disable();
- + if (last_task_used_audio == tsk)
- + save_audio(tsk);
- + preempt_enable();
- +#endif
- + return copy_to_user(uauregs, &tsk->thread.audio,
- + sizeof(struct audio_struct)) ? -EFAULT : 0;
- + } else {
- + /* First time Audio user. */
- + memset(uauregs, 0, sizeof(struct audio_struct));
- + return 0;
- + }
- +
- +#else
- + return -EFAULT;
- +#endif
- +}
- +
- +/*
- + * Set the child Audio state.
- + */
- +static int ptrace_setauregs(struct task_struct *tsk, void __user * uauregs)
- +{
- +#ifdef CONFIG_AUDIO
- + int ret;
- +
- +#ifdef CONFIG_UNLAZY_AUDIO
- + clear_audio(task_pt_regs(tsk));
- +#else
- + if (last_task_used_audio == tsk)
- + clear_audio(task_pt_regs(tsk));
- +#endif
- + ret =
- + copy_from_user(&tsk->thread.audio, uauregs,
- + sizeof(struct audio_struct)) ? -EFAULT : 0;
- +
- + if (!ret && !test_tsk_thread_flag(tsk, TIF_USEDAUDIO)) {
- + /* First time Audio user. */
- + set_tsk_thread_flag(tsk, TIF_USEDAUDIO);
- + }
- +
- + return ret;
- +#else
- + return -EFAULT;
- +#endif
- +}
- +
- +/* do_ptrace()
- + *
- + * Provide ptrace defined service.
- + */
- +long arch_ptrace(struct task_struct *child, long request, unsigned long addr,
- + unsigned long data)
- +{
- + int ret;
- +
- + switch (request) {
- + case PTRACE_PEEKUSR:
- + ret =
- + ptrace_read_user(child, addr, (unsigned long __user *)data);
- + break;
- +
- + case PTRACE_POKEUSR:
- + ret = ptrace_write_user(child, addr, data);
- + break;
- +
- + case PTRACE_GETREGS:
- + ret = ptrace_getregs(child, (void __user *)data);
- + break;
- +
- + case PTRACE_SETREGS:
- + ret = ptrace_setregs(child, (void __user *)data);
- + break;
- +
- + case PTRACE_GETFPREGS:
- + ret = ptrace_getfpregs(child, (void __user *)data);
- + break;
- +
- + case PTRACE_SETAUREGS:
- + ret = ptrace_setauregs(child, (void __user *)data);
- + break;
- +
- + case PTRACE_GETAUREGS:
- + ret = ptrace_getauregs(child, (void __user *)data);
- + break;
- +
- + case PTRACE_SETFPREGS:
- + ret = ptrace_setfpregs(child, (void __user *)data);
- + break;
- +/*
- + case PTRACE_GET_THREAD_AREA:
- + ret = put_user(task_thread_info(child)->tp_value,
- + (unsigned long __user *) data);
- + break;
- +*/
- +
- + default:
- + ret = ptrace_request(child, request, addr, data);
- + break;
- + }
- +
- + return ret;
- +}
- +
- +void user_enable_single_step(struct task_struct *child)
- +{
- + struct pt_regs *regs;
- + regs = task_pt_regs(child);
- +#ifdef CONFIG_HSS
- + regs->NDS32_ipsw |= PSW_mskHSS;
- +#else
- + ptrace_set_swbk(child);
- +#endif
- + set_tsk_thread_flag(child, TIF_SINGLESTEP);
- +}
- +
- +void user_disable_single_step(struct task_struct *child)
- +{
- + struct pt_regs *regs;
- + regs = task_pt_regs(child);
- +#ifdef CONFIG_HSS
- + regs->NDS32_ipsw &= ~PSW_mskHSS;
- +#else
- + ptrace_cancel_swbk(child);
- +#endif
- + clear_tsk_thread_flag(child, TIF_SINGLESTEP);
- +}
- +
- +/* sys_trace()
- + *
- + * syscall trace handler.
- + */
- +static inline void do_syscall_trace(void)
- +{
- + if (!test_thread_flag(TIF_SYSCALL_TRACE))
- + return;
- + if (!(current->ptrace & PT_PTRACED))
- + return;
- +
- + /* the 0x80 provides a way for the tracing parent to distinguish
- + between a syscall stop and SIGTRAP delivery */
- + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
- + ? 0x80 : 0));
- + /*
- + * this isn't the same as continuing with a signal, but it will do
- + * for normal use. strace only continues with a signal if the
- + * stopping signal is not SIGTRAP. -brl
- + */
- + if (current->exit_code) {
- + send_sig(current->exit_code, current, 1);
- + current->exit_code = 0;
- + }
- +}
- +
- +asmlinkage int syscall_trace_enter(int syscall, struct pt_regs *regs)
- +{
- + int orig_r0;
- +
- + orig_r0 = regs->NDS32_ORIG_r0;
- + regs->NDS32_ORIG_r0 = syscall;
- + do_syscall_trace();
- + syscall = regs->NDS32_ORIG_r0;
- + regs->NDS32_ORIG_r0 = orig_r0;
- + return syscall & 0xfff;
- +}
- +
- +asmlinkage void syscall_trace_leave(struct pt_regs *regs)
- +{
- + do_syscall_trace();
- +
- + /* synthsize a single-step */
- +#if !defined(CONFIG_HSS)
- + /* for SWBK, break should be remove */
- + ptrace_cancel_swbk(current);
- +#endif
- + if (test_thread_flag(TIF_SINGLESTEP)) {
- + printk(KERN_INFO "synthsize trap (tf=0x%0x\n",
- + (unsigned int)current_thread_info()->flags);
- + send_sigtrap(current, regs, 0, TRAP_BRKPT);
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/ptrace.h linux-3.4.110/arch/nds32/kernel/ptrace.h
- --- linux-3.4.110.orig/arch/nds32/kernel/ptrace.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/ptrace.h 2016-04-07 10:20:50.946081179 +0200
- @@ -0,0 +1,48 @@
- +/*
- + * linux/arch/nds32/kernel/ptrace.h
- + */
- +/* Copyright (C) 2000-2003 Russell King
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +/* ============================================================================
- + * Copyright (C) 2007 Andes Technology Corporation
- + * This file is part of Linux and should be licensed under the GPL.
- + * See the file COPYING for conditions for redistribution.
- + *
- + * Abstract:
- + *
- + * This program is for Andes NDS32 architecture.
- + *
- + * Revision History:
- + *
- + * Jul.31.2007 Initial ported by Tom, Shawn, and Steven,
- + * revised by Harry.
- + * Current implmentation is based on Andes Instruction
- + * Set Architecture Specification (AS-0001-0001)
- + * version:3.7 date:7-20-2007.
- + * It is original taken from ARM, then fit to NDS32.
- + *
- + * Note:
- + *
- + * Current layout: 0-31 GR, 32-34 SPR, 35-... SR, index start from zero.
- + *
- + * +----------+-----+--------------+
- + * | GR | SPR | SR |
- + * +-------------------------------+
- + * 0 32 35 ...
- + *
- + * ============================================================================
- + */
- +#ifndef __KERNEL_PTRACE_H__
- +#define __KERNEL_PTRACE_H__
- +
- +extern void ptrace_cancel_swbk(struct task_struct *);
- +extern void ptrace_set_swbk(struct task_struct *);
- +extern void ptrace_break(struct task_struct *, struct pt_regs *);
- +extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
- + int error_code, int si_code);
- +
- +#endif // __KERNEL_PTRACE_H__
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/relocate_kernel.S linux-3.4.110/arch/nds32/kernel/relocate_kernel.S
- --- linux-3.4.110.orig/arch/nds32/kernel/relocate_kernel.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/relocate_kernel.S 2016-04-07 10:20:50.946081179 +0200
- @@ -0,0 +1,89 @@
- +/*
- + * relocate_kernel.S - put the kernel image in place to boot
- + */
- +
- +#include <asm/kexec.h>
- +
- + .globl relocate_new_kernel
- +relocate_new_kernel:
- + la $r0, kexec_indirection_page
- + slli $r0, $r0, 2
- + srli $r0, $r0, 2
- + lwi $r0, [$r0]
- + la $r1, kexec_start_address
- + slli $r1, $r1, 2
- + srli $r1, $r1, 2
- + lwi $r1, [$r1]
- +
- +0: /* top, read another word for the indirection page */
- + lwi.bi $r3, [$r0], #4
- +
- + /* Is it a destination page. Put destination address to r4 */
- + andi $p0, $r3, #1
- + beqz $p0, 1f
- + li $p0, ~#1
- + and $r4, $r3, $p0
- + b 0b
- +1:
- + /* Is it an indirection page */
- + andi $p0, $r3, #2
- + beqz $p0, 1f
- + li $p0, ~#2
- + and $r0, $r3, $p0
- + b 0b
- +1:
- + /* are we done ? */
- + andi $p0, $r3, #4
- + beqz $p0, 1f
- + b 2f
- +1:
- + /* is it source ? */
- + andi $p0, $r3, #8
- + beqz $p0, 0b
- + li $p0, ~#8
- + and $r3, $r3, $p0
- + li $r6, #(1024/16) /* 16 words per loop */
- +9:
- + lmw.bim $r7, [$r3], $r22
- + smw.bim $r7, [$r4], $r22
- + addi $r6, $r6, -1
- + bnez $r6, 9b
- + b 0b
- +2:
- + /* Jump to relocated kernel */
- + move $lp, $r1
- + li $r0, 0
- + la $r1, kexec_mach_type
- + slli $r1, $r1, 2
- + srli $r1, $r1, 2
- + lwi $r1, [$r1]
- + la $r2, kexec_boot_atags
- + slli $r2, $r2, 2
- + srli $r2, $r2, 2
- + lwi $r2, [$r2]
- + ret
- +
- + .globl kexec_start_address
- +kexec_start_address:
- + .long 0x0
- +
- + .globl kexec_indirection_page
- +kexec_indirection_page:
- + .long 0x0
- +
- + .globl kexec_mach_type
- +kexec_mach_type:
- + .long 0x0
- +
- + /* phy addr of the atags for the new kernel */
- + .globl kexec_boot_atags
- +kexec_boot_atags:
- + .long 0x0
- +
- +relocate_new_kernel_end:
- +
- + .globl relocate_new_kernel_size
- +relocate_new_kernel_size:
- + .long relocate_new_kernel_end - relocate_new_kernel
- +
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/setup.c linux-3.4.110/arch/nds32/kernel/setup.c
- --- linux-3.4.110.orig/arch/nds32/kernel/setup.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/setup.c 2016-04-07 10:20:50.946081179 +0200
- @@ -0,0 +1,1049 @@
- +/*
- + * linux/arch/nds32/kernel/setup.c
- + *
- + * Copyright (C) 1995-2001 Russell King
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +/* ============================================================================
- + * Copyright (C) 2007 Andes Technology Corporation
- + * This file is part of Linux and should be licensed under the GPL.
- + * See the file COPYING for conditions for redistribution.
- + *
- + * Abstract:
- + *
- + * This program is for Andes NDS32 architecture.
- + *
- + * Revision History:
- + *
- + * Jul.05.2007 Initial ported by Tom, revised and patched for KGDB
- + * by Harry.
- + * Aug.26.2008 Some reworks on CPU info output for SMP.
- + *
- + * Note:
- + *
- + * ============================================================================
- + */
- +#include <linux/module.h>
- +#include <linux/ioport.h>
- +#include <linux/delay.h>
- +#include <linux/utsname.h>
- +#include <linux/initrd.h>
- +#include <linux/console.h>
- +#include <linux/bootmem.h>
- +#include <linux/seq_file.h>
- +#include <linux/screen_info.h>
- +#include <linux/root_dev.h>
- +#include <linux/cpu.h>
- +#include <linux/fs.h>
- +#include <linux/memblock.h>
- +#include <asm/cpu.h>
- +#include <asm/setup.h>
- +#include <asm/mach-types.h>
- +#include <asm/cacheflush.h>
- +#include <asm/mach/arch.h>
- +#include <asm/mach/time.h>
- +#include <asm/cpuver.h>
- +#include <asm/procinfo.h>
- +#include <asm/traps.h>
- +#include <asm/fpu.h>
- +#include <asm/cache_info.h>
- +#include <nds32_intrinsic.h>
- +
- +#ifndef MEM_SIZE
- +#define MEM_SIZE CONFIG_SDRAM_SIZE
- +#endif
- +
- +#ifndef RAMDISK_SIZE
- +#define RAMDISK_SIZE CONFIG_BLK_DEV_RAM_SIZE
- +#endif
- +
- +extern void (*init_arch_irq) (void);
- +
- +extern void paging_init(struct machine_desc *desc);
- +extern void reboot_setup(char *str);
- +extern int root_mountflags;
- +extern unsigned long _stext, _text, _etext, _sdata, _edata, _end;
- +extern unsigned int ag101_cpufreq_get(unsigned int dummy);
- +
- +unsigned long cpu_id, cpu_rev, cpu_cfgid;
- +char *endianness = NULL;
- +
- +unsigned int __machine_arch_type;
- +EXPORT_SYMBOL(__machine_arch_type);
- +
- +unsigned int elf_hwcap;
- +EXPORT_SYMBOL(elf_hwcap);
- +
- +unsigned char aux_device_present;
- +
- +char elf_platform[ELF_PLATFORM_SIZE];
- +EXPORT_SYMBOL(elf_platform);
- +
- +unsigned long phys_initrd_start __initdata = 0;
- +unsigned long phys_initrd_size __initdata = 0;
- +
- +static struct meminfo meminfo __initdata = { 0, };
- +
- +static const char *machine_name;
- +static struct proc_info_item proc_info;
- +static char command_line[COMMAND_LINE_SIZE];
- +
- +struct machine_desc *machine_desc __initdata;
- +
- +static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
- +
- +DEFINE_PER_CPU(struct cpuinfo_nds32, cpu_data);
- +
- +/*
- + * Standard memory resources
- + */
- +static struct resource mem_res[] = {
- + {
- + .name = "Video RAM",
- + .start = 0,
- + .end = 0,
- + .flags = IORESOURCE_MEM},
- + {
- + .name = "Kernel text",
- + .start = 0,
- + .end = 0,
- + .flags = IORESOURCE_MEM},
- + {
- + .name = "Kernel data",
- + .start = 0,
- + .end = 0,
- + .flags = IORESOURCE_MEM}
- +};
- +
- +#define video_ram mem_res[0]
- +#define kernel_code mem_res[1]
- +#define kernel_data mem_res[2]
- +
- +static struct resource io_res[] = {
- + {
- + .name = "reserved",
- + .start = 0x3bc,
- + .end = 0x3be,
- + .flags = IORESOURCE_IO | IORESOURCE_BUSY},
- + {
- + .name = "reserved",
- + .start = 0x378,
- + .end = 0x37f,
- + .flags = IORESOURCE_IO | IORESOURCE_BUSY},
- + {
- + .name = "reserved",
- + .start = 0x278,
- + .end = 0x27f,
- + .flags = IORESOURCE_IO | IORESOURCE_BUSY}
- +};
- +
- +#define lp0 io_res[0]
- +#define lp1 io_res[1]
- +#define lp2 io_res[2]
- +
- +/*
- + * The following string table, must sync with HWCAP_xx bitmask,
- + * which is defined in <asm/procinfo.h>
- + */
- +static const char *hwcap_str[] = {
- + "mfusr_pc",
- + "perf1",
- + "perf2",
- + "fpu",
- + "audio",
- + "16b",
- + "string",
- + "reduced_regs",
- + "video",
- + "encrypt",
- + "edm",
- + "lmdma",
- + "pfm",
- + "hsmp",
- + "trace",
- + "div",
- + "mac",
- + "l2c",
- + "dx_regs",
- + "v2",
- + NULL,
- +};
- +
- +static void __init squash_mem_tags(struct tag *tag)
- +{
- + for (; tag->hdr.size; tag = tag_next(tag))
- + if (tag->hdr.tag == ATAG_MEM)
- + tag->hdr.tag = ATAG_NONE;
- +}
- +
- +struct cache_info L1_cache_info[2];
- +
- +static void __init dump_cpu_info(int cpu)
- +{
- + int i = 0, aliasing_num;
- +#ifdef CONFIG_CACHE_L2
- + unsigned long l2set, l2way, l2clsz;
- +#endif
- + printk("CPU%d Features: ", cpu);
- +
- + for (i = 0; hwcap_str[i]; i++) {
- + if (elf_hwcap & (1 << i))
- + printk("%s ", hwcap_str[i]);
- + }
- +
- + printk("\n");
- +
- + L1_cache_info[ICACHE].cache_type = ICACHE;
- + L1_cache_info[ICACHE].ways = CACHE_WAY(ICACHE);
- + L1_cache_info[ICACHE].way_bits = ilog2(CACHE_WAY(ICACHE));
- + L1_cache_info[ICACHE].line_size = CACHE_LINE_SIZE(ICACHE);
- + L1_cache_info[ICACHE].line_bits = ilog2(CACHE_LINE_SIZE(ICACHE));
- + L1_cache_info[ICACHE].sets = CACHE_SET(ICACHE);
- + L1_cache_info[ICACHE].set_bits = ilog2(CACHE_SET(ICACHE));
- + L1_cache_info[ICACHE].size =
- + CACHE_SET(ICACHE) * CACHE_WAY(ICACHE) * CACHE_LINE_SIZE(ICACHE) /
- + 1024;
- + printk("L1I:%dKB/%dS/%dW/%dB\n", L1_cache_info[ICACHE].size,
- + L1_cache_info[ICACHE].sets, L1_cache_info[ICACHE].ways,
- + L1_cache_info[ICACHE].line_size);
- + aliasing_num =
- + L1_cache_info[ICACHE].size * 1024 / PAGE_SIZE /
- + L1_cache_info[ICACHE].ways;
- + if (aliasing_num & 1 && aliasing_num != 1)
- + printk
- + ("%s: not alising:%d, it should be multiple of 2 if it ia aliasing cache.\n",
- + __func__, aliasing_num);
- + L1_cache_info[ICACHE].aliasing_num = aliasing_num;
- + L1_cache_info[ICACHE].aliasing_mask = (aliasing_num - 1) << PAGE_SHIFT;
- + L1_cache_info[ICACHE].not_aliasing_mask =
- + ~L1_cache_info[ICACHE].aliasing_mask;
- + L1_cache_info[DCACHE].cache_type = DCACHE;
- + L1_cache_info[DCACHE].ways = CACHE_WAY(DCACHE);
- + L1_cache_info[DCACHE].way_bits = ilog2(CACHE_WAY(DCACHE));
- + L1_cache_info[DCACHE].line_size = CACHE_LINE_SIZE(DCACHE);
- + L1_cache_info[DCACHE].line_bits = ilog2(CACHE_LINE_SIZE(DCACHE));
- + L1_cache_info[DCACHE].sets = CACHE_SET(DCACHE);
- + L1_cache_info[DCACHE].set_bits = ilog2(CACHE_SET(DCACHE));
- + L1_cache_info[DCACHE].size =
- + CACHE_SET(DCACHE) * CACHE_WAY(DCACHE) * CACHE_LINE_SIZE(DCACHE) /
- + 1024;
- + printk("L1D:%dKB/%dS/%dW/%dB\n", L1_cache_info[DCACHE].size,
- + L1_cache_info[DCACHE].sets, L1_cache_info[DCACHE].ways,
- + L1_cache_info[DCACHE].line_size);
- + aliasing_num =
- + L1_cache_info[DCACHE].size * 1024 / PAGE_SIZE /
- + L1_cache_info[DCACHE].ways;
- +#ifdef CONFIG_HIGHMEM
- + if (aliasing_num > 1 && CONFIG_HIGHMEM)
- + WARN(1,
- + "%s: HIGHMEM is not supported for alising VIPT cache. aliasing_num:%d\n",
- + __func__, aliasing_num);
- +#else
- + if (aliasing_num & 1 && aliasing_num != 1)
- + printk
- + ("%s: not alising:%d, it should be multiple of 2 if it ia aliasing cache.\n",
- + __func__, aliasing_num);
- +#endif
- + L1_cache_info[DCACHE].aliasing_num = aliasing_num;
- + L1_cache_info[DCACHE].aliasing_mask = (aliasing_num - 1) << PAGE_SHIFT;
- + L1_cache_info[DCACHE].not_aliasing_mask =
- + ~L1_cache_info[DCACHE].aliasing_mask;
- +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
- + printk("L1 D-Cache is WRITE-THROUGH\n");
- +#else
- + printk("L1 D-Cache is WRITE-BACK\n");
- +#endif
- +
- +
- +#ifdef CONFIG_CACHE_L2
- + /* Here translation is on but I/O address is not mapped yet. */
- + SET_PSW(GET_PSW() & ~PSW_mskDT);
- + DSB();
- + l2set =
- + 64 << ((inl(L2CC_PA_BASE + L2_CA_CONF_OFF) & L2_CA_CONF_mskL2SET) >>
- + L2_CA_CONF_offL2SET);
- + l2way =
- + 1 +
- + ((inl(L2CC_PA_BASE + L2_CA_CONF_OFF) & L2_CA_CONF_mskL2WAY) >>
- + L2_CA_CONF_offL2WAY);
- + l2clsz =
- + 4 << ((inl(L2CC_PA_BASE + L2_CA_CONF_OFF) & L2_CA_CONF_mskL2CLSZ) >>
- + L2_CA_CONF_offL2CLSZ);
- + SET_PSW(GET_PSW() | PSW_mskDT);
- + DSB();
- +
- + printk("L2:%luKB/%luS/%luW/%luB\n",
- + l2set * l2way * l2clsz / 1024, l2set, l2way, l2clsz);
- +#endif
- +#ifdef CONFIG_FPU
- + /* Disable fpu and enable when it is used. */
- + disable_fpu();
- + printk("FPU is able to use.\n");
- +#endif
- +}
- +
- +static void __init setup_processor(void)
- +{
- + unsigned long tmp = 0;
- + struct proc_info_list *list;
- + extern struct proc_info_list __proc_info_begin, __proc_info_end;
- +
- + register unsigned coreid = GET_CPU_VER();
- + for (list = &__proc_info_begin; list < &__proc_info_end; list++)
- +// if (list->cpu_val == (GET_CPU_VER() & CPU_VER_mskCPUID))
- + if (list->cpu_val == (coreid & list->cpu_mask))
- + break;
- + /*
- + * If the architecture type is not recognised, then we
- + * can co nothing...
- + */
- + if (list >= &__proc_info_end) {
- + printk
- + ("Processor configuration botched (CPU_VER 0x%lx), unable to continue.\n",
- + GET_CPU_VER());
- + while (1) ;
- + }
- +
- + proc_info = *list->info;
- +
- + cpu_dcache_inval_all(); // XXX head.S turn $$ on, need change.
- + cpu_icache_inval_all();
- + DSB();
- + ISB();
- +
- + cpu_id = GET_CPU_ID();
- + cpu_rev = GET_CPU_REV();
- + cpu_cfgid = GET_CPU_CFGID();
- +
- + printk("CPU: %s, %s %s, CPU_VER 0x%08lx(id %lu, rev %lu, cfg %lu)\n",
- + list->arch_name,
- + proc_info.manufacturer, proc_info.cpu_name,
- + GET_CPU_VER(), cpu_id, cpu_rev, cpu_cfgid);
- +
- + elf_hwcap |= HWCAP_MFUSR_PC;
- +
- + if (((GET_MSC_CFG() & MSC_CFG_mskBASEV) >> MSC_CFG_offBASEV) == 0) {
- + if (CPU_IS_N1213_43U1HA0() || CPU_IS_N1213_43U1HB0())
- + elf_hwcap &= ~HWCAP_MFUSR_PC;
- +
- + if (GET_MSC_CFG() & MSC_CFG_mskDIV)
- + elf_hwcap |= HWCAP_DIV;
- +
- + if ((GET_MSC_CFG() & MSC_CFG_mskMAC)
- + || (cpu_id == 12 && cpu_rev < 4))
- + elf_hwcap |= HWCAP_MAC;
- + } else {
- + elf_hwcap |= HWCAP_V2;
- + elf_hwcap |= HWCAP_DIV;
- + elf_hwcap |= HWCAP_MAC;
- + }
- +
- + if (cpu_cfgid & 0x0001)
- + elf_hwcap |= HWCAP_EXT;
- +
- + if (cpu_cfgid & 0x0002)
- + elf_hwcap |= HWCAP_BASE16;
- +
- + if (cpu_cfgid & 0x0004)
- + elf_hwcap |= HWCAP_EXT2;
- +
- + if (cpu_cfgid & 0x0008)
- + elf_hwcap |= HWCAP_FPU;
- +
- + if (cpu_cfgid & 0x0010)
- + elf_hwcap |= HWCAP_STRING;
- +
- + if (GET_MMU_CFG() & MMU_CFG_mskDE)
- + endianness = "MSB";
- + else
- + endianness = "LSB";
- +
- + if (GET_MSC_CFG() & MSC_CFG_mskEDM)
- + elf_hwcap |= HWCAP_EDM;
- +
- + if (GET_MSC_CFG() & MSC_CFG_mskLMDMA)
- + elf_hwcap |= HWCAP_LMDMA;
- +
- + if (GET_MSC_CFG() & MSC_CFG_mskPFM)
- + elf_hwcap |= HWCAP_PFM;
- +
- + if (GET_MSC_CFG() & MSC_CFG_mskHSMP)
- + elf_hwcap |= HWCAP_HSMP;
- +
- + if (GET_MSC_CFG() & MSC_CFG_mskTRACE)
- + elf_hwcap |= HWCAP_TRACE;
- +
- + if (GET_MSC_CFG() & MSC_CFG_mskAUDIO)
- + elf_hwcap |= HWCAP_AUDIO;
- +
- + if (GET_MSC_CFG() & MSC_CFG_mskL2C)
- + elf_hwcap |= HWCAP_L2C;
- +
- +#ifdef CONFIG_ANDES_PAGE_SIZE_4KB
- + if (CPU_IS_N1213_43U1HA0()) {
- + /*
- + * Downsize dcache to bypass N1213-43u1h inconsistent
- + * use of PA and VA in fill-buffer logic issue.
- + */
- +
- + if ((CACHE_SET(DCACHE) * CACHE_LINE_SIZE(DCACHE)) > 4096)
- + tmp |= 0x02 << SDZ_CTL_offDCDZ;
- +
- + if ((CACHE_SET(ICACHE) * CACHE_LINE_SIZE(ICACHE)) > 4096)
- + tmp |= 0x02 << SDZ_CTL_offICDZ;
- +
- + SET_SDZ_CTL(tmp);
- + ISB();
- + printk("CPU%i enabled dcache downsizing to half set/4-way.\n",
- + smp_processor_id());
- + }
- +#endif /* CONFIG_ANDES_PAGE_SIZE_4KB */
- +
- +#ifdef CONFIG_CACHE_L2
- +#ifdef CONFIG_PLAT_AG102
- + SET_HSMP_SADDR((CPU_MEM_PA_BASE & HSMP_SADDR_mskSADDR) |
- + (0xC00 << HSMP_SADDR_offRANGE) | HSMP_SADDR_mskEN);
- +#endif
- +
- + /* Here translation is on but I/O address is not mapped yet. */
- + SET_PSW(GET_PSW() & ~PSW_mskDT);
- + DSB();
- +
- + /* This is the time when we enable L2$. */
- + /* All masters can't write another master register */
- + tmp = inl(L2CC_PA_BASE + L2CC_PROT_OFF);
- + tmp &= ~L2CC_PROT_mskMRWEN;
- + outl(tmp, L2CC_PA_BASE + L2CC_PROT_OFF);
- +
- + /* All masters share the whole cache memory space */
- + tmp = inl(L2CC_PA_BASE + L2CC_SETUP_OFF);
- + tmp &= ~L2CC_SETUP_mskPART;
- + outl(tmp, L2CC_PA_BASE + L2CC_SETUP_OFF);
- +
- + /* each master access self master, does not add master base */
- + tmp = inl(L2CC_PA_BASE + L2CC_CTRL_OFF);
- + tmp |= L2CC_CTRL_mskEN;
- + outl(tmp, L2CC_PA_BASE + L2CC_CTRL_OFF);
- +
- + SET_PSW(GET_PSW() | PSW_mskDT);
- + ISB();
- +#endif
- + tmp = GET_CACHE_CTL();
- +#ifndef CONFIG_CPU_DCACHE_DISABLE
- + tmp |= CACHE_CTL_mskDC_EN;
- +#endif
- +
- +#ifndef CONFIG_CPU_ICACHE_DISABLE
- + tmp |= CACHE_CTL_mskIC_EN;
- +#endif
- + SET_CACHE_CTL(tmp);
- + DSB();
- + ISB();
- +
- + sprintf(elf_platform, "%s %s", list->elf_name, endianness);
- +
- + dump_cpu_info(smp_processor_id());
- +}
- +
- +static struct machine_desc *__init setup_machine(unsigned int nr)
- +{
- + struct machine_desc *list;
- +
- + extern struct machine_desc __arch_info_begin, __arch_info_end;
- + /*
- + * locate machine in the list of supported machines.
- + */
- + for (list = &__arch_info_begin; list < &__arch_info_end; list++)
- + if (list->nr == nr)
- + break;
- + /*
- + * If the architecture type is not recognised, then we
- + * can co nothing...
- + */
- + if (list >= &__arch_info_end) {
- + printk("Architecture configuration botched (nr 0x%x), unable "
- + "to continue.\n", nr);
- + while (1) ;
- + }
- +
- + printk(KERN_INFO "Machine: %s\n", list->name);
- +
- + return list;
- +}
- +
- +static void __init early_initrd(char **p)
- +{
- + unsigned long start, size;
- +
- + start = memparse(*p, p);
- + if (**p == ',') {
- + size = memparse((*p) + 1, p);
- +
- + phys_initrd_start = start; //pa
- + phys_initrd_size = size;
- + }
- + printk(KERN_INFO
- + "phys_initrd_start at 0x%08lx, phys_initrd_size:0x%08lx\n",
- + phys_initrd_start, phys_initrd_size);
- + //memblock_reserve(phys_initrd_start, phys_initrd_size);
- +}
- +
- +__early_param("initrd=", early_initrd);
- +
- +/*
- + * Pick out the memory size. We look for mem=size@start,
- + * where start and size are "size[KkMm]"
- + */
- +static void __init early_mem(char **p)
- +{
- + static int usermem __initdata = 0;
- + unsigned long size, start;
- +
- + /*
- + * If the user specifies memory size, we
- + * blow away any automatically generated
- + * size.
- + */
- + if (usermem == 0) {
- + usermem = 1;
- + meminfo.nr_banks = 0;
- + }
- +
- + start = PHYS_OFFSET; //Tom 0x0
- + size = memparse(*p, p);
- + if (**p == '@')
- + start = memparse(*p + 1, p);
- +
- + meminfo.bank[meminfo.nr_banks].start = start;
- + meminfo.bank[meminfo.nr_banks].size = size;
- + meminfo.bank[meminfo.nr_banks].node = PHYS_TO_NID(start);
- + memblock_add_node(meminfo.bank[meminfo.nr_banks].start,
- + meminfo.bank[meminfo.nr_banks].size, 0);
- + meminfo.nr_banks += 1;
- +
- +}
- +
- +__early_param("mem=", early_mem);
- +
- +/*
- + * Initial parsing of the command line.
- + */
- +void __init parse_cmdline(char **cmdline_p, char *from)
- +{
- + char c = ' ', *to = command_line;
- + int len = 0;
- +
- + for (;;) {
- + if (c == ' ') {
- + extern struct early_params __early_begin, __early_end;
- + struct early_params *p;
- +
- + for (p = &__early_begin; p < &__early_end; p++) {
- + int len = strlen(p->arg);
- +
- + if (memcmp(from, p->arg, len) == 0) {
- + if (to != command_line)
- + to -= 1;
- + from += len;
- + p->fn(&from);
- +
- + while (*from != ' ' && *from != '\0')
- + from++;
- + break;
- + }
- + }
- + }
- + c = *from++;
- + if (!c)
- + break;
- + if (COMMAND_LINE_SIZE <= ++len)
- + break;
- + *to++ = c;
- + }
- + *to = '\0';
- + *cmdline_p = command_line;
- +}
- +
- +static void __init
- +setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
- +{
- +#ifdef CONFIG_BLK_DEV_RAM
- + extern int rd_size, rd_image_start, rd_prompt, rd_doload;
- +
- + rd_image_start = image_start;
- + rd_prompt = prompt;
- + rd_doload = doload;
- +
- + if (rd_sz)
- + rd_size = rd_sz;
- +#endif
- +}
- +
- +static void __init
- +request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
- +{
- + struct resource *res;
- + int i;
- +
- + kernel_code.start = virt_to_phys(&_text);
- + kernel_code.end = virt_to_phys(&_etext - 1);
- + kernel_data.start = virt_to_phys(&_sdata);
- + kernel_data.end = virt_to_phys(&_end - 1);
- +
- + for (i = 0; i < mi->nr_banks; i++) {
- + unsigned long virt_start, virt_end;
- +
- + if (mi->bank[i].size == 0)
- + continue;
- +
- + virt_start = __phys_to_virt(mi->bank[i].start);
- + virt_end = virt_start + mi->bank[i].size - 1;
- +
- + res = alloc_bootmem_low(sizeof(*res));
- + res->name = "System RAM";
- + res->start = __virt_to_phys(virt_start);
- + res->end = __virt_to_phys(virt_end);
- + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
- +
- + request_resource(&iomem_resource, res);
- +
- + if (kernel_code.start >= res->start &&
- + kernel_code.end <= res->end)
- + request_resource(res, &kernel_code);
- + if (kernel_data.start >= res->start &&
- + kernel_data.end <= res->end)
- + request_resource(res, &kernel_data);
- + }
- +
- + if (mdesc->video_start) {
- + video_ram.start = mdesc->video_start;
- + video_ram.end = mdesc->video_end;
- + request_resource(&iomem_resource, &video_ram);
- + }
- +
- + /*
- + * Some machines don't have the possibility of ever
- + * possessing lp0, lp1 or lp2
- + */
- + if (mdesc->reserve_lp0)
- + request_resource(&ioport_resource, &lp0);
- + if (mdesc->reserve_lp1)
- + request_resource(&ioport_resource, &lp1);
- + if (mdesc->reserve_lp2)
- + request_resource(&ioport_resource, &lp2);
- +}
- +
- +/*
- + * Tag parsing.
- + *
- + * This is the new way of passing data to the kernel at boot time. Rather
- + * than passing a fixed inflexible structure to the kernel, we pass a list
- + * of variable-sized tags to the kernel. The first tag must be a ATAG_CORE
- + * tag for the list to be recognised (to distinguish the tagged list from
- + * a param_struct). The list is terminated with a zero-length tag (this tag
- + * is not parsed in any way).
- + */
- +//flag bit 0 = read-only
- +static int __init parse_tag_core(const struct tag *tag)
- +{
- + if (tag->hdr.size > 2) {
- + if ((tag->u.core.flags & 1) == 0)
- + root_mountflags &= ~MS_RDONLY;
- + ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
- + }
- + return 0;
- +}
- +
- +__tagtable(ATAG_CORE, parse_tag_core);
- +
- +static int __init parse_tag_mem32(const struct tag *tag)
- +{
- + if (meminfo.nr_banks >= NR_BANKS) {
- + printk(KERN_WARNING
- + "Ignoring memory bank 0x%08x size %dKB\n",
- + tag->u.mem.start, tag->u.mem.size / 1024);
- + return -EINVAL;
- + }
- + meminfo.bank[meminfo.nr_banks].start = tag->u.mem.start;
- + meminfo.bank[meminfo.nr_banks].size = tag->u.mem.size;
- + memblock_add_node(meminfo.bank[meminfo.nr_banks].start,
- + meminfo.bank[meminfo.nr_banks].size, 0);
- + meminfo.bank[meminfo.nr_banks].node = PHYS_TO_NID(tag->u.mem.start);
- + meminfo.nr_banks += 1;
- +
- + return 0;
- +}
- +
- +__tagtable(ATAG_MEM, parse_tag_mem32);
- +
- +#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
- +struct screen_info screen_info = {
- + .orig_video_lines = 30,
- + .orig_video_cols = 80,
- + .orig_video_mode = 0,
- + .orig_video_ega_bx = 0,
- + .orig_video_isVGA = 1,
- + .orig_video_points = 8
- +};
- +
- +static int __init parse_tag_videotext(const struct tag *tag)
- +{
- + screen_info.orig_x = tag->u.videotext.x;
- + screen_info.orig_y = tag->u.videotext.y;
- + screen_info.orig_video_page = tag->u.videotext.video_page;
- + screen_info.orig_video_mode = tag->u.videotext.video_mode;
- + screen_info.orig_video_cols = tag->u.videotext.video_cols;
- + screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
- + screen_info.orig_video_lines = tag->u.videotext.video_lines;
- + screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
- + screen_info.orig_video_points = tag->u.videotext.video_points;
- + return 0;
- +}
- +
- +__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
- +#endif
- +
- +static int __init parse_tag_ramdisk(const struct tag *tag)
- +{
- + setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
- + (tag->u.ramdisk.flags & 2) == 0,
- + tag->u.ramdisk.start, tag->u.ramdisk.size);
- + return 0;
- +}
- +
- +__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
- +
- +static int __init parse_tag_initrd(const struct tag *tag)
- +{
- + printk(KERN_WARNING "ATAG_INITRD is deprecated; "
- + "please update your bootloader.\n");
- + phys_initrd_start = __virt_to_phys(tag->u.initrd.start);
- + phys_initrd_size = tag->u.initrd.size;
- + return 0;
- +}
- +
- +__tagtable(ATAG_INITRD, parse_tag_initrd);
- +
- +static int __init parse_tag_initrd2(const struct tag *tag)
- +{
- + phys_initrd_start = tag->u.initrd.start;
- + phys_initrd_size = tag->u.initrd.size;
- + return 0;
- +}
- +
- +__tagtable(ATAG_INITRD2, parse_tag_initrd2);
- +
- +static int __init parse_tag_revision(const struct tag *tag)
- +{
- + return 0;
- +}
- +
- +__tagtable(ATAG_REVISION, parse_tag_revision);
- +
- +static int __init parse_tag_cmdline(const struct tag *tag)
- +{
- + strlcpy(default_command_line, tag->u.cmdline.cmdline,
- + COMMAND_LINE_SIZE);
- + return 0;
- +}
- +
- +__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
- +
- +/*
- + * Scan the tag table for this tag, and call its parse function.
- + * The tag table is built by the linker from all the __tagtable
- + * declarations.
- + */
- +static int __init parse_tag(const struct tag *tag)
- +{
- + extern struct tagtable __tagtable_begin, __tagtable_end;
- + struct tagtable *t;
- +
- + for (t = &__tagtable_begin; t < &__tagtable_end; t++)
- + if (tag->hdr.tag == t->tag) {
- + t->parse(tag);
- + break;
- + }
- +
- + return t < &__tagtable_end;
- +}
- +
- +/*
- + * Parse all tags in the list, checking both the global and architecture
- + * specific tag tables.
- + */
- +static void __init parse_tags(const struct tag *t)
- +{
- + for (; t->hdr.size; t = tag_next(t))
- + if (!parse_tag(t))
- + printk(KERN_WARNING
- + "Ignoring unrecognised tag 0x%08x\n",
- + t->hdr.tag);
- +}
- +
- +/*
- + * This holds our defaults.
- + */
- +static struct init_tags {
- + struct tag_header hdr1;
- + struct tag_core core;
- + struct tag_header hdr2;
- + struct tag_mem32 mem;
- + struct tag_header hdr3;
- +} init_tags __initdata = {
- + {tag_size(tag_core), ATAG_CORE}, //hdr1
- + {0, PAGE_SIZE, 0xff},
- + {tag_size(tag_mem32), ATAG_MEM}, //hdr2
- + {MEM_SIZE, PHYS_OFFSET},
- + {0, ATAG_NONE}
- +};
- +
- +static unsigned long __init setup_memory(void)
- +{
- + unsigned long bootmap_size;
- + unsigned long ram_start_pfn;
- + unsigned long free_ram_start_pfn;
- + phys_addr_t memory_start, memory_end;
- + struct memblock_region *region;
- +
- + memory_end = memory_start = 0;
- +
- + /* Find main memory where is the kernel */
- + for_each_memblock(memory, region) {
- + memory_start = region->base;
- + memory_end = region->base + region->size;
- + printk(KERN_INFO "%s: Memory: 0x%x-0x%x\n", __func__,
- + memory_start, memory_end);
- + }
- +
- + if (!memory_end) {
- + panic("No memory!");
- + }
- +
- + ram_start_pfn = PFN_UP(memblock_start_of_DRAM());
- + /* free_ram_start_pfn is first page after kernel */
- + free_ram_start_pfn = PFN_UP(__pa(&_end));
- + max_pfn = PFN_DOWN(memblock_end_of_DRAM());
- +
- + /* it could update max_pfn */
- + if (max_pfn - ram_start_pfn <= MAXMEM_PFN)
- + max_low_pfn = max_pfn;
- + else {
- + max_low_pfn = MAXMEM_PFN + ram_start_pfn;
- +#ifndef CONFIG_HIGHMEM
- + max_pfn = MAXMEM_PFN + ram_start_pfn;
- +#endif
- + }
- + /* high_memory is related with VMALLOC */
- + high_memory = (void *)__va(max_low_pfn * PAGE_SIZE);
- + min_low_pfn = free_ram_start_pfn;
- +
- + /*
- + * initialize the boot-time allocator (with low memory only).
- + *
- + * This makes the memory from the end of the kernel to the end of
- + * RAM usable.
- + * init_bootmem sets the global values min_low_pfn, max_low_pfn.
- + */
- + bootmap_size = init_bootmem_node(NODE_DATA(0), free_ram_start_pfn,
- + ram_start_pfn, max_low_pfn);
- + free_bootmem(PFN_PHYS(free_ram_start_pfn),
- + (max_low_pfn - free_ram_start_pfn) << PAGE_SHIFT);
- + reserve_bootmem(PFN_PHYS(free_ram_start_pfn), bootmap_size,
- + BOOTMEM_DEFAULT);
- +
- + for_each_memblock(reserved, region) {
- + if (region->size != 0) {
- + printk(KERN_INFO "Reserved - 0x%08x-0x%08x\n",
- + (u32) region->base, (u32) region->size);
- + reserve_bootmem(region->base, region->size,
- + BOOTMEM_DEFAULT);
- + }
- + }
- + return max_low_pfn;
- +}
- +
- +void __init setup_arch(char **cmdline_p)
- +{
- + struct tag *tags = (struct tag *)&init_tags;
- + struct machine_desc *mdesc;
- + char *from = default_command_line;
- +
- + setup_processor();
- + mdesc = setup_machine(machine_arch_type);
- + machine_desc = mdesc;
- + machine_name = mdesc->name;
- +
- + if (mdesc->soft_reboot)
- + reboot_setup("s");
- +
- + if (mdesc->param_offset)
- + tags = phys_to_virt(mdesc->param_offset);
- +
- + if (tags->hdr.tag != ATAG_CORE)
- + tags = (struct tag *)&init_tags;
- +
- + if (tags->hdr.tag == ATAG_CORE) {
- + if (meminfo.nr_banks != 0)
- + squash_mem_tags(tags);
- + parse_tags(tags);
- + }
- +
- + init_mm.start_code = (unsigned long)&_text;
- + init_mm.end_code = (unsigned long)&_etext;
- + init_mm.end_data = (unsigned long)&_edata;
- + init_mm.brk = (unsigned long)&_end;
- +
- + memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
- + boot_command_line[COMMAND_LINE_SIZE - 1] = '\0';
- + parse_cmdline(cmdline_p, from);
- +
- + /* use generic way to parse */
- + parse_early_param();
- +
- + /* setup bootmem allocator */
- + setup_memory();
- +
- + strlcpy(command_line, from, COMMAND_LINE_SIZE);
- + *cmdline_p = command_line;
- +
- + paging_init(mdesc);
- + request_standard_resources(&meminfo, mdesc); //- for test only
- +
- +#ifdef CONFIG_SMP
- + smp_init_cpus();
- +#endif
- +
- + /*
- + * Set up various architecture-specific pointers
- + */
- + init_arch_irq = mdesc->init_irq;
- + system_timer = mdesc->timer;
- + if (mdesc->init_machine)
- + mdesc->init_machine();
- +
- +#if defined(CONFIG_VT)
- +#if defined(CONFIG_VGA_CONSOLE)
- + conswitchp = &vga_con;
- +#elif defined(CONFIG_DUMMY_CONSOLE)
- + conswitchp = &dummy_con; //+ Tom: we will reach here
- +#endif
- +#endif
- +
- + early_trap_init();
- +}
- +
- +/*
- + * cpu_init - initialise one CPU.
- + *
- + * cpu_init dumps the cache information, initialises SMP specific
- + * information.
- + */
- +
- +void __init cpu_init(void)
- +{
- + unsigned int cpu = smp_processor_id(), tmp = 0;
- +
- + if (cpu >= NR_CPUS) {
- + printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
- + BUG();
- + }
- +
- + if (system_state == SYSTEM_BOOTING)
- + dump_cpu_info(cpu);
- +
- + tmp = 1 << IVB_offESZ;
- +#ifdef CONFIG_EVIC
- + tmp |= 1 << IVB_offEVIC;
- +#endif
- + SET_IVB(tmp | IVB_BASE);
- + tmp = 0x10003;
- + SET_INT_MASK(tmp);
- + ISB();
- +}
- +
- +static int __init topology_init(void)
- +{
- + int cpu;
- +
- + for_each_possible_cpu(cpu)
- + register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu);
- +
- + return 0;
- +}
- +
- +subsys_initcall(topology_init);
- +
- +static int c_show(struct seq_file *m, void *v)
- +{
- + int i;
- +
- + seq_printf(m, "Processor\t: %s %s (id %lu, rev %lu, cfg %lu)\n",
- + proc_info.manufacturer, proc_info.cpu_name,
- + cpu_id, cpu_rev, cpu_cfgid);
- +#if defined(CONFIG_AG101_CPU_FREQ_SCALING_MODE) || defined(CONFIG_AG101_CPU_FREQ_FCS)
- + seq_printf(m, "MHz\t\t: %u\n", ag101_cpufreq_get(1) / 1000);
- +#endif
- +
- + seq_printf(m, "L1I\t\t: %luKB/%luS/%luW/%luB\n",
- + CACHE_SET(ICACHE) * CACHE_WAY(ICACHE) *
- + CACHE_LINE_SIZE(ICACHE) / 1024, CACHE_SET(ICACHE),
- + CACHE_WAY(ICACHE), CACHE_LINE_SIZE(ICACHE));
- +
- + seq_printf(m, "L1D\t\t: %luKB/%luS/%luW/%luB\n",
- + CACHE_SET(DCACHE) * CACHE_WAY(DCACHE) *
- + CACHE_LINE_SIZE(DCACHE) / 1024, CACHE_SET(DCACHE),
- + CACHE_WAY(DCACHE), CACHE_LINE_SIZE(DCACHE));
- +
- +#if defined(CONFIG_SMP)
- + for_each_online_cpu(i) {
- + seq_printf(m, "Processor\t: %d\n", i);
- + seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
- + per_cpu(cpu_data,
- + i).loops_per_jiffy / (500000UL / HZ),
- + (per_cpu(cpu_data, i).loops_per_jiffy /
- + (5000UL / HZ)) % 100);
- + }
- +#else /* CONFIG_SMP */
- + seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
- + loops_per_jiffy / (500000 / HZ),
- + (loops_per_jiffy / (5000 / HZ)) % 100);
- +#endif
- +
- + /* dump out the processor features */
- + seq_puts(m, "Features\t: ");
- +
- + for (i = 0; hwcap_str[i]; i++)
- + if (elf_hwcap & (1 << i))
- + seq_printf(m, "%s ", hwcap_str[i]);
- +
- + seq_puts(m, "\n\n");
- + seq_printf(m, "Hardware\t: %s\n", elf_platform);
- +
- + return 0;
- +}
- +
- +static void *c_start(struct seq_file *m, loff_t * pos)
- +{
- + return *pos < 1 ? (void *)1 : NULL;
- +}
- +
- +static void *c_next(struct seq_file *m, void *v, loff_t * pos)
- +{
- + ++*pos;
- + return NULL;
- +}
- +
- +static void c_stop(struct seq_file *m, void *v)
- +{
- +}
- +
- +struct seq_operations cpuinfo_op = {
- + .start = c_start,
- + .next = c_next,
- + .stop = c_stop,
- + .show = c_show
- +};
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/signal.c linux-3.4.110/arch/nds32/kernel/signal.c
- --- linux-3.4.110.orig/arch/nds32/kernel/signal.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/signal.c 2016-04-07 10:20:50.946081179 +0200
- @@ -0,0 +1,850 @@
- +/*
- + * linux/arch/nds32/kernel/signal.c
- + *
- + * Copyright (C) 1995-2002 Russell King
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#include <linux/errno.h>
- +#include <linux/signal.h>
- +#include <linux/ptrace.h>
- +#include <linux/personality.h>
- +#include <linux/freezer.h>
- +#include <linux/tracehook.h>
- +
- +#include <asm/cacheflush.h>
- +#include <asm/ucontext.h>
- +#include <asm/uaccess.h>
- +#include <asm/unistd.h>
- +#include <asm/fpu.h>
- +#include <asm/audio.h>
- +
- +#include "ptrace.h"
- +#include "signal.h"
- +#include "fpu.h"
- +#include "audio.h"
- +
- +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
- +
- +/*
- + * For NDS32 syscalls, we encode the syscall number into the instruction.
- + */
- +#if defined( __NDS32_EL__)
- +#define SWI_SYS_SIGRETURN (0xeb0e0a64)
- +#define SWI_SYS_RT_SIGRETURN (0xab150a64)
- +#define SWI_SYS_RESTART (0x0b000a64) /* syscall __NR_restart_syscall */
- +#define SWI_SYS_RESTART_LWIBI (0x0180af0d) /* lwi.bi $p0, [$sp], 4 */
- +#define SWI_SYS_RESTART_JRP0 (0x0068004a) /* jr $p0 */
- +#elif defined(__NDS32_EB__)
- +#define SWI_SYS_SIGRETURN (0x6400000b|(__NR_sigreturn<<5))
- +#define SWI_SYS_RT_SIGRETURN (0x6400000b|(__NR_rt_sigreturn<<5))
- +#define SWI_SYS_RESTART (0x640a000b) /* syscall __NR_restart_syscall */
- +#define SWI_SYS_RESTART_LWIBI (0x0daf8001) /* lwi.bi $p0, [$sp], 4 */
- +#define SWI_SYS_RESTART_JRP0 (0x4a006800) /* jr $p0 */
- +#else
- +#error "NDS32, but neither __NDS32_EB__, nor __NDS32_EL__???"
- +#endif
- +
- +#ifdef CONFIG_FPU
- +static struct fpu_struct init_fpuregs = {
- + .fs_regs = {[0 ... 31] = sNAN32},
- + .fd_regs = {[0 ... 15] = sNAN64},
- + .fpcsr = FPCSR_INIT
- +};
- +#endif
- +#ifdef CONFIG_AUDIO
- +static struct audio_struct init_audioregs = {
- + .auregs = {[0...31] = NAN32}
- +};
- +#endif
- +const unsigned long retcodes[2] = {
- + SWI_SYS_SIGRETURN,
- + SWI_SYS_RT_SIGRETURN
- +};
- +
- +const unsigned long syscall_restart_code[3] = {
- + SWI_SYS_RESTART, /* syscall __NR_restart_syscall */
- + SWI_SYS_RESTART_LWIBI, /* lwi.bi $p0, [$sp], 4 */
- + SWI_SYS_RESTART_JRP0 /* jr $p0 */
- +};
- +
- +static int do_signal(sigset_t * oldset, struct pt_regs *regs, int syscall);
- +
- +/*
- + * atomically swap in the new signal mask, and wait for a signal.
- + */
- +asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask,
- + old_sigset_t mask, struct pt_regs *regs)
- +{
- + sigset_t blocked;
- +
- + mask &= _BLOCKABLE;
- + current->saved_sigmask = current->blocked;
- + siginitset(&blocked, mask);
- + set_current_blocked(&blocked);
- +
- + current->state = TASK_INTERRUPTIBLE;
- + schedule();
- + set_thread_flag(TIF_RESTORE_SIGMASK);
- + return -ERESTARTNOHAND;
- +}
- +
- +asmlinkage int sys_rt_sigsuspend(sigset_t __user * unewset, size_t sigsetsize,
- + struct pt_regs *regs)
- +{
- + sigset_t newset;
- +
- + /* XXX: Don't preclude handling different sized sigset_t's. */
- + if (sigsetsize != sizeof(sigset_t))
- + return -EINVAL;
- +
- + if (copy_from_user(&newset, unewset, sizeof(newset)))
- + return -EFAULT;
- + sigdelsetmask(&newset, ~_BLOCKABLE);
- + current->saved_sigmask = current->blocked;
- + set_current_blocked(&newset);
- + current->state = TASK_INTERRUPTIBLE;
- + schedule();
- + set_thread_flag(TIF_RESTORE_SIGMASK);
- + return -ERESTARTNOHAND;
- +}
- +
- +asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user * act,
- + struct old_sigaction __user * oact)
- +{
- + struct k_sigaction new_ka, old_ka;
- + int ret;
- +
- + if (act) {
- + old_sigset_t mask;
- + if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
- + __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
- + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) {
- +
- + return -EFAULT;
- + }
- + __get_user(new_ka.sa.sa_flags, &act->sa_flags);
- + __get_user(mask, &act->sa_mask);
- +
- + siginitset(&new_ka.sa.sa_mask, mask);
- + }
- +
- + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
- +
- + if (!ret && oact) {
- +
- + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
- + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
- + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) {
- +
- + return -EFAULT;
- + }
- + __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
- + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
- + }
- +
- + return ret;
- +}
- +
- +/*
- + * Auxiliary signal frame. This saves stuff like FP state.
- + * The layout of this structure is not part of the user ABI.
- + */
- +struct aux_sigframe {
- +};
- +
- +/*
- + * Do a signal return; undo the signal stack. These are aligned to 64-bit.
- + */
- +struct sigframe {
- + struct sigcontext sc;
- + unsigned long extramask[_NSIG_WORDS - 1];
- + unsigned long retcode;
- + struct aux_sigframe aux __attribute__ ((aligned(8)));
- +};
- +
- +struct rt_sigframe {
- + struct siginfo __user *pinfo;
- + void __user *puc;
- + struct siginfo info;
- + struct ucontext uc;
- + unsigned long retcode;
- + struct aux_sigframe aux __attribute__ ((aligned(8)));
- +};
- +
- +#ifdef CONFIG_FPU
- +static inline int restore_sigcontext_fpu(struct pt_regs *regs,
- + struct sigcontext __user * sc)
- +{
- + struct task_struct *tsk = current;
- + unsigned long used_math_flag;
- + int ret = 0;
- +
- + if (!(GET_FUCOP_EXIST() & FUCOP_EXIST_mskCP0ISFPU))
- + return 0;
- +
- + __get_user_error(used_math_flag, &sc->used_math_flag, ret);
- +
- + if (!used_math_flag)
- + return 0;
- +
- + set_used_math();
- +
- +#ifdef CONFIG_UNLAZY_FPU
- + clear_fpu(regs);
- +#else
- + preempt_disable();
- + if (current == last_task_used_math) {
- + last_task_used_math = NULL;
- + release_fpu(regs);
- + }
- + preempt_enable();
- +#endif
- +
- + return __copy_from_user(&tsk->thread.fpu, &sc->fpu,
- + sizeof(struct fpu_struct));
- +}
- +
- +static inline int setup_sigcontext_fpu(struct pt_regs *regs,
- + struct sigcontext __user * sc)
- +{
- + struct task_struct *tsk = current;
- + int ret = 0;
- +
- + if (!(GET_FUCOP_EXIST() & FUCOP_EXIST_mskCP0ISFPU))
- + return 0;
- +
- + __put_user_error(used_math(), &sc->used_math_flag, ret);
- +
- + if (!used_math())
- + return ret;
- +
- + preempt_disable();
- +#ifdef CONFIG_UNLAZY_FPU
- + unlazy_fpu(tsk);
- +#else
- + if (last_task_used_math != NULL)
- + save_fpu(last_task_used_math);
- +#endif
- + ret = __copy_to_user(&sc->fpu, &tsk->thread.fpu,
- + sizeof(struct fpu_struct));
- +
- + grab_fpu(task_pt_regs(tsk));
- + fpload(&init_fpuregs);
- +#ifndef CONFIG_UNLAZY_FPU //Lazy FPU
- + last_task_used_math = current;
- +#endif
- + preempt_enable();
- + return ret;
- +}
- +#else
- +static inline int
- +restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user * sc)
- +{
- + return 0;
- +}
- +
- +static inline int
- +setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user * sc)
- +{
- + return 0;
- +}
- +#endif /* CONFIG_FPU */
- +
- +#ifdef CONFIG_AUDIO
- +static inline int restore_sigcontext_audio(struct pt_regs *regs,
- + struct sigcontext __user * sc)
- +{
- + struct task_struct *tsk = current;
- + unsigned long used_audio_flag;
- + int ret = 0;
- +
- + if (!(GET_MSC_CFG() & MSC_CFG_mskAUDIO))
- + return 0;
- +
- + __get_user_error(used_audio_flag, &sc->used_audio_flag, ret);
- +
- + if (!used_audio_flag)
- + return 0;
- +
- + set_tsk_thread_flag(tsk, TIF_USEDAUDIO);
- +#ifdef CONFIG_UNLAZY_AUDIO
- + clear_audio(regs);
- +#else
- + preempt_disable();
- + if (current == last_task_used_audio) {
- + last_task_used_audio = NULL;
- + clear_audio(regs);
- + }
- + preempt_enable();
- +#endif
- +
- + return __copy_from_user(&tsk->thread.audio, &sc->audio,
- + sizeof(struct audio_struct));
- +}
- +
- +static inline int setup_sigcontext_audio(struct pt_regs *regs,
- + struct sigcontext __user * sc)
- +{
- + struct task_struct *tsk = current;
- + int ret = 0;
- +
- + if (!(GET_MSC_CFG() & MSC_CFG_mskAUDIO))
- + return 0;
- +
- + __put_user_error(test_tsk_thread_flag(tsk, TIF_USEDAUDIO),
- + &sc->used_audio_flag, ret);
- +
- + if (!test_tsk_thread_flag(tsk, TIF_USEDAUDIO))
- + return ret;
- +
- + preempt_disable();
- +#ifdef CONFIG_UNLAZY_AUDIO
- + unlazy_audio(tsk);
- +#else
- + if (NULL != last_task_used_audio) {
- + save_audio(tsk);
- + }
- +#endif
- + ret = __copy_to_user(&sc->audio, &tsk->thread.audio,
- + sizeof(struct audio_struct));
- +
- + grab_audio(task_pt_regs(tsk));
- + audioload(&init_audioregs);
- +#ifndef CONFIG_UNLAZY_AUDIO //Lazy audio
- + last_task_used_audio = current;
- +#endif
- + preempt_enable();
- + return ret;
- +}
- +#else /*CONFIG_AUDIO */
- +static inline int
- +restore_sigcontext_audio(struct pt_regs *regs, struct sigcontext __user * sc)
- +{
- + return 0;
- +}
- +
- +static inline int
- +setup_sigcontext_audio(struct pt_regs *regs, struct sigcontext __user * sc)
- +{
- + return 0;
- +}
- +#endif
- +
- +static int restore_sigcontext(struct pt_regs *regs,
- + struct sigcontext __user * sc,
- + struct aux_sigframe __user * aux)
- +{
- + int err = 0;
- +
- + __get_user_error(regs->NDS32_r0, &sc->nds32_r0, err);
- + __get_user_error(regs->NDS32_r1, &sc->nds32_r1, err);
- + __get_user_error(regs->NDS32_r2, &sc->nds32_r2, err);
- + __get_user_error(regs->NDS32_r3, &sc->nds32_r3, err);
- + __get_user_error(regs->NDS32_r4, &sc->nds32_r4, err);
- + __get_user_error(regs->NDS32_r5, &sc->nds32_r5, err);
- + __get_user_error(regs->NDS32_r6, &sc->nds32_r6, err);
- + __get_user_error(regs->NDS32_r7, &sc->nds32_r7, err);
- + __get_user_error(regs->NDS32_r8, &sc->nds32_r8, err);
- + __get_user_error(regs->NDS32_r9, &sc->nds32_r9, err);
- + __get_user_error(regs->NDS32_r10, &sc->nds32_r10, err);
- + __get_user_error(regs->NDS32_r11, &sc->nds32_r11, err);
- + __get_user_error(regs->NDS32_r12, &sc->nds32_r12, err);
- + __get_user_error(regs->NDS32_r13, &sc->nds32_r13, err);
- + __get_user_error(regs->NDS32_r14, &sc->nds32_r14, err);
- + __get_user_error(regs->NDS32_r15, &sc->nds32_r15, err);
- + __get_user_error(regs->NDS32_r16, &sc->nds32_r16, err);
- + __get_user_error(regs->NDS32_r17, &sc->nds32_r17, err);
- + __get_user_error(regs->NDS32_r18, &sc->nds32_r18, err);
- + __get_user_error(regs->NDS32_r19, &sc->nds32_r19, err);
- + __get_user_error(regs->NDS32_r20, &sc->nds32_r20, err);
- +
- + __get_user_error(regs->NDS32_r21, &sc->nds32_r21, err);
- + __get_user_error(regs->NDS32_r22, &sc->nds32_r22, err);
- + __get_user_error(regs->NDS32_r23, &sc->nds32_r23, err);
- + __get_user_error(regs->NDS32_r24, &sc->nds32_r24, err);
- + __get_user_error(regs->NDS32_r25, &sc->nds32_r25, err);
- + __get_user_error(regs->NDS32_fp, &sc->nds32_fp, err);
- + __get_user_error(regs->NDS32_gp, &sc->nds32_gp, err);
- + __get_user_error(regs->NDS32_lp, &sc->nds32_lr, err);
- + __get_user_error(regs->NDS32_sp, &sc->nds32_sp, err);
- +
- + __get_user_error(regs->NDS32_ipc, &sc->nds32_ipc, err);
- +#if defined(CONFIG_HWZOL)
- + __get_user_error(regs->NDS32_lc, &sc->zol.nds32_lc, err);
- + __get_user_error(regs->NDS32_le, &sc->zol.nds32_le, err);
- + __get_user_error(regs->NDS32_lb, &sc->zol.nds32_lb, err);
- +#endif
- +
- + err |= !valid_user_regs(regs);
- + err |= restore_sigcontext_audio(regs, sc);
- + err |= restore_sigcontext_fpu(regs, sc);
- +
- + return err;
- +}
- +
- +asmlinkage int sys_sigreturn(struct pt_regs *regs)
- +{
- + struct sigframe __user *frame;
- + sigset_t set;
- +
- + /* Always make any pending restarted system calls return -EINTR */
- + current_thread_info()->restart_block.fn = do_no_restart_syscall;
- +
- + /*
- + * Since we stacked the signal on a 64-bit boundary,
- + * then 'sp' should be word aligned here. If it's
- + * not, then the user is trying to mess with us.
- + */
- + if (regs->NDS32_sp & 7)
- + goto badframe;
- +
- + frame = (struct sigframe __user *)regs->NDS32_sp;
- +
- + if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
- + goto badframe;
- +
- + if (__get_user(set.sig[0], &frame->sc.oldmask)
- + || (_NSIG_WORDS > 1
- + && __copy_from_user(&set.sig[1], &frame->extramask,
- + sizeof(frame->extramask))))
- + goto badframe;
- +
- + sigdelsetmask(&set, ~_BLOCKABLE);
- + spin_lock_irq(¤t->sighand->siglock);
- + current->blocked = set;
- + recalc_sigpending();
- + spin_unlock_irq(¤t->sighand->siglock);
- +
- + if (restore_sigcontext(regs, &frame->sc, &frame->aux))
- + goto badframe;
- +
- + return regs->NDS32_r0;
- +
- +badframe:
- + force_sig(SIGSEGV, current);
- + return 0;
- +}
- +
- +asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
- +{
- + struct rt_sigframe __user *frame;
- + sigset_t set;
- +
- + /* Always make any pending restarted system calls return -EINTR */
- + current_thread_info()->restart_block.fn = do_no_restart_syscall;
- +
- + /*
- + * Since we stacked the signal on a 64-bit boundary,
- + * then 'sp' should be word aligned here. If it's
- + * not, then the user is trying to mess with us.
- + */
- + if (regs->NDS32_sp & 7)
- + goto badframe;
- +
- + frame = (struct rt_sigframe __user *)regs->NDS32_sp;
- +
- + if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
- + goto badframe;
- +
- + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
- + goto badframe;
- +
- + sigdelsetmask(&set, ~_BLOCKABLE);
- + spin_lock_irq(¤t->sighand->siglock);
- + current->blocked = set;
- + recalc_sigpending();
- + spin_unlock_irq(¤t->sighand->siglock);
- +
- + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &frame->aux))
- + goto badframe;
- +
- + if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->NDS32_sp) ==
- + -EFAULT)
- + goto badframe;
- +
- + return regs->NDS32_r0;
- +
- +badframe:
- + force_sig(SIGSEGV, current);
- + return 0;
- +}
- +
- +static int setup_sigcontext(struct sigcontext __user * sc,
- + struct aux_sigframe __user * aux,
- + struct pt_regs *regs, unsigned long mask)
- +{
- + int err = 0;
- +
- + err |= setup_sigcontext_fpu(regs, sc);
- + err |= setup_sigcontext_audio(regs, sc);
- +
- + __put_user_error(regs->NDS32_r0, &sc->nds32_r0, err);
- + __put_user_error(regs->NDS32_r1, &sc->nds32_r1, err);
- + __put_user_error(regs->NDS32_r2, &sc->nds32_r2, err);
- + __put_user_error(regs->NDS32_r3, &sc->nds32_r3, err);
- + __put_user_error(regs->NDS32_r4, &sc->nds32_r4, err);
- + __put_user_error(regs->NDS32_r5, &sc->nds32_r5, err);
- + __put_user_error(regs->NDS32_r6, &sc->nds32_r6, err);
- + __put_user_error(regs->NDS32_r7, &sc->nds32_r7, err);
- + __put_user_error(regs->NDS32_r8, &sc->nds32_r8, err);
- + __put_user_error(regs->NDS32_r9, &sc->nds32_r9, err);
- + __put_user_error(regs->NDS32_r10, &sc->nds32_r10, err);
- + __put_user_error(regs->NDS32_r11, &sc->nds32_r11, err);
- + __put_user_error(regs->NDS32_r12, &sc->nds32_r12, err);
- + __put_user_error(regs->NDS32_r13, &sc->nds32_r13, err);
- + __put_user_error(regs->NDS32_r14, &sc->nds32_r14, err);
- + __put_user_error(regs->NDS32_r15, &sc->nds32_r15, err);
- + __put_user_error(regs->NDS32_r16, &sc->nds32_r16, err);
- + __put_user_error(regs->NDS32_r17, &sc->nds32_r17, err);
- + __put_user_error(regs->NDS32_r18, &sc->nds32_r18, err);
- + __put_user_error(regs->NDS32_r19, &sc->nds32_r19, err);
- + __put_user_error(regs->NDS32_r20, &sc->nds32_r20, err);
- +
- + __put_user_error(regs->NDS32_r21, &sc->nds32_r21, err);
- + __put_user_error(regs->NDS32_r22, &sc->nds32_r22, err);
- + __put_user_error(regs->NDS32_r23, &sc->nds32_r23, err);
- + __put_user_error(regs->NDS32_r24, &sc->nds32_r24, err);
- + __put_user_error(regs->NDS32_r25, &sc->nds32_r25, err);
- + __put_user_error(regs->NDS32_fp, &sc->nds32_fp, err);
- + __put_user_error(regs->NDS32_gp, &sc->nds32_gp, err);
- + __put_user_error(regs->NDS32_lp, &sc->nds32_lr, err);
- + __put_user_error(regs->NDS32_sp, &sc->nds32_sp, err);
- + __put_user_error(regs->NDS32_ipc, &sc->nds32_ipc, err);
- +#if defined(CONFIG_HWZOL)
- + __get_user_error(regs->NDS32_lc, &sc->zol.nds32_lc, err);
- + __get_user_error(regs->NDS32_le, &sc->zol.nds32_le, err);
- + __get_user_error(regs->NDS32_lb, &sc->zol.nds32_lb, err);
- +#endif
- +
- + __put_user_error(current->thread.trap_no, &sc->trap_no, err);
- + __put_user_error(current->thread.error_code, &sc->error_code, err);
- + __put_user_error(current->thread.address, &sc->fault_address, err);
- + __put_user_error(mask, &sc->oldmask, err);
- +
- + return err;
- +}
- +
- +static inline void __user *get_sigframe(struct k_sigaction *ka,
- + struct pt_regs *regs, int framesize)
- +{
- + unsigned long sp = regs->NDS32_sp;
- + void __user *frame;
- +
- + /*
- + * This is the X/Open sanctioned signal stack switching.
- + */
- + if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
- + sp = current->sas_ss_sp + current->sas_ss_size;
- +
- + /*
- + * ATPCS B01 mandates 8-byte alignment
- + */
- + frame = (void __user *)((sp - framesize) & ~7);
- +
- + /*
- + * Check that we can actually write to the signal frame.
- + */
- + if (!access_ok(VERIFY_WRITE, frame, framesize))
- + frame = NULL;
- +
- + return frame;
- +}
- +
- +static int setup_return(struct pt_regs *regs, struct k_sigaction *ka,
- + unsigned long __user * rc, void __user * frame,
- + int usig)
- +{
- + unsigned long handler = (unsigned long)ka->sa.sa_handler;
- + unsigned long retcode;
- + struct sigframe *sf = (struct sigframe *)frame;
- +
- + /*
- + * Maybe we need to deliver a 32-bit signal to a 26-bit task.
- + */
- + if (ka->sa.sa_flags & SA_RESTORER) {
- + retcode = (unsigned long)ka->sa.sa_restorer;
- + } else {
- +
- + unsigned int idx = 0; //thumb;
- + unsigned long line_size = CACHE_LINE_SIZE(ICACHE);
- + unsigned long start, end;
- +
- + if (ka->sa.sa_flags & SA_SIGINFO)
- + idx++;
- +
- + if (__put_user(retcodes[idx], rc))
- + return 1;
- +
- + /*
- + * Ensure that the instruction cache sees
- + * the return code written onto the stack.
- + */
- + start = (unsigned long)rc & ~(line_size - 1);
- + end = start + line_size;
- + flush_icache_range(start, end);
- +
- + retcode = KERN_SIGRETURN_CODE + (idx << 2);
- + }
- +
- + regs->NDS32_r0 = usig;
- + regs->NDS32_r1 = 0;
- + regs->NDS32_r2 = (unsigned long)&sf->sc;
- + regs->NDS32_sp = (unsigned long)frame;
- + regs->NDS32_lp = retcode;
- + regs->NDS32_ipc = handler;
- + /* Also store handler address in r15 for updating GP in the handler. */
- + regs->NDS32_r15 = handler;
- +
- + return 0;
- +}
- +
- +static int setup_frame(int usig, struct k_sigaction *ka, sigset_t * set,
- + struct pt_regs *regs)
- +{
- + struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame));
- + int err = 0;
- +
- + if (!frame)
- + return 1;
- +
- + err |= setup_sigcontext(&frame->sc, &frame->aux, regs, set->sig[0]);
- +
- + if (_NSIG_WORDS > 1) {
- + err |= __copy_to_user(frame->extramask, &set->sig[1],
- + sizeof(frame->extramask));
- + }
- +
- + if (err == 0)
- + err = setup_return(regs, ka, &frame->retcode, frame, usig);
- +
- + return err;
- +}
- +
- +static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t * info,
- + sigset_t * set, struct pt_regs *regs)
- +{
- + struct rt_sigframe __user *frame =
- + get_sigframe(ka, regs, sizeof(*frame));
- + stack_t stack;
- + int err = 0;
- +
- + if (!frame)
- + return 1;
- +
- + __put_user_error(&frame->info, &frame->pinfo, err);
- + __put_user_error(&frame->uc, &frame->puc, err);
- + err |= copy_siginfo_to_user(&frame->info, info);
- +
- + __put_user_error(0, &frame->uc.uc_flags, err);
- + __put_user_error(NULL, &frame->uc.uc_link, err);
- +
- + memset(&stack, 0, sizeof(stack));
- + stack.ss_sp = (void __user *)current->sas_ss_sp;
- + stack.ss_flags = sas_ss_flags(regs->NDS32_sp); //NDS32_sp
- + stack.ss_size = current->sas_ss_size;
- + err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack));
- +
- + err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->aux,
- + regs, set->sig[0]);
- + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
- +
- + if (err == 0)
- + err = setup_return(regs, ka, &frame->retcode, frame, usig);
- +
- + if (err == 0) {
- + /*
- + * For realtime signals we must also set the second and third
- + * arguments for the signal handler.
- + * -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
- + */
- + regs->NDS32_r1 = (unsigned long)&frame->info;
- + regs->NDS32_r2 = (unsigned long)&frame->uc;
- + }
- +
- + return err;
- +}
- +
- +static inline void setup_restart_syscall(struct pt_regs *regs)
- +{
- + regs->NDS32_r0 = regs->NDS32_ORIG_r0;
- + regs->NDS32_ipc -= 4;
- +}
- +
- +/*
- + * OK, we're invoking a handler
- + */
- +static void handle_signal(unsigned long sig, struct k_sigaction *ka,
- + siginfo_t * info, sigset_t * oldset,
- + struct pt_regs *regs, int syscall)
- +{
- + struct thread_info *thread = current_thread_info();
- + struct task_struct *tsk = current;
- + int usig = sig;
- + int ret;
- +
- + /*
- + * If we were from a system call, check for system call restarting...
- + */
- + if (syscall) {
- + switch (regs->NDS32_r0) {
- + case -ERESTART_RESTARTBLOCK:
- + case -ERESTARTNOHAND:
- + regs->NDS32_r0 = -EINTR;
- + break;
- + case -ERESTARTSYS:
- + if (!(ka->sa.sa_flags & SA_RESTART)) {
- + regs->NDS32_r0 = -EINTR;
- + break;
- + }
- + /* fallthrough */
- + case -ERESTARTNOINTR:
- + setup_restart_syscall(regs);
- + }
- + }
- +
- + /*
- + * translate the signal
- + */
- + if (usig < 32 && thread->exec_domain
- + && thread->exec_domain->signal_invmap)
- + usig = thread->exec_domain->signal_invmap[usig];
- +
- + /*
- + * Set up the stack frame
- + */
- + if (ka->sa.sa_flags & SA_SIGINFO)
- + ret = setup_rt_frame(usig, ka, info, oldset, regs);
- + else
- + ret = setup_frame(usig, ka, oldset, regs);
- +
- + /*
- + * Check that the resulting registers are actually sane.
- + */
- + ret |= !valid_user_regs(regs);
- +
- + /*
- + * Block the signal if we were unsuccessful.
- + */
- + if (ret == 0) {
- + spin_lock_irq(&tsk->sighand->siglock);
- + sigorsets(&tsk->blocked, &tsk->blocked, &ka->sa.sa_mask);
- + if (!(ka->sa.sa_flags & SA_NODEFER))
- + sigaddset(&tsk->blocked, sig);
- + recalc_sigpending();
- + spin_unlock_irq(&tsk->sighand->siglock);
- +#if 0 & defined(CONFIG_HSS)
- + /* COLE: i marked this tempory.
- + It doesn't behave the same as x86 */
- + /* Clear HSS when entering the signal handler,
- + User should be step into signal handler */
- + if (regs->NDS32_ipsw & PSW_mskHSS) {
- + regs->NDS32_ipsw &= ~PSW_mskHSS;
- + printk(KERN_INFO "clear for sig %d. pc=0x%08x\n", sig,
- + regs->NDS32_ipc);
- + }
- +#endif
- + return;
- + }
- +
- + force_sigsegv(sig, tsk);
- +}
- +
- +/*
- + * Note that 'init' is a special process: it doesn't get signals it doesn't
- + * want to handle. Thus you cannot kill init even with a SIGKILL even by
- + * mistake.
- + *
- + * Note that we go through the signals twice: once to check the signals that
- + * the kernel can handle, and then we build all the user-level signal handling
- + * stack-frames in one go after that.
- + */
- +asmlinkage int do_signal(sigset_t * oldset, struct pt_regs *regs, int syscall)
- +{
- + struct k_sigaction ka;
- + siginfo_t info;
- + int signr;
- +
- + /*
- + * We want the common case to go fast, which
- + * is why we may in certain cases get here from
- + * kernel mode. Just return without doing anything
- + * if so.
- + */
- +
- + if (!user_mode(regs))
- + return 0;
- +
- + if (try_to_freeze())
- + goto no_signal;
- +
- + if (test_thread_flag(TIF_RESTORE_SIGMASK))
- + oldset = ¤t->saved_sigmask;
- +
- + signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- +
- + if (signr > 0) {
- + handle_signal(signr, &ka, &info, oldset, regs, syscall);
- + /*
- + * A signal was successfully delivered; the saved
- + * sigmask will have been stored in the signal frame,
- + * and will be restored by sigreturn, so we can simply
- + * clear the TIF_RESTORE_SIGMASK flag.
- + */
- + if (test_thread_flag(TIF_RESTORE_SIGMASK))
- + clear_thread_flag(TIF_RESTORE_SIGMASK);
- + return 1;
- + }
- +
- +no_signal:
- + /*
- + * No signal to deliver to the process - restart the syscall.
- + */
- + if (syscall) {
- + switch (regs->NDS32_r0) {
- + u32 __user *usp;
- +
- + case -ERESTART_RESTARTBLOCK:
- + regs->NDS32_sp -= 4;
- + usp = (u32 __user *) regs->NDS32_sp;
- +
- + if (put_user(regs->NDS32_ipc, usp) == 0)
- + regs->NDS32_ipc = KERN_RESTART_CODE;
- + else {
- + regs->NDS32_sp += 4;
- + force_sigsegv(0, current);
- + }
- + regs->NDS32_r0 = regs->NDS32_ORIG_r0;
- + break;
- +
- + case -ERESTARTNOHAND:
- + case -ERESTARTSYS:
- + case -ERESTARTNOINTR:
- +
- + setup_restart_syscall(regs);
- + break;
- + }
- + if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
- + clear_thread_flag(TIF_RESTORE_SIGMASK);
- + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
- + }
- + }
- +
- + return 0;
- +}
- +
- +asmlinkage void do_notify_resume(struct pt_regs *regs,
- + unsigned int thread_flags, int syscall)
- +{
- + if (thread_flags & _TIF_SIGPENDING)
- + do_signal(¤t->blocked, regs, syscall);
- + if (thread_flags & _TIF_NOTIFY_RESUME) {
- + clear_thread_flag(TIF_NOTIFY_RESUME);
- + tracehook_notify_resume(regs);
- + if (current->replacement_session_keyring)
- + key_replace_session_keyring();
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/signal.h linux-3.4.110/arch/nds32/kernel/signal.h
- --- linux-3.4.110.orig/arch/nds32/kernel/signal.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/signal.h 2016-04-07 10:20:50.946081179 +0200
- @@ -0,0 +1,20 @@
- +/*
- + * linux/arch/arm/kernel/signal.h
- + *
- + * Copyright (C) 2005-2009 Russell King.
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <asm/fixmap.h>
- +
- +#define RETURN_SYSCALL_BASE (0x2000)
- +#define RETURN_SYSCALL_PA_BASE (PHYS_OFFSET | RETURN_SYSCALL_BASE)
- +
- +#define KERN_SIGRETURN_CODE (fix_to_virt(FIX_RETURN_SYSCALL))
- +#define KERN_RESTART_CODE (KERN_SIGRETURN_CODE + sizeof(retcodes))
- +
- +extern const unsigned long retcodes[2];
- +extern const unsigned long syscall_restart_code[3];
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/smp.c linux-3.4.110/arch/nds32/kernel/smp.c
- --- linux-3.4.110.orig/arch/nds32/kernel/smp.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/smp.c 2016-04-07 10:20:50.946081179 +0200
- @@ -0,0 +1,335 @@
- +/*
- + * linux/arch/nds32/kernel/smp.c
- + *
- + * Copyright (C) 2002 ARM Limited, All Rights Reserved.
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#include <linux/delay.h>
- +#include <linux/init.h>
- +#include <linux/spinlock.h>
- +#include <linux/sched.h>
- +#include <linux/irq.h>
- +#include <linux/interrupt.h>
- +#include <linux/cache.h>
- +#include <linux/profile.h>
- +#include <linux/errno.h>
- +#include <linux/mm.h>
- +#include <linux/cpu.h>
- +#include <linux/smp.h>
- +#include <linux/seq_file.h>
- +#include <asm/atomic.h>
- +#include <asm/cacheflush.h>
- +#include <asm/cpu.h>
- +#include <asm/processor.h>
- +#include <asm/tlbflush.h>
- +#include <asm/ptrace.h>
- +#include <linux/err.h>
- +#include <asm/irq_regs.h>
- +#include <asm/mmu_context.h>
- +#include <asm/mmu.h>
- +
- +void smp_init_cpus(void)
- +{
- + int i;
- + for (i = 0; i < NR_CPUS; i++)
- + cpu_set(i, cpu_possible_map);
- +}
- +
- +int setup_profiling_timer(unsigned int multiplier)
- +{
- + return 0;
- +}
- +
- +struct tlb_data {
- + struct vm_area_struct *vma;
- + unsigned long start;
- + unsigned long end;
- +};
- +
- +static void ipi_flush_tlb_all(void *data)
- +{
- + local_flush_tlb_all();
- +}
- +
- +void flush_tlb_all(void)
- +{
- + on_each_cpu(ipi_flush_tlb_all, NULL, 1);
- +}
- +
- +static void ipi_flush_tlb_mm(void *data)
- +{
- + struct mm_struct *mm = (struct mm_struct *)data;
- + local_flush_tlb_mm(mm);
- +}
- +
- +void flush_tlb_mm(struct mm_struct *mm)
- +{
- + on_each_cpu(ipi_flush_tlb_mm, mm, 1);
- +}
- +
- +static void ipi_flush_tlb_page(void *data)
- +{
- + struct tlb_data *t = (struct tlb_data *)data;
- + local_flush_tlb_page(t->vma, t->start);
- +}
- +
- +void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
- +{
- + struct tlb_data data;
- +
- + data.vma = vma;
- + data.start = addr;
- + on_each_cpu(ipi_flush_tlb_page, &data, 1);
- +}
- +
- +static void ipi_flush_tlb_range(void *data)
- +{
- + struct tlb_data *t = (struct tlb_data *)data;
- + local_flush_tlb_range(t->vma, t->start, t->end);
- +}
- +
- +void flush_tlb_range(struct vm_area_struct *vma,
- + unsigned long start, unsigned long end)
- +{
- + struct tlb_data data;
- +
- + data.vma = vma;
- + data.start = start;
- + data.end = end;
- + on_each_cpu(ipi_flush_tlb_range, &data, 1);
- +}
- +
- +static void ipi_flush_tlb_kernel_range(void *data)
- +{
- + struct tlb_data *t = (struct tlb_data *)data;
- + local_flush_tlb_kernel_range(t->start, t->end);
- +}
- +
- +void flush_tlb_kernel_range(unsigned long start, unsigned long end)
- +{
- + struct tlb_data data;
- +
- + data.start = start;
- + data.end = end;
- + on_each_cpu(ipi_flush_tlb_kernel_range, &data, 1);
- +}
- +
- +/* IPI implementation */
- +static inline unsigned long read_ipi_trigger(void)
- +{
- + /* AMIC IPI trigger register */
- + return *(volatile unsigned long *)(AMIC_VA_BASE + 0x40);
- +}
- +
- +static inline void write_ipi_trigger(const struct cpumask *mask)
- +{
- + unsigned long data = *cpus_addr(*mask);
- + *(volatile unsigned long *)(AMIC_VA_BASE + 0x40) = data;
- +}
- +
- +static inline void clear_ipi_status(void)
- +{
- + *(volatile unsigned long *)(AMIC_VA_BASE + 0x44) = 0xf;
- + asm("msync store\nisb");
- +}
- +
- +static void __init send_IPI_boot(int cpu, struct task_struct *tsk)
- +{
- + extern void secondary_startup(void);
- + unsigned long *ptr = (unsigned long *)(0xc0006000 + (cpu << 9));
- + ptr[5] = virt_to_phys(secondary_startup);
- + ptr[6] = (unsigned long)task_stack_page(tsk) + THREAD_SIZE - 8;
- + asm("cctl %0, L1D_VA_WB, alevel\n"::"r"(ptr));
- + asm("cctl %0, L1D_VA_INVAL, alevel\nmsync\ndsb\n"::"r"(ptr));
- + write_ipi_trigger(get_cpu_mask(cpu));
- +}
- +
- +static int __init wait_cpu_boot_done(int cpu)
- +{
- + int i, state;
- + for (i = 0; i < 10000; i++) {
- + state = read_ipi_trigger();
- + if ((state & (1 << cpu)) == 0)
- + break;
- + udelay(100);
- + }
- + return (i == 10000) ? -1 : 0;
- +}
- +
- +void __init secondary_start_kernel(void)
- +{
- + unsigned long tmp;
- + unsigned int cpu = smp_processor_id();
- +
- + atomic_inc(&init_mm.mm_count);
- + current->active_mm = &init_mm;
- +
- + /*
- + * enable cache.
- + */
- +
- +#ifdef CONFIG_ANDES_PAGE_SIZE_4KB
- + if (CPU_IS_N1213_43U1HA0()) {
- + /* Downsize cache to bypass cache aliasing issue */
- +
- + if ((CACHE_SET(ICACHE) * CACHE_LINE_SIZE(ICACHE)) > 4096)
- + tmp = 0x02 << SDZ_CTL_offICDZ;
- +
- + if ((CACHE_SET(DCACHE) * CACHE_LINE_SIZE(DCACHE)) > 4096)
- + tmp |= 0x02 << SDZ_CTL_offDCDZ;
- +
- + SET_SDZ_CTL(tmp);
- + ISB();
- +// printk("CPU%d enabled cache downsizing.\n", cpu);
- + }
- +#endif /* CONFIG_ANDES_PAGE_SIZE_4KB */
- +
- + tmp = GET_CACHE_CTL();
- +#ifndef CONFIG_CPU_DCACHE_DISABLE
- + tmp |= CACHE_CTL_mskDC_EN;
- +#endif
- +
- +#ifndef CONFIG_CPU_ICACHE_DISABLE
- + tmp |= CACHE_CTL_mskIC_EN;
- +#endif
- + SET_CACHE_CTL(tmp);
- + DSB();
- + ISB();
- +
- + preempt_disable();
- + local_irq_enable();
- +
- + //assume all of cores runs the same speed
- + //calibrate_delay();
- + /* store cpu info ot the second cpu */
- + smp_store_cpu_info(cpu);
- +
- + clear_ipi_status();
- + cpu_idle();
- +}
- +
- +/*
- + * Called by both boot and secondaries to move global data into
- + * per-processor storage.
- + */
- +void __init smp_store_cpu_info(unsigned int cpuid)
- +{
- + struct cpuinfo_nds32 *cpu_info = &per_cpu(cpu_data, cpuid);
- +
- + cpu_info->loops_per_jiffy = loops_per_jiffy;
- +}
- +
- +/* functions be used by generic layer */
- +void arch_send_call_function_single_ipi(int cpu)
- +{
- + write_ipi_trigger(get_cpu_mask(cpu));
- +}
- +
- +void arch_send_call_function_ipi_mask(const struct cpumask *mask)
- +{
- + write_ipi_trigger(mask);
- +}
- +
- +static void __init smp_boot_one_cpu(int cpu)
- +{
- + struct task_struct *idle;
- + int ret;
- +
- + idle = fork_idle(cpu);
- + if (IS_ERR(idle))
- + panic(KERN_ERR "Fork failed for CPU %d", cpu);
- +
- + send_IPI_boot(cpu, idle);
- + ret = wait_cpu_boot_done(cpu);
- + if (ret == 0)
- + cpu_set(cpu, cpu_online_map);
- + else
- + put_task_struct(idle);
- +}
- +
- +static void ipi_timer(void *data)
- +{
- + profile_tick(CPU_PROFILING);
- + update_process_times(user_mode(get_irq_regs()));
- +}
- +
- +void smp_send_timer(void)
- +{
- + smp_call_function(ipi_timer, NULL, 0);
- +}
- +
- +static void ipi_stop(void *data)
- +{
- + cpu_clear(smp_processor_id(), cpu_online_map);
- + local_irq_enable();
- + for (;;) ;
- +}
- +
- +void smp_send_stop(void)
- +{
- + smp_call_function(ipi_stop, NULL, 0);
- +}
- +
- +void smp_send_reschedule(int cpu)
- +{
- + write_ipi_trigger(get_cpu_mask(cpu));
- +}
- +
- +static void ipi_handler(unsigned int irq, struct irq_desc *desc)
- +{
- + clear_ipi_status();
- + generic_smp_call_function_single_interrupt();
- + generic_smp_call_function_interrupt();
- +}
- +
- +void __init smp_prepare_cpus(unsigned int max_cpus)
- +{
- + /*
- + * XXX detect how many cores exist
- + */
- + int i;
- + unsigned int cpu = smp_processor_id();
- +
- + /* store master core cpu info */
- + smp_store_cpu_info(cpu);
- + for (i = 0; i < max_cpus; i++)
- + cpu_set(i, cpu_present_map);
- +
- + /* setup IPI handler */
- + set_irq_chip(32, &dummy_irq_chip);
- + set_irq_chained_handler(32, ipi_handler);
- +}
- +
- +int __cpuinit __cpu_up(unsigned int cpu)
- +{
- + smp_boot_one_cpu(cpu);
- + return cpu_online(cpu) ? 0 : -ENOSYS;
- +}
- +
- +void __init smp_cpus_done(unsigned int max_cpus)
- +{
- + int cpu;
- + unsigned long bogosum = 0;
- +
- + for_each_online_cpu(cpu)
- + bogosum += per_cpu(cpu_data, cpu).loops_per_jiffy;
- +
- + printk(KERN_INFO "SMP: Total of %d processors activated "
- + "(%lu.%02lu BogoMIPS).\n",
- + num_online_cpus(),
- + bogosum / (500000 / HZ), (bogosum / (5000 / HZ)) % 100);
- +
- + /* now we can set all interruption don't cared */
- + *(volatile unsigned long *)(AMIC_VA_BASE + 0x4) = 0xffffffff;
- +}
- +
- +void __init smp_prepare_boot_cpu(void)
- +{
- + unsigned int cpu = smp_processor_id();
- + unsigned long *ptr = (unsigned long *)(0xc0006000 + (cpu << 9));
- + ptr[4] = 1;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/stacktrace.c linux-3.4.110/arch/nds32/kernel/stacktrace.c
- --- linux-3.4.110.orig/arch/nds32/kernel/stacktrace.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/stacktrace.c 2016-04-07 10:20:50.946081179 +0200
- @@ -0,0 +1,41 @@
- +#include <linux/sched.h>
- +#include <linux/stacktrace.h>
- +void save_stack_trace(struct stack_trace *trace)
- +{
- + save_stack_trace_tsk(current, trace);
- +}
- +
- +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
- +{
- + unsigned long *fpn;
- + int skip = trace->skip;
- + int savesched;
- +
- + if (tsk == current) {
- + __asm__ __volatile__("\tori\t%0, $fp, #0\n":"=r"(fpn));
- + savesched = 1;
- + } else {
- + fpn = (unsigned long *)thread_saved_fp(tsk);
- + savesched = 0;
- + }
- +
- + while (!kstack_end(fpn) && !((unsigned long)fpn & 0x3)
- + && (fpn >= (unsigned long *)TASK_SIZE)) {
- + unsigned long lpp, fpp;
- + lpp = fpn[0];
- + fpp = fpn[-1];
- + if (!__kernel_text_address(lpp))
- + break;
- +
- + if (savesched || !in_sched_functions(lpp)) {
- + if (skip) {
- + skip--;
- + } else {
- + trace->entries[trace->nr_entries++] = lpp;
- + if (trace->nr_entries >= trace->max_entries)
- + break;
- + }
- + }
- + fpn = (unsigned long *)fpp;
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/sys_nds32.c linux-3.4.110/arch/nds32/kernel/sys_nds32.c
- --- linux-3.4.110.orig/arch/nds32/kernel/sys_nds32.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/sys_nds32.c 2016-04-07 10:20:50.946081179 +0200
- @@ -0,0 +1,331 @@
- +/*
- + * linux/arch/nds32/kernel/sys_nds32.c
- + *
- + * Copyright (C) People who wrote linux/arch/i386/kernel/sys_i386.c
- + * Copyright (C) 2007 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * This file contains various random system calls that
- + * have a non-standard calling sequence on the Linux/nds32
- + * platform.
- + */
- +#include <linux/module.h>
- +#include <linux/errno.h>
- +#include <linux/sched.h>
- +#include <linux/slab.h>
- +#include <linux/mm.h>
- +#include <linux/sem.h>
- +#include <linux/msg.h>
- +#include <linux/shm.h>
- +#include <linux/stat.h>
- +#include <linux/syscalls.h>
- +#include <linux/mman.h>
- +#include <linux/fs.h>
- +#include <linux/file.h>
- +#include <linux/utsname.h>
- +#include <linux/ipc.h>
- +
- +#include <asm/uaccess.h>
- +#include <asm/unistd.h>
- +#include <asm/pfm.h>
- +
- +extern unsigned long do_mremap(unsigned long addr, unsigned long old_len,
- + unsigned long new_len, unsigned long flags,
- + unsigned long new_addr);
- +
- +struct mmap_arg_struct {
- + unsigned long addr;
- + unsigned long len;
- + unsigned long prot;
- + unsigned long flags;
- + unsigned long fd;
- + unsigned long offset;
- +};
- +
- +asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
- + unsigned long prot, unsigned long flags,
- + unsigned long fd, unsigned long pgoff)
- +{
- + if (pgoff & (~PAGE_MASK >> 12))
- + return -EINVAL;
- +
- + return sys_mmap_pgoff(addr, len, prot, flags, fd,
- + pgoff >> (PAGE_SHIFT - 12));
- +}
- +
- +asmlinkage unsigned long
- +sys_nds32_mremap(unsigned long addr, unsigned long old_len,
- + unsigned long new_len, unsigned long flags,
- + unsigned long new_addr)
- +{
- + unsigned long ret = -EINVAL;
- +
- + if (flags & MREMAP_FIXED && new_addr < FIRST_USER_ADDRESS)
- + goto out;
- +
- + down_write(¤t->mm->mmap_sem);
- + ret = do_mremap(addr, old_len, new_len, flags, new_addr);
- + up_write(¤t->mm->mmap_sem);
- +
- +out:
- + return ret;
- +}
- +
- +/*
- + * Perform the select(nd, in, out, ex, tv) and mmap() system
- + * calls.
- + */
- +
- +struct sel_arg_struct {
- + unsigned long n;
- + fd_set __user *inp, *outp, *exp;
- + struct timeval __user *tvp;
- +};
- +
- +asmlinkage int old_select(struct sel_arg_struct __user * arg)
- +{
- + struct sel_arg_struct a;
- +
- + if (copy_from_user(&a, arg, sizeof(a)))
- + return -EFAULT;
- + /* sys_select() does the appropriate kernel locking */
- + return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
- +}
- +
- +/*
- + * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- + *
- + * This is really horribly ugly.
- + */
- +asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second,
- + unsigned long third, void __user * ptr, long fifth)
- +{
- + int version, ret;
- +
- + version = call >> 16; /* hack for backward compatibility */
- + call &= 0xffff;
- +
- + switch (call) {
- + case SEMOP:
- + return sys_semtimedop(first, (struct sembuf __user *)ptr,
- + second, NULL);
- + case SEMTIMEDOP:
- + return sys_semtimedop(first, (struct sembuf __user *)ptr,
- + second,
- + (const struct timespec __user *)fifth);
- +
- + case SEMGET:
- + return sys_semget(first, second, third);
- + case SEMCTL:{
- + union semun fourth;
- + if (!ptr)
- + return -EINVAL;
- + if (get_user(fourth.__pad, (void __user * __user *)ptr))
- + return -EFAULT;
- + return sys_semctl(first, second, third, fourth);
- + }
- +
- + case MSGSND:
- + return sys_msgsnd(first, (struct msgbuf __user *)ptr,
- + second, third);
- + case MSGRCV:
- + switch (version) {
- + case 0:{
- + struct ipc_kludge tmp;
- + if (!ptr)
- + return -EINVAL;
- + if (copy_from_user
- + (&tmp, (struct ipc_kludge __user *)ptr,
- + sizeof(tmp)))
- + return -EFAULT;
- + return sys_msgrcv(first, tmp.msgp, second,
- + tmp.msgtyp, third);
- + }
- + default:
- + return sys_msgrcv(first,
- + (struct msgbuf __user *)ptr,
- + second, fifth, third);
- + }
- + case MSGGET:
- + return sys_msgget((key_t) first, second);
- + case MSGCTL:
- + return sys_msgctl(first, second, (struct msqid_ds __user *)ptr);
- +
- + case SHMAT:
- + switch (version) {
- + default:{
- + ulong raddr;
- + ret =
- + do_shmat(first, (char __user *)ptr, second,
- + &raddr);
- + if (ret)
- + return ret;
- + return put_user(raddr, (ulong __user *) third);
- + }
- + case 1: /* Of course, we don't support iBCS2! */
- + return -EINVAL;
- + }
- + case SHMDT:
- + return sys_shmdt((char __user *)ptr);
- + case SHMGET:
- + return sys_shmget(first, second, third);
- + case SHMCTL:
- + return sys_shmctl(first, second, (struct shmid_ds __user *)ptr);
- + default:
- + return -ENOSYS;
- + }
- +}
- +
- +/* Fork a new task - this creates a new program thread.
- + * This is called indirectly via a small wrapper
- + */
- +asmlinkage int sys_fork(struct pt_regs *regs)
- +{
- + return do_fork(SIGCHLD, regs->NDS32_sp, regs, 0, NULL, NULL);
- +}
- +
- +/* Clone a task - this clones the calling program thread.
- + * This is called indirectly via a small wrapper
- + */
- +asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
- + int __user * parent_tidptr, int tls_val,
- + int __user * child_tidptr, struct pt_regs *regs)
- +{
- + if (!newsp)
- + newsp = regs->NDS32_sp;
- +
- + return do_fork(clone_flags, newsp, regs, 0, parent_tidptr,
- + child_tidptr);
- +}
- +
- +asmlinkage int sys_vfork(struct pt_regs *regs)
- +{
- + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->NDS32_sp, regs,
- + 0, NULL, NULL);
- +}
- +
- +/* sys_execve() executes a new program.
- + * This is called indirectly via a small wrapper
- + */
- +asmlinkage int sys_execve(const char __user * filenamei,
- + const char __user * const __user * argv,
- + const char __user * const __user * envp,
- + struct pt_regs *regs)
- +{
- + int error;
- + char *filename;
- +
- + filename = getname(filenamei);
- + error = PTR_ERR(filename);
- + if (IS_ERR(filename))
- + goto out;
- +
- + error = do_execve(filename, argv, envp, regs);
- + putname(filename);
- +
- +out:
- + return error;
- +}
- +
- +asmlinkage unsigned long sys_getpagesize(void)
- +{
- + return PAGE_SIZE; /* Possibly older binaries want 8192 on sun4's? */
- +}
- +
- +int kernel_execve(const char *filename, const char *const argv[],
- + const char *const envp[])
- +{
- + struct pt_regs regs;
- + int ret;
- +
- + memset(®s, 0, sizeof(struct pt_regs));
- + ret = do_execve(filename, argv, envp, ®s);
- +
- + if (ret < 0) {
- + goto out;
- + }
- + /*
- + * Save argc to the register structure for userspace.
- + */
- + regs.NDS32_r0 = ret;
- +
- + /*
- + * We were successful. We won't be returning to our caller, but
- + * instead to user space by manipulating the kernel stack.
- + */
- + asm("addi $r0, %0, %1\n\t"
- + "move $r1, %2\n\t"
- + "move $r2, %3\n\t"
- + "bal memmove\n\t" /* copy regs to top of stack */
- + "move $r8, #0\n\t" /* not a syscall */
- + "move $r9, %0\n\t" /* thread structure */
- + "move $sp, $r0\n\t" /* reposition stack pointer */
- +"b resume_userspace":
- +: "r"(current_thread_info()),
- + "ir"(THREAD_SIZE - 8 - sizeof(regs)),
- + "r"(®s), "ir"(sizeof(regs))
- +#ifdef _GCC444
- +: "$r0", "$r1", "$r2", "$r4", "$r5", "$r8", "$r9", "$p0", "$p1",
- + "memory");
- +#else
- +: "$r0", "$r1", "$r2", "$r4", "$r5", "$r8", "$r9", "$r26", "$r27",
- + "memory");
- +#endif
- +out:
- + return ret;
- +}
- +
- +EXPORT_SYMBOL(kernel_execve);
- +
- +int sys_cacheflush(unsigned int start, unsigned int end)
- +{
- + struct vm_area_struct *vma;
- +
- + vma = find_vma(current->mm, start);
- + if (!vma)
- + return 0;
- + cpu_cache_wbinval_range_check(vma, start, end);
- + return 0;
- +}
- +
- +asmlinkage long sys_fadvise64_64_wrapper(int fd, int advice, loff_t offset,
- + loff_t len)
- +{
- + return sys_fadvise64_64(fd, offset, len, advice);
- +}
- +
- +asmlinkage int nds32_syscall(int number, struct pt_regs *regs)
- +{
- + switch (number) {
- + case 0x7000: /* cacheflush */
- + return sys_cacheflush(regs->NDS32_r1, regs->NDS32_r2);
- +
- +#ifdef CONFIG_OPROFILE
- + case __NR_pfmctl:
- + sys_pfmctl(regs->NDS32_r1, regs->NDS32_r2, regs->NDS32_r3,
- + regs->NDS32_r4);
- + return 0;
- +
- + case __NR_getpfm:
- + return sys_getpfm((struct pcounter __user *)regs->NDS32_r1);
- +
- + case __NR_setpfm:
- + return sys_setpfm(regs->NDS32_r1, regs->NDS32_r2,
- + regs->NDS32_r3,
- + (struct pcounter __user *)regs->NDS32_r4);
- +#endif
- + case __NR_wbna:
- + if (regs->NDS32_r1)
- + regs->NDS32_ipsw |= PSW_mskWBNA;
- + else
- + regs->NDS32_ipsw &= ~PSW_mskWBNA;
- + return 0;
- +
- + default:
- + return -ENOSYS;
- + }
- + return -ENOSYS;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/time.c linux-3.4.110/arch/nds32/kernel/time.c
- --- linux-3.4.110.orig/arch/nds32/kernel/time.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/time.c 2016-04-07 10:20:50.950081334 +0200
- @@ -0,0 +1,94 @@
- +/*
- + * linux/arch/nds32/kernel/time.c
- + *
- + * Copyright (C) 1991, 1992, 1995 Linus Torvalds
- + * Modifications for ARM (C) 1994-2001 Russell King
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * This file contains the ARM-specific time handling details:
- + * reading the RTC at bootup, etc...
- + *
- + * 1994-07-02 Alan Modra
- + * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
- + * 1998-12-20 Updated NTP code according to technical memorandum Jan '96
- + * "A Kernel Model for Precision Timekeeping" by Dave Mills
- + */
- +#include <linux/sched.h>
- +#include <linux/profile.h>
- +#include <linux/timer.h>
- +#include <asm/irq_regs.h>
- +#include <linux/syscore_ops.h>
- +
- +#include <asm/mach/arch.h>
- +#include <asm/mach/time.h>
- +
- +/*
- + * Our system timer.
- + */
- +struct sys_timer *system_timer;
- +
- +#ifdef CONFIG_SMP
- +unsigned long profile_pc(struct pt_regs *regs)
- +{
- + unsigned long fp, pc = instruction_pointer(regs);
- +
- + if (in_lock_functions(pc)) {
- + fp = regs->NDS32_fp;
- + pc = ((unsigned long *)fp)[-1];
- + }
- +
- + return pc;
- +}
- +
- +EXPORT_SYMBOL(profile_pc);
- +#endif
- +#if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS)
- +static int timer_suspend(void)
- +{
- + if (system_timer->suspend)
- + system_timer->suspend();
- +
- + return 0;
- +}
- +
- +static void timer_resume(void)
- +{
- + if (system_timer->resume)
- + system_timer->resume();
- +}
- +#else
- +#define timer_suspend NULL
- +#define timer_resume NULL
- +#endif
- +#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
- +u32 arch_gettimeoffset(void)
- +{
- + if (system_timer->offset != NULL)
- + return system_timer->offset() * 1000;
- +
- + return 0;
- +}
- +#endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */
- +static struct syscore_ops timer_syscore_ops = {
- + .suspend = timer_suspend,
- + .resume = timer_resume,
- +};
- +
- +static int __init timer_init_syscore_ops(void)
- +{
- + register_syscore_ops(&timer_syscore_ops);
- +
- + return 0;
- +}
- +
- +device_initcall(timer_init_syscore_ops);
- +
- +void __init time_init(void)
- +{
- + system_timer = machine_desc->timer;
- + system_timer->init(); // link to cpe_timer_init
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/traps.c linux-3.4.110/arch/nds32/kernel/traps.c
- --- linux-3.4.110.orig/arch/nds32/kernel/traps.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/traps.c 2016-04-07 10:20:50.950081334 +0200
- @@ -0,0 +1,733 @@
- +/*
- + * linux/arch/nds32/kernel/traps.c
- + *
- + * Copyright (C) 1995-2002 Russell King
- + * Fragments that appear the same as linux/arch/i386/kernel/traps.c (C) Linus Torvalds
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * 'traps.c' handles hardware exceptions after we have saved some state in
- + * 'linux/arch/nds32/lib/traps.S'. Mostly a debugging aid, but will probably
- + * kill the offending process.
- + */
- +/* ============================================================================
- + *
- + * linux/arch/nds32/kernel/traps.c
- + *
- + * Copyright (C) 2007 Andes Technology Corporation
- + * This file is part of Linux and should be licensed under the GPL.
- + * See the file COPYING for conditions for redistribution.
- + *
- + * Abstract:
- + *
- + * This program is trap handling for NDS32 core, initial refer from ARM.
- + *
- + * Revision History:
- + *
- + * Jul.16.2007 Initial ported by Tom, revised for KGDB by Harry.
- + *
- + * Note:
- + *
- + * ============================================================================
- + */
- +#include <linux/module.h>
- +#include <linux/personality.h>
- +#include <linux/kallsyms.h>
- +#include <linux/hardirq.h>
- +#include <linux/kdebug.h>
- +
- +#include <asm/cacheflush.h>
- +#include <asm/uaccess.h>
- +#include <asm/unistd.h>
- +#include <asm/traps.h>
- +#include <asm/fpu.h>
- +#include <asm/audio.h>
- +
- +#include <linux/ptrace.h>
- +#include <nds32_intrinsic.h>
- +#include "ptrace.h"
- +#include "signal.h"
- +
- +extern void show_pte(struct mm_struct *mm, unsigned long addr);
- +
- +#ifdef CONFIG_DEBUG_USER
- +unsigned int user_debug;
- +
- +static int __init user_debug_setup(char *str)
- +{
- + get_option(&str, &user_debug);
- + return 1;
- +}
- +
- +__setup("user_debug=", user_debug_setup);
- +#endif
- +
- +/*
- + * Dump out the contents of some memory nicely...
- + */
- +void dump_mem(const char *str, unsigned long bottom, unsigned long top)
- +{
- + unsigned long p = bottom & ~31;
- + mm_segment_t fs;
- + int i;
- +
- + /*
- + * We need to switch to kernel mode so that we can use __get_user
- + * to safely read from kernel space. Note that we now dump the
- + * code first, just in case the backtrace kills us.
- + */
- + fs = get_fs();
- + set_fs(KERNEL_DS);
- +
- + printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
- +
- + for (p = bottom & ~31; p < top;) {
- + printk("%04lx: ", p & 0xffff);
- +
- + for (i = 0; i < 8; i++, p += 4) {
- + unsigned int val;
- +
- + if (p < bottom || p >= top)
- + printk(" ");
- + else {
- + __get_user(val, (unsigned long *)p);
- + printk("%08x ", val);
- + }
- + }
- + printk("\n");
- + }
- +
- + set_fs(fs);
- +}
- +
- +EXPORT_SYMBOL(dump_mem);
- +
- +/* These intrinsic functions are not supported in V2 toolchains of BSP321. */
- +#ifndef __NDS32_BASELINE_V2__
- +#define DEBUG_TLB_CACHE
- +#endif
- +#ifdef DEBUG_TLB_CACHE
- +/* This is the number of TLB entries. User should change it if necessary. */
- +#define TLB_NUM 128
- +unsigned int tlb_misc_new[TLB_NUM], tlb_vpn_new[TLB_NUM], tlb_data_new[TLB_NUM];
- +/* To get the whole TLB contents once it uses va=0x0 */
- +void dump_tlb(unsigned long va)
- +{
- + unsigned int rd_num, tlb_vpn, tlb_misc, tlb_data, mmu_cfg, tlb_num;
- +
- + /* save tlb system registers */
- + tlb_vpn = __nds32__mfsr(NDS32_SR_TLB_VPN);
- + tlb_misc = __nds32__mfsr(NDS32_SR_TLB_MISC);
- + tlb_data = __nds32__mfsr(NDS32_SR_TLB_DATA);
- + mmu_cfg = __nds32__mfsr(NDS32_SR_MMU_CFG);
- + tlb_num =
- + (((mmu_cfg & MMU_CFG_mskTBW) >> MMU_CFG_offTBW) +
- + 1) * (1 << (((mmu_cfg & MMU_CFG_mskTBS) >> MMU_CFG_offTBS) + 2));
- +
- + for (rd_num = 0; rd_num < tlb_num; rd_num++) {
- + /* read tlb entry with index */
- + __nds32__tlbop_trd(rd_num);
- + __nds32__dsb();
- + tlb_vpn_new[rd_num] = __nds32__mfsr(NDS32_SR_TLB_VPN);
- + tlb_misc_new[rd_num] = __nds32__mfsr(NDS32_SR_TLB_MISC);
- + tlb_data_new[rd_num] = __nds32__mfsr(NDS32_SR_TLB_DATA);
- + }
- +
- + /* restore tlb system registers */
- + __nds32__mtsr(tlb_vpn, NDS32_SR_TLB_VPN);
- + __nds32__mtsr(tlb_misc, NDS32_SR_TLB_MISC);
- + __nds32__dsb();
- +
- + printk("cur VPN:%08x, MISC:%08x, DATA:%08x\n", tlb_vpn, tlb_misc,
- + tlb_data);
- + /* to read out all the data */
- + for (rd_num = 0; rd_num < tlb_num; rd_num++) {
- + /*unsigned int vpn = tlb_vpn_new[rd_num] & PAGE_MASK; */
- + if (tlb_data_new[rd_num] & 0x1)
- + if (va == 0x0
- + || (va != 0x0
- + && (tlb_vpn_new[rd_num] == (va & PAGE_MASK))))
- + printk
- + ("idx:0x%08x, VPN:%08x, MISC:%08x, DATA:%08x\n",
- + rd_num, tlb_vpn_new[rd_num],
- + tlb_misc_new[rd_num],
- + tlb_data_new[rd_num]);
- + }
- +}
- +
- +EXPORT_SYMBOL(dump_tlb);
- +
- +struct cache_element {
- + unsigned int pa;
- + unsigned int wd;
- + unsigned int cacheline[8];
- + unsigned char dirty;
- + unsigned char valid;
- + unsigned char lock;
- +};
- +
- +/* This is the number of cache entries. User should change it if necessary. */
- +#define CACHE_SET_NUM 0x100
- +#define CACHE_WAY_NUM 0x4
- +volatile struct cache_element ce[CACHE_SET_NUM][CACHE_WAY_NUM];
- +#define CCTL_mskDIRTY 0x400000
- +#define CCTL_offDIRTY 22
- +#define CCTL_mskVALID 0x2
- +#define CCTL_offVALID 1
- +#define CCTL_mskLOCK 0x1
- +#define CCTL_offLOCK 0
- +#define CCTL_mskTAG 0x3ffffc
- +#define CCTL_offTAG 0x2
- +extern unsigned long va2idx(unsigned long va, unsigned int cache_type,
- + unsigned long *way_offset);
- +#include <asm/cache_info.h>
- +extern struct cache_info L1_cache_info[2];
- +void dump_cache(unsigned int cache_type)
- +{
- + volatile unsigned long idx, way, ra, tag, i;
- + unsigned long sets, ways, line_size, set_bits, way_bits, line_bits,
- + way_offset;
- +
- + ways = L1_cache_info[DCACHE].ways;
- + sets = L1_cache_info[DCACHE].sets;
- + set_bits = L1_cache_info[cache_type].set_bits;
- + way_bits = L1_cache_info[cache_type].way_bits;
- + line_bits = L1_cache_info[cache_type].line_bits;
- + line_size = L1_cache_info[cache_type].line_size;
- + way_offset = set_bits + line_bits;
- +
- + if (cache_type != ICACHE && cache_type != DCACHE) {
- + printk("%s not supported cache_type:%x\n", __func__,
- + cache_type);
- + return;
- + }
- +
- + /* NDS32_CCTL_L1I_IX_RTAG Read tag L1I cache */
- + /* NDS32_CCTL_L1I_IX_RWD Read word data L1I cache */
- +
- + for (idx = 0; idx < sets; idx++) {
- + for (way = 0; way < ways; way++) {
- + ra = (way << way_offset) | (idx << line_bits);
- + if (cache_type == ICACHE)
- + tag =
- + __nds32__cctlidx_read
- + (NDS32_CCTL_L1I_IX_RTAG, ra);
- + else
- + tag =
- + __nds32__cctlidx_read
- + (NDS32_CCTL_L1D_IX_RTAG, ra);
- + ce[idx][way].dirty =
- + (unsigned char)(tag & CCTL_mskDIRTY) >>
- + CCTL_offDIRTY;
- + ce[idx][way].valid =
- + (unsigned char)(tag & CCTL_mskVALID) >>
- + CCTL_offVALID;
- + ce[idx][way].lock =
- + (unsigned char)(tag & CCTL_mskLOCK) >> CCTL_offLOCK;
- + ce[idx][way].pa =
- + (tag & CCTL_mskTAG) >> CCTL_offTAG << PAGE_SHIFT;
- + for (i = 0; i < line_size / 4; i++) {
- + if (cache_type == ICACHE)
- + ce[idx][way].cacheline[i] =
- + __nds32__cctlidx_read
- + (NDS32_CCTL_L1I_IX_RWD,
- + (ra | i << 2));
- + else
- + ce[idx][way].cacheline[i] =
- + __nds32__cctlidx_read
- + (NDS32_CCTL_L1D_IX_RWD,
- + (ra | i << 2));
- + }
- + }
- + }
- + printk("dump %s\n", cache_type ? "DCACHE" : "ICACHE");
- + printk("%8s %4s %4s %1s %1s %1s %8s %8s %8s %8s %8s %8s %8s %8s\n",
- + "ADDRESS", "SET", "WAY", "V", "D", "L", "00", "04", "08", "0C",
- + "10", "14", "18", "1C");
- + for (idx = 0; idx < sets; idx++) {
- + for (way = 0; way < ways; way++) {
- + printk("%08lx %04lx %04lx %1u %1u %1u ",
- + ce[idx][way].pa +
- + ((idx * line_size) % PAGE_SIZE), idx, way,
- + ce[idx][way].valid, ce[idx][way].dirty,
- + ce[idx][way].lock);
- + for (i = 0; i < line_size / 4; i++) {
- + printk("%08x ", ce[idx][way].cacheline[i]);
- + }
- + printk("\n");
- + }
- + }
- +}
- +
- +EXPORT_SYMBOL(dump_cache);
- +
- +void dump_cache_va(unsigned int cache_type, unsigned int va)
- +{
- + volatile struct cache_element cache_entry[4];
- + volatile unsigned long idx, way, tag, ra, i;
- + unsigned long ways, line_size, set_bits, line_bits, way_offset;
- +
- + ways = L1_cache_info[cache_type].ways;
- + line_size = CACHE_LINE_SIZE(cache_type);
- + set_bits = L1_cache_info[cache_type].set_bits;
- + line_bits = L1_cache_info[cache_type].line_bits;
- +
- + if (cache_type != ICACHE && cache_type != DCACHE) {
- + printk("%s not supported cache_type:%x\n", __func__,
- + cache_type);
- + return;
- + }
- + idx = va2idx(va, cache_type, &way_offset);
- + //idx = (va & (((1 << set_bits) - 1) << line_bits)) >> line_bits;
- + for (way = 0; way < ways; way++) {
- + ra = (way << way_offset) | idx;
- + if (cache_type == ICACHE)
- + tag = __nds32__cctlidx_read(NDS32_CCTL_L1I_IX_RTAG, ra);
- + else
- + tag = __nds32__cctlidx_read(NDS32_CCTL_L1D_IX_RTAG, ra);
- + cache_entry[way].dirty =
- + (unsigned char)(tag & CCTL_mskDIRTY) >> CCTL_offDIRTY;
- + cache_entry[way].valid =
- + (unsigned char)(tag & CCTL_mskVALID) >> CCTL_offVALID;
- + cache_entry[way].lock =
- + (unsigned char)(tag & CCTL_mskLOCK) >> CCTL_offLOCK;
- + cache_entry[way].pa =
- + (tag & CCTL_mskTAG) >> CCTL_offTAG << PAGE_SHIFT;
- + for (i = 0; i < line_size / 4; i++) {
- + if (cache_type == ICACHE)
- + cache_entry[way].cacheline[i] =
- + __nds32__cctlidx_read(NDS32_CCTL_L1I_IX_RWD,
- + (ra | i << 2));
- + else
- + cache_entry[way].cacheline[i] =
- + __nds32__cctlidx_read(NDS32_CCTL_L1D_IX_RWD,
- + (ra | i << 2));
- + }
- + }
- + printk("dump %s va:%x\n", cache_type ? "DCACHE" : "ICACHE", va);
- +
- + printk("%8s %4s %4s %1s %1s %1s %8s %8s %8s %8s %8s %8s %8s %8s\n",
- + "ADDRESS", "SET", "WAY", "V", "D", "L", "00", "04", "08", "0C",
- + "10", "14", "18", "1C");
- + for (way = 0; way < ways; way++) {
- + printk("%08lx %04lx %04lx %1u %1u %1u ",
- + cache_entry[way].pa +
- + (((idx >> line_bits) * line_size) % PAGE_SIZE),
- + (idx >> line_bits), way, cache_entry[way].valid,
- + cache_entry[way].dirty, cache_entry[way].lock);
- + for (i = 0; i < 8; i++) {
- + printk("%08x ", cache_entry[way].cacheline[i]);
- + }
- + printk("\n");
- + }
- +}
- +
- +EXPORT_SYMBOL(dump_cache_va);
- +#endif
- +
- +static void dump_instr(struct pt_regs *regs)
- +{
- + unsigned long addr = instruction_pointer(regs);
- + const int width = 8;
- + mm_segment_t fs;
- + int i;
- +
- + return;
- + /*
- + * We need to switch to kernel mode so that we can use __get_user
- + * to safely read from kernel space. Note that we now dump the
- + * code first, just in case the backtrace kills us.
- + */
- + fs = get_fs();
- + set_fs(KERNEL_DS);
- +
- + printk("Code: ");
- + for (i = -4; i < 1; i++) {
- + unsigned int val, bad;
- +
- + bad = __get_user(val, &((u32 *) addr)[i]);
- +
- + if (!bad)
- + printk(i == 0 ? "(%0*x) " : "%0*x ", width, val);
- + else {
- + printk("bad PC value.");
- + break;
- + }
- + }
- + printk("\n");
- +
- + set_fs(fs);
- +}
- +
- +#define LOOP_TIMES (100)
- +void dump_stack(void)
- +{
- + int cnt = LOOP_TIMES;
- +#ifndef CONFIG_FRAME_POINTER
- + unsigned long *stack;
- + unsigned long addr;
- +
- + __asm__ __volatile__("\tori\t%0, $sp, #0\n":"=r"(stack));
- + printk("Call Trace:\n");
- + while (!kstack_end(stack)) {
- + addr = *stack++;
- + if (__kernel_text_address(addr)) {
- + printk("[<%08lx>] ", addr);
- + print_symbol("%s\n", addr);
- + }
- + cnt--;
- + if (cnt < 0)
- + break;
- + }
- + printk("\n");
- +#else
- + unsigned long *fpn;
- + __asm__ __volatile__("\tori\t%0, $fp, #0\n":"=r"(fpn));
- + printk("Call Trace:\n");
- + while (!kstack_end((void *)fpn) && !((unsigned long)fpn & 0x3)
- + && ((unsigned long)fpn >= TASK_SIZE)) {
- + unsigned long lpp, fpp;
- +#if !defined(NDS32_ABI_2)
- + lpp = fpn[0];
- + fpp = fpn[1];
- +#else
- + lpp = fpn[0];
- + fpp = fpn[-1];
- +#endif
- + if (__kernel_text_address(lpp)) {
- + printk("[<%08lx>] ", lpp);
- + print_symbol("%s\n", lpp);
- + fpn = (unsigned long *)fpp;
- + }
- + cnt--;
- + if (cnt < 0)
- + break;
- + }
- + printk("\n");
- +#endif
- +}
- +
- +EXPORT_SYMBOL(dump_stack);
- +
- +void show_stack(struct task_struct *tsk, unsigned long *sp)
- +{
- + unsigned long fp;
- +
- + if (!tsk)
- + tsk = current;
- +
- + if (tsk != current)
- + fp = thread_saved_fp(tsk);
- + else
- + asm("move %0, $fp":"=r"(fp));
- +
- + dump_stack();
- + barrier();
- +}
- +
- +DEFINE_SPINLOCK(die_lock);
- +
- +/*
- + * This function is protected against re-entrancy.
- + */
- +void die(const char *str, struct pt_regs *regs, int err)
- +{
- + struct task_struct *tsk = current;
- + static int die_counter;
- +
- + console_verbose();
- + spin_lock_irq(&die_lock);
- + bust_spinlocks(1);
- +
- + printk("Internal error: %s: %x [#%d]\n", str, err, ++die_counter);
- + print_modules();
- + printk("CPU: %i\n", smp_processor_id());
- + show_regs(regs);
- + printk("Process %s (pid: %d, stack limit = 0x%p)\n",
- + tsk->comm, tsk->pid, task_thread_info(tsk) + 1);
- +
- + if (!user_mode(regs) || in_interrupt()) {
- + dump_mem("Stack: ", regs->NDS32_sp,
- + 8192 + (unsigned long)task_thread_info(tsk));
- + dump_instr(regs);
- + dump_stack();
- + }
- +
- + bust_spinlocks(0);
- + spin_unlock_irq(&die_lock);
- + do_exit(SIGSEGV);
- +}
- +
- +void die_if_kernel(const char *str, struct pt_regs *regs, int err)
- +{
- + if (user_mode(regs))
- + return;
- +
- + die(str, regs, err);
- +}
- +
- +int bad_syscall(int n, struct pt_regs *regs)
- +{
- + struct thread_info *thread = current_thread_info();
- + siginfo_t info;
- +
- + if (current->personality != PER_LINUX && thread->exec_domain->handler) {
- + thread->exec_domain->handler(n, regs);
- + return regs->NDS32_r0;
- + }
- +#ifdef CONFIG_DEBUG_USER
- + if (user_debug & UDBG_SYSCALL) {
- + printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n",
- + current->pid, current->comm, n);
- + dump_instr(regs);
- + }
- +#endif
- +
- + info.si_signo = SIGILL;
- + info.si_errno = 0;
- + info.si_code = ILL_ILLTRP;
- + info.si_addr = (void __user *)instruction_pointer(regs) - 4;
- +
- + force_sig_info(SIGILL, &info, current);
- + die_if_kernel("Oops - bad syscall", regs, n);
- + return regs->NDS32_r0;
- +}
- +
- +void __pte_error(const char *file, int line, unsigned long val)
- +{
- + printk("%s:%d: bad pte %08lx.\n", file, line, val);
- +}
- +
- +void __pmd_error(const char *file, int line, unsigned long val)
- +{
- + printk("%s:%d: bad pmd %08lx.\n", file, line, val);
- +}
- +
- +void __pgd_error(const char *file, int line, unsigned long val)
- +{
- + printk("%s:%d: bad pgd %08lx.\n", file, line, val);
- +}
- +
- +extern char exception_vector[73][64];
- +void __init trap_init(void)
- +{
- + return;
- +}
- +
- +void __init early_trap_init(void)
- +{
- + unsigned long ivb = 0;
- + unsigned long base = 0xc0000000;
- +
- + memcpy((unsigned long *)base, (unsigned long *)exception_vector,
- + sizeof(exception_vector));
- + ivb = __nds32__mfsr(NDS32_SR_IVB);
- +#ifdef CONFIG_EVIC
- + __nds32__mtsr((ivb & ~IVB_mskESZ) | (2 << IVB_offESZ) |
- + (1 << IVB_offEVIC) | IVB_BASE, NDS32_SR_IVB);
- +#else
- + /* Check platform support. */
- +# if defined (CONFIG_IVIC_INTC)
- + if (((ivb & IVB_mskNIVIC) >> IVB_offNIVIC) >= 2)
- + panic
- + ("IVIC mode is not allowed on the platform with interrupt controller\n");
- +# elif defined(CONFIG_IVIC)
- + if (((ivb & IVB_mskNIVIC) >> IVB_offNIVIC) < 2)
- + panic
- + ("IVIC mode is not allowed on the platform without interrupt controller\n");
- +# endif
- + __nds32__mtsr((ivb & ~IVB_mskESZ) | (2 << IVB_offESZ) | IVB_BASE,
- + NDS32_SR_IVB);
- +#endif
- + __nds32__mtsr(0x10003, NDS32_SR_INT_MASK);
- + /*
- + * Copy signal return handlers into the vector page, and
- + * set sigreturn to be a pointer to these.
- + */
- + memcpy((void *)KERN_SIGRETURN_CODE, retcodes, sizeof(retcodes));
- + memcpy((void *)KERN_RESTART_CODE, syscall_restart_code,
- + sizeof(syscall_restart_code));
- +
- + /*
- + * 0x2000 is 8K-aligned of 0x1240 = 73 vectors * 64byte
- + * 0x1000 is page saving sigreturn & restart code
- + */
- + flush_icache_range(base, base + 0x3000);
- +}
- +
- +#if 0
- +COLE:use send_sigtrap instread
- + static __inline__ void do_trap(int trapnr, int signr, const char *str,
- + struct pt_regs *regs,
- + unsigned long error_code, siginfo_t * info)
- +{
- + if (user_mode(regs)) {
- + /* trap_signal */
- + struct task_struct *tsk = current;
- + tsk->thread.error_code = error_code;
- + tsk->thread.trap_no = trapnr;
- + if (info)
- + force_sig_info(signr, info, tsk);
- + else
- + force_sig(signr, tsk);
- + return;
- + } else {
- + /* kernel_trap */
- + if (!fixup_exception(regs))
- + die(str, regs, error_code);
- + return;
- + }
- +}
- +#endif
- +
- +/*
- + * I modified original debug_trap to apply KGDB stuff,
- + * Harry@Jul.18.2007
- + */
- +void do_debug_trap(unsigned long entry, unsigned long addr,
- + unsigned long type, struct pt_regs *regs)
- +{
- + if (notify_die(DIE_DEBUG, "debug", regs, addr, type, SIGTRAP)
- + == NOTIFY_STOP)
- + return;
- +
- +#if !defined(CONFIG_HSS)
- + /* clear the swbk; otherwise the user will see it */
- + if (test_tsk_thread_flag(current, TIF_SINGLESTEP))
- + ptrace_cancel_swbk(current);
- +#endif
- +
- + /* do_trap(1, SIGTRAP, 0, regs, 0, NULL); */
- + if (user_mode(regs)) {
- + /* trap_signal */
- + send_sigtrap(current, regs, 0, TRAP_BRKPT);
- + } else {
- + /* kernel_trap */
- + if (!fixup_exception(regs))
- + die("unexpected kernel_trap", regs, 0);
- + }
- +}
- +
- +void unhandled_interruption(struct pt_regs *regs)
- +{
- + siginfo_t si;
- + printk("unhandled_interruption\n");
- + show_regs(regs);
- + if (!user_mode(regs))
- + do_exit(SIGKILL);
- + si.si_signo = SIGKILL;
- + si.si_errno = 0;
- + force_sig_info(SIGKILL, &si, current);
- +}
- +
- +void unhandled_exceptions(unsigned long entry, unsigned long addr,
- + unsigned long type, struct pt_regs *regs)
- +{
- + siginfo_t si;
- + printk("Unhandled Exception: entry: %lx addr:%lx itype:%lx\n", entry,
- + addr, type);
- + show_regs(regs);
- + if (!user_mode(regs))
- + do_exit(SIGKILL);
- + si.si_signo = SIGKILL;
- + si.si_errno = 0;
- + si.si_addr = (void *)addr;
- + force_sig_info(SIGKILL, &si, current);
- +}
- +
- +extern int do_page_fault(unsigned long entry, unsigned long addr,
- + unsigned int error_code, struct pt_regs *regs);
- +
- +/*
- + * 2:DEF dispatch for TLB MISC exception handler
- +*/
- +
- +void do_dispatch_tlb_misc(unsigned long entry, unsigned long addr,
- + unsigned long type, struct pt_regs *regs)
- +{
- + type = type & (ITYPE_mskINST | ITYPE_mskETYPE);
- + if ((type & 0xf) < 5)
- + do_page_fault(entry, addr, type, regs);
- + else
- + unhandled_exceptions(entry, addr, type, regs);
- +}
- +
- +int (*do_unaligned_access) (unsigned long entry, unsigned long addr,
- + unsigned long type, struct pt_regs * regs) = NULL;
- +
- +EXPORT_SYMBOL(do_unaligned_access);
- +
- +void do_revinsn(struct pt_regs *regs)
- +{
- + siginfo_t si;
- + printk("Reserved Instruction\n");
- + show_regs(regs);
- + if (!user_mode(regs))
- + do_exit(SIGILL);
- + si.si_signo = SIGILL;
- + si.si_errno = 0;
- + force_sig_info(SIGILL, &si, current);
- +}
- +
- +/*
- + * 7:DEF dispatch for General exception handler
- + */
- +void do_dispatch_general(unsigned long entry, unsigned long addr,
- + unsigned long itype, struct pt_regs *regs,
- + unsigned long oipc)
- +{
- + unsigned int swid = itype >> ITYPE_offSWID;
- + unsigned long type = itype & (ITYPE_mskINST | ITYPE_mskETYPE);
- + if (type == 0) { /* Alignment check */
- +
- + if (do_unaligned_access) {
- +
- + int ret = do_unaligned_access(entry, addr, type, regs);
- +
- + if (ret == 0)
- + return;
- +
- + if (ret == -EFAULT)
- + printk
- + ("Unhandled unaligned access exception\n");
- + }
- + do_page_fault(entry, addr, type, regs);
- + } else if (type == 1) /* Reserved instruction */
- + do_revinsn(regs);
- + else if (type == 6) { /* Coprocessor */
- + if (((GET_ITYPE() & ITYPE_mskSTYPE) >> ITYPE_offSTYPE) == 3) {
- +#ifdef CONFIG_AUDIO
- + preempt_disable();
- + do_audio_context_switch(type, regs);
- + preempt_enable();
- +#else
- + unhandled_exceptions(entry, addr, type, regs);
- +#endif
- + } else {
- +#ifdef CONFIG_FPU
- + do_fpu_exception(type, regs);
- +#else
- + unhandled_exceptions(entry, addr, type, regs);
- +#endif
- + }
- + } else if (type == 2 && swid == 0x1a) {
- + /* trap, used on v3 EDM target debugging workaround */
- + /*
- + * DIPC(OIPC) is passed as parameter before
- + * interrupt is enabled, so the DIPC will not be corrupted
- + * even though interrupts are coming in
- + */
- + /*
- + * 1. update ipc
- + * 2. update pt_regs ipc with oipc
- + * 3. update pt_regs ipsw (clear DEX)
- + */
- + __asm__ volatile ("mtsr %0, $IPC\n\t"::"r" (oipc));
- + regs->NDS32_ipc = oipc;
- + regs->NDS32_ipsw &= ~0x400;
- + do_debug_trap(entry, addr, itype, regs);
- + } else
- + unhandled_exceptions(entry, addr, type, regs);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/kernel/vmlinux.lds.S linux-3.4.110/arch/nds32/kernel/vmlinux.lds.S
- --- linux-3.4.110.orig/arch/nds32/kernel/vmlinux.lds.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/kernel/vmlinux.lds.S 2016-04-07 10:20:50.950081334 +0200
- @@ -0,0 +1,74 @@
- +#include <asm/page.h>
- +#include <asm/thread_info.h>
- +#include <asm/cache.h>
- +#include <asm/memory.h>
- +
- +#define LOAD_OFFSET (PAGE_OFFSET - PHYS_OFFSET)
- +#include <asm-generic/vmlinux.lds.h>
- +
- +OUTPUT_ARCH(nds32)
- +ENTRY(_stext_lma)
- +jiffies = jiffies_64;
- +
- +SECTIONS
- +{
- + _stext_lma = TEXTADDR - LOAD_OFFSET;
- + . = TEXTADDR;
- + __init_begin = .;
- + HEAD_TEXT_SECTION
- + INIT_TEXT_SECTION(PAGE_SIZE)
- + /* These sections are arch specific. */
- + .arch_info : AT(ADDR(.arch_info) - LOAD_OFFSET) {
- + . = ALIGN(4);
- + VMLINUX_SYMBOL(__proc_info_begin) = .;
- + *(.proc.info.init)
- + VMLINUX_SYMBOL(__proc_info_end) = .;
- + __arch_info_begin = .;
- + *(.arch.info)
- + __arch_info_end = .;
- + __tagtable_begin = .;
- + *(.taglist)
- + __tagtable_end = .;
- + . = ALIGN(16);
- + __pv_table_begin = .;
- + *(.pv_table)
- + __pv_table_end = .;
- + __early_begin = .;
- + *(__early_param)
- + __early_end = .;
- + }
- +
- + INIT_DATA_SECTION(16)
- + PERCPU_SECTION(L1_CACHE_BYTES)
- + __init_end = .;
- +
- + . = ALIGN(PAGE_SIZE);
- + _stext = .;
- + /* Real text segment */
- + .text : AT(ADDR(.text) - LOAD_OFFSET) {
- + _text = .; /* Text and read-only data */
- + TEXT_TEXT
- + SCHED_TEXT
- + LOCK_TEXT
- + KPROBES_TEXT
- + IRQENTRY_TEXT
- + *(.fixup)
- + }
- +
- + _etext = .; /* End of text and rodata section */
- +
- + _sdata = .;
- + RO_DATA_SECTION(PAGE_SIZE)
- + RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
- + _edata = .;
- +
- + EXCEPTION_TABLE(16)
- + NOTES
- + BSS_SECTION(4, 4, 4)
- + _end = .;
- +
- + STABS_DEBUG
- + DWARF_DEBUG
- +
- + DISCARDS
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/copy_page.S linux-3.4.110/arch/nds32/lib/copy_page.S
- --- linux-3.4.110.orig/arch/nds32/lib/copy_page.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/copy_page.S 2016-04-07 10:20:50.950081334 +0200
- @@ -0,0 +1,36 @@
- +/*
- + * linux/arch/nds32/lib/copypage.S
- + * Copyright (C) 2009 Andes Technology Corporation
- + */
- +#include <linux/linkage.h>
- +#include <asm/page.h>
- +
- + .text
- +ENTRY(copy_page)
- + pushm $r2, $r10
- + movi $r2, PAGE_SIZE >> 5
- +.Lcopy_loop:
- + lmw.bim $r3, [$r1], $r10
- + smw.bim $r3, [$r0], $r10
- + subi45 $r2, #1
- + bnez38 $r2, .Lcopy_loop
- + popm $r2, $r10
- + ret
- +
- +ENTRY(clear_page)
- + pushm $r1, $r9
- + movi $r1, PAGE_SIZE >> 5
- + movi55 $r2, #0
- + movi55 $r3, #0
- + movi55 $r4, #0
- + movi55 $r5, #0
- + movi55 $r6, #0
- + movi55 $r7, #0
- + movi55 $r8, #0
- + movi55 $r9, #0
- +.Lclear_loop:
- + smw.bim $r2, [$r0], $r9
- + subi45 $r1, #1
- + bnez38 $r1, .Lclear_loop
- + popm $r1, $r9
- + ret
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/csum_partial.c linux-3.4.110/arch/nds32/lib/csum_partial.c
- --- linux-3.4.110.orig/arch/nds32/lib/csum_partial.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/csum_partial.c 2016-04-07 10:20:50.950081334 +0200
- @@ -0,0 +1,135 @@
- +/*
- + * INET An implementation of the TCP/IP protocol suite for the LINUX
- + * operating system. INET is implemented using the BSD Socket
- + * interface as the means of communication with the user level.
- + *
- + * MIPS specific IP/TCP/UDP checksumming routines
- + *
- + * Authors: Ralf Baechle, <ralf@waldorf-gmbh.de>
- + * Lots of code moved from tcp.c and ip.c; see those files
- + * for more names.
- + *
- + * This program is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU General Public License
- + * as published by the Free Software Foundation; either version
- + * 2 of the License, or (at your option) any later version.
- + */
- +#include <linux/module.h>
- +#include <linux/types.h>
- +
- +#include <net/checksum.h>
- +#include <asm/byteorder.h>
- +#include <asm/string.h>
- +#include <asm/uaccess.h>
- +
- +#define addc(_t,_r) \
- + __asm__ __volatile__ ( \
- + "add\t%0, %0, %1\n\t" \
- + "slt\t$p1, %0, %1\n\t" \
- + "add\r%0, %0, $p1\n\t" \
- + : "=r"(_t) \
- + : "r"(_r), "0"(_t));
- +
- +static inline unsigned short from32to16(unsigned int x)
- +{
- + /* 32 bits --> 16 bits + carry */
- + x = (x & 0xffff) + (x >> 16);
- + /* 16 bits + carry --> 16 bits including carry */
- + x = (x & 0xffff) + (x >> 16);
- + return (unsigned short)x;
- +}
- +
- +static inline unsigned int do_csum(const unsigned char *buff, int len)
- +{
- + int odd;
- + register unsigned int result = 0;
- + register unsigned int count;
- + if (len <= 0)
- + goto out;
- + odd = 1 & (unsigned long)buff;
- + if (odd) {
- + result = be16_to_cpu(*buff);
- + len--;
- + buff++;
- + }
- + count = len >> 1; /* nr of 16-bit words.. */
- + if (count) {
- + if (2 & (unsigned long)buff) {
- + result += *(unsigned short *)buff;
- + count--;
- + len -= 2;
- + buff += 2;
- + }
- + count >>= 1; /* nr of 32-bit words.. */
- + if (count) {
- + while (count >= 8) {
- + __asm__
- + __volatile__("lmw.bi $r17, [%1], $r24\n\t"
- + "add\t%0, %0, $r17\n\t"
- + "slt\t$p1, %0, $r17\n\t"
- + "add\r%0, %0, $p1\n\t"
- + "add\t%0, %0, $r18\n\t"
- + "slt\t$p1, %0, $r18\n\t"
- + "add\r%0, %0, $p1\n\t"
- + "add\t%0, %0, $r19\n\t"
- + "slt\t$p1, %0, $r19\n\t"
- + "add\r%0, %0, $p1\n\t"
- + "add\t%0, %0, $r20\n\t"
- + "slt\t$p1, %0, $r20\n\t"
- + "add\r%0, %0, $p1\n\t"
- + "add\t%0, %0, $r21\n\t"
- + "slt\t$p1, %0, $r21\n\t"
- + "add\r%0, %0, $p1\n\t"
- + "add\t%0, %0, $r22\n\t"
- + "slt\t$p1, %0, $r22\n\t"
- + "add\r%0, %0, $p1\n\t"
- + "add\t%0, %0, $r23\n\t"
- + "slt\t$p1, %0, $r23\n\t"
- + "add\r%0, %0, $p1\n\t"
- + "add\t%0, %0, $r24\n\t"
- + "slt\t$p1, %0, $r24\n\t"
- + "add\r%0, %0, $p1\n\t":"=r"
- + (result)
- + :"r"(buff), "0"(result)
- + :"$r17", "$r18", "$r19",
- + "$r20", "$r21", "$r22", "$r23",
- + "$r24");
- + count -= 8;
- + buff += 32;
- + }
- + while (count) {
- + unsigned int w = *(unsigned int *)buff;
- + count--;
- + buff += 4;
- + addc(result, w);
- + }
- + result = (result & 0xffff) + (result >> 16);
- + }
- + if (len & 2) {
- + result += *(unsigned short *)buff;
- + buff += 2;
- + }
- + }
- + if (len & 1)
- + result += le16_to_cpu(*buff);
- + result = from32to16(result);
- + if (odd)
- + result = swab16(result);
- +out:
- + return result;
- +}
- +
- +/*
- + * computes a partial checksum, e.g. for TCP/UDP fragments
- + */
- +/*
- + * why bother folding?
- + */
- +unsigned int csum_partial(const void *buff, int len, unsigned int sum)
- +{
- + unsigned int result = 0;
- +// printk("csum_partial %x %x %x\n", buff, len, sum);
- + result = do_csum(buff, len);
- + addc(result, sum);
- + return (unsigned short)from32to16(result);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/csum_partial_copy.c linux-3.4.110/arch/nds32/lib/csum_partial_copy.c
- --- linux-3.4.110.orig/arch/nds32/lib/csum_partial_copy.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/csum_partial_copy.c 2016-04-07 10:20:50.950081334 +0200
- @@ -0,0 +1,58 @@
- +/*
- + * INET An implementation of the TCP/IP protocol suite for the LINUX
- + * operating system. INET is implemented using the BSD Socket
- + * interface as the means of communication with the user level.
- + *
- + * MIPS specific IP/TCP/UDP checksumming routines
- + *
- + * Authors: Ralf Baechle, <ralf@waldorf-gmbh.de>
- + * Lots of code moved from tcp.c and ip.c; see those files
- + * for more names.
- + *
- + * This program is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU General Public License
- + * as published by the Free Software Foundation; either version
- + * 2 of the License, or (at your option) any later version.
- + */
- +#include <linux/kernel.h>
- +#include <net/checksum.h>
- +#include <linux/types.h>
- +#include <asm/byteorder.h>
- +#include <asm/string.h>
- +#include <asm/uaccess.h>
- +
- +/*
- + * copy while checksumming, otherwise like csum_partial
- + */
- +unsigned int csum_partial_copy_nocheck(const unsigned char *src,
- + unsigned char *dst, int len,
- + unsigned int sum)
- +{
- + /*
- + * It's 2:30 am and I don't feel like doing it real ...
- + * This is lots slower than the real thing (tm)
- + */
- + sum = csum_partial(src, len, sum);
- + memcpy(dst, src, len);
- +
- + return sum;
- +}
- +
- +/*
- + * Copy from userspace and compute checksum. If we catch an exception
- + * then zero the rest of the buffer.
- + */
- +unsigned int csum_partial_copy_from_user(const unsigned char *src,
- + unsigned char *dst, int len,
- + unsigned int sum, int *err_ptr)
- +{
- + int missing;
- +
- + missing = copy_from_user(dst, src, len);
- + if (missing) {
- + memset(dst + len - missing, 0, missing);
- + *err_ptr = -EFAULT;
- + }
- +
- + return csum_partial(dst, len, sum);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/divmod.c linux-3.4.110/arch/nds32/lib/divmod.c
- --- linux-3.4.110.orig/arch/nds32/lib/divmod.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/divmod.c 2016-04-07 10:20:50.950081334 +0200
- @@ -0,0 +1,46 @@
- +extern unsigned long udivmodsi4(unsigned long num, unsigned long den,
- + int modwanted);
- +
- +long __divsi3(long a, long b)
- +{
- + int neg = 0;
- + long res;
- +
- + if (a < 0) {
- + a = -a;
- + neg = !neg;
- + }
- +
- + if (b < 0) {
- + b = -b;
- + neg = !neg;
- + }
- +
- + res = udivmodsi4(a, b, 0);
- +
- + if (neg)
- + res = -res;
- +
- + return res;
- +}
- +
- +long __modsi3(long a, long b)
- +{
- + int neg = 0;
- + long res;
- +
- + if (a < 0) {
- + a = -a;
- + neg = 1;
- + }
- +
- + if (b < 0)
- + b = -b;
- +
- + res = udivmodsi4(a, b, 1);
- +
- + if (neg)
- + res = -res;
- +
- + return res;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/findbit.S linux-3.4.110/arch/nds32/lib/findbit.S
- --- linux-3.4.110.orig/arch/nds32/lib/findbit.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/findbit.S 2016-04-07 10:20:50.950081334 +0200
- @@ -0,0 +1,108 @@
- +/*
- + * linux/arch/nds32/lib/findbit.S
- + *
- + * Copyright (C) 1995-2000 Russell King
- + * Copyright (C) 2006 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <linux/linkage.h>
- +
- + .text
- +
- +/*
- + * Purpose : Find a 'zero' bit
- + * Prototype: int find_first_zero_bit(void *addr, int maxbit);
- + */
- +ENTRY(_find_first_zero_bit)
- + move $r2, #0
- + move $p0, #0 ! Reset bit count
- +next_word:
- + move $r4, #4
- + lmw.bim $p1, [$r0], $p1
- + li $r3, #0xffffffff ! Inversion mask
- + xor $p1, $p1, $r3 ! Inverted the word
- + addi $p0, $p0, #32
- + beqz $p1, next_word
- + addi $p0, $p0, #-32
- +next_byte:
- + beqz $r4, next_word
- + andi $r3, $p1, #0xff ! Get the next byte
- + bnez $r3, found ! Found zero bit in this byte
- + addi $p0, $p0, #8 ! Update bit count
- + addi $r4, $r4, #-1
- + srli $p1, $p1, #8
- + bgt $r1, $p0, next_byte
- + addi $r0, $r1, #1 ! Return not found
- + ret
- +
- +/*
- + * Purpose : Find next 'zero' bit
- + * Prototype: int find_next_zero_bit(void *addr, int maxbit, int offset)
- + */
- +ENTRY(_find_next_zero_bit)
- + beqz $r2, _find_first_zero_bit ! If offset=0, goto find_first_zero_bit
- + srli $p0, $r2, #5 ! Get offset byte count
- + slli $p0, $p0, #2
- + add $r0, $r0, $p0 ! $r0 is the first word to load
- + lmw.bim $p1, [$r0], $p1
- + li $p0, #0xffffffff ! Inversion mask
- + xor $p1, $p1, $p0 ! Inverted the word
- + andi $r4, $r2, #31 ! Left bits in offset
- + srl $p1, $p1, $r4 ! Shift out the left bits
- + xor $p0, $p0, $p0
- + subri $r4, $r4, #31
- +loop:
- + andi $r3, $p1, #0xff ! The first byte to check
- + bnez $r3, found ! Found zero bit in this byte
- + addi $p0, $p0, #8
- + addi $r4, $r4, #-8
- + srli $p1, $p1, #8 ! Move on to the next byte
- + bgtz $r4, loop
- + b next_word
- +
- +/*
- + * One or more bits in the LSB of $p1 are assumed to be set.
- + */
- +
- +found:
- + move $p1, $r3
- + xor $r4, $r4, $r4
- + andi $r5, $p1, #0x0f ! Get bits 0-3
- + move $r3, #4 ! For 0 case (no set bit found)
- + cmovn $r3, $r4, $r5 ! Not 0 case (There's set bit in these 4 bits)
- + add $p0, $p0, $r3 ! Update bit count
- + slli $r3, $p1, #4 ! Not 0 case (Find set bit in these 4 bits)
- + cmovn $p1, $r3, $r5 ! For 0 case (Find set bit in the rest 4 bits)
- + andi $r5, $p1, #0x30 ! Get 4-5
- + move $r3, #2 ! For 0 case (no set bit found)
- + cmovn $r3, $r4, $r5 ! Not 0 case (There's set bit in these 2 bits)
- + add $p0, $p0, $r3 ! Update bit count
- + slli $r3, $p1, #2 ! Not 0 case (Find set bit in these 2 bits)
- + cmovn $p1, $r3, $r5 ! For 0 case (Find set bit in the rest 2 bits)
- + andi $r5, $p1, #0x40 ! Get bit 6
- + move $r3, #1 ! For 0 case (bit 6 is not set)
- + cmovn $r3, $r4, $r5 ! Not 0 case (bit 6 is set bit)
- + add $r5, $p0, $r3
- + add $r0, $r5, $r2
- + ret
- +
- +ENTRY(_ext2_find_first_zero_bit)
- + pushm $r2, $r4
- + move $r2, #0
- + move $p0, #0 ! Reset bit count
- +1:
- + lbi.bi $r3, [$r0], #1
- + xori $r3, $r3, #0xff
- + addi $p0, $p0, #8
- + beqz $r3, 1b
- + addi $p0, $p0, #-8
- +
- +2:
- + b found ! No return
- + popm $r2, $r4
- + ret
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/getuser.S linux-3.4.110/arch/nds32/lib/getuser.S
- --- linux-3.4.110.orig/arch/nds32/lib/getuser.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/getuser.S 2016-04-07 10:20:50.950081334 +0200
- @@ -0,0 +1,79 @@
- +/*
- + * linux/arch/nds32/lib/getuser.S
- + *
- + * Copyright (C) 2001 Russell King
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * Idea from x86 version, (C) Copyright 1998 Linus Torvalds
- + *
- + * These functions have a non-standard call interface to make them more
- + * efficient, especially as they return an error value in addition to
- + * the "real" return value.
- + *
- + * __get_user_X
- + *
- + * Inputs: $r0 contains the address
- + * Outputs: $r0 is the error code
- + * $r2, $r3 contains the zero-extended value
- + * lr corrupted
- + *
- + * No other registers must be altered. (see include/asm-nds32/uaccess.h
- + * for specific ASM register usage).
- + *
- + * Note that ADDR_LIMIT is either 0 or 0xc0000000.
- + * Note also that it is intended that __get_user_bad is not global.
- + */
- +#include <asm/asm-offsets.h>
- +#include <asm/thread_info.h>
- +#include <asm/errno.h>
- +#include <linux/linkage.h>
- +
- +
- +ENTRY(__get_user_1)
- +1: lbi $r2, [$r0]
- + move $r0, #0
- + ret
- +
- +ENTRY(__get_user_2)
- +2: lbi.bi $r2, [$r0], #1
- +3: lbi $r3, [$r0]
- +#ifndef __NDS32_EB__
- + slli $p1, $r3, #8
- + or $r2, $r2, $p1
- +#else
- + slli $p1, $r2, #8
- + or $r2, $r3, $p1
- +#endif
- + move $r0, #0
- + ret
- +
- +ENTRY(__get_user_4)
- +4: lwi $r2, [$r0]
- + move $r0, #0
- + ret
- +
- +ENTRY(__get_user_8)
- +5: lwi.bi $r2, [$r0], #4
- +6: lwi $r3, [$r0]
- + move $r0, #0
- + ret
- +
- +__get_user_bad_8:
- + move $r3, #0
- +__get_user_bad:
- + move $r2, #0
- + move $r0, #-EFAULT
- + ret
- +
- +.section __ex_table, "a"
- + .long 1b, __get_user_bad
- + .long 2b, __get_user_bad
- + .long 3b, __get_user_bad
- + .long 4b, __get_user_bad
- + .long 5b, __get_user_bad_8
- + .long 6b, __get_user_bad_8
- +.previous
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/libgcc2.c linux-3.4.110/arch/nds32/lib/libgcc2.c
- --- linux-3.4.110.orig/arch/nds32/lib/libgcc2.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/libgcc2.c 2016-04-07 10:20:50.950081334 +0200
- @@ -0,0 +1,351 @@
- +#define BITS_PER_UNIT 8
- +#include "longlong.h"
- +typedef unsigned int UQItype __attribute__ ((mode(QI)));
- +typedef int SItype __attribute__ ((mode(SI)));
- +typedef unsigned int USItype __attribute__ ((mode(SI)));
- +typedef int DItype __attribute__ ((mode(DI)));
- +typedef unsigned int UDItype __attribute__ ((mode(DI)));
- +
- +typedef int word_type __attribute__ ((mode(__word__)));
- +
- +#define Wtype SItype
- +#define UWtype USItype
- +#define DWtype DItype
- +#define UDWtype UDItype
- +
- +#ifdef __NDS32_EB__
- +struct DWstruct {
- + Wtype high, low;
- +};
- +#else
- +struct DWstruct {
- + Wtype low, high;
- +};
- +#endif
- +
- +typedef union {
- + struct DWstruct s;
- + DWtype ll;
- +} DWunion;
- +DWtype __negdi2(DWtype u)
- +{
- + const DWunion uu = {.ll = u };
- + const DWunion w = { {.low = -uu.s.low,
- + .high = -uu.s.high - ((UWtype) - uu.s.low > 0)}
- + };
- +
- + return w.ll;
- +}
- +
- +DWtype __lshrdi3(DWtype u, word_type b)
- +{
- + const DWunion uu = {.ll = u };
- + const word_type bm = (sizeof(Wtype) * BITS_PER_UNIT) - b;
- + DWunion w;
- +
- + if (b == 0)
- + return u;
- +
- + if (bm <= 0) {
- + w.s.high = 0;
- + w.s.low = (UWtype) uu.s.high >> -bm;
- + } else {
- + const UWtype carries = (UWtype) uu.s.high << bm;
- +
- + w.s.high = (UWtype) uu.s.high >> b;
- + w.s.low = ((UWtype) uu.s.low >> b) | carries;
- + }
- +
- + return w.ll;
- +}
- +
- +DWtype __ashldi3(DWtype u, word_type b)
- +{
- + const DWunion uu = {.ll = u };
- + const word_type bm = (sizeof(Wtype) * BITS_PER_UNIT) - b;
- + DWunion w;
- +
- + if (b == 0)
- + return u;
- +
- + if (bm <= 0) {
- + w.s.low = 0;
- + w.s.high = (UWtype) uu.s.low << -bm;
- + } else {
- + const UWtype carries = (UWtype) uu.s.low >> bm;
- +
- + w.s.low = (UWtype) uu.s.low << b;
- + w.s.high = ((UWtype) uu.s.high << b) | carries;
- + }
- +
- + return w.ll;
- +}
- +
- +DWtype __ashrdi3(DWtype u, word_type b)
- +{
- + const DWunion uu = {.ll = u };
- + const word_type bm = (sizeof(Wtype) * BITS_PER_UNIT) - b;
- + DWunion w;
- +
- + if (b == 0)
- + return u;
- +
- + if (bm <= 0) {
- + /* w.s.high = 1..1 or 0..0 */
- + w.s.high = uu.s.high >> (sizeof(Wtype) * BITS_PER_UNIT - 1);
- + w.s.low = uu.s.high >> -bm;
- + } else {
- + const UWtype carries = (UWtype) uu.s.high << bm;
- +
- + w.s.high = uu.s.high >> b;
- + w.s.low = ((UWtype) uu.s.low >> b) | carries;
- + }
- +
- + return w.ll;
- +}
- +
- +DWtype __muldi3(DWtype u, DWtype v)
- +{
- + const DWunion uu = {.ll = u };
- + const DWunion vv = {.ll = v };
- + DWunion w = {.ll = __umulsidi3(uu.s.low, vv.s.low) };
- +
- + w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
- + + (UWtype) uu.s.high * (UWtype) vv.s.low);
- +
- + return w.ll;
- +}
- +
- +const UQItype __clz_tab[] = {
- + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
- + 5, 5, 5, 5, 5, 5, 5, 5,
- + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- + 6, 6, 6, 6, 6, 6, 6, 6,
- + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- + 7, 7, 7, 7, 7, 7, 7, 7,
- + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- + 7, 7, 7, 7, 7, 7, 7, 7,
- + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- + 8, 8, 8, 8, 8, 8, 8, 8,
- + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- + 8, 8, 8, 8, 8, 8, 8, 8,
- + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- + 8, 8, 8, 8, 8, 8, 8, 8,
- + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- + 8, 8, 8, 8, 8, 8, 8, 8,
- +};
- +
- +UDWtype __udivmoddi4(UDWtype n, UDWtype d, UDWtype * rp)
- +{
- + const DWunion nn = {.ll = n };
- + const DWunion dd = {.ll = d };
- + DWunion rr;
- + UWtype d0, d1, n0, n1, n2;
- + UWtype q0, q1;
- + UWtype b, bm;
- + DWunion ww;
- +
- + d0 = dd.s.low;
- + d1 = dd.s.high;
- + n0 = nn.s.low;
- + n1 = nn.s.high;
- +
- +#if !UDIV_NEEDS_NORMALIZATION
- + if (d1 == 0) {
- + if (d0 > n1) {
- + /* 0q = nn / 0D */
- +
- + udiv_qrnnd(q0, n0, n1, n0, d0);
- + q1 = 0;
- +
- + /* Remainder in n0. */
- + } else {
- + /* qq = NN / 0d */
- +
- + if (d0 == 0)
- + d0 = 1 / d0; /* Divide intentionally by zero. */
- +
- + udiv_qrnnd(q1, n1, 0, n1, d0);
- + udiv_qrnnd(q0, n0, n1, n0, d0);
- +
- + /* Remainder in n0. */
- + }
- +
- + if (rp != 0) {
- + rr.s.low = n0;
- + rr.s.high = 0;
- + *rp = rr.ll;
- + }
- + }
- +#else /* UDIV_NEEDS_NORMALIZATION */
- +
- + if (d1 == 0) {
- + if (d0 > n1) {
- + /* 0q = nn / 0D */
- +
- + count_leading_zeros(bm, d0);
- +
- + if (bm != 0) {
- + /* Normalize, i.e. make the most significant bit of the
- + denominator set. */
- +
- + d0 = d0 << bm;
- + n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
- + n0 = n0 << bm;
- + }
- +
- + udiv_qrnnd(q0, n0, n1, n0, d0);
- + q1 = 0;
- +
- + /* Remainder in n0 >> bm. */
- + } else {
- + /* qq = NN / 0d */
- +
- + if (d0 == 0)
- + d0 = 1 / d0; /* Divide intentionally by zero. */
- +
- + count_leading_zeros(bm, d0);
- +
- + if (bm == 0) {
- + /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
- + conclude (the most significant bit of n1 is set) /\ (the
- + leading quotient digit q1 = 1).
- +
- + This special case is necessary, not an optimization.
- + (Shifts counts of W_TYPE_SIZE are undefined.) */
- +
- + n1 -= d0;
- + q1 = 1;
- + } else {
- + /* Normalize. */
- +
- + b = W_TYPE_SIZE - bm;
- +
- + d0 = d0 << bm;
- + n2 = n1 >> b;
- + n1 = (n1 << bm) | (n0 >> b);
- + n0 = n0 << bm;
- +
- + udiv_qrnnd(q1, n1, n2, n1, d0);
- + }
- +
- + /* n1 != d0... */
- +
- + udiv_qrnnd(q0, n0, n1, n0, d0);
- +
- + /* Remainder in n0 >> bm. */
- + }
- +
- + if (rp != 0) {
- + rr.s.low = n0 >> bm;
- + rr.s.high = 0;
- + *rp = rr.ll;
- + }
- + }
- +#endif /* UDIV_NEEDS_NORMALIZATION */
- +
- + else {
- + if (d1 > n1) {
- + /* 00 = nn / DD */
- +
- + q0 = 0;
- + q1 = 0;
- +
- + /* Remainder in n1n0. */
- + if (rp != 0) {
- + rr.s.low = n0;
- + rr.s.high = n1;
- + *rp = rr.ll;
- + }
- + } else {
- + /* 0q = NN / dd */
- +
- + count_leading_zeros(bm, d1);
- + if (bm == 0) {
- + /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
- + conclude (the most significant bit of n1 is set) /\ (the
- + quotient digit q0 = 0 or 1).
- +
- + This special case is necessary, not an optimization. */
- +
- + /* The condition on the next line takes advantage of that
- + n1 >= d1 (true due to program flow). */
- + if (n1 > d1 || n0 >= d0) {
- + q0 = 1;
- + sub_ddmmss(n1, n0, n1, n0, d1, d0);
- + } else
- + q0 = 0;
- +
- + q1 = 0;
- +
- + if (rp != 0) {
- + rr.s.low = n0;
- + rr.s.high = n1;
- + *rp = rr.ll;
- + }
- + } else {
- + UWtype m1, m0;
- + /* Normalize. */
- +
- + b = W_TYPE_SIZE - bm;
- +
- + d1 = (d1 << bm) | (d0 >> b);
- + d0 = d0 << bm;
- + n2 = n1 >> b;
- + n1 = (n1 << bm) | (n0 >> b);
- + n0 = n0 << bm;
- +
- + udiv_qrnnd(q0, n1, n2, n1, d1);
- + umul_ppmm(m1, m0, q0, d0);
- +
- + if (m1 > n1 || (m1 == n1 && m0 > n0)) {
- + q0--;
- + sub_ddmmss(m1, m0, m1, m0, d1, d0);
- + }
- +
- + q1 = 0;
- +
- + /* Remainder in (n1n0 - m1m0) >> bm. */
- + if (rp != 0) {
- + sub_ddmmss(n1, n0, n1, n0, m1, m0);
- + rr.s.low = (n1 << b) | (n0 >> bm);
- + rr.s.high = n1 >> bm;
- + *rp = rr.ll;
- + }
- + }
- + }
- + }
- +
- + ww.s.low = q0, ww.s.high = q1;
- + return ww.ll;
- +}
- +
- +UDWtype __umoddi3(UDWtype u, UDWtype v)
- +{
- + UDWtype w;
- +
- + (void)__udivmoddi4(u, v, &w);
- +
- + return w;
- +}
- +
- +UDWtype __udivdi3(UDWtype n, UDWtype d)
- +{
- + return __udivmoddi4(n, d, (UDWtype *) 0);
- +}
- +
- +word_type __ucmpdi2(DWtype a, DWtype b)
- +{
- + const DWunion au = {.ll = a };
- + const DWunion bu = {.ll = b };
- +
- + if ((UWtype) au.s.high < (UWtype) bu.s.high)
- + return 0;
- + else if ((UWtype) au.s.high > (UWtype) bu.s.high)
- + return 2;
- + if ((UWtype) au.s.low < (UWtype) bu.s.low)
- + return 0;
- + else if ((UWtype) au.s.low > (UWtype) bu.s.low)
- + return 2;
- + return 1;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/longlong.h linux-3.4.110/arch/nds32/lib/longlong.h
- --- linux-3.4.110.orig/arch/nds32/lib/longlong.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/longlong.h 2016-04-07 10:20:50.950081334 +0200
- @@ -0,0 +1,105 @@
- +#define __BITS4 (W_TYPE_SIZE / 4)
- +#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
- +#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
- +#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
- +
- +#define W_TYPE_SIZE (4 * 8)
- +#define UHWtype USItype
- +
- +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- + do { \
- + UWtype __x; \
- + __x = (al) - (bl); \
- + (sh) = (ah) - (bh) - (__x > (al)); \
- + (sl) = __x; \
- + } while (0)
- +
- +#define umul_ppmm(w1, w0, u, v) \
- + do { \
- + UWtype __x0, __x1, __x2, __x3; \
- + UHWtype __ul, __vl, __uh, __vh; \
- + \
- + __ul = __ll_lowpart (u); \
- + __uh = __ll_highpart (u); \
- + __vl = __ll_lowpart (v); \
- + __vh = __ll_highpart (v); \
- + \
- + __x0 = (UWtype) __ul * __vl; \
- + __x1 = (UWtype) __ul * __vh; \
- + __x2 = (UWtype) __uh * __vl; \
- + __x3 = (UWtype) __uh * __vh; \
- + \
- + __x1 += __ll_highpart (__x0);/* this can't give carry */ \
- + __x1 += __x2; /* but this indeed can */ \
- + if (__x1 < __x2) /* did we get it? */ \
- + __x3 += __ll_B; /* yes, add it in the proper pos. */ \
- + \
- + (w1) = __x3 + __ll_highpart (__x1); \
- + (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \
- + } while (0)
- +
- +#define __umulsidi3(u, v) \
- + ({DWunion __w; \
- + umul_ppmm (__w.s.high, __w.s.low, u, v); \
- + __w.ll; })
- +
- +#define __udiv_qrnnd_c(q, r, n1, n0, d) \
- + do { \
- + UWtype __d1, __d0, __q1, __q0; \
- + UWtype __r1, __r0, __m; \
- + __d1 = __ll_highpart (d); \
- + __d0 = __ll_lowpart (d); \
- + \
- + __r1 = (n1) % __d1; \
- + __q1 = (n1) / __d1; \
- + __m = (UWtype) __q1 * __d0; \
- + __r1 = __r1 * __ll_B | __ll_highpart (n0); \
- + if (__r1 < __m) \
- + { \
- + __q1--, __r1 += (d); \
- + if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
- + if (__r1 < __m) \
- + __q1--, __r1 += (d); \
- + } \
- + __r1 -= __m; \
- + \
- + __r0 = __r1 % __d1; \
- + __q0 = __r1 / __d1; \
- + __m = (UWtype) __q0 * __d0; \
- + __r0 = __r0 * __ll_B | __ll_lowpart (n0); \
- + if (__r0 < __m) \
- + { \
- + __q0--, __r0 += (d); \
- + if (__r0 >= (d)) \
- + if (__r0 < __m) \
- + __q0--, __r0 += (d); \
- + } \
- + __r0 -= __m; \
- + \
- + (q) = (UWtype) __q1 * __ll_B | __q0; \
- + (r) = __r0; \
- + } while (0)
- +
- +#define UDIV_NEEDS_NORMALIZATION 1
- +#define udiv_qrnnd __udiv_qrnnd_c
- +
- +#define count_leading_zeros(count, x) \
- + do { \
- + UWtype __xr = (x); \
- + UWtype __a; \
- + \
- + if (W_TYPE_SIZE <= 32) \
- + { \
- + __a = __xr < ((UWtype)1<<2*__BITS4) \
- + ? (__xr < ((UWtype)1<<__BITS4) ? 0 : __BITS4) \
- + : (__xr < ((UWtype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
- + } \
- + else \
- + { \
- + for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \
- + if (((__xr >> __a) & 0xff) != 0) \
- + break; \
- + } \
- + \
- + (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \
- + } while (0)
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/Makefile linux-3.4.110/arch/nds32/lib/Makefile
- --- linux-3.4.110.orig/arch/nds32/lib/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/Makefile 2016-04-07 10:20:50.950081334 +0200
- @@ -0,0 +1,19 @@
- +#
- +# linux/arch/nds32/lib/Makefile
- +#
- +# Copyright (C) 2006 Andes Technology Corporation
- +#
- +
- +lib-y := csum_partial_copy.o csum_partial.o \
- + copy_page.o memcpy.o memmove.o \
- + memset.o memzero.o strncpy_from_user.o \
- + strnlen_user.o strchr.o strrchr.o \
- + uaccess.o getuser.o \
- + putuser.o libgcc2.o divmod.o udivmod.o udivmodsi4.o
- +
- +ifdef CONFIG_FUNCTION_TRACER
- +CFLAGS_REMOVE_libgcc2.o = -pg
- +CFLAGS_REMOVE_divmod.o = -pg
- +CFLAGS_REMOVE_udivmod.o = -pg
- +CFLAGS_REMOVE_udivmodsi4.o = -pg
- +endif
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/memcpy.S linux-3.4.110/arch/nds32/lib/memcpy.S
- --- linux-3.4.110.orig/arch/nds32/lib/memcpy.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/memcpy.S 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,101 @@
- +/*
- + * linux/arch/nds32/lib/memcpy.S -- Memory copy function.
- + *
- + * This file is subject to the terms and conditions of the GNU General Public
- + * License. See the file "COPYING" in the main directory of this archive
- + * for more details.
- + *
- + * Copyright (C) 2001 Hiroyuki Kondo, and Hirokazu Takata
- + * Copyright (C) 2004 Hirokazu Takata
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + */
- +
- +#include <linux/linkage.h>
- +
- +/*
- + void *memcpy(void *dst, const void *src, int n);
- +
- + dst: $r0
- + src: $r1
- + n : $r2
- + ret: $r0 - pointer to the memory area dst.
- +*/
- +
- +#include <linux/linkage.h>
- +
- + .text
- +
- +ENTRY(memcpy)
- + move $r5, $r0
- + beq $r0, $r1, quit_memcpy
- + beqz $r2, quit_memcpy
- + srli $r3, $r2, #5 ! check if len < cache-line size 32
- + beqz $r3, word_copy_entry
- + andi $r4, $r0, #0x3 ! check byte-align
- + beqz $r4, unalign_word_copy_entry
- +
- + addi $r4, $r4,#-4
- + abs $r4, $r4 ! check how many un-align byte to copy
- + sub $r2, $r2, $r4 ! update $R2
- +
- +unalign_byte_copy:
- + lbi.bi $r3, [$r1], #1
- + addi $r4, $r4, #-1
- + sbi.bi $r3, [$r0], #1
- + bnez $r4, unalign_byte_copy
- + beqz $r2, quit_memcpy
- +
- +unalign_word_copy_entry:
- + andi $r3, $r0, 0x1f ! check cache-line unaligncount
- + beqz $r3, cache_copy
- +
- + addi $r3, $r3, #-32
- + abs $r3, $r3
- + sub $r2, $r2, $r3 ! update $R2
- +
- +unalign_word_copy:
- + lmw.bim $r4, [$r1], $r4
- + addi $r3, $r3, #-4
- + smw.bim $r4, [$r0], $r4
- + bnez $r3, unalign_word_copy
- + beqz $r2, quit_memcpy
- +
- + addi $r3, $r2, #-32 ! to check $r2< cache_line , than go to word_copy
- + bltz $r3, word_copy_entry
- +cache_copy:
- + srli $r3, $r2, #5
- + beqz $r3, word_copy_entry
- + pushm $r6, $r13
- +3:
- + lmw.bim $r6, [$r1], $r13
- + addi $r3, $r3, #-1
- + smw.bim $r6, [$r0], $r13
- + bnez $r3, 3b
- + popm $r6, $r13
- +
- +word_copy_entry:
- + andi $r2, $r2, #31
- +
- + beqz $r2, quit_memcpy
- +5:
- + srli $r3, $r2, #2
- + beqz $r3, byte_copy
- +word_copy:
- + lmw.bim $r4, [$r1], $r4
- + addi $r3, $r3, #-1
- + smw.bim $r4, [$r0], $r4
- + bnez $r3, word_copy
- + andi $r2, $r2, #3
- + beqz $r2, quit_memcpy
- +byte_copy:
- + lbi.bi $r3, [$r1], #1
- + addi $r2, $r2, #-1
- +
- + sbi.bi $r3, [$r0], #1
- + bnez $r2, byte_copy
- +quit_memcpy:
- + move $r0, $r5
- + ret
- +
- + .end
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/memmove.S linux-3.4.110/arch/nds32/lib/memmove.S
- --- linux-3.4.110.orig/arch/nds32/lib/memmove.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/memmove.S 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,80 @@
- +/*
- + * linux/arch/nds32/lib/memmove.S -- Memory move function.
- + *
- + * This file is subject to the terms and conditions of the GNU General Public
- + * License. See the file "COPYING" in the main directory of this archive
- + * for more details.
- + *
- + * Copyright (C) 2001 Hiroyuki Kondo, and Hirokazu Takata
- + * Copyright (C) 2004 Hirokazu Takata
- + * Copyright (C) 2006 Andes Technology Corporation
- + *
- + */
- +
- +#include <linux/linkage.h>
- +
- +/*
- + void *memmove(void *dst, const void *src, int n);
- +
- + dst: $r0
- + src: $r1
- + n : $r2
- + ret: $r0 - pointer to the memory area dst.
- +*/
- + .text
- +
- +ENTRY(memmove)
- + move $r5, $r0 ! Set return value = det
- + beq $r0, $r1, exit_memcpy ! Exit when det = src
- + beqz $r2, exit_memcpy ! Exit when n = 0
- + pushm $t0, $t1 ! Save reg
- + srli $p1, $r2, #2 ! $p1 is how many words to copy
- +
- + ! Avoid data lost when memory overlap
- + ! Copy data reversely when src < dst
- + slt $p0, $r0, $r1 ! check if $r0 < $r1
- + beqz $p0, do_reverse ! branch if dst > src
- +
- + ! No reverse, dst < src
- + andi $r2, $r2, #3 ! How many bytes are less than a word
- + li $t0, #1 ! Determining copy direction in byte_cpy
- + beqz $p1, byte_cpy ! When n is less than a word
- +
- +word_cpy:
- + lmw.bim $p0, [$r1], $p0 ! Read a word from src
- + addi $p1, $p1, #-1 ! How many words left to copy
- + smw.bim $p0, [$r0], $p0 ! Copy the word to det
- + bnez $p1, word_cpy ! If remained words > 0
- + beqz $r2, end_memcpy ! No left bytes to copy
- + b byte_cpy
- +
- +do_reverse:
- + add $r0, $r0, $r2 ! Start with the end of $r0
- + add $r1, $r1, $r2 ! Start with the end of $r1
- + andi $r2, $r2, #3 ! How many bytes are less than a word
- + li $t0, #-1 ! Determining copy direction in byte_cpy
- + beqz $p1, reverse_byte_cpy ! When n is less than a word
- +
- +reverse_word_cpy:
- + lmw.adm $p0, [$r1], $p0 ! Read a word from src
- + addi $p1, $p1, #-1 ! How many words left to copy
- + smw.adm $p0, [$r0], $p0 ! Copy the word to det
- + bnez $p1, reverse_word_cpy ! If remained words > 0
- + beqz $r2, end_memcpy ! No left bytes to copy
- +
- +reverse_byte_cpy:
- + addi $r0, $r0, #-1
- + addi $r1, $r1, #-1
- +byte_cpy: ! Less than 4 bytes to copy now
- + lb.bi $p0, [$r1], $t0 ! Read a byte from src
- + addi $r2, $r2, #-1 ! How many bytes left to copy
- + sb.bi $p0, [$r0], $t0 ! copy the byte to det
- + bnez $r2, byte_cpy ! If remained bytes > 0
- +
- +end_memcpy:
- + popm $t0, $t1
- +exit_memcpy:
- + move $r0, $r5
- + ret
- +
- + .end
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/memset.S linux-3.4.110/arch/nds32/lib/memset.S
- --- linux-3.4.110.orig/arch/nds32/lib/memset.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/memset.S 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,51 @@
- +
- +/*
- + * linux/arch/nds32/lib/memset.S -- memset function.
- + *
- + * This file is subject to the terms and conditions of the GNU General Public
- + * License. See the file "COPYING" in the main directory of this archive
- + * for more details.
- + *
- + * Copyright (C) 2001,2002 Hiroyuki Kondo, and Hirokazu Takata
- + * Copyright (C) 2004 Hirokazu Takata
- + * Copyright (C) 2006 Andes Technology Corporation
- + *
- + */
- +#include <linux/linkage.h>
- +#include <asm/assembler.h>
- +
- +/*
- + void *memset(void *dst, int val, int len);
- +
- + dst: $r0
- + val: $r1
- + len: $r2
- + ret: $r0 - pointer to the memory area dst.
- +*/
- + .text
- +ENTRY(memset)
- + move $r5, $r0 ! Return value
- + beqz $r2, end_memset ! Exit when len = 0
- + srli $p1, $r2, 2 ! $p1 is how many words to copy
- + andi $r2, $r2, 3 ! How many bytes are less than a word
- + beqz $p1, byte_set ! When n is less than a word
- +
- + ! set $r1 from ??????ab to abababab
- + andi $r1, $r1, #0x00ff ! $r1 = 000000ab
- + slli $p0, $r1, #8 ! $p0 = 0000ab00
- + or $r1, $r1, $p0 ! $r1 = 0000abab
- + slli $p0, $r1, #16 ! $p0 = abab0000
- + or $r1, $r1, $p0 ! $r1 = abababab
- +word_set:
- + addi $p1, $p1, #-1 ! How many words left to copy
- + smw.bim $r1, [$r0], $r1 ! Copy the word to det
- + bnez $p1, word_set ! Still words to set, continue looping
- + beqz $r2, end_memset ! No left byte to set
- +byte_set: ! Less than 4 bytes left to set
- + addi $r2, $r2, #-1 ! Decrease len by 1
- + sbi.bi $r1, [$r0], #1 ! Set data of the next byte to $r1
- + bnez $r2, byte_set ! Still bytes left to set
- +end_memset:
- + move $r0, $r5
- + ret
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/memzero.S linux-3.4.110/arch/nds32/lib/memzero.S
- --- linux-3.4.110.orig/arch/nds32/lib/memzero.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/memzero.S 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,36 @@
- +/*
- + * linux/arch/nds32/lib/memzero.S
- + *
- + * Copyright (C) 1995-2000 Russell King
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#include <linux/linkage.h>
- +#include <asm/assembler.h>
- +
- + .text
- +/*
- + * void *__memzero(void *dst, int len);
- + *
- + * dst: $r0
- + * len: $r1
- + * ret: $r0 - pointer to the memory area dst.
- + *
- + * Call memset(dst, 0, len) to perform memzero.
- + * Currently no optimization because only being referenced in 31 files
- + * (For comparison, memset being referenced in 2527 files)
- + */
- +ENTRY(__memzero)
- + beqz $r1, 1f
- + push $lp
- + move $r2, $r1
- + move $r1, #0
- + push $r0
- + bal memset
- + pop $r0
- + pop $lp
- +1:
- + ret
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/putuser.S linux-3.4.110/arch/nds32/lib/putuser.S
- --- linux-3.4.110.orig/arch/nds32/lib/putuser.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/putuser.S 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,68 @@
- +/*
- + * linux/arch/nds32/lib/putuser.S
- + *
- + * Copyright (C) 2001 Russell King
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * Idea from x86 version, (C) Copyright 1998 Linus Torvalds
- + *
- + * These functions have a non-standard call interface to make
- + * them more efficient, especially as they return an error
- + * value in addition to the "real" return value.
- + *
- + * __put_user_X
- + *
- + * Inputs: $r0 contains the address
- + * $r2, $r3 contains the value
- + * Outputs: $r0 is the error code
- + * lr corrupted
- + *
- + * No other registers must be altered. (see include/asm-arm/uaccess.h
- + * for specific ASM register usage).
- + *
- + * Note that ADDR_LIMIT is either 0 or 0xc0000000
- + * Note also that it is intended that __put_user_bad is not global.
- + */
- +#include <asm/asm-offsets.h>
- +#include <asm/thread_info.h>
- +#include <asm/errno.h>
- +#include <linux/linkage.h>
- +
- + .text
- +
- +ENTRY(__put_user_1)
- +1: sb $r2, [$r0]
- + move $r0, #0
- + ret
- +
- +ENTRY(__put_user_2)
- +2: shi $r2, [$r0] ! Store input halfword
- + move $r0, #0
- + ret
- +
- +ENTRY(__put_user_4)
- +3: sw $r2, [$r0]
- + move $r0, #0
- + ret
- +
- +ENTRY(__put_user_8)
- +5: swi.bi $r2, [$r0], #4
- +6: sw $r3, [$r0]
- + move $r0, #0
- + ret
- +
- +__put_user_bad:
- + move $r0, #-EFAULT
- + ret
- +
- +.section __ex_table, "a"
- + .long 1b, __put_user_bad
- + .long 2b, __put_user_bad
- + .long 3b, __put_user_bad
- + .long 5b, __put_user_bad
- + .long 6b, __put_user_bad
- +.previous
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/strchr.S linux-3.4.110/arch/nds32/lib/strchr.S
- --- linux-3.4.110.orig/arch/nds32/lib/strchr.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/strchr.S 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,37 @@
- +/*
- + * linux/arch/nds32/lib/strchr.S
- + *
- + * Copyright (C) 1995-2000 Russell King
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * ASM optimised string functions
- + */
- +#include <linux/linkage.h>
- +#include <asm/assembler.h>
- +
- +/*
- + * Prototype: char *strrchr(const char *s, int c);
- + * Purpose : Returns a pointer to the first occurrence of the character c
- + * in the string s. Here "character" means "byte" - these functions
- + * do not work with wide or multi-byte characters.
- + */
- +
- + .text
- +
- +ENTRY(strchr)
- + move $r5, $r0 ! Setup return value
- + andi $r1, $r1, #0xff ! Wipe out useless bits
- +loop:
- + lbi.bi $p0, [$r5], #1 ! Load the next byte
- + beqz $p0, exit ! Reach EOS (NULL), return NULL
- + bne $p0, $r1, loop ! Continue if != c
- + addi $r5, $r5, #-1 ! Found
- +exit:
- + cmovz $r5, $p0, $p0 ! Return NULL if EOS (NULL)
- + move $r0, $r5
- + ret
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/strncpy_from_user.S linux-3.4.110/arch/nds32/lib/strncpy_from_user.S
- --- linux-3.4.110.orig/arch/nds32/lib/strncpy_from_user.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/strncpy_from_user.S 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,45 @@
- +/*
- + * linux/arch/nds32/lib/strncpy_from_user.S
- + *
- + * Copyright (C) 1995-2000 Russell King
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#include <linux/linkage.h>
- +#include <asm/assembler.h>
- +#include <asm/errno.h>
- +
- +
- +/*
- + * Copy a string from user space to kernel space.
- + * $r0 = dst, $r1 = src, $r2 = n (byte length)
- + * returns the number of characters copied (strlen of copied string),
- + * -EFAULT on exception, or "len" if we fill the whole buffer
- + */
- +
- + .text
- + .align 4
- +ENTRY(__arch_strncpy_from_user)
- + move $p1, $r1 ! Record the start src addr
- +loop:
- + addi $r2, $r2, #-1 ! Decrease n by 1
- + bltz $r2, exit ! Exit if n < 0
- +USER( lbi.bi, $p0, [$r1], #1) ! Load the byte from src
- + sbi.bi $p0, [$r0], #1 ! Store the byte to dst
- + bnez $p0, loop ! Continue looping if terminator is not reached
- + addi $r1, $r1, #-1 ! Don't count the terminator
- +exit:
- + sub $r0, $r1, $p1 ! Get copied count
- + ret
- +
- + .section .fixup,"ax"
- + .align 0
- +9001: xor $p0, $p0, $p0
- + sb $p0, [$r0] ! Zero the buffer
- + move $r0, -EFAULT ! Return -EFAULT
- + ret
- + .previous
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/strnlen_user.S linux-3.4.110/arch/nds32/lib/strnlen_user.S
- --- linux-3.4.110.orig/arch/nds32/lib/strnlen_user.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/strnlen_user.S 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,43 @@
- +/*
- + * linux/arch/nds32/lib/strnlen_user.S
- + *
- + * Copyright (C) 1995-2000 Russell King
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#include <linux/linkage.h>
- +#include <asm/assembler.h>
- +#include <asm/errno.h>
- +
- + .text
- +
- +/* Prototype: unsigned long ___arch_strnlen_user(const char *str, long n)
- + * Purpose : get length of a string in user memory
- + * Params : str - address of string in user memory
- + * Returns : length of string *including terminator*
- + * or zero on exception, or n + 1 if too long
- + */
- + .align 4
- +ENTRY(__arch_strnlen_user)
- + move $p0, $r0 ! Record the start addr
- + ! beqz $r0, exit ! Exit when Null address
- + beqz $r1, exit ! Exit when n = 0
- +loop:
- +USER( lbi.bi, $p1, [$r0], #1) ! Load the next byte
- + beqz $p1, exit ! Exit when terminator is reached
- + addi $r1, $r1, #-1 ! Decrease n by 1
- + bnez $r1, loop ! Continue looping if n != 0
- + addi $r0, $r0, #1 ! Return n+1 if too long
- +exit:
- + sub $r0, $r0, $p0 ! Get the counted length
- + ret
- +
- + .section .fixup,"ax"
- + .align 0
- +9001: move $r0, #0 ! Return 0 on exception
- + ret
- + .previous
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/strrchr.S linux-3.4.110/arch/nds32/lib/strrchr.S
- --- linux-3.4.110.orig/arch/nds32/lib/strrchr.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/strrchr.S 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,37 @@
- +/*
- + * linux/arch/nds32/lib/strrchr.S
- + *
- + * Copyright (C) 1995-2000 Russell King
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * ASM optimised string functions
- + */
- +#include <linux/linkage.h>
- +#include <asm/assembler.h>
- +
- + .text
- +/*
- + * Prototype: char *strrchr(const char *s, int c);
- + * Purpose : Returns a pointer to the last occurrence of the character c
- + * in the string s. Here "character" means "byte" - these functions
- + * do not work with wide or multi-byte characters.
- + */
- + .align 4
- +ENTRY(strrchr)
- + move $r5, #0
- + beqz $r0, exit
- + andi $r1, $r1, #0xff ! Wipe out useless bits
- +loop:
- + lbi $p0, [$r0] ! Load the next byte
- + xor $p1, $p0, $r1 ! Test if the byte == c
- + cmovz $r5, $r0, $p1 ! Save the current position
- + addi $r0, $r0, #1 ! Move on to the next byte
- + bnez $p0, loop ! Continue if not NULL (EOS)
- +exit:
- + move $r0, $r5
- + ret
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/uaccess.S linux-3.4.110/arch/nds32/lib/uaccess.S
- --- linux-3.4.110.orig/arch/nds32/lib/uaccess.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/uaccess.S 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,159 @@
- +/*
- + * linux/arch/nds32/lib/uaccess.S
- + *
- + * Copyright (C) 1995, 1996,1997,1998 Russell King
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * Routines to block copy data to/from user memory
- + * These are highly optimised both for the 4k page size
- + * and for various alignments.
- + */
- +#include <linux/linkage.h>
- +#include <asm/assembler.h>
- +#include <asm/errno.h>
- +
- + .text
- +
- +//#define PAGE_SHIFT 12
- +
- +/* Prototype: int __arch_copy_to_user(void *to, const char *from, size_t n)
- + * Purpose : copy a block to user memory from kernel memory
- + * Params : to - user memory
- + * : from - kernel memory
- + * : n - number of bytes to copy
- + * Returns : Number of bytes NOT copied.
- + */
- +
- +ENTRY(__arch_copy_to_user)
- + push $r0
- + push $r2
- + beqz $r2, ctu_exit
- + srli $p0, $r2, #2 ! $p0 = number of word to clear
- + andi $r2, $r2, #3 ! Bytes less than a word to copy
- + beqz $p0, byte_ctu ! Only less than a word to copy
- +word_ctu:
- + lmw.bim $p1, [$r1], $p1 ! Load the next word
- +USER( smw.bim,$p1, [$r0], $p1) ! Store the next word
- + addi $p0, $p0, #-1 ! Decrease word count
- + bnez $p0, word_ctu ! Continue looping to copy all words
- + beqz $r2, ctu_exit ! No left bytes to copy
- +byte_ctu:
- + lbi.bi $p1, [$r1], #1 ! Load the next byte
- +USER( sbi.bi, $p1, [$r0], #1) ! Store the next byte
- + addi $r2, $r2, #-1 ! Decrease byte count
- + bnez $r2, byte_ctu ! Continue looping to clear all left bytes
- +ctu_exit:
- + move $r0, $r2 ! Set return value
- + pop $r2
- + pop $r2 ! Pop saved $r0 to $r2 to not corrupt return value
- + ret
- +
- + .section .fixup,"ax"
- + .align 0
- +9001:
- + pop $p1 ! Original $r2, n
- + pop $p0 ! Original $r0, void *to
- + sub $r1, $r0, $p0 ! Bytes copied
- + sub $r2, $p1, $r1 ! Bytes left to copy
- + push $lp
- + move $r0, $p0
- + bal __memzero ! Clean up the memory
- + pop $lp
- + move $r0, $r2
- + ret
- +
- + .previous
- +
- +/* Prototype: unsigned long __arch_copy_from_user(void *to,const void *from,unsigned long n);
- + * Purpose : copy a block from user memory to kernel memory
- + * Params : to - kernel memory
- + * : from - user memory
- + * : n - number of bytes to copy
- + * Returns : Number of bytes NOT copied.
- + */
- +
- +
- +ENTRY(__arch_copy_from_user)
- + push $r1
- + push $r2
- + beqz $r2, cfu_exit
- + srli $p0, $r2, #2 ! $p0 = number of word to clear
- + andi $r2, $r2, #3 ! Bytes less than a word to copy
- + beqz $p0, byte_cfu ! Only less than a word to copy
- +word_cfu:
- +USER( lmw.bim,$p1, [$r1], $p1) ! Load the next word
- + smw.bim $p1, [$r0], $p1 ! Store the next word
- + addi $p0, $p0, #-1 ! Decrease word count
- + bnez $p0, word_cfu ! Continue looping to copy all words
- + beqz $r2, cfu_exit ! No left bytes to copy
- +byte_cfu:
- +USER( lbi.bi, $p1, [$r1], #1) ! Load the next byte
- + sbi.bi $p1, [$r0], #1 ! Store the next byte
- + addi $r2, $r2, #-1 ! Decrease byte count
- + bnez $r2, byte_cfu ! Continue looping to clear all left bytes
- +cfu_exit:
- + move $r0, $r2 ! Set return value
- + pop $r2
- + pop $r1
- + ret
- +
- + .section .fixup,"ax"
- + .align 0
- + /*
- + * We took an exception. $r0 contains a pointer to
- + * the byte not copied.
- + */
- +9001:
- + pop $p1 ! Original $r2, n
- + pop $p0 ! Original $r0, void *to
- + sub $r1, $r1, $p0 ! Bytes copied
- + sub $r2, $p1, $r1 ! Bytes left to copy
- + push $lp
- + bal __memzero ! Clean up the memory
- + pop $lp
- + move $r0, $r2
- + ret
- + .previous
- +
- +/* Prototype: int __arch_clear_user(void *addr, size_t sz)
- + * Purpose : clear some user memory
- + * Params : addr - user memory address to clear
- + * : sz - number of bytes to clear
- + * Returns : number of bytes NOT cleared
- + */
- + .align 5
- +ENTRY(__arch_clear_user)
- + pushm $r0, $r1
- + beqz $r1, clear_exit
- + xor $p1, $p1, $p1 ! Use $p1=0 to clear mem
- + srli $p0, $r1, #2 ! $p0 = number of word to clear
- + andi $r1, $r1, #3 ! Bytes less than a word to copy
- + beqz $p0, byte_clear ! Only less than a word to clear
- +word_clear:
- +USER( smw.bim,$p1, [$r0], $p1) ! Clear the word
- + addi $p0, $p0, #-1 ! Decrease word count
- + bnez $p0, word_clear ! Continue looping to clear all words
- + beqz $r1, clear_exit ! No left bytes to copy
- +byte_clear:
- +USER( sbi.bi, $p1, [$r0], #1) ! Clear the byte
- + addi $r1, $r1, #-1 ! Decrease byte count
- + bnez $r1, byte_clear ! Continue looping to clear all left bytes
- +clear_exit:
- + move $r0, $r1 ! Set return value
- + pop $r1
- + pop $r1 ! Pop saved $r0 to $r1 to not corrupt return value
- + ret
- +
- + .section .fixup,"ax"
- + .align 0
- +9001:
- + popm $p0, $p1 ! $p0 = original $r0, *addr, $p1 = original $r1, n
- + sub $p0, $r0, $p0 ! Bytes copied
- + sub $r0, $p1, $p0 ! Bytes left to copy
- + ret
- + .previous
- +
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/udivmod.c linux-3.4.110/arch/nds32/lib/udivmod.c
- --- linux-3.4.110.orig/arch/nds32/lib/udivmod.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/udivmod.c 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,12 @@
- +extern unsigned long udivmodsi4(unsigned long num, unsigned long den,
- + int modwanted);
- +
- +long __udivsi3(long a, long b)
- +{
- + return udivmodsi4(a, b, 0);
- +}
- +
- +long __umodsi3(long a, long b)
- +{
- + return udivmodsi4(a, b, 1);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/lib/udivmodsi4.c linux-3.4.110/arch/nds32/lib/udivmodsi4.c
- --- linux-3.4.110.orig/arch/nds32/lib/udivmodsi4.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/lib/udivmodsi4.c 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,21 @@
- +unsigned long udivmodsi4(unsigned long num, unsigned long den, int modwanted)
- +{
- + unsigned long bit = 1;
- + unsigned long res = 0;
- +
- + while (den < num && bit && !(den & (1L << 31))) {
- + den <<= 1;
- + bit <<= 1;
- + }
- + while (bit) {
- + if (num >= den) {
- + num -= den;
- + res |= bit;
- + }
- + bit >>= 1;
- + den >>= 1;
- + }
- + if (modwanted)
- + return num;
- + return res;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/Makefile linux-3.4.110/arch/nds32/Makefile
- --- linux-3.4.110.orig/arch/nds32/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/Makefile 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,100 @@
- +#
- +# arch/nds32/Makefile
- +#
- +# This file is subject to the terms and conditions of the GNU General Public
- +# License. See the file "COPYING" in the main directory of this archive
- +# for more details.
- +#
- +# Copyright (C) 1995-2001 by Russell King
- +
- +LDFLAGS_vmlinux :=-nostdlib --no-undefined -X
- +OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
- +GZFLAGS :=-9
- +KBUILD_CFLAGS +=-pipe -mno-sched-prolog-epilog
- +
- +# Do not use arch/nds32/defconfig - it's always outdated.
- +# Select a platform tht is kept up-to-date
- +KBUILD_DEFCONFIG := orca_defconfig
- +
- +ifeq ($(CONFIG_FRAME_POINTER),y)
- +KBUILD_CFLAGS +=-fno-omit-frame-pointer
- +endif
- +
- +comma = ,
- +
- +# This selects which instruction set is used.
- +# Note that GCC does not numerically define an architecture version
- +# macro, but instead defines a whole series of macros which makes
- +# testing for a specific architecture or later rather impossible.
- +arch-y +=-D__nds32__
- +gcc_ver :=$(shell $(CC) -E -dM -xc /dev/null | grep __VERSION__ | sed 's/\#define __VERSION__ //')
- +ifeq ($(shell expr `echo $(gcc_ver)` \>= 4.9.2 ), 1)
- +arch-y += \
- + $(shell $(CC) -E -dM -xc /dev/null | \
- + grep -o -m1 NDS32_EXT_FPU_SP | \
- + sed -e 's/NDS32_EXT_FPU_SP/-mno-ext-fpu-sp -mfloat-abi=soft/') \
- + $(shell $(CC) -E -dM -xc /dev/null | \
- + grep -o -m1 NDS32_EXT_FPU_DP | \
- + sed -e 's/NDS32_EXT_FPU_DP/-mno-ext-fpu-dp -mfloat-abi=soft/')
- +tune-y =-D__OPTIMIZE__ -mcmodel=large -D__ARCH_WANT_SYS_WAITPID
- +else
- +$(shell echo $(__VERSION__))
- +arch-y += $(shell $(CC) -E -dM -xc /dev/null | grep -o -m1 NDS32_EXT_FPU_SP | \
- + sed -e 's/NDS32_EXT_FPU_SP/-mno-ext-fpu-sp/') \
- + $(shell $(CC) -E -dM -xc /dev/null | grep -o -m1 NDS32_EXT_FPU_DP | \
- + sed -e 's/NDS32_EXT_FPU_DP/-mno-ext-fpu-dp/') \
- + $(shell $(CC) -E -dM -xc /dev/null | grep -o -m1 NDS32_ABI | \
- + sed -e 's/NDS32_ABI/-mabi=2/')
- +tune-y =-D__OPTIMIZE__ -G0 -D__ARCH_WANT_SYS_WAITPID -D_GCC444
- +endif
- +
- +# This is a workaround for FUNCTION_TRACER because v3push will push $fp, $gp and $lp.
- +ifdef CONFIG_FUNCTION_TRACER
- +arch-y += -mno-v3push
- +endif
- +# This selects how we optimise for the processor.
- +# Need -Unds32 for gcc < 3.x
- +CHECKFLAGS += -D__nds32__
- +
- +KBUILD_CFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -Unds32 -DSTRICT_MM_TYPECHECKS # for c-style checking for page.h
- +KBUILD_AFLAGS +=$(AFLAGS_ABI) $(arch-y) $(tune-y)
- +
- +#Default value
- +head-y := arch/nds32/kernel/head.o arch/nds32/kernel/init_task.o
- +textaddr-y := 0xC000C000
- +
- +TEXTADDR := $(textaddr-y)
- +
- +export TEXTADDR DATAADDR GZFLAGS
- +
- +
- +# If we have a machine-specific directory, then include it in the build.
- +core-y += arch/nds32/kernel/ arch/nds32/mm/
- +core-y += arch/nds32/platforms/
- +core-$(CONFIG_FPU) += arch/nds32/math-emu/
- +
- +drivers-$(CONFIG_OPROFILE) += arch/nds32/oprofile/
- +
- +libs-y += arch/nds32/lib/
- +
- +boot := arch/nds32/boot
- +
- +.PHONY: FORCE
- +
- +Image: vmlinux
- + $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
- +
- +CLEAN_FILES += include/asm-nds32/constants.h*
- +
- +# We use MRPROPER_FILES and CLEAN_FILES now
- +archclean:
- + $(Q)$(MAKE) $(clean)=$(boot)
- +
- +.PHONY: arch/nds32/kernel/asm-offsets.s
- +arch/nds32/kernel/asm-offsets.s: arch/nds32/kernel/asm-offsets.c
- + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
- +
- +
- +define archhelp
- + echo ' Image - kernel image (arch/$(ARCH)/boot/Image)'
- +endef
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_add.c linux-3.4.110/arch/nds32/math-emu/dp_add.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/dp_add.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/dp_add.c 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,179 @@
- +/* IEEE754 floating point arithmetic
- + * double precision: common utilities
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + *
- + */
- +
- +#include "ieee754dp.h"
- +
- +ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)
- +{
- + COMPXDP;
- + COMPYDP;
- +
- + EXPLODEXDP;
- + EXPLODEYDP;
- +
- + CLEARCX;
- +
- + FLUSHXDP;
- + FLUSHYDP;
- +
- + switch (CLPAIR(xc, yc)) {
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754dp_nanxcpt(ieee754dp_indef(), "add", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
- + return y;
- +
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
- + return x;
- +
- + /* Infinity handling
- + */
- +
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
- + if (xs == ys)
- + return x;
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754dp_xcpt(ieee754dp_indef(), "add", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
- + return y;
- +
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
- + return x;
- +
- + /* Zero handling
- + */
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
- + if (xs == ys)
- + return x;
- + else
- + return ieee754dp_zero(ieee754_csr.rm == IEEE754_RD);
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
- + return x;
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
- + return y;
- +
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
- + DPDNORMX;
- +
- + /* FALL THROUGH */
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
- + DPDNORMY;
- + break;
- +
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
- + DPDNORMX;
- + break;
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
- + break;
- + }
- + assert(xm & DP_HIDDEN_BIT);
- + assert(ym & DP_HIDDEN_BIT);
- +
- + /* provide guard,round and stick bit space */
- + xm <<= 3;
- + ym <<= 3;
- +
- + if (xe > ye) {
- + /* have to shift y fraction right to align
- + */
- + int s = xe - ye;
- + ym = XDPSRS(ym, s);
- + ye += s;
- + } else if (ye > xe) {
- + /* have to shift x fraction right to align
- + */
- + int s = ye - xe;
- + xm = XDPSRS(xm, s);
- + xe += s;
- + }
- + assert(xe == ye);
- + assert(xe <= DP_EMAX);
- +
- + if (xs == ys) {
- + /* generate 28 bit result of adding two 27 bit numbers
- + * leaving result in xm,xs,xe
- + */
- + xm = xm + ym;
- + xe = xe;
- + xs = xs;
- +
- + if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */
- + xm = XDPSRS1(xm);
- + xe++;
- + }
- + } else {
- + if (xm >= ym) {
- + xm = xm - ym;
- + xe = xe;
- + xs = xs;
- + } else {
- + xm = ym - xm;
- + xe = xe;
- + xs = ys;
- + }
- + if (xm == 0)
- + return ieee754dp_zero(ieee754_csr.rm == IEEE754_RD);
- +
- + /* normalize to rounding precision */
- + while ((xm >> (DP_MBITS + 3)) == 0) {
- + xm <<= 1;
- + xe--;
- + }
- +
- + }
- + DPNORMRET2(xs, xe, xm, "add", x, y);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_cmp.c linux-3.4.110/arch/nds32/math-emu/dp_cmp.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/dp_cmp.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/dp_cmp.c 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,66 @@
- +/* IEEE754 floating point arithmetic
- + * double precision: common utilities
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754dp.h"
- +
- +int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp, int sig)
- +{
- + COMPXDP;
- + COMPYDP;
- +
- + EXPLODEXDP;
- + EXPLODEYDP;
- + FLUSHXDP;
- + FLUSHYDP;
- + CLEARCX; /* Even clear inexact flag here */
- +
- + if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) {
- + if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN)
- + SETCX(IEEE754_INVALID_OPERATION);
- + if (cmp & IEEE754_CUN)
- + return 1;
- + if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
- + if (sig && SETANDTESTCX(IEEE754_INVALID_OPERATION))
- + return ieee754si_xcpt(0, "fcmpf", x);
- + }
- + return 0;
- + } else {
- + s64 vx = x.bits;
- + s64 vy = y.bits;
- +
- + if (vx < 0)
- + vx = -vx ^ DP_SIGN_BIT;
- + if (vy < 0)
- + vy = -vy ^ DP_SIGN_BIT;
- +
- + if (vx < vy)
- + return (cmp & IEEE754_CLT) != 0;
- + else if (vx == vy)
- + return (cmp & IEEE754_CEQ) != 0;
- + else
- + return (cmp & IEEE754_CGT) != 0;
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_div.c linux-3.4.110/arch/nds32/math-emu/dp_div.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/dp_div.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/dp_div.c 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,155 @@
- +/* IEEE754 floating point arithmetic
- + * double precision: common utilities
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754dp.h"
- +
- +ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)
- +{
- + COMPXDP;
- + COMPYDP;
- +
- + EXPLODEXDP;
- + EXPLODEYDP;
- +
- + CLEARCX;
- +
- + FLUSHXDP;
- + FLUSHYDP;
- +
- + switch (CLPAIR(xc, yc)) {
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754dp_nanxcpt(ieee754dp_indef(), "div", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
- + return y;
- +
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
- + return x;
- +
- + /* Infinity handling
- + */
- +
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
- + return ieee754dp_zero(xs ^ ys);
- +
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
- + return ieee754dp_inf(xs ^ ys);
- +
- + /* Zero handling
- + */
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
- + SETCX(IEEE754_ZERO_DIVIDE);
- + return ieee754dp_xcpt(ieee754dp_inf(xs ^ ys), "div", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
- + return ieee754dp_zero(xs == ys ? 0 : 1);
- +
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
- + DPDNORMX;
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
- + DPDNORMY;
- + break;
- +
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
- + DPDNORMX;
- + break;
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
- + break;
- + }
- + assert(xm & DP_HIDDEN_BIT);
- + assert(ym & DP_HIDDEN_BIT);
- +
- + /* provide rounding space */
- + xm <<= 3;
- + ym <<= 3;
- +
- + {
- + /* now the dirty work */
- +
- + u64 rm = 0;
- + int re = xe - ye;
- + u64 bm;
- +
- + for (bm = DP_MBIT(DP_MBITS + 2); bm; bm >>= 1) {
- + if (xm >= ym) {
- + xm -= ym;
- + rm |= bm;
- + if (xm == 0)
- + break;
- + }
- + xm <<= 1;
- + }
- + rm <<= 1;
- + if (xm)
- + rm |= 1; /* have remainder, set sticky */
- +
- + assert(rm);
- +
- + /* normalise rm to rounding precision ?
- + */
- + while ((rm >> (DP_MBITS + 3)) == 0) {
- + rm <<= 1;
- + re--;
- + }
- +
- + DPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_fint.c linux-3.4.110/arch/nds32/math-emu/dp_fint.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/dp_fint.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/dp_fint.c 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,79 @@
- +/* IEEE754 floating point arithmetic
- + * double precision: common utilities
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754dp.h"
- +
- +ieee754dp ieee754dp_fint(int x)
- +{
- + u64 xm;
- + int xe;
- + int xs;
- +
- + CLEARCX;
- +
- + if (x == 0)
- + return ieee754dp_zero(0);
- + if (x == 1 || x == -1)
- + return ieee754dp_one(x < 0);
- + if (x == 10 || x == -10)
- + return ieee754dp_ten(x < 0);
- +
- + xs = (x < 0);
- + if (xs) {
- + if (x == (1 << 31))
- + xm = ((unsigned)1 << 31); /* max neg can't be safely negated */
- + else
- + xm = -x;
- + } else {
- + xm = x;
- + }
- +
- +#if 1
- + /* normalize - result can never be inexact or overflow */
- + xe = DP_MBITS;
- + while ((xm >> DP_MBITS) == 0) {
- + xm <<= 1;
- + xe--;
- + }
- + return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
- +#else
- + /* normalize */
- + xe = DP_MBITS + 3;
- + while ((xm >> (DP_MBITS + 3)) == 0) {
- + xm <<= 1;
- + xe--;
- + }
- + DPNORMRET1(xs, xe, xm, "fint", x);
- +#endif
- +}
- +
- +ieee754dp ieee754dp_funs(unsigned int u)
- +{
- + if ((int)u < 0)
- + return ieee754dp_add(ieee754dp_1e31(),
- + ieee754dp_fint(u & ~(1 << 31)));
- + return ieee754dp_fint(u);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_flong.c linux-3.4.110/arch/nds32/math-emu/dp_flong.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/dp_flong.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/dp_flong.c 2016-04-07 10:20:50.958081643 +0200
- @@ -0,0 +1,77 @@
- +/* IEEE754 floating point arithmetic
- + * double precision: common utilities
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754dp.h"
- +
- +ieee754dp ieee754dp_flong(s64 x)
- +{
- + u64 xm;
- + int xe;
- + int xs;
- +
- + CLEARCX;
- +
- + if (x == 0)
- + return ieee754dp_zero(0);
- + if (x == 1 || x == -1)
- + return ieee754dp_one(x < 0);
- + if (x == 10 || x == -10)
- + return ieee754dp_ten(x < 0);
- +
- + xs = (x < 0);
- + if (xs) {
- + if (x == (1ULL << 63))
- + xm = (1ULL << 63); /* max neg can't be safely negated */
- + else
- + xm = -x;
- + } else {
- + xm = x;
- + }
- +
- + /* normalize */
- + xe = DP_MBITS + 3;
- + if (xm >> (DP_MBITS + 1 + 3)) {
- + /* shunt out overflow bits */
- + while (xm >> (DP_MBITS + 1 + 3)) {
- + XDPSRSX1();
- + }
- + } else {
- + /* normalize in grs extended double precision */
- + while ((xm >> (DP_MBITS + 3)) == 0) {
- + xm <<= 1;
- + xe--;
- + }
- + }
- + DPNORMRET1(xs, xe, xm, "dp_flong", x);
- +}
- +
- +ieee754dp ieee754dp_fulong(u64 u)
- +{
- + if ((s64) u < 0)
- + return ieee754dp_add(ieee754dp_1e63(),
- + ieee754dp_flong(u & ~(1ULL << 63)));
- + return ieee754dp_flong(u);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_frexp.c linux-3.4.110/arch/nds32/math-emu/dp_frexp.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/dp_frexp.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/dp_frexp.c 2016-04-07 10:20:50.974082262 +0200
- @@ -0,0 +1,52 @@
- +/* IEEE754 floating point arithmetic
- + * double precision: common utilities
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754dp.h"
- +
- +/* close to ieeep754dp_logb
- +*/
- +ieee754dp ieee754dp_frexp(ieee754dp x, int *eptr)
- +{
- + COMPXDP;
- + CLEARCX;
- + EXPLODEXDP;
- +
- + switch (xc) {
- + case IEEE754_CLASS_SNAN:
- + case IEEE754_CLASS_QNAN:
- + case IEEE754_CLASS_INF:
- + case IEEE754_CLASS_ZERO:
- + *eptr = 0;
- + return x;
- + case IEEE754_CLASS_DNORM:
- + DPDNORMX;
- + break;
- + case IEEE754_CLASS_NORM:
- + break;
- + }
- + *eptr = xe + 1;
- + return builddp(xs, -1 + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_fsp.c linux-3.4.110/arch/nds32/math-emu/dp_fsp.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/dp_fsp.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/dp_fsp.c 2016-04-07 10:20:50.974082262 +0200
- @@ -0,0 +1,71 @@
- +/* IEEE754 floating point arithmetic
- + * double precision: common utilities
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754dp.h"
- +
- +ieee754dp ieee754dp_fsp(ieee754sp x)
- +{
- + COMPXSP;
- +
- + EXPLODEXSP;
- +
- + CLEARCX;
- +
- + FLUSHXSP;
- +
- + switch (xc) {
- + case IEEE754_CLASS_SNAN:
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754dp_nanxcpt(ieee754dp_indef(), "fsp");
- + case IEEE754_CLASS_QNAN:
- + return ieee754dp_nanxcpt(builddp(xs,
- + DP_EMAX + 1 + DP_EBIAS,
- + ((u64) xm
- + << (DP_MBITS -
- + SP_MBITS))), "fsp", x);
- + case IEEE754_CLASS_INF:
- + return ieee754dp_inf(xs);
- + case IEEE754_CLASS_ZERO:
- + return ieee754dp_zero(xs);
- + case IEEE754_CLASS_DNORM:
- + /* normalize */
- + while ((xm >> SP_MBITS) == 0) {
- + xm <<= 1;
- + xe--;
- + }
- + break;
- + case IEEE754_CLASS_NORM:
- + break;
- + }
- +
- + /* CANT possibly overflow,underflow, or need rounding
- + */
- +
- + /* drop the hidden bit */
- + xm &= ~SP_HIDDEN_BIT;
- +
- + return builddp(xs, xe + DP_EBIAS, (u64) xm << (DP_MBITS - SP_MBITS));
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_logb.c linux-3.4.110/arch/nds32/math-emu/dp_logb.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/dp_logb.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/dp_logb.c 2016-04-07 10:20:50.974082262 +0200
- @@ -0,0 +1,53 @@
- +/* IEEE754 floating point arithmetic
- + * double precision: common utilities
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754dp.h"
- +
- +ieee754dp ieee754dp_logb(ieee754dp x)
- +{
- + COMPXDP;
- +
- + CLEARCX;
- +
- + EXPLODEXDP;
- +
- + switch (xc) {
- + case IEEE754_CLASS_SNAN:
- + return ieee754dp_nanxcpt(x, "logb", x);
- + case IEEE754_CLASS_QNAN:
- + return x;
- + case IEEE754_CLASS_INF:
- + return ieee754dp_inf(0);
- + case IEEE754_CLASS_ZERO:
- + return ieee754dp_inf(1);
- + case IEEE754_CLASS_DNORM:
- + DPDNORMX;
- + break;
- + case IEEE754_CLASS_NORM:
- + break;
- + }
- + return ieee754dp_fint(xe);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_modf.c linux-3.4.110/arch/nds32/math-emu/dp_modf.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/dp_modf.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/dp_modf.c 2016-04-07 10:20:50.974082262 +0200
- @@ -0,0 +1,79 @@
- +/* IEEE754 floating point arithmetic
- + * double precision: common utilities
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754dp.h"
- +
- +/* modf function is always exact for a finite number
- +*/
- +ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip)
- +{
- + COMPXDP;
- +
- + CLEARCX;
- +
- + EXPLODEXDP;
- +
- + switch (xc) {
- + case IEEE754_CLASS_SNAN:
- + case IEEE754_CLASS_QNAN:
- + case IEEE754_CLASS_INF:
- + case IEEE754_CLASS_ZERO:
- + *ip = x;
- + return x;
- + case IEEE754_CLASS_DNORM:
- + /* far to small */
- + *ip = ieee754dp_zero(xs);
- + return x;
- + case IEEE754_CLASS_NORM:
- + break;
- + }
- + if (xe < 0) {
- + *ip = ieee754dp_zero(xs);
- + return x;
- + }
- + if (xe >= DP_MBITS) {
- + *ip = x;
- + return ieee754dp_zero(xs);
- + }
- + /* generate ipart mantissa by clearing bottom bits
- + */
- + *ip = builddp(xs, xe + DP_EBIAS,
- + ((xm >> (DP_MBITS - xe)) << (DP_MBITS - xe)) &
- + ~DP_HIDDEN_BIT);
- +
- + /* generate fpart mantissa by clearing top bits
- + * and normalizing (must be able to normalize)
- + */
- + xm = (xm << (64 - (DP_MBITS - xe))) >> (64 - (DP_MBITS - xe));
- + if (xm == 0)
- + return ieee754dp_zero(xs);
- +
- + while ((xm >> DP_MBITS) == 0) {
- + xm <<= 1;
- + xe--;
- + }
- + return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_mul.c linux-3.4.110/arch/nds32/math-emu/dp_mul.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/dp_mul.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/dp_mul.c 2016-04-07 10:20:50.974082262 +0200
- @@ -0,0 +1,170 @@
- +/* IEEE754 floating point arithmetic
- + * double precision: common utilities
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754dp.h"
- +
- +ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y)
- +{
- + COMPXDP;
- + COMPYDP;
- +
- + EXPLODEXDP;
- + EXPLODEYDP;
- +
- + CLEARCX;
- +
- + FLUSHXDP;
- + FLUSHYDP;
- +
- + switch (CLPAIR(xc, yc)) {
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754dp_nanxcpt(ieee754dp_indef(), "mul", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
- + return y;
- +
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
- + return x;
- +
- + /* Infinity handling */
- +
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754dp_xcpt(ieee754dp_indef(), "mul", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
- + return ieee754dp_inf(xs ^ ys);
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
- + return ieee754dp_zero(xs ^ ys);
- +
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
- + DPDNORMX;
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
- + DPDNORMY;
- + break;
- +
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
- + DPDNORMX;
- + break;
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
- + break;
- + }
- + /* rm = xm * ym, re = xe+ye basicly */
- + assert(xm & DP_HIDDEN_BIT);
- + assert(ym & DP_HIDDEN_BIT);
- + {
- + int re = xe + ye;
- + int rs = xs ^ ys;
- + u64 rm;
- +
- + /* shunt to top of word */
- + xm <<= 64 - (DP_MBITS + 1);
- + ym <<= 64 - (DP_MBITS + 1);
- +
- + /* multiply 32bits xm,ym to give high 32bits rm with stickness
- + */
- +
- + /* 32 * 32 => 64 */
- +#define DPXMULT(x, y) ((u64)(x) * (u64)y)
- +
- + {
- + unsigned lxm = xm;
- + unsigned hxm = xm >> 32;
- + unsigned lym = ym;
- + unsigned hym = ym >> 32;
- + u64 lrm;
- + u64 hrm;
- +
- + lrm = DPXMULT(lxm, lym);
- + hrm = DPXMULT(hxm, hym);
- +
- + {
- + u64 t = DPXMULT(lxm, hym);
- + {
- + u64 at = lrm + (t << 32);
- + hrm += at < lrm;
- + lrm = at;
- + }
- + hrm = hrm + (t >> 32);
- + }
- +
- + {
- + u64 t = DPXMULT(hxm, lym);
- + {
- + u64 at = lrm + (t << 32);
- + hrm += at < lrm;
- + lrm = at;
- + }
- + hrm = hrm + (t >> 32);
- + }
- + rm = hrm | (lrm != 0);
- + }
- +
- + /*
- + * sticky shift down to normal rounding precision
- + */
- + if ((s64) rm < 0) {
- + rm = (rm >> (64 - (DP_MBITS + 1 + 3))) |
- + ((rm << (DP_MBITS + 1 + 3)) != 0);
- + re++;
- + } else {
- + rm = (rm >> (64 - (DP_MBITS + 1 + 3 + 1))) |
- + ((rm << (DP_MBITS + 1 + 3 + 1)) != 0);
- + }
- + assert(rm & (DP_HIDDEN_BIT << 3));
- + DPNORMRET2(rs, re, rm, "mul", x, y);
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_scalb.c linux-3.4.110/arch/nds32/math-emu/dp_scalb.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/dp_scalb.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/dp_scalb.c 2016-04-07 10:20:50.974082262 +0200
- @@ -0,0 +1,56 @@
- +/* IEEE754 floating point arithmetic
- + * double precision: common utilities
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754dp.h"
- +
- +ieee754dp ieee754dp_scalb(ieee754dp x, int n)
- +{
- + COMPXDP;
- +
- + CLEARCX;
- +
- + EXPLODEXDP;
- +
- + switch (xc) {
- + case IEEE754_CLASS_SNAN:
- + return ieee754dp_nanxcpt(x, "scalb", x, n);
- + case IEEE754_CLASS_QNAN:
- + case IEEE754_CLASS_INF:
- + case IEEE754_CLASS_ZERO:
- + return x;
- + case IEEE754_CLASS_DNORM:
- + DPDNORMX;
- + break;
- + case IEEE754_CLASS_NORM:
- + break;
- + }
- + DPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
- +}
- +
- +ieee754dp ieee754dp_ldexp(ieee754dp x, int n)
- +{
- + return ieee754dp_scalb(x, n);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_simple.c linux-3.4.110/arch/nds32/math-emu/dp_simple.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/dp_simple.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/dp_simple.c 2016-04-07 10:20:50.974082262 +0200
- @@ -0,0 +1,87 @@
- +/* IEEE754 floating point arithmetic
- + * double precision: common utilities
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754dp.h"
- +
- +int ieee754dp_finite(ieee754dp x)
- +{
- + return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS;
- +}
- +
- +ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y)
- +{
- + CLEARCX;
- + DPSIGN(x) = DPSIGN(y);
- + return x;
- +}
- +
- +ieee754dp ieee754dp_neg(ieee754dp x)
- +{
- + COMPXDP;
- +
- + EXPLODEXDP;
- + CLEARCX;
- + FLUSHXDP;
- +
- + /*
- + * Invert the sign ALWAYS to prevent an endless recursion on
- + * pow() in libc.
- + */
- + /* quick fix up */
- + DPSIGN(x) ^= 1;
- +
- + if (xc == IEEE754_CLASS_SNAN) {
- + ieee754dp y = ieee754dp_indef();
- + SETCX(IEEE754_INVALID_OPERATION);
- + DPSIGN(y) = DPSIGN(x);
- + return ieee754dp_nanxcpt(y, "neg");
- + }
- +
- + if (ieee754dp_isnan(x)) /* but not infinity */
- + return ieee754dp_nanxcpt(x, "neg", x);
- + return x;
- +}
- +
- +ieee754dp ieee754dp_abs(ieee754dp x)
- +{
- + COMPXDP;
- +
- + EXPLODEXDP;
- + CLEARCX;
- + FLUSHXDP;
- +
- + if (xc == IEEE754_CLASS_SNAN) {
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754dp_nanxcpt(ieee754dp_indef(), "neg");
- + }
- +
- + if (ieee754dp_isnan(x)) /* but not infinity */
- + return ieee754dp_nanxcpt(x, "abs", x);
- +
- + /* quick fix up */
- + DPSIGN(x) = 0;
- + return x;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_sqrt.c linux-3.4.110/arch/nds32/math-emu/dp_sqrt.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/dp_sqrt.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/dp_sqrt.c 2016-04-07 10:20:50.974082262 +0200
- @@ -0,0 +1,164 @@
- +/* IEEE754 floating point arithmetic
- + * double precision square root
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754dp.h"
- +
- +static const unsigned table[] = {
- + 0, 1204, 3062, 5746, 9193, 13348, 18162, 23592,
- + 29598, 36145, 43202, 50740, 58733, 67158, 75992,
- + 85215, 83599, 71378, 60428, 50647, 41945, 34246,
- + 27478, 21581, 16499, 12183, 8588, 5674, 3403,
- + 1742, 661, 130
- +};
- +
- +ieee754dp ieee754dp_sqrt(ieee754dp x)
- +{
- + struct _ieee754_csr oldcsr;
- + ieee754dp y, z, t;
- + unsigned scalx, yh;
- + COMPXDP;
- +
- + EXPLODEXDP;
- + CLEARCX;
- + FLUSHXDP;
- +
- + /* x == INF or NAN? */
- + switch (xc) {
- + case IEEE754_CLASS_QNAN:
- + /* sqrt(Nan) = Nan */
- + return ieee754dp_nanxcpt(x, "sqrt");
- + case IEEE754_CLASS_SNAN:
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt");
- + case IEEE754_CLASS_ZERO:
- + /* sqrt(0) = 0 */
- + return x;
- + case IEEE754_CLASS_INF:
- + if (xs) {
- + /* sqrt(-Inf) = Nan */
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt");
- + }
- + /* sqrt(+Inf) = Inf */
- + return x;
- + case IEEE754_CLASS_DNORM:
- + DPDNORMX;
- + /* fall through */
- + case IEEE754_CLASS_NORM:
- + if (xs) {
- + /* sqrt(-x) = Nan */
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt");
- + }
- + break;
- + }
- +
- + /* save old csr; switch off INX enable & flag; set RN rounding */
- + oldcsr = ieee754_csr;
- + ieee754_csr.mx &= ~IEEE754_INEXACT;
- + ieee754_csr.sx &= ~IEEE754_INEXACT;
- + ieee754_csr.rm = IEEE754_RN;
- +
- + /* adjust exponent to prevent overflow */
- + scalx = 0;
- + if (xe > 512) { /* x > 2**-512? */
- + xe -= 512; /* x = x / 2**512 */
- + scalx += 256;
- + } else if (xe < -512) { /* x < 2**-512? */
- + xe += 512; /* x = x * 2**512 */
- + scalx -= 256;
- + }
- +
- + y = x = builddp(0, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
- +
- + /* magic initial approximation to almost 8 sig. bits */
- + yh = y.bits >> 32;
- + yh = (yh >> 1) + 0x1ff80000;
- + yh = yh - table[(yh >> 15) & 31];
- + y.bits = ((u64) yh << 32) | (y.bits & 0xffffffff);
- +
- + /* Heron's rule once with correction to improve to ~18 sig. bits */
- + /* t=x/y; y=y+t; py[n0]=py[n0]-0x00100006; py[n1]=0; */
- + t = ieee754dp_div(x, y);
- + y = ieee754dp_add(y, t);
- + y.bits -= 0x0010000600000000LL;
- + y.bits &= 0xffffffff00000000LL;
- +
- + /* triple to almost 56 sig. bits: y ~= sqrt(x) to within 1 ulp */
- + /* t=y*y; z=t; pt[n0]+=0x00100000; t+=z; z=(x-z)*y; */
- + z = t = ieee754dp_mul(y, y);
- + t.parts.bexp += 0x001;
- + t = ieee754dp_add(t, z);
- + z = ieee754dp_mul(ieee754dp_sub(x, z), y);
- +
- + /* t=z/(t+x) ; pt[n0]+=0x00100000; y+=t; */
- + t = ieee754dp_div(z, ieee754dp_add(t, x));
- + t.parts.bexp += 0x001;
- + y = ieee754dp_add(y, t);
- +
- + /* twiddle last bit to force y correctly rounded */
- +
- + /* set RZ, clear INEX flag */
- + ieee754_csr.rm = IEEE754_RZ;
- + ieee754_csr.sx &= ~IEEE754_INEXACT;
- +
- + /* t=x/y; ...chopped quotient, possibly inexact */
- + t = ieee754dp_div(x, y);
- +
- + if (ieee754_csr.sx & IEEE754_INEXACT || t.bits != y.bits) {
- +
- + if (!(ieee754_csr.sx & IEEE754_INEXACT))
- + /* t = t-ulp */
- + t.bits -= 1;
- +
- + /* add inexact to result status */
- + oldcsr.cx |= IEEE754_INEXACT;
- + oldcsr.sx |= IEEE754_INEXACT;
- +
- + switch (oldcsr.rm) {
- + case IEEE754_RP:
- + y.bits += 1;
- + /* drop through */
- + case IEEE754_RN:
- + t.bits += 1;
- + break;
- + }
- +
- + /* y=y+t; ...chopped sum */
- + y = ieee754dp_add(y, t);
- +
- + /* adjust scalx for correctly rounded sqrt(x) */
- + scalx -= 1;
- + }
- +
- + /* py[n0]=py[n0]+scalx; ...scale back y */
- + y.parts.bexp += scalx;
- +
- + /* restore rounding mode, possibly set inexact */
- + ieee754_csr = oldcsr;
- +
- + return y;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_sub.c linux-3.4.110/arch/nds32/math-emu/dp_sub.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/dp_sub.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/dp_sub.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,187 @@
- +/* IEEE754 floating point arithmetic
- + * double precision: common utilities
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754dp.h"
- +
- +ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)
- +{
- + COMPXDP;
- + COMPYDP;
- +
- + EXPLODEXDP;
- + EXPLODEYDP;
- +
- + CLEARCX;
- +
- + FLUSHXDP;
- + FLUSHYDP;
- +
- + switch (CLPAIR(xc, yc)) {
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754dp_nanxcpt(ieee754dp_indef(), "sub", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
- + return y;
- +
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
- + return x;
- +
- + /* Infinity handling
- + */
- +
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
- + if (xs != ys)
- + return x;
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754dp_xcpt(ieee754dp_indef(), "sub", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
- + return ieee754dp_inf(ys ^ 1);
- +
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
- + return x;
- +
- + /* Zero handling
- + */
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
- + if (xs != ys)
- + return x;
- + else
- + return ieee754dp_zero(ieee754_csr.rm == IEEE754_RD);
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
- + return x;
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
- + /* quick fix up */
- + DPSIGN(y) ^= 1;
- + return y;
- +
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
- + DPDNORMX;
- + /* FAAL THOROUGH */
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
- + /* normalize ym,ye */
- + DPDNORMY;
- + break;
- +
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
- + /* normalize xm,xe */
- + DPDNORMX;
- + break;
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
- + break;
- + }
- + /* flip sign of y and handle as add */
- + ys ^= 1;
- +
- + assert(xm & DP_HIDDEN_BIT);
- + assert(ym & DP_HIDDEN_BIT);
- +
- + /* provide guard,round and stick bit dpace */
- + xm <<= 3;
- + ym <<= 3;
- +
- + if (xe > ye) {
- + /* have to shift y fraction right to align
- + */
- + int s = xe - ye;
- + ym = XDPSRS(ym, s);
- + ye += s;
- + } else if (ye > xe) {
- + /* have to shift x fraction right to align
- + */
- + int s = ye - xe;
- + xm = XDPSRS(xm, s);
- + xe += s;
- + }
- + assert(xe == ye);
- + assert(xe <= DP_EMAX);
- +
- + if (xs == ys) {
- + /* generate 28 bit result of adding two 27 bit numbers
- + */
- + xm = xm + ym;
- + xe = xe;
- + xs = xs;
- +
- + if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */
- + xm = XDPSRS1(xm); /* shift preserving sticky */
- + xe++;
- + }
- + } else {
- + if (xm >= ym) {
- + xm = xm - ym;
- + xe = xe;
- + xs = xs;
- + } else {
- + xm = ym - xm;
- + xe = xe;
- + xs = ys;
- + }
- + if (xm == 0) {
- + if (ieee754_csr.rm == IEEE754_RD)
- + return ieee754dp_zero(1); /* round negative inf. => sign = -1 */
- + else
- + return ieee754dp_zero(0); /* other round modes => sign = 1 */
- + }
- +
- + /* normalize to rounding precision
- + */
- + while ((xm >> (DP_MBITS + 3)) == 0) {
- + xm <<= 1;
- + xe--;
- + }
- + }
- + DPNORMRET2(xs, xe, xm, "sub", x, y);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_tint.c linux-3.4.110/arch/nds32/math-emu/dp_tint.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/dp_tint.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/dp_tint.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,121 @@
- +/* IEEE754 floating point arithmetic
- + * double precision: common utilities
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include <linux/kernel.h>
- +#include "ieee754dp.h"
- +
- +int ieee754dp_tint(ieee754dp x)
- +{
- + COMPXDP;
- +
- + CLEARCX;
- +
- + EXPLODEXDP;
- + FLUSHXDP;
- +
- + switch (xc) {
- + case IEEE754_CLASS_SNAN:
- + case IEEE754_CLASS_QNAN:
- + case IEEE754_CLASS_INF:
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x);
- + case IEEE754_CLASS_ZERO:
- + return 0;
- + case IEEE754_CLASS_DNORM:
- + case IEEE754_CLASS_NORM:
- + break;
- + }
- + if (xe > 31) {
- + /* Set invalid. We will only use overflow for floating
- + point overflow */
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x);
- + }
- + /* oh gawd */
- + if (xe > DP_MBITS) {
- + xm <<= xe - DP_MBITS;
- + } else if (xe < DP_MBITS) {
- + u64 residue;
- + int round;
- + int sticky;
- + int odd;
- +
- + if (xe < -1) {
- + residue = xm;
- + round = 0;
- + sticky = residue != 0;
- + xm = 0;
- + } else {
- + residue = xm << (64 - DP_MBITS + xe);
- + round = (residue >> 63) != 0;
- + sticky = (residue << 1) != 0;
- + xm >>= DP_MBITS - xe;
- + }
- + /* Note: At this point upper 32 bits of xm are guaranteed
- + to be zero */
- + odd = (xm & 0x1) != 0x0;
- + switch (ieee754_csr.rm) {
- + case IEEE754_RN:
- + if (round && (sticky || odd))
- + xm++;
- + break;
- + case IEEE754_RZ:
- + break;
- + case IEEE754_RU: /* toward +Infinity */
- + if ((round || sticky) && !xs)
- + xm++;
- + break;
- + case IEEE754_RD: /* toward -Infinity */
- + if ((round || sticky) && xs)
- + xm++;
- + break;
- + }
- + /* look for valid corner case 0x80000000 */
- + if ((xm >> 31) != 0 && (xs == 0 || xm != 0x80000000)) {
- + /* This can happen after rounding */
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x);
- + }
- + if (round || sticky)
- + SETCX(IEEE754_INEXACT);
- + }
- + if (xs)
- + return -xm;
- + else
- + return xm;
- +}
- +
- +unsigned int ieee754dp_tuns(ieee754dp x)
- +{
- + ieee754dp hb = ieee754dp_1e31();
- +
- + /* what if x < 0 ?? */
- + if (ieee754dp_lt(x, hb))
- + return (unsigned)ieee754dp_tint(x);
- +
- + return (unsigned)ieee754dp_tint(ieee754dp_sub(x, hb)) |
- + ((unsigned)1 << 31);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_tlong.c linux-3.4.110/arch/nds32/math-emu/dp_tlong.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/dp_tlong.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/dp_tlong.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,123 @@
- +/* IEEE754 floating point arithmetic
- + * double precision: common utilities
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754dp.h"
- +
- +s64 ieee754dp_tlong(ieee754dp x)
- +{
- + COMPXDP;
- +
- + CLEARCX;
- +
- + EXPLODEXDP;
- + FLUSHXDP;
- +
- + switch (xc) {
- + case IEEE754_CLASS_SNAN:
- + case IEEE754_CLASS_QNAN:
- + case IEEE754_CLASS_INF:
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
- + case IEEE754_CLASS_ZERO:
- + return 0;
- + case IEEE754_CLASS_DNORM:
- + case IEEE754_CLASS_NORM:
- + break;
- + }
- + if (xe >= 63) {
- + /* look for valid corner case */
- + if (xe == 63 && xs && xm == DP_HIDDEN_BIT)
- + return -0x8000000000000000LL;
- + /* Set invalid. We will only use overflow for floating
- + point overflow */
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
- + }
- + /* oh gawd */
- + if (xe > DP_MBITS) {
- + xm <<= xe - DP_MBITS;
- + } else if (xe < DP_MBITS) {
- + u64 residue;
- + int round;
- + int sticky;
- + int odd;
- +
- + if (xe < -1) {
- + residue = xm;
- + round = 0;
- + sticky = residue != 0;
- + xm = 0;
- + } else {
- + /* Shifting a u64 64 times does not work,
- + * so we do it in two steps. Be aware that xe
- + * may be -1 */
- + residue = xm << (xe + 1);
- + residue <<= 63 - DP_MBITS;
- + round = (residue >> 63) != 0;
- + sticky = (residue << 1) != 0;
- + xm >>= DP_MBITS - xe;
- + }
- + odd = (xm & 0x1) != 0x0;
- + switch (ieee754_csr.rm) {
- + case IEEE754_RN:
- + if (round && (sticky || odd))
- + xm++;
- + break;
- + case IEEE754_RZ:
- + break;
- + case IEEE754_RU: /* toward +Infinity */
- + if ((round || sticky) && !xs)
- + xm++;
- + break;
- + case IEEE754_RD: /* toward -Infinity */
- + if ((round || sticky) && xs)
- + xm++;
- + break;
- + }
- + if ((xm >> 63) != 0) {
- + /* This can happen after rounding */
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
- + }
- + if (round || sticky)
- + SETCX(IEEE754_INEXACT);
- + }
- + if (xs)
- + return -xm;
- + else
- + return xm;
- +}
- +
- +u64 ieee754dp_tulong(ieee754dp x)
- +{
- + ieee754dp hb = ieee754dp_1e63();
- +
- + /* what if x < 0 ?? */
- + if (ieee754dp_lt(x, hb))
- + return (u64) ieee754dp_tlong(x);
- +
- + return (u64) ieee754dp_tlong(ieee754dp_sub(x, hb)) | (1ULL << 63);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/fpuemu.c linux-3.4.110/arch/nds32/math-emu/fpuemu.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/fpuemu.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/fpuemu.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,565 @@
- +/*
- + * linux/arch/nds32/math-emu/fpuemu.c: a nds32 coprocessor (fpu) instruction emulator
- + *
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
- + * Copyright (C) 2000 MIPS Technologies, Inc.
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * A complete emulator for MIPS coprocessor 1 instructions. This is
- + * required for #float(switch) or #float(trap), where it catches all
- + * COP1 instructions via the "CoProcessor Unusable" exception.
- + *
- + * More surprisingly it is also required for #float(ieee), to help out
- + * the hardware fpu at the boundaries of the IEEE-754 representation
- + * (denormalised values, infinities, underflow, etc). It is made
- + * quite nasty because emulation of some non-COP1 instructions is
- + * required, e.g. in branch delay slots.
- + *
- + * Note if you know that you won't have an fpu, then you'll get much
- + * better performance by compiling with -msoft-float!
- + */
- +#include <linux/sched.h>
- +#include <linux/debugfs.h>
- +
- +#include <asm/processor.h>
- +#include <asm/ptrace.h>
- +#include <asm/bitfield.h>
- +#include <asm/uaccess.h>
- +
- +#include "ieee754.h"
- +#include "insn.h"
- +#include "fpu_emulator.h"
- +
- +/* Function which emulates a floating point instruction. */
- +
- +static int fpu_emu(struct pt_regs *, struct fpu_struct *, unsigned long);
- +
- +/* Further private data for which no space exists in fpu_struct */
- +
- +struct fpu_emulator_stats fpuemustats;
- +
- +/* rounding mode */
- +#define FPU_FPCSR_RN 0x0 /* nearest */
- +#define FPU_FPCSR_RU 0x1 /* towards +Infinity */
- +#define FPU_FPCSR_RD 0x2 /* towards -Infinity */
- +#define FPU_FPCSR_RZ 0x3 /* towards zero */
- +
- +/* Convert Mips rounding mode (0..3) to IEEE library modes. */
- +static const unsigned char ieee_rm[4] = {
- + [FPU_FPCSR_RN] = IEEE754_RN,
- + [FPU_FPCSR_RU] = IEEE754_RU,
- + [FPU_FPCSR_RD] = IEEE754_RD,
- + [FPU_FPCSR_RZ] = IEEE754_RZ,
- +};
- +
- +/* Convert IEEE library modes to NDS32 rounding mode (0..3). */
- +static const unsigned char nds32_rm[4] = {
- + [IEEE754_RN] = FPU_FPCSR_RN,
- + [IEEE754_RZ] = FPU_FPCSR_RZ,
- + [IEEE754_RD] = FPU_FPCSR_RD,
- + [IEEE754_RU] = FPU_FPCSR_RU,
- +};
- +
- +/*
- + * In the Linux kernel, we support selection of FPR format on the
- + * basis of the Status.FR bit. This does imply that, if a full 32
- + * FPRs are desired, there needs to be a flip-flop that can be written
- + * to one at that bit position. In any case, O32 MIPS ABI uses
- + * only the even FPRs (Status.FR = 0).
- + */
- +
- +#define CP0_STATUS_FR_SUPPORT
- +
- +#ifdef CP0_STATUS_FR_SUPPORT
- +#define FR_BIT ST0_FR
- +#else
- +#define FR_BIT 0
- +#endif
- +
- +#define SIFROMREG(si, x) ((si) = *((unsigned long *)ctx + x))
- +#define SITOREG(si, x) (*((unsigned long *)ctx + x)= (si))
- +
- +#ifdef __NDS32_EL__
- +#define DIFROMREG(di, x) ((di) = (unsigned long long)ptr[2*x] << 32 | (unsigned long long)ptr[2*x+1])
- +#define DITOREG(di, x) ptr[2*x] = (di) >> 32; ptr[2*x+1] = (unsigned long)(di)
- +#else
- +#define DIFROMREG(di, x) ((di) = (unsigned long long)ptr[2*x+1] << 32 | (unsigned long long)ptr[2*x])
- +#define DITOREG(di, x) ptr[2*x+1] = (di) >> 32; ptr[2*x] = (unsigned long)(di)
- +#endif
- +
- +#define SPFROMREG(sp, x) SIFROMREG((sp).bits, x)
- +#define SPTOREG(sp, x) SITOREG((sp).bits, x)
- +#define DPFROMREG(dp, x) DIFROMREG((dp).bits, x)
- +#define DPTOREG(dp, x) DITOREG((dp).bits, x)
- +
- +#define DEF3OP(name, p, f1, f2, f3) \
- +static ieee754##p fpemu_##p##_##name(ieee754##p r, ieee754##p s, \
- + ieee754##p t) \
- +{ \
- + struct _ieee754_csr ieee754_csr_save; \
- + s = f1(s, t); \
- + ieee754_csr_save = ieee754_csr; \
- + s = f2(s, r); \
- + ieee754_csr_save.cx |= ieee754_csr.cx; \
- + ieee754_csr_save.sx |= ieee754_csr.sx; \
- + s = f3(s); \
- + ieee754_csr.cx |= ieee754_csr_save.cx; \
- + ieee754_csr.sx |= ieee754_csr_save.sx; \
- + return s; \
- +}
- +
- +DEF3OP(madd, sp, ieee754sp_mul, ieee754sp_add,);
- +DEF3OP(msub, sp, ieee754sp_mul, ieee754sp_sub,);
- +DEF3OP(nmadd, sp, ieee754sp_mul, ieee754sp_add, ieee754sp_neg);
- +DEF3OP(nmsub, sp, ieee754sp_mul, ieee754sp_sub, ieee754sp_neg);
- +DEF3OP(madd, dp, ieee754dp_mul, ieee754dp_add,);
- +DEF3OP(msub, dp, ieee754dp_mul, ieee754dp_sub,);
- +DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg);
- +DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg);
- +
- +/*
- + * Emulate the floating point instruction w/ denorm input pointed at by IPC.
- + * According to spec, only FPU arithmetic, data format conversion, and compare instructions.
- + */
- +
- +static int fpuEmulate(struct pt_regs *regs, struct fpu_struct *fpu)
- +{
- + unsigned long insn = 0, addr = regs->NDS32_ipc;
- + unsigned long emulpc, contpc;
- + unsigned char *pc = (void *)&insn;
- + char c;
- + int i = 0;
- +
- + for (i = 0; i < 4; i++) {
- + if (__get_user(c, (unsigned char *)addr++))
- + return SIGBUS;
- + *pc++ = c;
- + }
- +
- + insn = be32_to_cpu(insn);
- +
- + emulpc = regs->NDS32_ipc;
- + contpc = regs->NDS32_ipc + 4;
- +
- + fpuemustats.emulated++;
- + switch (NDS32Insn_OPCODE(insn)) {
- + case cop0_op:
- + switch (NDS32Insn_OPCODE_COP0(insn)) {
- +
- + case fs1_op:
- + case fs2_op:
- + case fd1_op:
- + case fd2_op:
- + {
- + int sig;
- +
- + /* a real fpu computation instruction */
- + if ((sig = fpu_emu(regs, fpu, insn)))
- + return sig;
- + }
- + break;
- +
- + default:
- + return SIGILL;
- + }
- + break;
- + default:
- + return SIGILL;
- + }
- +
- + /* we did it !! */
- + regs->NDS32_ipc = contpc;
- +
- + return 0;
- +}
- +
- +/*
- + * Conversion table from NDS32 fcmp TYP
- + * cond = ieee754dp_cmp(x,y,IEEE754_UN,sig);
- + */
- +static const unsigned char cmptab[8] = {
- + IEEE754_CEQ,
- + IEEE754_CLT,
- + IEEE754_CLT | IEEE754_CEQ,
- + IEEE754_CUN,
- + 0,
- + 0,
- + 0,
- + 0,
- +};
- +
- +/*
- + * Emulate a single FPU arithmetic instruction.
- + */
- +static int fpu_emu(struct pt_regs *xcp, struct fpu_struct *ctx,
- + unsigned long insn)
- +{
- + int rfmt; /* resulting format */
- + unsigned rfpcsr = 0; /* resulting csr */
- + unsigned long *ptr = (unsigned long *)ctx;
- + union {
- + ieee754dp d;
- + ieee754sp s;
- + int w;
- + } rv; /* resulting value */
- +
- + fpuemustats.fpuops++;
- + switch (rfmt = NDS32Insn_OPCODE_COP0(insn)) {
- + case fs1_op:{
- + union {
- + ieee754sp(*t) (ieee754sp, ieee754sp, ieee754sp);
- + ieee754sp(*b) (ieee754sp, ieee754sp);
- + ieee754sp(*u) (ieee754sp);
- + } handler;
- +
- + switch (NDS32Insn_OPCODE_BIT69(insn)) {
- + case fadds_op:
- + handler.b = ieee754sp_add;
- + goto scopbop;
- + case fsubs_op:
- + handler.b = ieee754sp_sub;
- + goto scopbop;
- + case fmadds_op:
- + handler.t = fpemu_sp_madd;
- + goto scoptop;
- + case fmsubs_op:
- + handler.t = fpemu_sp_msub;
- + goto scoptop;
- + case fnmadds_op:
- + handler.t = fpemu_sp_nmadd;
- + goto scoptop;
- + case fnmsubs_op:
- + handler.t = fpemu_sp_nmsub;
- + goto scoptop;
- + case fmuls_op:
- + handler.b = ieee754sp_mul;
- + goto scopbop;
- + case fdivs_op:
- + handler.b = ieee754sp_div;
- + goto scopbop;
- +
- + /* binary op on handler */
- +scoptop:
- + {
- + ieee754sp fd, fr, fs, ft;
- +
- + SPFROMREG(fr,
- + NDS32Insn_OPCODE_Rt(insn));
- + SPFROMREG(fs,
- + NDS32Insn_OPCODE_Ra(insn));
- + SPFROMREG(ft,
- + NDS32Insn_OPCODE_Rb(insn));
- + fd = (*handler.t) (fr, fs, ft);
- + SPTOREG(fd, NDS32Insn_OPCODE_Rt(insn));
- + }
- +scopbop:
- + {
- + ieee754sp fs, ft;
- +
- + SPFROMREG(fs,
- + NDS32Insn_OPCODE_Ra(insn));
- + SPFROMREG(ft,
- + NDS32Insn_OPCODE_Rb(insn));
- +
- + rv.s = (*handler.b) (fs, ft);
- + goto copcsr;
- + }
- +scopuop:
- + {
- + ieee754sp fs;
- +
- + SPFROMREG(fs,
- + NDS32Insn_OPCODE_Ra(insn));
- + rv.s = (*handler.u) (fs);
- + goto copcsr;
- + }
- +copcsr:
- + if (ieee754_cxtest(IEEE754_INEXACT))
- + rfpcsr |= FPCSR_mskIEX;
- + if (ieee754_cxtest(IEEE754_UNDERFLOW))
- + rfpcsr |= FPCSR_mskUDF;
- + if (ieee754_cxtest(IEEE754_OVERFLOW))
- + rfpcsr |= FPCSR_mskOVF;
- + if (ieee754_cxtest(IEEE754_ZERO_DIVIDE))
- + rfpcsr |= FPCSR_mskDBZ;
- + if (ieee754_cxtest(IEEE754_INVALID_OPERATION))
- + rfpcsr |= FPCSR_mskIVO;
- + break;
- +
- + case fs1_f2op_op:
- + switch (NDS32Insn_OPCODE_BIT1014(insn)) {
- + case fs2d_op:{
- + ieee754sp fs;
- + SPFROMREG(fs,
- + NDS32Insn_OPCODE_Ra
- + (insn));
- + rv.d = ieee754dp_fsp(fs);
- + rfmt = fd1_op;
- + goto copcsr;
- + }
- + case fsqrts_op:
- + handler.u = ieee754sp_sqrt;
- + goto scopuop;
- + case fabss_op:
- + handler.u = ieee754sp_abs;
- + goto scopuop;
- + default:
- + return SIGILL;
- + }
- + default:
- + return SIGILL;
- + }
- + break;
- + }
- +
- + case fs2_op:
- + switch (NDS32Insn_OPCODE_BIT69(insn)) {
- + case fcmpeqs_op:
- + case fcmpeqs_e_op:
- + case fcmplts_op:
- + case fcmplts_e_op:
- + case fcmples_op:
- + case fcmples_e_op:
- + case fcmpuns_op:
- + case fcmpuns_e_op:
- + {
- + unsigned int cmpop =
- + NDS32Insn_OPCODE_BIT69(insn);
- + if (cmpop < 0x8) {
- + ieee754sp fs, ft;
- +
- + SPFROMREG(fs,
- + NDS32Insn_OPCODE_Ra(insn));
- + SPFROMREG(ft,
- + NDS32Insn_OPCODE_Rb(insn));
- + rv.w =
- + ieee754sp_cmp(fs, ft,
- + cmptab[(cmpop >> 1) &
- + 0x7],
- + cmpop & 0x1);
- + if ((cmpop & 0x1)
- + &&
- + ieee754_cxtest
- + (IEEE754_INVALID_OPERATION))
- + rfpcsr = FPCSR_mskIVO;
- + else
- + goto copcsr;
- + } else
- + return SIGILL;
- + }
- + break;
- +
- + default:
- + return SIGILL;
- + }
- + break;
- +
- + case fd1_op:
- + {
- + union {
- + ieee754dp(*t) (ieee754dp, ieee754dp, ieee754dp);
- + ieee754dp(*b) (ieee754dp, ieee754dp);
- + ieee754dp(*u) (ieee754dp);
- + } handler;
- +
- + switch (NDS32Insn_OPCODE_BIT69(insn)) {
- + case faddd_op:
- + handler.b = ieee754dp_add;
- + goto dcopbop;
- + case fsubd_op:
- + handler.b = ieee754dp_sub;
- + goto dcopbop;
- + case fmaddd_op:
- + handler.t = fpemu_dp_madd;
- + goto tdcoptop;
- + case fmsubd_op:
- + handler.t = fpemu_dp_msub;
- + goto tdcoptop;
- + case fnmaddd_op:
- + handler.t = fpemu_dp_nmadd;
- + goto tdcoptop;
- + case fnmsubd_op:
- + handler.t = fpemu_dp_nmsub;
- + goto tdcoptop;
- +
- +tdcoptop:
- + {
- + ieee754dp fd, fr, fs, ft;
- +
- + DPFROMREG(fr,
- + NDS32Insn_OPCODE_Rt(insn));
- + DPFROMREG(fs,
- + NDS32Insn_OPCODE_Ra(insn));
- + DPFROMREG(ft,
- + NDS32Insn_OPCODE_Rb(insn));
- + fd = (*handler.t) (fr, fs, ft);
- + DPTOREG(fd, NDS32Insn_OPCODE_Rt(insn));
- + goto copcsr;
- + }
- +
- + case fmuld_op:
- + handler.b = ieee754dp_mul;
- + goto dcopbop;
- + case fdivd_op:
- + handler.b = ieee754dp_div;
- + goto dcopbop;
- +
- + /* binary op on handler */
- +dcopbop: {
- + ieee754dp fs, ft;
- +
- + DPFROMREG(fs,
- + NDS32Insn_OPCODE_Ra(insn));
- + DPFROMREG(ft,
- + NDS32Insn_OPCODE_Rb(insn));
- +
- + rv.d = (*handler.b) (fs, ft);
- + goto copcsr;
- + }
- +dcopuop: {
- + ieee754dp fs;
- +
- + DPFROMREG(fs,
- + NDS32Insn_OPCODE_Ra(insn));
- + rv.d = (*handler.u) (fs);
- + goto copcsr;
- + }
- +
- + case fd1_f2op_op:
- + switch (NDS32Insn_OPCODE_BIT1014(insn)) {
- + case fd2s_op:{
- + ieee754dp fs;
- +
- + DPFROMREG(fs,
- + NDS32Insn_OPCODE_Ra
- + (insn));
- + rv.s = ieee754sp_fdp(fs);
- + rfmt = fd1_op;
- + goto copcsr;
- + }
- + case fsqrtd_op:
- + handler.u = ieee754dp_sqrt;
- + goto dcopuop;
- + case fabsd_op:
- + handler.u = ieee754dp_abs;
- + goto dcopuop;
- + default:
- + return SIGILL;
- + }
- + default:
- + return SIGILL;
- + }
- + break;
- + }
- +
- + case fd2_op:
- + switch (NDS32Insn_OPCODE_BIT69(insn)) {
- + case fcmpeqd_op:
- + case fcmpeqd_e_op:
- + case fcmpltd_op:
- + case fcmpltd_e_op:
- + case fcmpled_op:
- + case fcmpled_e_op:
- + case fcmpund_op:
- + case fcmpund_e_op:
- + {
- + unsigned cmpop = NDS32Insn_OPCODE_BIT69(insn);
- + if (cmpop < 0x8) {
- + ieee754dp fs, ft;
- +
- + DPFROMREG(fs,
- + NDS32Insn_OPCODE_Ra(insn));
- + DPFROMREG(ft,
- + NDS32Insn_OPCODE_Rb(insn));
- + rv.w =
- + ieee754dp_cmp(fs, ft,
- + cmptab[(cmpop >> 1) &
- + 0x7],
- + cmpop & 0x1);
- + rfmt = fs2_op;
- + if ((cmpop & 0x1)
- + &&
- + ieee754_cxtest
- + (IEEE754_INVALID_OPERATION))
- + rfpcsr = FPCSR_mskIVO;
- + else
- + goto copcsr;
- + } else
- + return SIGILL;
- + }
- + break;
- + default:
- + return SIGILL;
- + }
- + break;
- +
- + default:
- + return SIGILL;
- + }
- +
- + /*
- + * Now we can safely write the result back to the register file.
- + */
- + switch (rfmt) {
- + case fd1_op:
- + case fd2_op:
- + DPTOREG(rv.d, NDS32Insn_OPCODE_Rt(insn));
- + break;
- + case fs1_op:
- + case fs2_op:
- + SPTOREG(rv.s, NDS32Insn_OPCODE_Rt(insn));
- + break;
- + default:
- + return SIGILL;
- + }
- +
- + /*
- + * Update the fpu CSR register for this operation.
- + * If an exception is required, generate a tidy SIGFPE exception,
- + * without updating the result register.
- + * Note: cause exception bits do not accumulate, they are rewritten
- + * for each op; only the flag/sticky bits accumulate.
- + */
- + ctx->fpcsr = (ctx->fpcsr & ~FPCSR_mskALL) | rfpcsr;
- + if ((ctx->fpcsr << 5) & ctx->fpcsr & FPCSR_mskALLE) {
- + return SIGFPE;
- + }
- +
- + return 0;
- +}
- +
- +int do_fpu_denorm(struct pt_regs *regs, struct fpu_struct *fpu)
- +{
- + int sig = 0;
- +
- + /*
- + * The 'ieee754_csr' is an alias of
- + * fpcsr->RM. No need to copy fpcsr->RM to
- + * ieee754_csr. But ieee754_csr.rm is ieee
- + * library modes. (not NDS32 rounding mode)
- + */
- + /* convert to ieee library modes */
- + ieee754_csr.rm = ieee_rm[ieee754_csr.rm];
- + sig = fpuEmulate(regs, fpu);
- + /* revert to NDS32 rounding mode */
- + ieee754_csr.rm = nds32_rm[ieee754_csr.rm];
- +
- + return sig;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/fpu_emulator.h linux-3.4.110/arch/nds32/math-emu/fpu_emulator.h
- --- linux-3.4.110.orig/arch/nds32/math-emu/fpu_emulator.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/fpu_emulator.h 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,36 @@
- +/*
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * Further private data for which no space exists in mips_fpu_struct.
- + * This should be subsumed into the mips_fpu_struct structure as
- + * defined in processor.h as soon as the absurd wired absolute assembler
- + * offsets become dynamic at compile time.
- + *
- + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
- + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
- + */
- +#ifndef _ASM_FPU_EMULATOR_H
- +#define _ASM_FPU_EMULATOR_H
- +
- +struct fpu_emulator_stats {
- + unsigned int emulated;
- + unsigned int loads;
- + unsigned int stores;
- + unsigned int fpuops;
- + unsigned int errors;
- +};
- +
- +extern struct fpu_emulator_stats fpuemustats;
- +
- +#endif /* _ASM_FPU_EMULATOR_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754.c linux-3.4.110/arch/nds32/math-emu/ieee754.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/ieee754.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/ieee754.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,125 @@
- +/* ieee754 floating point arithmetic
- + * single and double precision
- + *
- + * BUGS
- + * not much dp done
- + * doesn't generate IEEE754_INEXACT
- + *
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754int.h"
- +#include "ieee754sp.h"
- +#include "ieee754dp.h"
- +
- +#define DP_EBIAS 1023
- +#define DP_EMIN (-1022)
- +#define DP_EMAX 1023
- +
- +#define SP_EBIAS 127
- +#define SP_EMIN (-126)
- +#define SP_EMAX 127
- +
- +/* special constants
- +*/
- +
- +#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__NDS32_EL__)
- +#define SPSTR(s, b, m) {m, b, s}
- +#define DPSTR(s, b, mh, ml) {ml, mh, b, s}
- +#endif
- +
- +#ifdef __NDS32_EB__
- +#define SPSTR(s, b, m) {s, b, m}
- +#define DPSTR(s, b, mh, ml) {s, b, mh, ml}
- +#endif
- +
- +const struct ieee754dp_konst __ieee754dp_spcvals[] = {
- + DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* + zero */
- + DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* - zero */
- + DPSTR(0, DP_EBIAS, 0, 0), /* + 1.0 */
- + DPSTR(1, DP_EBIAS, 0, 0), /* - 1.0 */
- + DPSTR(0, 3 + DP_EBIAS, 0x40000, 0), /* + 10.0 */
- + DPSTR(1, 3 + DP_EBIAS, 0x40000, 0), /* - 10.0 */
- + DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* + infinity */
- + DPSTR(1, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* - infinity */
- + DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0x7FFFF, 0xFFFFFFFF), /* + indef quiet Nan */
- + DPSTR(0, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* + max */
- + DPSTR(1, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* - max */
- + DPSTR(0, DP_EMIN + DP_EBIAS, 0, 0), /* + min normal */
- + DPSTR(1, DP_EMIN + DP_EBIAS, 0, 0), /* - min normal */
- + DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* + min denormal */
- + DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* - min denormal */
- + DPSTR(0, 31 + DP_EBIAS, 0, 0), /* + 1.0e31 */
- + DPSTR(0, 63 + DP_EBIAS, 0, 0), /* + 1.0e63 */
- +};
- +
- +const struct ieee754sp_konst __ieee754sp_spcvals[] = {
- + SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 0), /* + zero */
- + SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 0), /* - zero */
- + SPSTR(0, SP_EBIAS, 0), /* + 1.0 */
- + SPSTR(1, SP_EBIAS, 0), /* - 1.0 */
- + SPSTR(0, 3 + SP_EBIAS, 0x200000), /* + 10.0 */
- + SPSTR(1, 3 + SP_EBIAS, 0x200000), /* - 10.0 */
- + SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0), /* + infinity */
- + SPSTR(1, SP_EMAX + 1 + SP_EBIAS, 0), /* - infinity */
- + SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0x3FFFFF), /* + indef quiet Nan */
- + SPSTR(0, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* + max normal */
- + SPSTR(1, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* - max normal */
- + SPSTR(0, SP_EMIN + SP_EBIAS, 0), /* + min normal */
- + SPSTR(1, SP_EMIN + SP_EBIAS, 0), /* - min normal */
- + SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 1), /* + min denormal */
- + SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 1), /* - min denormal */
- + SPSTR(0, 31 + SP_EBIAS, 0), /* + 1.0e31 */
- + SPSTR(0, 63 + SP_EBIAS, 0), /* + 1.0e63 */
- +};
- +
- +int ieee754si_xcpt(int r, const char *op, ...)
- +{
- + struct ieee754xctx ax;
- +
- + if (!TSTX())
- + return r;
- + ax.op = op;
- + ax.rt = IEEE754_RT_SI;
- + ax.rv.si = r;
- + va_start(ax.ap, op);
- + ieee754_xcpt(&ax);
- + va_end(ax.ap);
- + return ax.rv.si;
- +}
- +
- +s64 ieee754di_xcpt(s64 r, const char *op, ...)
- +{
- + struct ieee754xctx ax;
- +
- + if (!TSTX())
- + return r;
- + ax.op = op;
- + ax.rt = IEEE754_RT_DI;
- + ax.rv.di = r;
- + va_start(ax.ap, op);
- + ieee754_xcpt(&ax);
- + va_end(ax.ap);
- + return ax.rv.di;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754d.c linux-3.4.110/arch/nds32/math-emu/ieee754d.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/ieee754d.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/ieee754d.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,134 @@
- +/*
- + * Some debug functions
- + *
- + * MIPS floating point support
- + *
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * Nov 7, 2000
- + * Modified to build and operate in Linux kernel environment.
- + *
- + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
- + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
- + */
- +
- +#include <linux/kernel.h>
- +#include "ieee754.h"
- +
- +#define DP_EBIAS 1023
- +#define DP_EMIN (-1022)
- +#define DP_EMAX 1023
- +#define DP_FBITS 52
- +
- +#define SP_EBIAS 127
- +#define SP_EMIN (-126)
- +#define SP_EMAX 127
- +#define SP_FBITS 23
- +
- +#define DP_MBIT(x) ((u64)1 << (x))
- +#define DP_HIDDEN_BIT DP_MBIT(DP_FBITS)
- +#define DP_SIGN_BIT DP_MBIT(63)
- +
- +#define SP_MBIT(x) ((u32)1 << (x))
- +#define SP_HIDDEN_BIT SP_MBIT(SP_FBITS)
- +#define SP_SIGN_BIT SP_MBIT(31)
- +
- +#define SPSIGN(sp) (sp.parts.sign)
- +#define SPBEXP(sp) (sp.parts.bexp)
- +#define SPMANT(sp) (sp.parts.mant)
- +
- +#define DPSIGN(dp) (dp.parts.sign)
- +#define DPBEXP(dp) (dp.parts.bexp)
- +#define DPMANT(dp) (dp.parts.mant)
- +
- +ieee754dp ieee754dp_dump(char *m, ieee754dp x)
- +{
- + int i;
- +
- + printk("%s", m);
- + printk("<%08x,%08x>\n", (unsigned)(x.bits >> 32), (unsigned)x.bits);
- + printk("\t=");
- + switch (ieee754dp_class(x)) {
- + case IEEE754_CLASS_QNAN:
- + case IEEE754_CLASS_SNAN:
- + printk("Nan %c", DPSIGN(x) ? '-' : '+');
- + for (i = DP_FBITS - 1; i >= 0; i--)
- + printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
- + break;
- + case IEEE754_CLASS_INF:
- + printk("%cInfinity", DPSIGN(x) ? '-' : '+');
- + break;
- + case IEEE754_CLASS_ZERO:
- + printk("%cZero", DPSIGN(x) ? '-' : '+');
- + break;
- + case IEEE754_CLASS_DNORM:
- + printk("%c0.", DPSIGN(x) ? '-' : '+');
- + for (i = DP_FBITS - 1; i >= 0; i--)
- + printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
- + printk("e%d", DPBEXP(x) - DP_EBIAS);
- + break;
- + case IEEE754_CLASS_NORM:
- + printk("%c1.", DPSIGN(x) ? '-' : '+');
- + for (i = DP_FBITS - 1; i >= 0; i--)
- + printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
- + printk("e%d", DPBEXP(x) - DP_EBIAS);
- + break;
- + default:
- + printk("Illegal/Unknown IEEE754 value class");
- + }
- + printk("\n");
- + return x;
- +}
- +
- +ieee754sp ieee754sp_dump(char *m, ieee754sp x)
- +{
- + int i;
- +
- + printk("%s=", m);
- + printk("<%08x>\n", (unsigned)x.bits);
- + printk("\t=");
- + switch (ieee754sp_class(x)) {
- + case IEEE754_CLASS_QNAN:
- + case IEEE754_CLASS_SNAN:
- + printk("Nan %c", SPSIGN(x) ? '-' : '+');
- + for (i = SP_FBITS - 1; i >= 0; i--)
- + printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
- + break;
- + case IEEE754_CLASS_INF:
- + printk("%cInfinity", SPSIGN(x) ? '-' : '+');
- + break;
- + case IEEE754_CLASS_ZERO:
- + printk("%cZero", SPSIGN(x) ? '-' : '+');
- + break;
- + case IEEE754_CLASS_DNORM:
- + printk("%c0.", SPSIGN(x) ? '-' : '+');
- + for (i = SP_FBITS - 1; i >= 0; i--)
- + printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
- + printk("e%d", SPBEXP(x) - SP_EBIAS);
- + break;
- + case IEEE754_CLASS_NORM:
- + printk("%c1.", SPSIGN(x) ? '-' : '+');
- + for (i = SP_FBITS - 1; i >= 0; i--)
- + printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
- + printk("e%d", SPBEXP(x) - SP_EBIAS);
- + break;
- + default:
- + printk("Illegal/Unknown IEEE754 value class");
- + }
- + printk("\n");
- + return x;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754dp.c linux-3.4.110/arch/nds32/math-emu/ieee754dp.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/ieee754dp.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/ieee754dp.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,239 @@
- +/* IEEE754 floating point arithmetic
- + * double precision: common utilities
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754dp.h"
- +
- +int ieee754dp_class(ieee754dp x)
- +{
- + COMPXDP;
- + EXPLODEXDP;
- + return xc;
- +}
- +
- +int ieee754dp_isnan(ieee754dp x)
- +{
- + return ieee754dp_class(x) >= IEEE754_CLASS_SNAN;
- +}
- +
- +int ieee754dp_issnan(ieee754dp x)
- +{
- + assert(ieee754dp_isnan(x));
- + return ((DPMANT(x) & DP_MBIT(DP_MBITS - 1)) == DP_MBIT(DP_MBITS - 1));
- +}
- +
- +ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...)
- +{
- + struct ieee754xctx ax;
- + if (!TSTX())
- + return r;
- +
- + ax.op = op;
- + ax.rt = IEEE754_RT_DP;
- + ax.rv.dp = r;
- + va_start(ax.ap, op);
- + ieee754_xcpt(&ax);
- + va_end(ax.ap);
- + return ax.rv.dp;
- +}
- +
- +ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...)
- +{
- + struct ieee754xctx ax;
- +
- + assert(ieee754dp_isnan(r));
- +
- + if (!ieee754dp_issnan(r)) /* QNAN does not cause invalid op !! */
- + return r;
- +
- + if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) {
- + /* not enabled convert to a quiet NaN */
- + DPMANT(r) &= (~DP_MBIT(DP_MBITS - 1));
- + if (ieee754dp_isnan(r))
- + return r;
- + else
- + return ieee754dp_indef();
- + }
- +
- + ax.op = op;
- + ax.rt = 0;
- + ax.rv.dp = r;
- + va_start(ax.ap, op);
- + ieee754_xcpt(&ax);
- + va_end(ax.ap);
- + return ax.rv.dp;
- +}
- +
- +ieee754dp ieee754dp_bestnan(ieee754dp x, ieee754dp y)
- +{
- + assert(ieee754dp_isnan(x));
- + assert(ieee754dp_isnan(y));
- +
- + if (DPMANT(x) > DPMANT(y))
- + return x;
- + else
- + return y;
- +}
- +
- +static u64 get_rounding(int sn, u64 xm)
- +{
- + /* inexact must round of 3 bits
- + */
- + if (xm & (DP_MBIT(3) - 1)) {
- + switch (ieee754_csr.rm) {
- + case IEEE754_RZ:
- + break;
- + case IEEE754_RN:
- + xm += 0x3 + ((xm >> 3) & 1);
- + /* xm += (xm&0x8)?0x4:0x3 */
- + break;
- + case IEEE754_RU: /* toward +Infinity */
- + if (!sn) /* ?? */
- + xm += 0x8;
- + break;
- + case IEEE754_RD: /* toward -Infinity */
- + if (sn) /* ?? */
- + xm += 0x8;
- + break;
- + }
- + }
- + return xm;
- +}
- +
- +/* generate a normal/denormal number with over,under handling
- + * sn is sign
- + * xe is an unbiased exponent
- + * xm is 3bit extended precision value.
- + */
- +ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
- +{
- + assert(xm); /* we don't gen exact zeros (probably should) */
- +
- + assert((xm >> (DP_MBITS + 1 + 3)) == 0); /* no execess */
- + assert(xm & (DP_HIDDEN_BIT << 3));
- +
- + if (xe < DP_EMIN) {
- + /* strip lower bits */
- + int es = DP_EMIN - xe;
- +
- + if (ieee754_csr.nod) {
- + SETCX(IEEE754_UNDERFLOW);
- + SETCX(IEEE754_INEXACT);
- +
- + switch (ieee754_csr.rm) {
- + case IEEE754_RN:
- + return ieee754dp_zero(sn);
- + case IEEE754_RZ:
- + return ieee754dp_zero(sn);
- + case IEEE754_RU: /* toward +Infinity */
- + if (sn == 0)
- + return ieee754dp_min(0);
- + else
- + return ieee754dp_zero(1);
- + case IEEE754_RD: /* toward -Infinity */
- + if (sn == 0)
- + return ieee754dp_zero(0);
- + else
- + return ieee754dp_min(1);
- + }
- + }
- +
- + if (xe == DP_EMIN - 1
- + && get_rounding(sn, xm) >> (DP_MBITS + 1 + 3)) {
- + /* Not tiny after rounding */
- + SETCX(IEEE754_INEXACT);
- + xm = get_rounding(sn, xm);
- + xm >>= 1;
- + /* Clear grs bits */
- + xm &= ~(DP_MBIT(3) - 1);
- + xe++;
- + } else {
- + /* sticky right shift es bits
- + */
- + xm = XDPSRS(xm, es);
- + xe += es;
- + assert((xm & (DP_HIDDEN_BIT << 3)) == 0);
- + assert(xe == DP_EMIN);
- + }
- + }
- + if (xm & (DP_MBIT(3) - 1)) {
- + SETCX(IEEE754_INEXACT);
- + if ((xm & (DP_HIDDEN_BIT << 3)) == 0) {
- + SETCX(IEEE754_UNDERFLOW);
- + }
- +
- + /* inexact must round of 3 bits
- + */
- + xm = get_rounding(sn, xm);
- + /* adjust exponent for rounding add overflowing
- + */
- + if (xm >> (DP_MBITS + 3 + 1)) {
- + /* add causes mantissa overflow */
- + xm >>= 1;
- + xe++;
- + }
- + }
- + /* strip grs bits */
- + xm >>= 3;
- +
- + assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */
- + assert(xe >= DP_EMIN);
- +
- + if (xe > DP_EMAX) {
- + SETCX(IEEE754_OVERFLOW);
- + SETCX(IEEE754_INEXACT);
- + /* -O can be table indexed by (rm,sn) */
- + switch (ieee754_csr.rm) {
- + case IEEE754_RN:
- + return ieee754dp_inf(sn);
- + case IEEE754_RZ:
- + return ieee754dp_max(sn);
- + case IEEE754_RU: /* toward +Infinity */
- + if (sn == 0)
- + return ieee754dp_inf(0);
- + else
- + return ieee754dp_max(1);
- + case IEEE754_RD: /* toward -Infinity */
- + if (sn == 0)
- + return ieee754dp_max(0);
- + else
- + return ieee754dp_inf(1);
- + }
- + }
- + /* gen norm/denorm/zero */
- +
- + if ((xm & DP_HIDDEN_BIT) == 0) {
- + /* we underflow (tiny/zero) */
- + assert(xe == DP_EMIN);
- + if (ieee754_csr.mx & IEEE754_UNDERFLOW)
- + SETCX(IEEE754_UNDERFLOW);
- + return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm);
- + } else {
- + assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */
- + assert(xm & DP_HIDDEN_BIT);
- +
- + return builddp(sn, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754dp.h linux-3.4.110/arch/nds32/math-emu/ieee754dp.h
- --- linux-3.4.110.orig/arch/nds32/math-emu/ieee754dp.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/ieee754dp.h 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,83 @@
- +/*
- + * IEEE754 floating point
- + * double precision internal header file
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +
- +#include "ieee754int.h"
- +
- +#define assert(expr) ((void)0)
- +
- +/* 3bit extended double precision sticky right shift */
- +#define XDPSRS(v,rs) \
- + ((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0))
- +
- +#define XDPSRSX1() \
- + (xe++, (xm = (xm >> 1) | (xm & 1)))
- +
- +#define XDPSRS1(v) \
- + (((v) >> 1) | ((v) & 1))
- +
- +/* convert denormal to normalized with extended exponent */
- +#define DPDNORMx(m,e) \
- + while( (m >> DP_MBITS) == 0) { m <<= 1; e--; }
- +#define DPDNORMX DPDNORMx(xm, xe)
- +#define DPDNORMY DPDNORMx(ym, ye)
- +
- +static inline ieee754dp builddp(int s, int bx, u64 m)
- +{
- + ieee754dp r;
- +
- + assert((s) == 0 || (s) == 1);
- + assert((bx) >= DP_EMIN - 1 + DP_EBIAS
- + && (bx) <= DP_EMAX + 1 + DP_EBIAS);
- + assert(((m) >> DP_MBITS) == 0);
- +
- + r.parts.sign = s;
- + r.parts.bexp = bx;
- + r.parts.mant = m;
- + return r;
- +}
- +
- +extern int ieee754dp_isnan(ieee754dp);
- +extern int ieee754dp_issnan(ieee754dp);
- +extern int ieee754si_xcpt(int, const char *, ...);
- +extern s64 ieee754di_xcpt(s64, const char *, ...);
- +extern ieee754dp ieee754dp_xcpt(ieee754dp, const char *, ...);
- +extern ieee754dp ieee754dp_nanxcpt(ieee754dp, const char *, ...);
- +extern ieee754dp ieee754dp_bestnan(ieee754dp, ieee754dp);
- +extern ieee754dp ieee754dp_format(int, int, u64);
- +
- +
- +#define DPNORMRET2(s, e, m, name, a0, a1) \
- +{ \
- + ieee754dp V = ieee754dp_format(s, e, m); \
- + if(TSTX()) \
- + return ieee754dp_xcpt(V, name, a0, a1); \
- + else \
- + return V; \
- +}
- +
- +#define DPNORMRET1(s, e, m, name, a0) DPNORMRET2(s, e, m, name, a0, a0)
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754.h linux-3.4.110/arch/nds32/math-emu/ieee754.h
- --- linux-3.4.110.orig/arch/nds32/math-emu/ieee754.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/ieee754.h 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,467 @@
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * Nov 7, 2000
- + * Modification to allow integration with Linux kernel
- + *
- + * Kevin D. Kissell, kevink@mips.com and Carsten Langgard, carstenl@mips.com
- + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
- + */
- +#ifndef __ARCH_MIPS_MATH_EMU_IEEE754_H
- +#define __ARCH_MIPS_MATH_EMU_IEEE754_H
- +
- +#include <asm/byteorder.h>
- +#include <linux/types.h>
- +#include <linux/sched.h>
- +
- +/*
- + * Not very pretty, but the Linux kernel's normal va_list definition
- + * does not allow it to be used as a structure element, as it is here.
- + */
- +#ifndef _STDARG_H
- +#include <stdarg.h>
- +#endif
- +
- +#ifdef __LITTLE_ENDIAN
- +struct ieee754dp_konst {
- + unsigned mantlo:32;
- + unsigned manthi:20;
- + unsigned bexp:11;
- + unsigned sign:1;
- +};
- +struct ieee754sp_konst {
- + unsigned mant:23;
- + unsigned bexp:8;
- + unsigned sign:1;
- +};
- +
- +typedef union _ieee754dp {
- + struct ieee754dp_konst oparts;
- + struct {
- + u64 mant:52;
- + unsigned int bexp:11;
- + unsigned int sign:1;
- + } parts;
- + u64 bits;
- + double d;
- +} ieee754dp;
- +
- +typedef union _ieee754sp {
- + struct ieee754sp_konst parts;
- + float f;
- + u32 bits;
- +} ieee754sp;
- +#endif
- +
- +#ifdef __BIG_ENDIAN
- +struct ieee754dp_konst {
- + unsigned sign:1;
- + unsigned bexp:11;
- + unsigned manthi:20;
- + unsigned mantlo:32;
- +};
- +
- +typedef union _ieee754dp {
- + struct ieee754dp_konst oparts;
- + struct {
- + unsigned int sign:1;
- + unsigned int bexp:11;
- + u64 mant:52;
- + } parts;
- + double d;
- + u64 bits;
- +} ieee754dp;
- +
- +struct ieee754sp_konst {
- + unsigned sign:1;
- + unsigned bexp:8;
- + unsigned mant:23;
- +};
- +
- +typedef union _ieee754sp {
- + struct ieee754sp_konst parts;
- + float f;
- + u32 bits;
- +} ieee754sp;
- +#endif
- +
- +/*
- + * single precision (often aka float)
- +*/
- +int ieee754sp_finite(ieee754sp x);
- +int ieee754sp_class(ieee754sp x);
- +
- +ieee754sp ieee754sp_abs(ieee754sp x);
- +ieee754sp ieee754sp_neg(ieee754sp x);
- +ieee754sp ieee754sp_scalb(ieee754sp x, int);
- +ieee754sp ieee754sp_logb(ieee754sp x);
- +
- +/* x with sign of y */
- +ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y);
- +
- +ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y);
- +ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y);
- +ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y);
- +ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y);
- +
- +ieee754sp ieee754sp_fint(int x);
- +ieee754sp ieee754sp_funs(unsigned x);
- +ieee754sp ieee754sp_flong(s64 x);
- +ieee754sp ieee754sp_fulong(u64 x);
- +ieee754sp ieee754sp_fdp(ieee754dp x);
- +
- +int ieee754sp_tint(ieee754sp x);
- +unsigned int ieee754sp_tuns(ieee754sp x);
- +s64 ieee754sp_tlong(ieee754sp x);
- +u64 ieee754sp_tulong(ieee754sp x);
- +
- +int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop, int sig);
- +/*
- + * basic sp math
- + */
- +ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip);
- +ieee754sp ieee754sp_frexp(ieee754sp x, int *exp);
- +ieee754sp ieee754sp_ldexp(ieee754sp x, int exp);
- +
- +ieee754sp ieee754sp_ceil(ieee754sp x);
- +ieee754sp ieee754sp_floor(ieee754sp x);
- +ieee754sp ieee754sp_trunc(ieee754sp x);
- +
- +ieee754sp ieee754sp_sqrt(ieee754sp x);
- +
- +/*
- + * double precision (often aka double)
- +*/
- +int ieee754dp_finite(ieee754dp x);
- +int ieee754dp_class(ieee754dp x);
- +
- +/* x with sign of y */
- +ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y);
- +
- +ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y);
- +ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y);
- +ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y);
- +ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y);
- +
- +ieee754dp ieee754dp_abs(ieee754dp x);
- +ieee754dp ieee754dp_neg(ieee754dp x);
- +ieee754dp ieee754dp_scalb(ieee754dp x, int);
- +
- +/* return exponent as integer in floating point format
- + */
- +ieee754dp ieee754dp_logb(ieee754dp x);
- +
- +ieee754dp ieee754dp_fint(int x);
- +ieee754dp ieee754dp_funs(unsigned x);
- +ieee754dp ieee754dp_flong(s64 x);
- +ieee754dp ieee754dp_fulong(u64 x);
- +ieee754dp ieee754dp_fsp(ieee754sp x);
- +
- +ieee754dp ieee754dp_ceil(ieee754dp x);
- +ieee754dp ieee754dp_floor(ieee754dp x);
- +ieee754dp ieee754dp_trunc(ieee754dp x);
- +
- +int ieee754dp_tint(ieee754dp x);
- +unsigned int ieee754dp_tuns(ieee754dp x);
- +s64 ieee754dp_tlong(ieee754dp x);
- +u64 ieee754dp_tulong(ieee754dp x);
- +
- +int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop, int sig);
- +/*
- + * basic sp math
- + */
- +ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip);
- +ieee754dp ieee754dp_frexp(ieee754dp x, int *exp);
- +ieee754dp ieee754dp_ldexp(ieee754dp x, int exp);
- +
- +ieee754dp ieee754dp_ceil(ieee754dp x);
- +ieee754dp ieee754dp_floor(ieee754dp x);
- +ieee754dp ieee754dp_trunc(ieee754dp x);
- +
- +ieee754dp ieee754dp_sqrt(ieee754dp x);
- +
- +
- +
- +/* 5 types of floating point number
- +*/
- +#define IEEE754_CLASS_NORM 0x00
- +#define IEEE754_CLASS_ZERO 0x01
- +#define IEEE754_CLASS_DNORM 0x02
- +#define IEEE754_CLASS_INF 0x03
- +#define IEEE754_CLASS_SNAN 0x04
- +#define IEEE754_CLASS_QNAN 0x05
- +
- +/* exception numbers */
- +#define IEEE754_INVALID_OPERATION 0x01
- +#define IEEE754_ZERO_DIVIDE 0x02
- +#define IEEE754_OVERFLOW 0x04
- +#define IEEE754_UNDERFLOW 0x08
- +#define IEEE754_INEXACT 0x10
- +
- +/* cmp operators
- +*/
- +#define IEEE754_CLT 0x01
- +#define IEEE754_CEQ 0x02
- +#define IEEE754_CGT 0x04
- +#define IEEE754_CUN 0x08
- +
- +/* rounding mode
- +*/
- +#define IEEE754_RN 0 /* round to nearest */
- +#define IEEE754_RZ 1 /* round toward zero */
- +#define IEEE754_RD 2 /* round toward -Infinity */
- +#define IEEE754_RU 3 /* round toward +Infinity */
- +
- +/* other naming */
- +#define IEEE754_RM IEEE754_RD
- +#define IEEE754_RP IEEE754_RU
- +
- +/* "normal" comparisons
- +*/
- +static inline int ieee754sp_eq(ieee754sp x, ieee754sp y)
- +{
- + return ieee754sp_cmp(x, y, IEEE754_CEQ, 0);
- +}
- +
- +static inline int ieee754sp_ne(ieee754sp x, ieee754sp y)
- +{
- + return ieee754sp_cmp(x, y,
- + IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0);
- +}
- +
- +static inline int ieee754sp_lt(ieee754sp x, ieee754sp y)
- +{
- + return ieee754sp_cmp(x, y, IEEE754_CLT, 0);
- +}
- +
- +static inline int ieee754sp_le(ieee754sp x, ieee754sp y)
- +{
- + return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0);
- +}
- +
- +static inline int ieee754sp_gt(ieee754sp x, ieee754sp y)
- +{
- + return ieee754sp_cmp(x, y, IEEE754_CGT, 0);
- +}
- +
- +
- +static inline int ieee754sp_ge(ieee754sp x, ieee754sp y)
- +{
- + return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0);
- +}
- +
- +static inline int ieee754dp_eq(ieee754dp x, ieee754dp y)
- +{
- + return ieee754dp_cmp(x, y, IEEE754_CEQ, 0);
- +}
- +
- +static inline int ieee754dp_ne(ieee754dp x, ieee754dp y)
- +{
- + return ieee754dp_cmp(x, y,
- + IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0);
- +}
- +
- +static inline int ieee754dp_lt(ieee754dp x, ieee754dp y)
- +{
- + return ieee754dp_cmp(x, y, IEEE754_CLT, 0);
- +}
- +
- +static inline int ieee754dp_le(ieee754dp x, ieee754dp y)
- +{
- + return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0);
- +}
- +
- +static inline int ieee754dp_gt(ieee754dp x, ieee754dp y)
- +{
- + return ieee754dp_cmp(x, y, IEEE754_CGT, 0);
- +}
- +
- +static inline int ieee754dp_ge(ieee754dp x, ieee754dp y)
- +{
- + return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0);
- +}
- +
- +
- +/*
- + * Like strtod
- + */
- +ieee754dp ieee754dp_fstr(const char *s, char **endp);
- +char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af);
- +
- +
- +/*
- + * The control status register
- + */
- +struct _ieee754_csr {
- +#ifdef __BIG_ENDIAN
- + unsigned pad0:12;
- + unsigned cx:7; /* exceptions this operation */
- + unsigned nod:1; /* set 1 for no denormalised numbers */
- + unsigned mx:5; /* exception enable mask */
- + unsigned sx:5; /* exceptions total */
- + unsigned rm:2; /* current rounding mode */
- +#endif
- +#ifdef __LITTLE_ENDIAN
- + unsigned rm:2; /* current rounding mode */
- + unsigned sx:5; /* exceptions total */
- + unsigned mx:5; /* exception enable mask */
- + unsigned nod:1; /* set 1 for no denormalised numbers */
- + unsigned cx:7; /* exceptions this operation */
- + unsigned pad0:12;
- +#endif
- +};
- +#define ieee754_csr (*(struct _ieee754_csr *)(¤t->thread.fpu.fpcsr))
- +
- +static inline unsigned ieee754_getrm(void)
- +{
- + return (ieee754_csr.rm);
- +}
- +static inline unsigned ieee754_setrm(unsigned rm)
- +{
- + return (ieee754_csr.rm = rm);
- +}
- +
- +/*
- + * get current exceptions
- + */
- +static inline unsigned ieee754_getcx(void)
- +{
- + return (ieee754_csr.cx);
- +}
- +
- +/* test for current exception condition
- + */
- +static inline int ieee754_cxtest(unsigned n)
- +{
- + return (ieee754_csr.cx & n);
- +}
- +
- +/*
- + * get sticky exceptions
- + */
- +static inline unsigned ieee754_getsx(void)
- +{
- + return (ieee754_csr.sx);
- +}
- +
- +/* clear sticky conditions
- +*/
- +static inline unsigned ieee754_clrsx(void)
- +{
- + return (ieee754_csr.sx = 0);
- +}
- +
- +/* test for sticky exception condition
- + */
- +static inline int ieee754_sxtest(unsigned n)
- +{
- + return (ieee754_csr.sx & n);
- +}
- +
- +/* debugging */
- +ieee754sp ieee754sp_dump(char *s, ieee754sp x);
- +ieee754dp ieee754dp_dump(char *s, ieee754dp x);
- +
- +#define IEEE754_SPCVAL_PZERO 0
- +#define IEEE754_SPCVAL_NZERO 1
- +#define IEEE754_SPCVAL_PONE 2
- +#define IEEE754_SPCVAL_NONE 3
- +#define IEEE754_SPCVAL_PTEN 4
- +#define IEEE754_SPCVAL_NTEN 5
- +#define IEEE754_SPCVAL_PINFINITY 6
- +#define IEEE754_SPCVAL_NINFINITY 7
- +#define IEEE754_SPCVAL_INDEF 8
- +#define IEEE754_SPCVAL_PMAX 9 /* +max norm */
- +#define IEEE754_SPCVAL_NMAX 10 /* -max norm */
- +#define IEEE754_SPCVAL_PMIN 11 /* +min norm */
- +#define IEEE754_SPCVAL_NMIN 12 /* +min norm */
- +#define IEEE754_SPCVAL_PMIND 13 /* +min denorm */
- +#define IEEE754_SPCVAL_NMIND 14 /* +min denorm */
- +#define IEEE754_SPCVAL_P1E31 15 /* + 1.0e31 */
- +#define IEEE754_SPCVAL_P1E63 16 /* + 1.0e63 */
- +
- +extern const struct ieee754dp_konst __ieee754dp_spcvals[];
- +extern const struct ieee754sp_konst __ieee754sp_spcvals[];
- +#define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals)
- +#define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals)
- +
- +/*
- + * Return infinity with given sign
- + */
- +#define ieee754dp_inf(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
- +#define ieee754dp_zero(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
- +#define ieee754dp_one(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
- +#define ieee754dp_ten(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
- +#define ieee754dp_indef() (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF])
- +#define ieee754dp_max(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
- +#define ieee754dp_min(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
- +#define ieee754dp_mind(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
- +#define ieee754dp_1e31() (ieee754dp_spcvals[IEEE754_SPCVAL_P1E31])
- +#define ieee754dp_1e63() (ieee754dp_spcvals[IEEE754_SPCVAL_P1E63])
- +
- +#define ieee754sp_inf(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
- +#define ieee754sp_zero(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
- +#define ieee754sp_one(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
- +#define ieee754sp_ten(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
- +#define ieee754sp_indef() (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF])
- +#define ieee754sp_max(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
- +#define ieee754sp_min(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
- +#define ieee754sp_mind(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
- +#define ieee754sp_1e31() (ieee754sp_spcvals[IEEE754_SPCVAL_P1E31])
- +#define ieee754sp_1e63() (ieee754sp_spcvals[IEEE754_SPCVAL_P1E63])
- +
- +/*
- + * Indefinite integer value
- + */
- +#define ieee754si_indef() INT_MAX
- +#ifdef LONG_LONG_MAX
- +#define ieee754di_indef() LONG_LONG_MAX
- +#else
- +#define ieee754di_indef() ((s64)(~0ULL>>1))
- +#endif
- +
- +/* IEEE exception context, passed to handler */
- +struct ieee754xctx {
- + const char *op; /* operation name */
- + int rt; /* result type */
- + union {
- + ieee754sp sp; /* single precision */
- + ieee754dp dp; /* double precision */
- +#ifdef IEEE854_XP
- + ieee754xp xp; /* extended precision */
- +#endif
- + int si; /* standard signed integer (32bits) */
- + s64 di; /* extended signed integer (64bits) */
- + } rv; /* default result format implied by op */
- + va_list ap;
- +};
- +
- +/* result types for xctx.rt */
- +#define IEEE754_RT_SP 0
- +#define IEEE754_RT_DP 1
- +#define IEEE754_RT_XP 2
- +#define IEEE754_RT_SI 3
- +#define IEEE754_RT_DI 4
- +
- +extern void ieee754_xcpt(struct ieee754xctx *xcp);
- +
- +/* compat */
- +#define ieee754dp_fix(x) ieee754dp_tint(x)
- +#define ieee754sp_fix(x) ieee754sp_tint(x)
- +
- +#endif /* __ARCH_MIPS_MATH_EMU_IEEE754_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754int.h linux-3.4.110/arch/nds32/math-emu/ieee754int.h
- --- linux-3.4.110.orig/arch/nds32/math-emu/ieee754int.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/ieee754int.h 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,165 @@
- +/*
- + * IEEE754 floating point
- + * common internal header file
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +
- +#include "ieee754.h"
- +
- +#define DP_EBIAS 1023
- +#define DP_EMIN (-1022)
- +#define DP_EMAX 1023
- +#define DP_MBITS 52
- +
- +#define SP_EBIAS 127
- +#define SP_EMIN (-126)
- +#define SP_EMAX 127
- +#define SP_MBITS 23
- +
- +#define DP_MBIT(x) ((u64)1 << (x))
- +#define DP_HIDDEN_BIT DP_MBIT(DP_MBITS)
- +#define DP_SIGN_BIT DP_MBIT(63)
- +
- +#define SP_MBIT(x) ((u32)1 << (x))
- +#define SP_HIDDEN_BIT SP_MBIT(SP_MBITS)
- +#define SP_SIGN_BIT SP_MBIT(31)
- +
- +
- +#define SPSIGN(sp) (sp.parts.sign)
- +#define SPBEXP(sp) (sp.parts.bexp)
- +#define SPMANT(sp) (sp.parts.mant)
- +
- +#define DPSIGN(dp) (dp.parts.sign)
- +#define DPBEXP(dp) (dp.parts.bexp)
- +#define DPMANT(dp) (dp.parts.mant)
- +
- +#define CLPAIR(x, y) ((x)*6+(y))
- +
- +#define CLEARCX \
- + (ieee754_csr.cx = 0)
- +
- +#define SETCX(x) \
- + (ieee754_csr.cx |= (x), ieee754_csr.sx |= (x))
- +
- +#define SETANDTESTCX(x) \
- + (SETCX(x), ieee754_csr.mx & (x))
- +
- +#define TSTX() \
- + (ieee754_csr.cx & ieee754_csr.mx)
- +
- +
- +#define COMPXSP \
- + unsigned xm; int xe; int xs; int xc
- +
- +#define COMPYSP \
- + unsigned ym; int ye; int ys; int yc
- +
- +#define EXPLODESP(v, vc, vs, ve, vm) \
- +{\
- + vs = SPSIGN(v);\
- + ve = SPBEXP(v);\
- + vm = SPMANT(v);\
- + if(ve == SP_EMAX+1+SP_EBIAS){\
- + if(vm == 0)\
- + vc = IEEE754_CLASS_INF;\
- + else if(vm & SP_MBIT(SP_MBITS-1)) \
- + vc = IEEE754_CLASS_SNAN;\
- + else \
- + vc = IEEE754_CLASS_QNAN;\
- + } else if(ve == SP_EMIN-1+SP_EBIAS) {\
- + if(vm) {\
- + ve = SP_EMIN;\
- + vc = IEEE754_CLASS_DNORM;\
- + } else\
- + vc = IEEE754_CLASS_ZERO;\
- + } else {\
- + ve -= SP_EBIAS;\
- + vm |= SP_HIDDEN_BIT;\
- + vc = IEEE754_CLASS_NORM;\
- + }\
- +}
- +#define EXPLODEXSP EXPLODESP(x, xc, xs, xe, xm)
- +#define EXPLODEYSP EXPLODESP(y, yc, ys, ye, ym)
- +
- +
- +#define COMPXDP \
- +u64 xm; int xe; int xs; int xc
- +
- +#define COMPYDP \
- +u64 ym; int ye; int ys; int yc
- +
- +#define EXPLODEDP(v, vc, vs, ve, vm) \
- +{\
- + vm = DPMANT(v);\
- + vs = DPSIGN(v);\
- + ve = DPBEXP(v);\
- + if(ve == DP_EMAX+1+DP_EBIAS){\
- + if(vm == 0)\
- + vc = IEEE754_CLASS_INF;\
- + else if(vm & DP_MBIT(DP_MBITS-1)) \
- + vc = IEEE754_CLASS_SNAN;\
- + else \
- + vc = IEEE754_CLASS_QNAN;\
- + } else if(ve == DP_EMIN-1+DP_EBIAS) {\
- + if(vm) {\
- + ve = DP_EMIN;\
- + vc = IEEE754_CLASS_DNORM;\
- + } else\
- + vc = IEEE754_CLASS_ZERO;\
- + } else {\
- + ve -= DP_EBIAS;\
- + vm |= DP_HIDDEN_BIT;\
- + vc = IEEE754_CLASS_NORM;\
- + }\
- +}
- +#define EXPLODEXDP EXPLODEDP(x, xc, xs, xe, xm)
- +#define EXPLODEYDP EXPLODEDP(y, yc, ys, ye, ym)
- +
- +#define FLUSHDP(v, vc, vs, ve, vm) \
- + if(vc==IEEE754_CLASS_DNORM) {\
- + if(ieee754_csr.nod) {\
- + SETCX(IEEE754_INEXACT);\
- + vc = IEEE754_CLASS_ZERO;\
- + ve = DP_EMIN-1+DP_EBIAS;\
- + vm = 0;\
- + v = ieee754dp_zero(vs);\
- + }\
- + }
- +
- +#define FLUSHSP(v, vc, vs, ve, vm) \
- + if(vc==IEEE754_CLASS_DNORM) {\
- + if(ieee754_csr.nod) {\
- + SETCX(IEEE754_INEXACT);\
- + vc = IEEE754_CLASS_ZERO;\
- + ve = SP_EMIN-1+SP_EBIAS;\
- + vm = 0;\
- + v = ieee754sp_zero(vs);\
- + }\
- + }
- +
- +#define FLUSHXDP FLUSHDP(x, xc, xs, xe, xm)
- +#define FLUSHYDP FLUSHDP(y, yc, ys, ye, ym)
- +#define FLUSHXSP FLUSHSP(x, xc, xs, xe, xm)
- +#define FLUSHYSP FLUSHSP(y, yc, ys, ye, ym)
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754m.c linux-3.4.110/arch/nds32/math-emu/ieee754m.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/ieee754m.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/ieee754m.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,55 @@
- +/*
- + * floor, trunc, ceil
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754.h"
- +
- +ieee754dp ieee754dp_floor(ieee754dp x)
- +{
- + ieee754dp i;
- +
- + if (ieee754dp_lt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
- + return ieee754dp_sub(i, ieee754dp_one(0));
- + else
- + return i;
- +}
- +
- +ieee754dp ieee754dp_ceil(ieee754dp x)
- +{
- + ieee754dp i;
- +
- + if (ieee754dp_gt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
- + return ieee754dp_add(i, ieee754dp_one(0));
- + else
- + return i;
- +}
- +
- +ieee754dp ieee754dp_trunc(ieee754dp x)
- +{
- + ieee754dp i;
- +
- + (void)ieee754dp_modf(x, &i);
- + return i;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754sp.c linux-3.4.110/arch/nds32/math-emu/ieee754sp.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/ieee754sp.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/ieee754sp.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,239 @@
- +/* IEEE754 floating point arithmetic
- + * single precision
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754sp.h"
- +
- +int ieee754sp_class(ieee754sp x)
- +{
- + COMPXSP;
- + EXPLODEXSP;
- + return xc;
- +}
- +
- +int ieee754sp_isnan(ieee754sp x)
- +{
- + return ieee754sp_class(x) >= IEEE754_CLASS_SNAN;
- +}
- +
- +int ieee754sp_issnan(ieee754sp x)
- +{
- + assert(ieee754sp_isnan(x));
- + return (SPMANT(x) & SP_MBIT(SP_MBITS - 1));
- +}
- +
- +ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...)
- +{
- + struct ieee754xctx ax;
- +
- + if (!TSTX())
- + return r;
- +
- + ax.op = op;
- + ax.rt = IEEE754_RT_SP;
- + ax.rv.sp = r;
- + va_start(ax.ap, op);
- + ieee754_xcpt(&ax);
- + va_end(ax.ap);
- + return ax.rv.sp;
- +}
- +
- +ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...)
- +{
- + struct ieee754xctx ax;
- +
- + assert(ieee754sp_isnan(r));
- +
- + if (!ieee754sp_issnan(r)) /* QNAN does not cause invalid op !! */
- + return r;
- +
- + if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) {
- + /* not enabled convert to a quiet NaN */
- + SPMANT(r) &= (~SP_MBIT(SP_MBITS - 1));
- + if (ieee754sp_isnan(r))
- + return r;
- + else
- + return ieee754sp_indef();
- + }
- +
- + ax.op = op;
- + ax.rt = 0;
- + ax.rv.sp = r;
- + va_start(ax.ap, op);
- + ieee754_xcpt(&ax);
- + va_end(ax.ap);
- + return ax.rv.sp;
- +}
- +
- +ieee754sp ieee754sp_bestnan(ieee754sp x, ieee754sp y)
- +{
- + assert(ieee754sp_isnan(x));
- + assert(ieee754sp_isnan(y));
- +
- + if (SPMANT(x) > SPMANT(y))
- + return x;
- + else
- + return y;
- +}
- +
- +static unsigned get_rounding(int sn, unsigned xm)
- +{
- + /* inexact must round of 3 bits
- + */
- + if (xm & (SP_MBIT(3) - 1)) {
- + switch (ieee754_csr.rm) {
- + case IEEE754_RZ:
- + break;
- + case IEEE754_RN:
- + xm += 0x3 + ((xm >> 3) & 1);
- + /* xm += (xm&0x8)?0x4:0x3 */
- + break;
- + case IEEE754_RU: /* toward +Infinity */
- + if (!sn) /* ?? */
- + xm += 0x8;
- + break;
- + case IEEE754_RD: /* toward -Infinity */
- + if (sn) /* ?? */
- + xm += 0x8;
- + break;
- + }
- + }
- + return xm;
- +}
- +
- +/* generate a normal/denormal number with over,under handling
- + * sn is sign
- + * xe is an unbiased exponent
- + * xm is 3bit extended precision value.
- + */
- +ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
- +{
- + assert(xm); /* we don't gen exact zeros (probably should) */
- +
- + assert((xm >> (SP_MBITS + 1 + 3)) == 0); /* no execess */
- + assert(xm & (SP_HIDDEN_BIT << 3));
- +
- + if (xe < SP_EMIN) {
- + /* strip lower bits */
- + int es = SP_EMIN - xe;
- +
- + if (ieee754_csr.nod) {
- + SETCX(IEEE754_UNDERFLOW);
- + SETCX(IEEE754_INEXACT);
- +
- + switch (ieee754_csr.rm) {
- + case IEEE754_RN:
- + return ieee754sp_zero(sn);
- + case IEEE754_RZ:
- + return ieee754sp_zero(sn);
- + case IEEE754_RU: /* toward +Infinity */
- + if (sn == 0)
- + return ieee754sp_min(0);
- + else
- + return ieee754sp_zero(1);
- + case IEEE754_RD: /* toward -Infinity */
- + if (sn == 0)
- + return ieee754sp_zero(0);
- + else
- + return ieee754sp_min(1);
- + }
- + }
- +
- + if (xe == SP_EMIN - 1
- + && get_rounding(sn, xm) >> (SP_MBITS + 1 + 3)) {
- + /* Not tiny after rounding */
- + SETCX(IEEE754_INEXACT);
- + xm = get_rounding(sn, xm);
- + xm >>= 1;
- + /* Clear grs bits */
- + xm &= ~(SP_MBIT(3) - 1);
- + xe++;
- + } else {
- + /* sticky right shift es bits
- + */
- + SPXSRSXn(es);
- + assert((xm & (SP_HIDDEN_BIT << 3)) == 0);
- + assert(xe == SP_EMIN);
- + }
- + }
- + if (xm & (SP_MBIT(3) - 1)) {
- + SETCX(IEEE754_INEXACT);
- + if ((xm & (SP_HIDDEN_BIT << 3)) == 0) {
- + SETCX(IEEE754_UNDERFLOW);
- + }
- +
- + /* inexact must round of 3 bits
- + */
- + xm = get_rounding(sn, xm);
- + /* adjust exponent for rounding add overflowing
- + */
- + if (xm >> (SP_MBITS + 1 + 3)) {
- + /* add causes mantissa overflow */
- + xm >>= 1;
- + xe++;
- + }
- + }
- + /* strip grs bits */
- + xm >>= 3;
- +
- + assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */
- + assert(xe >= SP_EMIN);
- +
- + if (xe > SP_EMAX) {
- + SETCX(IEEE754_OVERFLOW);
- + SETCX(IEEE754_INEXACT);
- + /* -O can be table indexed by (rm,sn) */
- + switch (ieee754_csr.rm) {
- + case IEEE754_RN:
- + return ieee754sp_inf(sn);
- + case IEEE754_RZ:
- + return ieee754sp_max(sn);
- + case IEEE754_RU: /* toward +Infinity */
- + if (sn == 0)
- + return ieee754sp_inf(0);
- + else
- + return ieee754sp_max(1);
- + case IEEE754_RD: /* toward -Infinity */
- + if (sn == 0)
- + return ieee754sp_max(0);
- + else
- + return ieee754sp_inf(1);
- + }
- + }
- + /* gen norm/denorm/zero */
- +
- + if ((xm & SP_HIDDEN_BIT) == 0) {
- + /* we underflow (tiny/zero) */
- + assert(xe == SP_EMIN);
- + if (ieee754_csr.mx & IEEE754_UNDERFLOW)
- + SETCX(IEEE754_UNDERFLOW);
- + return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm);
- + } else {
- + assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */
- + assert(xm & SP_HIDDEN_BIT);
- +
- + return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754sp.h linux-3.4.110/arch/nds32/math-emu/ieee754sp.h
- --- linux-3.4.110.orig/arch/nds32/math-emu/ieee754sp.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/ieee754sp.h 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,89 @@
- +/*
- + * IEEE754 floating point
- + * double precision internal header file
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +
- +#include "ieee754int.h"
- +
- +#define assert(expr) ((void)0)
- +
- +/* 3bit extended single precision sticky right shift */
- +#define SPXSRSXn(rs) \
- + (xe += rs, \
- + xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0))
- +
- +#define SPXSRSX1() \
- + (xe++, (xm = (xm >> 1) | (xm & 1)))
- +
- +#define SPXSRSYn(rs) \
- + (ye+=rs, \
- + ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0))
- +
- +#define SPXSRSY1() \
- + (ye++, (ym = (ym >> 1) | (ym & 1)))
- +
- +/* convert denormal to normalized with extended exponent */
- +#define SPDNORMx(m,e) \
- + while( (m >> SP_MBITS) == 0) { m <<= 1; e--; }
- +#define SPDNORMX SPDNORMx(xm, xe)
- +#define SPDNORMY SPDNORMx(ym, ye)
- +
- +static inline ieee754sp buildsp(int s, int bx, unsigned m)
- +{
- + ieee754sp r;
- +
- + assert((s) == 0 || (s) == 1);
- + assert((bx) >= SP_EMIN - 1 + SP_EBIAS
- + && (bx) <= SP_EMAX + 1 + SP_EBIAS);
- + assert(((m) >> SP_MBITS) == 0);
- +
- + r.parts.sign = s;
- + r.parts.bexp = bx;
- + r.parts.mant = m;
- +
- + return r;
- +}
- +
- +extern int ieee754sp_isnan(ieee754sp);
- +extern int ieee754sp_issnan(ieee754sp);
- +extern int ieee754si_xcpt(int, const char *, ...);
- +extern s64 ieee754di_xcpt(s64, const char *, ...);
- +extern ieee754sp ieee754sp_xcpt(ieee754sp, const char *, ...);
- +extern ieee754sp ieee754sp_nanxcpt(ieee754sp, const char *, ...);
- +extern ieee754sp ieee754sp_bestnan(ieee754sp, ieee754sp);
- +extern ieee754sp ieee754sp_format(int, int, unsigned);
- +
- +
- +#define SPNORMRET2(s, e, m, name, a0, a1) \
- +{ \
- + ieee754sp V = ieee754sp_format(s, e, m); \
- + if(TSTX()) \
- + return ieee754sp_xcpt(V, name, a0, a1); \
- + else \
- + return V; \
- +}
- +
- +#define SPNORMRET1(s, e, m, name, a0) SPNORMRET2(s, e, m, name, a0, a0)
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754xcpt.c linux-3.4.110/arch/nds32/math-emu/ieee754xcpt.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/ieee754xcpt.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/ieee754xcpt.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,48 @@
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +/**************************************************************************
- + * Nov 7, 2000
- + * Added preprocessor hacks to map to Linux kernel diagnostics.
- + *
- + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
- + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
- + *************************************************************************/
- +
- +#include <linux/kernel.h>
- +#include "ieee754.h"
- +
- +/*
- + * Very naff exception handler (you can plug in your own and
- + * override this).
- + */
- +
- +static const char *const rtnames[] = {
- + "sp", "dp", "xp", "si", "di"
- +};
- +
- +void ieee754_xcpt(struct ieee754xctx *xcp)
- +{
- + printk(KERN_DEBUG "floating point exception in \"%s\", type=%s\n",
- + xcp->op, rtnames[xcp->rt]);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/insn.h linux-3.4.110/arch/nds32/math-emu/insn.h
- --- linux-3.4.110.orig/arch/nds32/math-emu/insn.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/insn.h 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,101 @@
- +#ifndef _ASM_INST_H
- +#define _ASM_INST_H
- +
- +#define cop0_op 0x35
- +
- +/*
- + * COP0 field of opcodes.
- + */
- +#define fs1_op 0x0
- +#define fs2_op 0x4
- +#define fd1_op 0x8
- +#define fd2_op 0xc
- +
- +/*
- + * FS1 opcode.
- + */
- +enum fs1 {
- + fadds_op, fsubs_op, fcpynss_op, fcpyss_op,
- + fmadds_op, fmsubs_op, fcmovns_op, fcmovzs_op,
- + fnmadds_op, fnmsubs_op,
- + fmuls_op = 0xc, fdivs_op,
- + fs1_f2op_op = 0xf
- +};
- +
- +/*
- + * FS1/F2OP opcode.
- + */
- +enum fs1_f2 {
- + fs2d_op, fsqrts_op, fabss_op = 0x5,
- + fui2s_op = 0x8, fsi2s_op = 0xc,
- + fs2ui_op = 0x10, fs2ui_z_op = 0x14,
- + fs2si_op = 0x18, fs2si_z_op = 0x1c
- +};
- +
- +/*
- + * FS2 opcode.
- + */
- +enum fs2 {
- + fcmpeqs_op, fcmpeqs_e_op, fcmplts_op, fcmplts_e_op,
- + fcmples_op, fcmples_e_op, fcmpuns_op, fcmpuns_e_op
- +};
- +
- +/*
- + * FD1 opcode.
- + */
- +enum fd1 {
- + faddd_op, fsubd_op, fcpynsd_op, fcpysd_op,
- + fmaddd_op, fmsubd_op, fcmovnd_op, fcmovzd_op,
- + fnmaddd_op, fnmsubd_op,
- + fmuld_op = 0xc, fdivd_op, fd1_f2op_op = 0xf
- +};
- +
- +/*
- + * FD1/F2OP opcode.
- + */
- +enum fd1_f2 {
- + fd2s_op, fsqrtd_op, fabsd_op = 0x5,
- + fui2d_op = 0x8, fsi2d_op = 0xc,
- + fd2ui_op = 0x10, fd2ui_z_op = 0x14,
- + fd2si_op = 0x18, fd2si_z_op = 0x1c
- +};
- +
- +/*
- + * FD2 opcode.
- + */
- +enum fd2 {
- + fcmpeqd_op, fcmpeqd_e_op, fcmpltd_op, fcmpltd_e_op,
- + fcmpled_op, fcmpled_e_op, fcmpund_op, fcmpund_e_op
- +};
- +
- +
- +#define NDS32Insn(x) x
- +
- +#define I_OPCODE_off 25
- +#define NDS32Insn_OPCODE(x) (NDS32Insn(x) >> I_OPCODE_off)
- +
- +#define I_OPCODE_offRt 20
- +#define I_OPCODE_mskRt (0x1fUL << I_OPCODE_offRt)
- +#define NDS32Insn_OPCODE_Rt(x) ((NDS32Insn(x) & I_OPCODE_mskRt) >> I_OPCODE_offRt)
- +
- +#define I_OPCODE_offRa 15
- +#define I_OPCODE_mskRa (0x1fUL << I_OPCODE_offRa)
- +#define NDS32Insn_OPCODE_Ra(x) ((NDS32Insn(x) & I_OPCODE_mskRa) >> I_OPCODE_offRa)
- +
- +#define I_OPCODE_offRb 10
- +#define I_OPCODE_mskRb (0x1fUL << I_OPCODE_offRb)
- +#define NDS32Insn_OPCODE_Rb(x) ((NDS32Insn(x) & I_OPCODE_mskRb) >> I_OPCODE_offRb)
- +
- +#define I_OPCODE_offbit1014 10
- +#define I_OPCODE_mskbit1014 (0x1fUL << I_OPCODE_offbit1014)
- +#define NDS32Insn_OPCODE_BIT1014(x) ((NDS32Insn(x) & I_OPCODE_mskbit1014) >> I_OPCODE_offbit1014)
- +
- +#define I_OPCODE_offbit69 6
- +#define I_OPCODE_mskbit69 (0xfUL << I_OPCODE_offbit69)
- +#define NDS32Insn_OPCODE_BIT69(x) ((NDS32Insn(x) & I_OPCODE_mskbit69) >> I_OPCODE_offbit69)
- +
- +#define I_OPCODE_offCOP0 0
- +#define I_OPCODE_mskCOP0 (0x3fUL << I_OPCODE_offCOP0)
- +#define NDS32Insn_OPCODE_COP0(x) ((NDS32Insn(x) & I_OPCODE_mskCOP0) >> I_OPCODE_offCOP0)
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/Makefile linux-3.4.110/arch/nds32/math-emu/Makefile
- --- linux-3.4.110.orig/arch/nds32/math-emu/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/Makefile 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,13 @@
- +#
- +# Makefile for the Linux/nds32 kernel FPU emulation.
- +#
- +
- +obj-y := fpuemu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \
- + ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \
- + dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \
- + dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \
- + sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \
- + sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \
- + dp_sqrt.o sp_sqrt.o
- +
- +EXTRA_CFLAGS += -Werror
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_add.c linux-3.4.110/arch/nds32/math-emu/sp_add.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/sp_add.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/sp_add.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,173 @@
- +/* IEEE754 floating point arithmetic
- + * single precision
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754sp.h"
- +
- +ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)
- +{
- + COMPXSP;
- + COMPYSP;
- +
- + EXPLODEXSP;
- + EXPLODEYSP;
- +
- + CLEARCX;
- +
- + FLUSHXSP;
- + FLUSHYSP;
- +
- + switch (CLPAIR(xc, yc)) {
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754sp_nanxcpt(ieee754sp_indef(), "add", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
- + return y;
- +
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
- + return x;
- +
- + /* Infinity handling
- + */
- +
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
- + if (xs == ys)
- + return x;
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754sp_xcpt(ieee754sp_indef(), "add", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
- + return y;
- +
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
- + return x;
- +
- + /* Zero handling
- + */
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
- + if (xs == ys)
- + return x;
- + else
- + return ieee754sp_zero(ieee754_csr.rm == IEEE754_RD);
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
- + return x;
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
- + return y;
- +
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
- + SPDNORMX;
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
- + SPDNORMY;
- + break;
- +
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
- + SPDNORMX;
- + break;
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
- + break;
- + }
- + assert(xm & SP_HIDDEN_BIT);
- + assert(ym & SP_HIDDEN_BIT);
- +
- + /* provide guard,round and stick bit space */
- + xm <<= 3;
- + ym <<= 3;
- +
- + if (xe > ye) {
- + /* have to shift y fraction right to align
- + */
- + int s = xe - ye;
- + SPXSRSYn(s);
- + } else if (ye > xe) {
- + /* have to shift x fraction right to align
- + */
- + int s = ye - xe;
- + SPXSRSXn(s);
- + }
- + assert(xe == ye);
- + assert(xe <= SP_EMAX);
- +
- + if (xs == ys) {
- + /* generate 28 bit result of adding two 27 bit numbers
- + * leaving result in xm,xs,xe
- + */
- + xm = xm + ym;
- + xe = xe;
- + xs = xs;
- +
- + if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */
- + SPXSRSX1();
- + }
- + } else {
- + if (xm >= ym) {
- + xm = xm - ym;
- + xe = xe;
- + xs = xs;
- + } else {
- + xm = ym - xm;
- + xe = xe;
- + xs = ys;
- + }
- + if (xm == 0)
- + return ieee754sp_zero(ieee754_csr.rm == IEEE754_RD);
- +
- + /* normalize in extended single precision */
- + while ((xm >> (SP_MBITS + 3)) == 0) {
- + xm <<= 1;
- + xe--;
- + }
- +
- + }
- + SPNORMRET2(xs, xe, xm, "add", x, y);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_cmp.c linux-3.4.110/arch/nds32/math-emu/sp_cmp.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/sp_cmp.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/sp_cmp.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,66 @@
- +/* IEEE754 floating point arithmetic
- + * single precision
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754sp.h"
- +
- +int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp, int sig)
- +{
- + COMPXSP;
- + COMPYSP;
- +
- + EXPLODEXSP;
- + EXPLODEYSP;
- + FLUSHXSP;
- + FLUSHYSP;
- + CLEARCX; /* Even clear inexact flag here */
- +
- + if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) {
- + if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN)
- + SETCX(IEEE754_INVALID_OPERATION);
- + if (cmp & IEEE754_CUN)
- + return 1;
- + if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
- + if (sig && SETANDTESTCX(IEEE754_INVALID_OPERATION))
- + return ieee754si_xcpt(0, "fcmpf", x);
- + }
- + return 0;
- + } else {
- + int vx = x.bits;
- + int vy = y.bits;
- +
- + if (vx < 0)
- + vx = -vx ^ SP_SIGN_BIT;
- + if (vy < 0)
- + vy = -vy ^ SP_SIGN_BIT;
- +
- + if (vx < vy)
- + return (cmp & IEEE754_CLT) != 0;
- + else if (vx == vy)
- + return (cmp & IEEE754_CEQ) != 0;
- + else
- + return (cmp & IEEE754_CGT) != 0;
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_div.c linux-3.4.110/arch/nds32/math-emu/sp_div.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/sp_div.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/sp_div.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,155 @@
- +/* IEEE754 floating point arithmetic
- + * single precision
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754sp.h"
- +
- +ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)
- +{
- + COMPXSP;
- + COMPYSP;
- +
- + EXPLODEXSP;
- + EXPLODEYSP;
- +
- + CLEARCX;
- +
- + FLUSHXSP;
- + FLUSHYSP;
- +
- + switch (CLPAIR(xc, yc)) {
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754sp_nanxcpt(ieee754sp_indef(), "div", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
- + return y;
- +
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
- + return x;
- +
- + /* Infinity handling
- + */
- +
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
- + return ieee754sp_zero(xs ^ ys);
- +
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
- + return ieee754sp_inf(xs ^ ys);
- +
- + /* Zero handling
- + */
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
- + SETCX(IEEE754_ZERO_DIVIDE);
- + return ieee754sp_xcpt(ieee754sp_inf(xs ^ ys), "div", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
- + return ieee754sp_zero(xs == ys ? 0 : 1);
- +
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
- + SPDNORMX;
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
- + SPDNORMY;
- + break;
- +
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
- + SPDNORMX;
- + break;
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
- + break;
- + }
- + assert(xm & SP_HIDDEN_BIT);
- + assert(ym & SP_HIDDEN_BIT);
- +
- + /* provide rounding space */
- + xm <<= 3;
- + ym <<= 3;
- +
- + {
- + /* now the dirty work */
- +
- + unsigned rm = 0;
- + int re = xe - ye;
- + unsigned bm;
- +
- + for (bm = SP_MBIT(SP_MBITS + 2); bm; bm >>= 1) {
- + if (xm >= ym) {
- + xm -= ym;
- + rm |= bm;
- + if (xm == 0)
- + break;
- + }
- + xm <<= 1;
- + }
- + rm <<= 1;
- + if (xm)
- + rm |= 1; /* have remainder, set sticky */
- +
- + assert(rm);
- +
- + /* normalise rm to rounding precision ?
- + */
- + while ((rm >> (SP_MBITS + 3)) == 0) {
- + rm <<= 1;
- + re--;
- + }
- +
- + SPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_fdp.c linux-3.4.110/arch/nds32/math-emu/sp_fdp.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/sp_fdp.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/sp_fdp.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,76 @@
- +/* IEEE754 floating point arithmetic
- + * single precision
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754sp.h"
- +
- +ieee754sp ieee754sp_fdp(ieee754dp x)
- +{
- + COMPXDP;
- + ieee754sp nan;
- +
- + EXPLODEXDP;
- +
- + CLEARCX;
- +
- + FLUSHXDP;
- +
- + switch (xc) {
- + case IEEE754_CLASS_SNAN:
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754sp_nanxcpt(ieee754sp_indef(), "fdp");
- + case IEEE754_CLASS_QNAN:
- + nan = buildsp(xs, SP_EMAX + 1 + SP_EBIAS, (u32)
- + (xm >> (DP_MBITS - SP_MBITS)));
- + if (!ieee754sp_isnan(nan))
- + nan = ieee754sp_indef();
- + return ieee754sp_nanxcpt(nan, "fdp", x);
- + case IEEE754_CLASS_INF:
- + return ieee754sp_inf(xs);
- + case IEEE754_CLASS_ZERO:
- + return ieee754sp_zero(xs);
- + case IEEE754_CLASS_DNORM:
- + /* can't possibly be sp representable */
- + SETCX(IEEE754_UNDERFLOW);
- + SETCX(IEEE754_INEXACT);
- + if ((ieee754_csr.rm == IEEE754_RU && !xs) ||
- + (ieee754_csr.rm == IEEE754_RD && xs))
- + return ieee754sp_xcpt(ieee754sp_mind(xs), "fdp", x);
- + return ieee754sp_xcpt(ieee754sp_zero(xs), "fdp", x);
- + case IEEE754_CLASS_NORM:
- + break;
- + }
- +
- + {
- + u32 rm;
- +
- + /* convert from DP_MBITS to SP_MBITS+3 with sticky right shift
- + */
- + rm = (xm >> (DP_MBITS - (SP_MBITS + 3))) |
- + ((xm << (64 - (DP_MBITS - (SP_MBITS + 3)))) != 0);
- +
- + SPNORMRET1(xs, xe, rm, "fdp", x);
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_fint.c linux-3.4.110/arch/nds32/math-emu/sp_fint.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/sp_fint.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/sp_fint.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,78 @@
- +/* IEEE754 floating point arithmetic
- + * single precision
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754sp.h"
- +
- +ieee754sp ieee754sp_fint(int x)
- +{
- + unsigned xm;
- + int xe;
- + int xs;
- +
- + CLEARCX;
- +
- + if (x == 0)
- + return ieee754sp_zero(0);
- + if (x == 1 || x == -1)
- + return ieee754sp_one(x < 0);
- + if (x == 10 || x == -10)
- + return ieee754sp_ten(x < 0);
- +
- + xs = (x < 0);
- + if (xs) {
- + if (x == (1 << 31))
- + xm = ((unsigned)1 << 31); /* max neg can't be safely negated */
- + else
- + xm = -x;
- + } else {
- + xm = x;
- + }
- + xe = SP_MBITS + 3;
- +
- + if (xm >> (SP_MBITS + 1 + 3)) {
- + /* shunt out overflow bits
- + */
- + while (xm >> (SP_MBITS + 1 + 3)) {
- + SPXSRSX1();
- + }
- + } else {
- + /* normalize in grs extended single precision
- + */
- + while ((xm >> (SP_MBITS + 3)) == 0) {
- + xm <<= 1;
- + xe--;
- + }
- + }
- + SPNORMRET1(xs, xe, xm, "fint", x);
- +}
- +
- +ieee754sp ieee754sp_funs(unsigned int u)
- +{
- + if ((int)u < 0)
- + return ieee754sp_add(ieee754sp_1e31(),
- + ieee754sp_fint(u & ~(1 << 31)));
- + return ieee754sp_fint(u);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_flong.c linux-3.4.110/arch/nds32/math-emu/sp_flong.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/sp_flong.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/sp_flong.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,77 @@
- +/* IEEE754 floating point arithmetic
- + * single precision
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754sp.h"
- +
- +ieee754sp ieee754sp_flong(s64 x)
- +{
- + u64 xm; /* <--- need 64-bit mantissa temp */
- + int xe;
- + int xs;
- +
- + CLEARCX;
- +
- + if (x == 0)
- + return ieee754sp_zero(0);
- + if (x == 1 || x == -1)
- + return ieee754sp_one(x < 0);
- + if (x == 10 || x == -10)
- + return ieee754sp_ten(x < 0);
- +
- + xs = (x < 0);
- + if (xs) {
- + if (x == (1ULL << 63))
- + xm = (1ULL << 63); /* max neg can't be safely negated */
- + else
- + xm = -x;
- + } else {
- + xm = x;
- + }
- + xe = SP_MBITS + 3;
- +
- + if (xm >> (SP_MBITS + 1 + 3)) {
- + /* shunt out overflow bits
- + */
- + while (xm >> (SP_MBITS + 1 + 3)) {
- + SPXSRSX1();
- + }
- + } else {
- + /* normalize in grs extended single precision */
- + while ((xm >> (SP_MBITS + 3)) == 0) {
- + xm <<= 1;
- + xe--;
- + }
- + }
- + SPNORMRET1(xs, xe, xm, "sp_flong", x);
- +}
- +
- +ieee754sp ieee754sp_fulong(u64 u)
- +{
- + if ((s64) u < 0)
- + return ieee754sp_add(ieee754sp_1e63(),
- + ieee754sp_flong(u & ~(1ULL << 63)));
- + return ieee754sp_flong(u);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_frexp.c linux-3.4.110/arch/nds32/math-emu/sp_frexp.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/sp_frexp.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/sp_frexp.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,52 @@
- +/* IEEE754 floating point arithmetic
- + * single precision
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754sp.h"
- +
- +/* close to ieeep754sp_logb
- +*/
- +ieee754sp ieee754sp_frexp(ieee754sp x, int *eptr)
- +{
- + COMPXSP;
- + CLEARCX;
- + EXPLODEXSP;
- +
- + switch (xc) {
- + case IEEE754_CLASS_SNAN:
- + case IEEE754_CLASS_QNAN:
- + case IEEE754_CLASS_INF:
- + case IEEE754_CLASS_ZERO:
- + *eptr = 0;
- + return x;
- + case IEEE754_CLASS_DNORM:
- + SPDNORMX;
- + break;
- + case IEEE754_CLASS_NORM:
- + break;
- + }
- + *eptr = xe + 1;
- + return buildsp(xs, -1 + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_logb.c linux-3.4.110/arch/nds32/math-emu/sp_logb.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/sp_logb.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/sp_logb.c 2016-04-07 10:20:50.978082417 +0200
- @@ -0,0 +1,53 @@
- +/* IEEE754 floating point arithmetic
- + * single precision
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754sp.h"
- +
- +ieee754sp ieee754sp_logb(ieee754sp x)
- +{
- + COMPXSP;
- +
- + CLEARCX;
- +
- + EXPLODEXSP;
- +
- + switch (xc) {
- + case IEEE754_CLASS_SNAN:
- + return ieee754sp_nanxcpt(x, "logb", x);
- + case IEEE754_CLASS_QNAN:
- + return x;
- + case IEEE754_CLASS_INF:
- + return ieee754sp_inf(0);
- + case IEEE754_CLASS_ZERO:
- + return ieee754sp_inf(1);
- + case IEEE754_CLASS_DNORM:
- + SPDNORMX;
- + break;
- + case IEEE754_CLASS_NORM:
- + break;
- + }
- + return ieee754sp_fint(xe);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_modf.c linux-3.4.110/arch/nds32/math-emu/sp_modf.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/sp_modf.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/sp_modf.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,79 @@
- +/* IEEE754 floating point arithmetic
- + * single precision
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754sp.h"
- +
- +/* modf function is always exact for a finite number
- +*/
- +ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip)
- +{
- + COMPXSP;
- +
- + CLEARCX;
- +
- + EXPLODEXSP;
- +
- + switch (xc) {
- + case IEEE754_CLASS_SNAN:
- + case IEEE754_CLASS_QNAN:
- + case IEEE754_CLASS_INF:
- + case IEEE754_CLASS_ZERO:
- + *ip = x;
- + return x;
- + case IEEE754_CLASS_DNORM:
- + /* far to small */
- + *ip = ieee754sp_zero(xs);
- + return x;
- + case IEEE754_CLASS_NORM:
- + break;
- + }
- + if (xe < 0) {
- + *ip = ieee754sp_zero(xs);
- + return x;
- + }
- + if (xe >= SP_MBITS) {
- + *ip = x;
- + return ieee754sp_zero(xs);
- + }
- + /* generate ipart mantissa by clearing bottom bits
- + */
- + *ip = buildsp(xs, xe + SP_EBIAS,
- + ((xm >> (SP_MBITS - xe)) << (SP_MBITS - xe)) &
- + ~SP_HIDDEN_BIT);
- +
- + /* generate fpart mantissa by clearing top bits
- + * and normalizing (must be able to normalize)
- + */
- + xm = (xm << (32 - (SP_MBITS - xe))) >> (32 - (SP_MBITS - xe));
- + if (xm == 0)
- + return ieee754sp_zero(xs);
- +
- + while ((xm >> SP_MBITS) == 0) {
- + xm <<= 1;
- + xe--;
- + }
- + return buildsp(xs, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_mul.c linux-3.4.110/arch/nds32/math-emu/sp_mul.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/sp_mul.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/sp_mul.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,168 @@
- +/* IEEE754 floating point arithmetic
- + * single precision
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754sp.h"
- +
- +ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y)
- +{
- + COMPXSP;
- + COMPYSP;
- +
- + EXPLODEXSP;
- + EXPLODEYSP;
- +
- + CLEARCX;
- +
- + FLUSHXSP;
- + FLUSHYSP;
- +
- + switch (CLPAIR(xc, yc)) {
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754sp_nanxcpt(ieee754sp_indef(), "mul", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
- + return y;
- +
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
- + return x;
- +
- + /* Infinity handling */
- +
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754sp_xcpt(ieee754sp_indef(), "mul", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
- + return ieee754sp_inf(xs ^ ys);
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
- + return ieee754sp_zero(xs ^ ys);
- +
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
- + SPDNORMX;
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
- + SPDNORMY;
- + break;
- +
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
- + SPDNORMX;
- + break;
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
- + break;
- + }
- + /* rm = xm * ym, re = xe+ye basicly */
- + assert(xm & SP_HIDDEN_BIT);
- + assert(ym & SP_HIDDEN_BIT);
- +
- + {
- + int re = xe + ye;
- + int rs = xs ^ ys;
- + unsigned rm;
- +
- + /* shunt to top of word */
- + xm <<= 32 - (SP_MBITS + 1);
- + ym <<= 32 - (SP_MBITS + 1);
- +
- + /* multiply 32bits xm,ym to give high 32bits rm with stickness
- + */
- + {
- + unsigned short lxm = xm & 0xffff;
- + unsigned short hxm = xm >> 16;
- + unsigned short lym = ym & 0xffff;
- + unsigned short hym = ym >> 16;
- + unsigned lrm;
- + unsigned hrm;
- +
- + lrm = lxm * lym; /* 16 * 16 => 32 */
- + hrm = hxm * hym; /* 16 * 16 => 32 */
- +
- + {
- + unsigned t = lxm * hym; /* 16 * 16 => 32 */
- + {
- + unsigned at = lrm + (t << 16);
- + hrm += at < lrm;
- + lrm = at;
- + }
- + hrm = hrm + (t >> 16);
- + }
- +
- + {
- + unsigned t = hxm * lym; /* 16 * 16 => 32 */
- + {
- + unsigned at = lrm + (t << 16);
- + hrm += at < lrm;
- + lrm = at;
- + }
- + hrm = hrm + (t >> 16);
- + }
- + rm = hrm | (lrm != 0);
- + }
- +
- + /*
- + * sticky shift down to normal rounding precision
- + */
- + if ((int)rm < 0) {
- + rm = (rm >> (32 - (SP_MBITS + 1 + 3))) |
- + ((rm << (SP_MBITS + 1 + 3)) != 0);
- + re++;
- + } else {
- + rm = (rm >> (32 - (SP_MBITS + 1 + 3 + 1))) |
- + ((rm << (SP_MBITS + 1 + 3 + 1)) != 0);
- + }
- + assert(rm & (SP_HIDDEN_BIT << 3));
- +
- + SPNORMRET2(rs, re, rm, "mul", x, y);
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_scalb.c linux-3.4.110/arch/nds32/math-emu/sp_scalb.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/sp_scalb.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/sp_scalb.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,56 @@
- +/* IEEE754 floating point arithmetic
- + * single precision
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754sp.h"
- +
- +ieee754sp ieee754sp_scalb(ieee754sp x, int n)
- +{
- + COMPXSP;
- +
- + CLEARCX;
- +
- + EXPLODEXSP;
- +
- + switch (xc) {
- + case IEEE754_CLASS_SNAN:
- + return ieee754sp_nanxcpt(x, "scalb", x, n);
- + case IEEE754_CLASS_QNAN:
- + case IEEE754_CLASS_INF:
- + case IEEE754_CLASS_ZERO:
- + return x;
- + case IEEE754_CLASS_DNORM:
- + SPDNORMX;
- + break;
- + case IEEE754_CLASS_NORM:
- + break;
- + }
- + SPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
- +}
- +
- +ieee754sp ieee754sp_ldexp(ieee754sp x, int n)
- +{
- + return ieee754sp_scalb(x, n);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_simple.c linux-3.4.110/arch/nds32/math-emu/sp_simple.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/sp_simple.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/sp_simple.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,87 @@
- +/* IEEE754 floating point arithmetic
- + * single precision
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754sp.h"
- +
- +int ieee754sp_finite(ieee754sp x)
- +{
- + return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS;
- +}
- +
- +ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y)
- +{
- + CLEARCX;
- + SPSIGN(x) = SPSIGN(y);
- + return x;
- +}
- +
- +ieee754sp ieee754sp_neg(ieee754sp x)
- +{
- + COMPXSP;
- +
- + EXPLODEXSP;
- + CLEARCX;
- + FLUSHXSP;
- +
- + /*
- + * Invert the sign ALWAYS to prevent an endless recursion on
- + * pow() in libc.
- + */
- + /* quick fix up */
- + SPSIGN(x) ^= 1;
- +
- + if (xc == IEEE754_CLASS_SNAN) {
- + ieee754sp y = ieee754sp_indef();
- + SETCX(IEEE754_INVALID_OPERATION);
- + SPSIGN(y) = SPSIGN(x);
- + return ieee754sp_nanxcpt(y, "neg");
- + }
- +
- + if (ieee754sp_isnan(x)) /* but not infinity */
- + return ieee754sp_nanxcpt(x, "neg", x);
- + return x;
- +}
- +
- +ieee754sp ieee754sp_abs(ieee754sp x)
- +{
- + COMPXSP;
- +
- + EXPLODEXSP;
- + CLEARCX;
- + FLUSHXSP;
- +
- + if (xc == IEEE754_CLASS_SNAN) {
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754sp_nanxcpt(ieee754sp_indef(), "abs");
- + }
- +
- + if (ieee754sp_isnan(x)) /* but not infinity */
- + return ieee754sp_nanxcpt(x, "abs", x);
- +
- + /* quick fix up */
- + SPSIGN(x) = 0;
- + return x;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_sqrt.c linux-3.4.110/arch/nds32/math-emu/sp_sqrt.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/sp_sqrt.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/sp_sqrt.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,116 @@
- +/* IEEE754 floating point arithmetic
- + * single precision square root
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754sp.h"
- +
- +ieee754sp ieee754sp_sqrt(ieee754sp x)
- +{
- + int ix, s, q, m, t, i;
- + unsigned int r;
- + COMPXSP;
- +
- + /* take care of Inf and NaN */
- +
- + EXPLODEXSP;
- + CLEARCX;
- + FLUSHXSP;
- +
- + /* x == INF or NAN? */
- + switch (xc) {
- + case IEEE754_CLASS_QNAN:
- + /* sqrt(Nan) = Nan */
- + return ieee754sp_nanxcpt(x, "sqrt");
- + case IEEE754_CLASS_SNAN:
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt");
- + case IEEE754_CLASS_ZERO:
- + /* sqrt(0) = 0 */
- + return x;
- + case IEEE754_CLASS_INF:
- + if (xs) {
- + /* sqrt(-Inf) = Nan */
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt");
- + }
- + /* sqrt(+Inf) = Inf */
- + return x;
- + case IEEE754_CLASS_DNORM:
- + case IEEE754_CLASS_NORM:
- + if (xs) {
- + /* sqrt(-x) = Nan */
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt");
- + }
- + break;
- + }
- +
- + ix = x.bits;
- +
- + /* normalize x */
- + m = (ix >> 23);
- + if (m == 0) { /* subnormal x */
- + for (i = 0; (ix & 0x00800000) == 0; i++)
- + ix <<= 1;
- + m -= i - 1;
- + }
- + m -= 127; /* unbias exponent */
- + ix = (ix & 0x007fffff) | 0x00800000;
- + if (m & 1) /* odd m, double x to make it even */
- + ix += ix;
- + m >>= 1; /* m = [m/2] */
- +
- + /* generate sqrt(x) bit by bit */
- + ix += ix;
- + q = s = 0; /* q = sqrt(x) */
- + r = 0x01000000; /* r = moving bit from right to left */
- +
- + while (r != 0) {
- + t = s + r;
- + if (t <= ix) {
- + s = t + r;
- + ix -= t;
- + q += r;
- + }
- + ix += ix;
- + r >>= 1;
- + }
- +
- + if (ix != 0) {
- + SETCX(IEEE754_INEXACT);
- + switch (ieee754_csr.rm) {
- + case IEEE754_RP:
- + q += 2;
- + break;
- + case IEEE754_RN:
- + q += (q & 1);
- + break;
- + }
- + }
- + ix = (q >> 1) + 0x3f000000;
- + ix += (m << 23);
- + x.bits = ix;
- + return x;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_sub.c linux-3.4.110/arch/nds32/math-emu/sp_sub.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/sp_sub.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/sp_sub.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,180 @@
- +/* IEEE754 floating point arithmetic
- + * single precision
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754sp.h"
- +
- +ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)
- +{
- + COMPXSP;
- + COMPYSP;
- +
- + EXPLODEXSP;
- + EXPLODEYSP;
- +
- + CLEARCX;
- +
- + FLUSHXSP;
- + FLUSHYSP;
- +
- + switch (CLPAIR(xc, yc)) {
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754sp_nanxcpt(ieee754sp_indef(), "sub", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
- + return y;
- +
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
- + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
- + return x;
- +
- + /* Infinity handling
- + */
- +
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
- + if (xs != ys)
- + return x;
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754sp_xcpt(ieee754sp_indef(), "sub", x, y);
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
- + return ieee754sp_inf(ys ^ 1);
- +
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
- + return x;
- +
- + /* Zero handling
- + */
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
- + if (xs != ys)
- + return x;
- + else
- + return ieee754sp_zero(ieee754_csr.rm == IEEE754_RD);
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
- + return x;
- +
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
- + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
- + /* quick fix up */
- + DPSIGN(y) ^= 1;
- + return y;
- +
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
- + SPDNORMX;
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
- + SPDNORMY;
- + break;
- +
- + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
- + SPDNORMX;
- + break;
- +
- + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
- + break;
- + }
- + /* flip sign of y and handle as add */
- + ys ^= 1;
- +
- + assert(xm & SP_HIDDEN_BIT);
- + assert(ym & SP_HIDDEN_BIT);
- +
- + /* provide guard,round and stick bit space */
- + xm <<= 3;
- + ym <<= 3;
- +
- + if (xe > ye) {
- + /* have to shift y fraction right to align
- + */
- + int s = xe - ye;
- + SPXSRSYn(s);
- + } else if (ye > xe) {
- + /* have to shift x fraction right to align
- + */
- + int s = ye - xe;
- + SPXSRSXn(s);
- + }
- + assert(xe == ye);
- + assert(xe <= SP_EMAX);
- +
- + if (xs == ys) {
- + /* generate 28 bit result of adding two 27 bit numbers
- + */
- + xm = xm + ym;
- + xe = xe;
- + xs = xs;
- +
- + if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */
- + SPXSRSX1(); /* shift preserving sticky */
- + }
- + } else {
- + if (xm >= ym) {
- + xm = xm - ym;
- + xe = xe;
- + xs = xs;
- + } else {
- + xm = ym - xm;
- + xe = xe;
- + xs = ys;
- + }
- + if (xm == 0) {
- + if (ieee754_csr.rm == IEEE754_RD)
- + return ieee754sp_zero(1); /* round negative inf. => sign = -1 */
- + else
- + return ieee754sp_zero(0); /* other round modes => sign = 1 */
- + }
- + /* normalize to rounding precision
- + */
- + while ((xm >> (SP_MBITS + 3)) == 0) {
- + xm <<= 1;
- + xe--;
- + }
- + }
- + SPNORMRET2(xs, xe, xm, "sub", x, y);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_tint.c linux-3.4.110/arch/nds32/math-emu/sp_tint.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/sp_tint.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/sp_tint.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,125 @@
- +/* IEEE754 floating point arithmetic
- + * single precision
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include <linux/kernel.h>
- +#include "ieee754sp.h"
- +
- +int ieee754sp_tint(ieee754sp x)
- +{
- + COMPXSP;
- +
- + CLEARCX;
- +
- + EXPLODEXSP;
- + FLUSHXSP;
- +
- + switch (xc) {
- + case IEEE754_CLASS_SNAN:
- + case IEEE754_CLASS_QNAN:
- + case IEEE754_CLASS_INF:
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x);
- + case IEEE754_CLASS_ZERO:
- + return 0;
- + case IEEE754_CLASS_DNORM:
- + case IEEE754_CLASS_NORM:
- + break;
- + }
- + if (xe >= 31) {
- + /* look for valid corner case */
- + if (xe == 31 && xs && xm == SP_HIDDEN_BIT)
- + return -0x80000000;
- + /* Set invalid. We will only use overflow for floating
- + point overflow */
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x);
- + }
- + /* oh gawd */
- + if (xe > SP_MBITS) {
- + xm <<= xe - SP_MBITS;
- + } else {
- + u32 residue;
- + int round;
- + int sticky;
- + int odd;
- +
- + if (xe < -1) {
- + residue = xm;
- + round = 0;
- + sticky = residue != 0;
- + xm = 0;
- + } else {
- + /* Shifting a u32 32 times does not work,
- + * so we do it in two steps. Be aware that xe
- + * may be -1 */
- + residue = xm << (xe + 1);
- + residue <<= 31 - SP_MBITS;
- + round = (residue >> 31) != 0;
- + sticky = (residue << 1) != 0;
- + xm >>= SP_MBITS - xe;
- + }
- + odd = (xm & 0x1) != 0x0;
- + switch (ieee754_csr.rm) {
- + case IEEE754_RN:
- + if (round && (sticky || odd))
- + xm++;
- + break;
- + case IEEE754_RZ:
- + break;
- + case IEEE754_RU: /* toward +Infinity */
- + if ((round || sticky) && !xs)
- + xm++;
- + break;
- + case IEEE754_RD: /* toward -Infinity */
- + if ((round || sticky) && xs)
- + xm++;
- + break;
- + }
- + if ((xm >> 31) != 0) {
- + /* This can happen after rounding */
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x);
- + }
- + if (round || sticky)
- + SETCX(IEEE754_INEXACT);
- + }
- + if (xs)
- + return -xm;
- + else
- + return xm;
- +}
- +
- +unsigned int ieee754sp_tuns(ieee754sp x)
- +{
- + ieee754sp hb = ieee754sp_1e31();
- +
- + /* what if x < 0 ?? */
- + if (ieee754sp_lt(x, hb))
- + return (unsigned)ieee754sp_tint(x);
- +
- + return (unsigned)ieee754sp_tint(ieee754sp_sub(x, hb)) |
- + ((unsigned)1 << 31);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_tlong.c linux-3.4.110/arch/nds32/math-emu/sp_tlong.c
- --- linux-3.4.110.orig/arch/nds32/math-emu/sp_tlong.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/math-emu/sp_tlong.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,119 @@
- +/* IEEE754 floating point arithmetic
- + * single precision
- + */
- +/*
- + * MIPS floating point support
- + * Copyright (C) 1994-2000 Algorithmics Ltd.
- + * http://www.algor.co.uk
- + *
- + * ########################################################################
- + *
- + * This program is free software; you can distribute it and/or modify it
- + * under the terms of the GNU General Public License (Version 2) as
- + * published by the Free Software Foundation.
- + *
- + * This program is distributed in the hope it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + * for more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program; if not, write to the Free Software Foundation, Inc.,
- + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- + *
- + * ########################################################################
- + */
- +
- +#include "ieee754sp.h"
- +
- +s64 ieee754sp_tlong(ieee754sp x)
- +{
- + COMPXDP; /* <-- need 64-bit mantissa tmp */
- +
- + CLEARCX;
- +
- + EXPLODEXSP;
- + FLUSHXSP;
- +
- + switch (xc) {
- + case IEEE754_CLASS_SNAN:
- + case IEEE754_CLASS_QNAN:
- + case IEEE754_CLASS_INF:
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
- + case IEEE754_CLASS_ZERO:
- + return 0;
- + case IEEE754_CLASS_DNORM:
- + case IEEE754_CLASS_NORM:
- + break;
- + }
- + if (xe >= 63) {
- + /* look for valid corner case */
- + if (xe == 63 && xs && xm == SP_HIDDEN_BIT)
- + return -0x8000000000000000LL;
- + /* Set invalid. We will only use overflow for floating
- + point overflow */
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
- + }
- + /* oh gawd */
- + if (xe > SP_MBITS) {
- + xm <<= xe - SP_MBITS;
- + } else if (xe < SP_MBITS) {
- + u32 residue;
- + int round;
- + int sticky;
- + int odd;
- +
- + if (xe < -1) {
- + residue = xm;
- + round = 0;
- + sticky = residue != 0;
- + xm = 0;
- + } else {
- + residue = xm << (32 - SP_MBITS + xe);
- + round = (residue >> 31) != 0;
- + sticky = (residue << 1) != 0;
- + xm >>= SP_MBITS - xe;
- + }
- + odd = (xm & 0x1) != 0x0;
- + switch (ieee754_csr.rm) {
- + case IEEE754_RN:
- + if (round && (sticky || odd))
- + xm++;
- + break;
- + case IEEE754_RZ:
- + break;
- + case IEEE754_RU: /* toward +Infinity */
- + if ((round || sticky) && !xs)
- + xm++;
- + break;
- + case IEEE754_RD: /* toward -Infinity */
- + if ((round || sticky) && xs)
- + xm++;
- + break;
- + }
- + if ((xm >> 63) != 0) {
- + /* This can happen after rounding */
- + SETCX(IEEE754_INVALID_OPERATION);
- + return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
- + }
- + if (round || sticky)
- + SETCX(IEEE754_INEXACT);
- + }
- + if (xs)
- + return -xm;
- + else
- + return xm;
- +}
- +
- +u64 ieee754sp_tulong(ieee754sp x)
- +{
- + ieee754sp hb = ieee754sp_1e63();
- +
- + /* what if x < 0 ?? */
- + if (ieee754sp_lt(x, hb))
- + return (u64) ieee754sp_tlong(x);
- +
- + return (u64) ieee754sp_tlong(ieee754sp_sub(x, hb)) | (1ULL << 63);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/mm/alignment.c linux-3.4.110/arch/nds32/mm/alignment.c
- --- linux-3.4.110.orig/arch/nds32/mm/alignment.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/mm/alignment.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,560 @@
- +/*
- + * linux/arch/nds32/mm/alignment.c
- + *
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/proc_fs.h>
- +#include <linux/uaccess.h>
- +
- +#include <asm/unaligned.h>
- +
- +#ifdef CONFIG_PROC_FS
- +extern struct proc_dir_entry *proc_dir_cpu;
- +#endif
- +
- +#define DEBUG(enable, tagged, ...) \
- + do{ \
- + if (enable) { \
- + if (tagged) \
- + printk(KERN_WARNING "[ %30s() ] ", __func__); \
- + printk(KERN_WARNING __VA_ARGS__); \
- + } \
- + } while (0)
- +
- +#define RT(inst) (((inst) >> 20) & 0x1FUL)
- +#define RA(inst) (((inst) >> 15) & 0x1FUL)
- +#define RB(inst) (((inst) >> 10) & 0x1FUL)
- +#define SV(inst) (((inst) >> 8) & 0x3UL)
- +#define IMM(inst) (((inst) >> 0) & 0x3FFFUL)
- +
- +#define RA3(inst) (((inst) >> 3) & 0x7UL)
- +#define RT3(inst) (((inst) >> 6) & 0x7UL)
- +#define IMM3U(inst) (((inst) >> 0) & 0x7UL)
- +
- +#define RA5(inst) (((inst) >> 0) & 0x1FUL)
- +#define RT4(inst) (((inst) >> 5) & 0xFUL)
- +
- +extern int (*do_unaligned_access)
- + (unsigned long entry, unsigned long addr,
- + unsigned long type, struct pt_regs * regs);
- +extern int va_present(struct mm_struct *mm, unsigned long addr);
- +extern int va_kernel_present(unsigned long addr);
- +extern int va_readable(struct pt_regs *regs, unsigned long addr);
- +extern int va_writable(struct pt_regs *regs, unsigned long addr);
- +
- +static int mode = 0x3;
- +module_param(mode, int, 1);
- +
- +static inline unsigned long *idx_to_addr(struct pt_regs *regs, int idx)
- +{
- + /* this should be consistent with ptrace.h */
- + if (idx >= 0 && idx <= 25) /* R0-R25 */
- + return ®s->NDS32_r0 + idx;
- + else if (idx >= 28 && idx <= 30) /* FP, GP, LP */
- + return ®s->NDS32_fp + (idx - 28);
- + else if (idx == 31) /* SP */
- + return ®s->NDS32_sp;
- + else
- + return NULL; /* cause a segfault */
- +}
- +
- +static inline unsigned long get_inst(unsigned long addr)
- +{
- + /* FIXME: consider 16-bit inst. */
- + return be32_to_cpu(get_unaligned((u32 *) addr));
- +}
- +
- +static inline unsigned long get_data(unsigned long addr, int len)
- +{
- + if (len == 4)
- + return get_unaligned((u32 *) addr);
- + else
- + return get_unaligned((u16 *) addr);
- +}
- +
- +static inline void set_data(unsigned long addr, unsigned long val, int len)
- +{
- + if (len == 4)
- + put_unaligned(val, (u32 *) addr);
- + else
- + put_unaligned(val, (u16 *) addr);
- +}
- +
- +static inline unsigned long sign_extend(unsigned long val, int len)
- +{
- + unsigned long ret = 0;
- + unsigned char *s, *t;
- + int i = 0;
- +
- + val = cpu_to_le32(val);
- +
- + s = (void *)&val;
- + t = (void *)&ret;
- +
- + while (i++ < len)
- + *t++ = *s++;
- +
- + if (((*(t - 1)) & 0x80) && (i < 4)) {
- +
- + while (i++ <= 4)
- + *t++ = 0xff;
- + }
- +
- + return le32_to_cpu(ret);
- +}
- +
- +static inline int do_16(unsigned long inst, struct pt_regs *regs)
- +{
- + int imm, regular, load, len, addr_mode, idx_mode;
- + unsigned long unaligned_addr, target_val, source_idx, target_idx,
- + shift = 0;
- + switch ((inst >> 9) & 0x3F) {
- +
- + case 0x12: /* LHI333 */
- + imm = 1;
- + regular = 1;
- + load = 1;
- + len = 2;
- + addr_mode = 3;
- + idx_mode = 3;
- + break;
- + case 0x10: /* LWI333 */
- + imm = 1;
- + regular = 1;
- + load = 1;
- + len = 4;
- + addr_mode = 3;
- + idx_mode = 3;
- + break;
- + case 0x11: /* LWI333.bi */
- + imm = 1;
- + regular = 0;
- + load = 1;
- + len = 4;
- + addr_mode = 3;
- + idx_mode = 3;
- + break;
- + case 0x1A: /* LWI450 */
- + imm = 0;
- + regular = 1;
- + load = 1;
- + len = 4;
- + addr_mode = 5;
- + idx_mode = 4;
- + break;
- + case 0x16: /* SHI333 */
- + imm = 1;
- + regular = 1;
- + load = 0;
- + len = 2;
- + addr_mode = 3;
- + idx_mode = 3;
- + break;
- + case 0x14: /* SWI333 */
- + imm = 1;
- + regular = 1;
- + load = 0;
- + len = 4;
- + addr_mode = 3;
- + idx_mode = 3;
- + break;
- + case 0x15: /* SWI333.bi */
- + imm = 1;
- + regular = 0;
- + load = 0;
- + len = 4;
- + addr_mode = 3;
- + idx_mode = 3;
- + break;
- + case 0x1B: /* SWI450 */
- + imm = 0;
- + regular = 1;
- + load = 0;
- + len = 4;
- + addr_mode = 5;
- + idx_mode = 4;
- + break;
- +
- + default:
- + return -EFAULT;
- + }
- +
- + if (addr_mode == 3) {
- + unaligned_addr = *idx_to_addr(regs, RA3(inst));
- + source_idx = RA3(inst);
- + } else {
- + unaligned_addr = *idx_to_addr(regs, RA5(inst));
- + source_idx = RA5(inst);
- + }
- +
- + if (idx_mode == 3)
- + target_idx = RT3(inst);
- + else
- + target_idx = RT4(inst);
- +
- + if (imm)
- + shift = IMM3U(inst) * len;
- +
- + if (regular)
- + unaligned_addr += shift;
- + else
- + *idx_to_addr(regs, source_idx) = unaligned_addr + shift;
- +
- + if (load) {
- +
- + if (!va_readable(regs, unaligned_addr))
- + return -EACCES;
- +
- + if (!access_ok(VERIFY_READ, (void *)unaligned_addr, len))
- + return -EACCES;
- +
- + *idx_to_addr(regs, target_idx) = get_data(unaligned_addr, len);
- + } else {
- +
- + if (!va_writable(regs, unaligned_addr))
- + return -EACCES;
- +
- + if (!access_ok(VERIFY_WRITE, (void *)unaligned_addr, len))
- + return -EACCES;
- +
- + target_val = *idx_to_addr(regs, target_idx);
- + set_data(unaligned_addr, target_val, len);
- + }
- +
- + regs->NDS32_ipc += 2;
- +
- + return 0;
- +}
- +
- +static inline int do_32(unsigned long inst, struct pt_regs *regs)
- +{
- + int imm, regular, load, len, sign_ext;
- + unsigned long unsligned_addr, target_val, shift;
- +
- + unsligned_addr = *idx_to_addr(regs, RA(inst));
- +
- + switch ((inst >> 25) << 1) {
- +
- + case 0x02: /* LHI */
- + imm = 1;
- + regular = 1;
- + load = 1;
- + len = 2;
- + sign_ext = 0;
- + break;
- + case 0x0A: /* LHI.bi */
- + imm = 1;
- + regular = 0;
- + load = 1;
- + len = 2;
- + sign_ext = 0;
- + break;
- + case 0x22: /* LHSI */
- + imm = 1;
- + regular = 1;
- + load = 1;
- + len = 2;
- + sign_ext = 1;
- + break;
- + case 0x2A: /* LHSI.bi */
- + imm = 1;
- + regular = 0;
- + load = 1;
- + len = 2;
- + sign_ext = 1;
- + break;
- + case 0x04: /* LWI */
- + imm = 1;
- + regular = 1;
- + load = 1;
- + len = 4;
- + sign_ext = 0;
- + break;
- + case 0x0C: /* LWI.bi */
- + imm = 1;
- + regular = 0;
- + load = 1;
- + len = 4;
- + sign_ext = 0;
- + break;
- + case 0x12: /* SHI */
- + imm = 1;
- + regular = 1;
- + load = 0;
- + len = 2;
- + sign_ext = 0;
- + break;
- + case 0x1A: /* SHI.bi */
- + imm = 1;
- + regular = 0;
- + load = 0;
- + len = 2;
- + sign_ext = 0;
- + break;
- + case 0x14: /* SWI */
- + imm = 1;
- + regular = 1;
- + load = 0;
- + len = 4;
- + sign_ext = 0;
- + break;
- + case 0x1C: /* SWI.bi */
- + imm = 1;
- + regular = 0;
- + load = 0;
- + len = 4;
- + sign_ext = 0;
- + break;
- +
- + default:
- + switch (inst & 0xff) {
- +
- + case 0x01: /* LH */
- + imm = 0;
- + regular = 1;
- + load = 1;
- + len = 2;
- + sign_ext = 0;
- + break;
- + case 0x05: /* LH.bi */
- + imm = 0;
- + regular = 0;
- + load = 1;
- + len = 2;
- + sign_ext = 0;
- + break;
- + case 0x11: /* LHS */
- + imm = 0;
- + regular = 1;
- + load = 1;
- + len = 2;
- + sign_ext = 1;
- + break;
- + case 0x15: /* LHS.bi */
- + imm = 0;
- + regular = 0;
- + load = 1;
- + len = 2;
- + sign_ext = 1;
- + break;
- + case 0x02: /* LW */
- + imm = 0;
- + regular = 1;
- + load = 1;
- + len = 4;
- + sign_ext = 0;
- + break;
- + case 0x06: /* LW.bi */
- + imm = 0;
- + regular = 0;
- + load = 1;
- + len = 4;
- + sign_ext = 0;
- + break;
- + case 0x09: /* SH */
- + imm = 0;
- + regular = 1;
- + load = 0;
- + len = 2;
- + sign_ext = 0;
- + break;
- + case 0x0D: /* SH.bi */
- + imm = 0;
- + regular = 0;
- + load = 0;
- + len = 2;
- + sign_ext = 0;
- + break;
- + case 0x0A: /* SW */
- + imm = 0;
- + regular = 1;
- + load = 0;
- + len = 4;
- + sign_ext = 0;
- + break;
- + case 0x0E: /* SW.bi */
- + imm = 0;
- + regular = 0;
- + load = 0;
- + len = 4;
- + sign_ext = 0;
- + break;
- +
- + default:
- + return -EFAULT;
- + }
- + }
- +
- + if (imm)
- + shift = IMM(inst) * len;
- + else
- + shift = *idx_to_addr(regs, RB(inst)) << SV(inst);
- +
- + if (regular)
- + unsligned_addr += shift;
- + else
- + *idx_to_addr(regs, RA(inst)) = unsligned_addr + shift;
- +
- + if (load) {
- +
- + if (!va_readable(regs, unsligned_addr))
- + return -EACCES;
- +
- + if (!access_ok(VERIFY_READ, (void *)unsligned_addr, len))
- + return -EACCES;
- +
- + if (sign_ext)
- + *idx_to_addr(regs, RT(inst)) =
- + sign_extend(get_data(unsligned_addr, len), len);
- + else
- + *idx_to_addr(regs, RT(inst)) =
- + get_data(unsligned_addr, len);
- + } else {
- +
- + if (!va_writable(regs, unsligned_addr))
- + return -EACCES;
- +
- + if (!access_ok(VERIFY_WRITE, (void *)unsligned_addr, len))
- + return -EACCES;
- +
- + target_val = *idx_to_addr(regs, RT(inst));
- + set_data(unsligned_addr, target_val, len);
- + }
- +
- + regs->NDS32_ipc += 4;
- +
- + return 0;
- +}
- +
- +static int _do_unaligned_access(unsigned long entry, unsigned long addr,
- + unsigned long type, struct pt_regs *regs)
- +{
- + unsigned long inst;
- + int ret = -EFAULT;
- +
- + if (user_mode(regs)) {
- + /* user mode */
- + if (!va_present(current->mm, addr))
- + return ret;
- + } else {
- + /* kernel mode */
- + if (!va_kernel_present(addr))
- + return ret;
- + }
- +
- + inst = get_inst(regs->NDS32_ipc);
- +
- + DEBUG(mode & 0x04, 1,
- + "Faulting Addr: 0x%08lx, PC: 0x%08lx [ 0x%08lx ]\n", addr,
- + regs->NDS32_ipc, inst);
- +
- + if ((user_mode(regs) && (mode & 0x01))
- + || (!user_mode(regs) && (mode & 0x02))) {
- +
- + mm_segment_t seg = get_fs();
- +
- + set_fs(KERNEL_DS);
- +
- + if (inst & 0x80000000)
- + ret = do_16((inst >> 16) & 0xffff, regs);
- + else
- + ret = do_32(inst, regs);
- +
- + set_fs(seg);
- + }
- +
- + return ret;
- +}
- +
- +#ifdef CONFIG_PROC_FS
- +
- +static int proc_alignment_read(char *page, char **start, off_t off, int count,
- + int *eof, void *data)
- +{
- + char *p = page;
- + int len;
- +
- + p += sprintf(p, "(0x01) User Mode: %s\n", mode & 0x01 ? "on" : "off");
- + p += sprintf(p, "(0x02) Kernel Mode: %s\n", mode & 0x02 ? "on" : "off");
- + p += sprintf(p, "(0x04) Warning: %s\n", mode & 0x04 ? "on" : "off");
- +
- + len = (p - page) - off;
- + if (len < 0)
- + len = 0;
- +
- + *eof = (len <= count) ? 1 : 0;
- + *start = page + off;
- +
- + return len;
- +}
- +
- +#define INPUTLEN 12 /* '0' + 'x' + 8digit + '\n' + '\0' */
- +
- +static int proc_alignment_write(struct file *file, const char __user * buffer,
- + unsigned long count, void *data)
- +{
- + unsigned long en;
- + char *endp;
- + char inbuf[INPUTLEN];
- +
- + if (count > INPUTLEN - 1)
- + return -EFAULT;
- +
- + if (copy_from_user(inbuf, buffer, count))
- + return -EFAULT;
- +
- + inbuf[count - 1] = '\0';
- +
- + en = simple_strtoul(inbuf, &endp, 0);
- + if (en > 0x07)
- + return -EFAULT;
- +
- + mode = en & 0x7;
- +
- + return count;
- +}
- +
- +#endif /* CONFIG_PROC_FS */
- +
- +static int __init unaligned_access_init(void)
- +{
- +#ifdef CONFIG_PROC_FS
- + static struct proc_dir_entry *res_alignment;
- +
- + if (!proc_dir_cpu)
- + if (!(proc_dir_cpu = proc_mkdir("cpu", NULL)))
- + return -ENOMEM;
- +
- + if (!
- + (res_alignment =
- + create_proc_entry("alignment", S_IWUSR | S_IRUGO, proc_dir_cpu)))
- + return -ENOMEM;
- +
- + res_alignment->read_proc = proc_alignment_read;
- + res_alignment->write_proc = proc_alignment_write;
- +#endif
- + do_unaligned_access = _do_unaligned_access;
- +
- + return 0;
- +}
- +
- +static void __exit unaligned_access_exit(void)
- +{
- +#ifdef CONFIG_PROC_FS
- + remove_proc_entry("alignment", proc_dir_cpu);
- +#endif
- + do_unaligned_access = NULL;
- +}
- +
- +MODULE_AUTHOR("Roy Lee");
- +MODULE_DESCRIPTION("Unaligned Access Handler");
- +MODULE_LICENSE("GPL");
- +
- +module_init(unaligned_access_init);
- +module_exit(unaligned_access_exit);
- diff -Nur linux-3.4.110.orig/arch/nds32/mm/cacheflush.c linux-3.4.110/arch/nds32/mm/cacheflush.c
- --- linux-3.4.110.orig/arch/nds32/mm/cacheflush.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/mm/cacheflush.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,355 @@
- +#include <linux/mm.h>
- +#include <linux/sched.h>
- +#include <linux/fs.h>
- +#include <linux/pagemap.h>
- +#include <linux/module.h>
- +#include <asm/cacheflush.h>
- +#include <asm/proc-fns.h>
- +#include <asm/shmparam.h>
- +#include <asm/cache_info.h>
- +
- +extern struct cache_info L1_cache_info[2];
- +
- +#ifdef CONFIG_CPU_CACHE_NONALIASING
- +void flush_cache_mm(struct mm_struct *mm)
- +{
- +}
- +
- +void flush_cache_dup_mm(struct mm_struct *mm)
- +{
- +}
- +
- +void flush_cache_range(struct vm_area_struct *vma,
- + unsigned long start, unsigned long end)
- +{
- +}
- +
- +void flush_cache_page(struct vm_area_struct *vma,
- + unsigned long addr, unsigned long pfn)
- +{
- +}
- +
- +void flush_cache_vmap(unsigned long start, unsigned long end)
- +{
- +}
- +
- +void flush_cache_vunmap(unsigned long start, unsigned long end)
- +{
- +}
- +
- +void flush_dcache_page(struct page *page)
- +{
- + struct address_space *mapping;
- +
- + if (!PageHighMem(page)) {
- + mapping = page_mapping(page);
- + if (mapping && !mapping_mapped(mapping))
- + set_bit(PG_dcache_dirty, &page->flags);
- + else
- + cpu_dcache_wbinval_page((unsigned long)
- + page_address(page));
- + } else {
- + unsigned long kaddr = (unsigned long)kmap_atomic(page);
- + cpu_dcache_wbinval_page(kaddr);
- + kunmap_atomic((void *)kaddr);
- + }
- +}
- +
- +void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
- + unsigned long vaddr, void *dst, void *src, int len)
- +{
- + unsigned long line_size, start, end;
- +
- + memcpy(dst, src, len);
- + if (vma->vm_flags & VM_EXEC) {
- + line_size = L1_cache_info[DCACHE].line_size;
- + start = (unsigned long)dst & ~(line_size - 1);
- + end =
- + ((unsigned long)dst + len + line_size - 1) & ~(line_size -
- + 1);
- + cpu_cache_wbinval_range(start, end, 1);
- + }
- +}
- +
- +void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
- + unsigned long vaddr, void *dst, void *src, int len)
- +{
- + memcpy(dst, src, len);
- +}
- +
- +void flush_icache_range(unsigned long start, unsigned long end)
- +{
- + cpu_cache_wbinval_range(start, end, 1);
- +}
- +
- +void flush_icache_page(struct vm_area_struct *vma, struct page *page)
- +{
- +}
- +
- +void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
- + pte_t * pte)
- +{
- + struct page *page;
- + unsigned long pfn = pte_pfn(*pte);
- +
- + if (!pfn_valid(pfn))
- + return;
- +
- + if (vma->vm_mm == current->active_mm)
- + asm("mtsr %1, $mr2\ndsb\n"
- + "tlbop %0, RWR\nisb\n"
- + ::"r"(*pte), "r"(addr));
- +
- + page = pfn_to_page(pfn);
- +
- + if ((test_and_clear_bit(PG_dcache_dirty, &page->flags)) ||
- + (vma->vm_flags & VM_EXEC)) {
- +
- + if (!PageHighMem(page)) {
- + cpu_cache_wbinval_page((unsigned long)
- + page_address(page),
- + vma->vm_flags & VM_EXEC);
- + } else {
- + unsigned long kaddr = (unsigned long)kmap_atomic(page);
- + cpu_cache_wbinval_page(kaddr, vma->vm_flags & VM_EXEC);
- + kunmap_atomic((void *)kaddr);
- + }
- + }
- +}
- +#else
- +int va_present(struct mm_struct *mm, unsigned long addr);
- +
- +static inline unsigned long aliasing(unsigned long addr, unsigned long page)
- +{
- + return ((addr & PAGE_MASK) ^ page) & (REALSHMLBA - 1);
- +}
- +
- +static inline unsigned long kremap0(unsigned long uaddr, unsigned long pa)
- +{
- + unsigned long kaddr, pte;
- +
- +#define BASE_ADDR0 0xffffc000
- + kaddr = BASE_ADDR0 | (uaddr & L1_cache_info[DCACHE].aliasing_mask);
- + pte = (pa | PAGE_KERNEL);
- + asm("mtsr %1, $mr2\ndsb\n"
- + "tlbop %0, RWLK\nisb\n"
- + ::"r"(pte), "r"(kaddr));
- + return kaddr;
- +}
- +
- +static inline void kunmap01(unsigned long kaddr)
- +{
- + asm volatile ("tlbop %0, UNLK\n\t"
- + "tlbop %0, INV\n\t"
- + ::"r" (kaddr));
- +}
- +
- +static inline unsigned long kremap1(unsigned long uaddr, unsigned long pa)
- +{
- + unsigned long kaddr, pte;
- +
- +#define BASE_ADDR1 0xffff8000
- + kaddr = BASE_ADDR1 | (uaddr & L1_cache_info[DCACHE].aliasing_mask);
- + pte = (pa | PAGE_KERNEL);
- + asm("mtsr %1, $mr2\ndsb\n"
- + "tlbop %0, RWLK\nisb\n"
- + ::"r"(pte), "r"(kaddr));
- + return kaddr;
- +}
- +
- +void flush_cache_mm(struct mm_struct *mm)
- +{
- + cpu_dcache_wbinval_all();
- + cpu_icache_inval_all();
- +}
- +
- +void flush_cache_dup_mm(struct mm_struct *mm)
- +{
- +}
- +
- +void flush_cache_range(struct vm_area_struct *vma,
- + unsigned long start, unsigned long end)
- +{
- + if ((end - start) > 8 * PAGE_SIZE) {
- + cpu_dcache_wbinval_all();
- + if (vma->vm_flags & VM_EXEC)
- + cpu_icache_inval_all();
- + return;
- + }
- +
- + while (start < end) {
- + if (va_present(vma->vm_mm, start))
- + cpu_cache_wbinval_page(start, vma->vm_flags & VM_EXEC);
- + start += PAGE_SIZE;
- + }
- +}
- +
- +void flush_cache_page(struct vm_area_struct *vma,
- + unsigned long addr, unsigned long pfn)
- +{
- + unsigned long vto, flags;
- +
- + local_irq_save(flags);
- + vto = kremap0(addr, pfn << PAGE_SHIFT);
- + cpu_cache_wbinval_page(vto, vma->vm_flags & VM_EXEC);
- + kunmap01(vto);
- + local_irq_restore(flags);
- +}
- +
- +void flush_cache_vmap(unsigned long start, unsigned long end)
- +{
- + cpu_dcache_wbinval_all();
- +}
- +
- +void flush_cache_vunmap(unsigned long start, unsigned long end)
- +{
- + cpu_dcache_wbinval_all();
- +}
- +
- +void copy_user_highpage(struct page *to, struct page *from,
- + unsigned long vaddr, struct vm_area_struct *vma)
- +{
- + unsigned long vto, vfrom, flags, kto, kfrom, pfrom, pto;
- + kto = ((unsigned long)page_address(to) & PAGE_MASK);
- + kfrom = ((unsigned long)page_address(from) & PAGE_MASK);
- + pto = page_to_phys(to);
- + pfrom = page_to_phys(from);
- +
- + if (aliasing(vaddr, (unsigned long)kfrom))
- + cpu_dcache_wb_page((unsigned long)kfrom);
- + if (aliasing(vaddr, (unsigned long)kto))
- + cpu_dcache_inval_page((unsigned long)kto);
- + local_irq_save(flags);
- + vto = kremap0(vaddr, pto);
- + vfrom = kremap1(vaddr, pfrom);
- + copy_page((void *)vto, (void *)vfrom);
- + kunmap01(vfrom);
- + kunmap01(vto);
- + local_irq_restore(flags);
- +}
- +
- +EXPORT_SYMBOL(copy_user_highpage);
- +
- +void clear_user_highpage(struct page *page, unsigned long vaddr)
- +{
- + unsigned long vto, flags, kto;
- +
- + kto = ((unsigned long)page_address(page) & PAGE_MASK);
- +
- + local_irq_save(flags);
- + if (aliasing(kto, vaddr) && kto != 0) {
- + cpu_dcache_inval_page(kto);
- + cpu_icache_inval_page(kto);
- + }
- + vto = kremap0(vaddr, page_to_phys(page));
- + clear_page((void *)vto);
- + kunmap01(vto);
- + local_irq_restore(flags);
- +}
- +
- +EXPORT_SYMBOL(clear_user_highpage);
- +
- +void flush_dcache_page(struct page *page)
- +{
- + struct address_space *mapping;
- +
- + mapping = page_mapping(page);
- + if (mapping && !mapping_mapped(mapping))
- + set_bit(PG_dcache_dirty, &page->flags);
- + else {
- + int i, pc;
- + unsigned long vto, kaddr, flags;
- + cpu_dcache_wbinval_page((unsigned long)page_address(page));
- + kaddr = (unsigned long)page_address(page);
- + pc = CACHE_SET(DCACHE) * CACHE_LINE_SIZE(DCACHE) / PAGE_SIZE;
- + for (i = 0; i < pc; i++) {
- + local_irq_save(flags);
- + vto = kremap0(kaddr + i * PAGE_SIZE, __pa(kaddr));
- + cpu_dcache_wbinval_page(vto);
- + kunmap01(vto);
- + local_irq_restore(flags);
- + }
- + }
- +}
- +
- +void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
- + unsigned long vaddr, void *dst, void *src, int len)
- +{
- + unsigned long line_size, start, end, vto, flags;
- +
- + local_irq_save(flags);
- + vto = kremap0(vaddr, page_to_phys(page));
- + dst = (void *)(vto | (vaddr & (PAGE_SIZE - 1)));
- + memcpy(dst, src, len);
- + if (vma->vm_flags & VM_EXEC) {
- + line_size = L1_cache_info[DCACHE].line_size;
- + start = (unsigned long)dst & ~(line_size - 1);
- + end =
- + ((unsigned long)dst + len + line_size - 1) & ~(line_size -
- + 1);
- + cpu_cache_wbinval_range(start, end, 1);
- + }
- + kunmap01(vto);
- + local_irq_restore(flags);
- +}
- +
- +void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
- + unsigned long vaddr, void *dst, void *src, int len)
- +{
- + unsigned long vto, flags;
- +
- + local_irq_save(flags);
- + vto = kremap0(vaddr, page_to_phys(page));
- + src = (void *)(vto | (vaddr & (PAGE_SIZE - 1)));
- + memcpy(dst, src, len);
- + kunmap01(vto);
- + local_irq_restore(flags);
- +}
- +
- +void flush_anon_page(struct vm_area_struct *vma,
- + struct page *page, unsigned long vaddr)
- +{
- + if (!PageAnon(page))
- + return;
- +
- + if (vma->vm_mm != current->active_mm)
- + return;
- +
- + cpu_cache_wbinval_page(vaddr & PAGE_MASK, vma->vm_flags & VM_EXEC);
- +}
- +
- +void flush_kernel_dcache_page(struct page *page)
- +{
- + cpu_dcache_wbinval_page((unsigned long)page_address(page));
- +}
- +
- +void flush_icache_range(unsigned long start, unsigned long end)
- +{
- + cpu_cache_wbinval_range(start, end, 1);
- +}
- +
- +void flush_icache_page(struct vm_area_struct *vma, struct page *page)
- +{
- +}
- +
- +void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
- + pte_t * pte)
- +{
- + struct page *page;
- + unsigned long pfn = pte_pfn(*pte);
- +
- + if (!pfn_valid(pfn))
- + return;
- +
- + if (vma->vm_mm == current->active_mm) {
- + asm("mtsr %1, $mr2\ndsb\n"
- + "tlbop %0, RWR\nisb\n"
- + ::"r"(*pte), "r"(addr));
- + }
- +
- + page = pfn_to_page(pfn);
- + if (test_and_clear_bit(PG_dcache_dirty, &page->flags) ||
- + (vma->vm_flags & VM_EXEC))
- + cpu_dcache_wbinval_page((unsigned long)page_address(page));
- +}
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/mm/cctl.c linux-3.4.110/arch/nds32/mm/cctl.c
- --- linux-3.4.110.orig/arch/nds32/mm/cctl.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/mm/cctl.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,284 @@
- +/*
- + * linux/arch/nds32/mm/cctl.c
- + *
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include "cctl.h"
- +
- +#define DEBUG( enable, tagged, ...) \
- + do{ \
- + if( enable){ \
- + if( tagged) \
- + printk( "[ %30s() ] ", __func__); \
- + printk( __VA_ARGS__); \
- + } \
- + } while( 0)
- +
- +static int debug = 1;
- +module_param(debug, int, 0);
- +
- +static int proc_read_cache_en(char *page, char **start, off_t off,
- + int count, int *eof, void *data)
- +{
- +
- + if (!strncmp(data, "ic_en", 7))
- + return sprintf(page, "I-cache: %s\n",
- + (GET_CACHE_CTL() & CACHE_CTL_mskIC_EN) ?
- + "Enabled" : "Disabled");
- + else
- + return sprintf(page, "D-cache: %s\n",
- + (GET_CACHE_CTL() & CACHE_CTL_mskDC_EN) ?
- + "Enabled" : "Disabled");
- +}
- +
- +static int proc_write_cache_en(struct file *file, const char *buffer,
- + unsigned long count, void *data)
- +{
- +
- + unsigned long en, saved_gie;
- + char inbuf[INPUTLEN];
- +
- + if (count > INPUTLEN - 1)
- + count = INPUTLEN - 1;
- +
- + if (copy_from_user(inbuf, buffer, count))
- + return -EFAULT;
- +
- + inbuf[count] = '\0';
- +
- + if (!sscanf(inbuf, "%lu", &en) || en > 1)
- + return -EFAULT;
- +
- + GIE_SAVE(&saved_gie);
- +
- + if (!strncmp(data, "ic_en", 7)) {
- +
- + if (en && !(GET_CACHE_CTL() & CACHE_CTL_mskIC_EN)) {
- +
- + SET_CACHE_CTL(GET_CACHE_CTL() | CACHE_CTL_mskIC_EN);
- + DEBUG(debug, 1, "I-cache: Enabled\n");
- + } else if (!en && (GET_CACHE_CTL() & CACHE_CTL_mskIC_EN)) {
- +
- + SET_CACHE_CTL(GET_CACHE_CTL() & ~CACHE_CTL_mskIC_EN);
- + cpu_icache_inval_all();
- + DEBUG(debug, 1, "I-cache: Disabled\n");
- + }
- + } else {
- + if (en && !(GET_CACHE_CTL() & CACHE_CTL_mskDC_EN)) {
- +
- + SET_CACHE_CTL(GET_CACHE_CTL() | CACHE_CTL_mskDC_EN);
- + DEBUG(debug, 1, "D-cache: Enabled\n");
- + } else if (!en && (GET_CACHE_CTL() & CACHE_CTL_mskDC_EN)) {
- +
- + SET_CACHE_CTL(GET_CACHE_CTL() & ~CACHE_CTL_mskDC_EN);
- + cpu_dcache_wbinval_all();
- + DEBUG(debug, 1, "D-cache: Disabled\n");
- + }
- + }
- +
- + GIE_RESTORE(saved_gie);
- +
- + return count;
- +}
- +
- +struct entry_struct proc_table_cache_en[] = {
- +
- + {"ic_en", 0644, proc_read_cache_en, proc_write_cache_en},
- + {"dc_en", 0644, proc_read_cache_en, proc_write_cache_en},
- + {NULL, 0, NULL, NULL}
- +};
- +
- +static int sprint_cache_sdz(char *buf, unsigned long size, unsigned long way,
- + unsigned sdz)
- +{
- +
- + return sprintf(buf, "[%c] %luK x %lu\n[%c] %luK x %lu\n"
- + "[%c] %luK x %lu\n[%c] %luK x %lu\n",
- + (sdz == 0) ? '*' : ' ', (size / 1024), way,
- + (sdz == 1) ? '*' : ' ', (size / 1024), way / 2,
- + (sdz == 2) ? '*' : ' ', (size / 1024) / 2, way,
- + (sdz == 3) ? '*' : ' ', (size / 1024) / 2, way / 2);
- +}
- +
- +static int proc_read_cache_sdz(char *page, char **start, off_t off,
- + int count, int *eof, void *data)
- +{
- +
- + if (!strncmp(data, "ic_sdz", 7)) {
- +
- + return sprint_cache_sdz(page,
- + CACHE_LINE_SIZE(ICACHE) *
- + CACHE_SET(ICACHE), CACHE_WAY(ICACHE),
- + (GET_SDZ_CTL() & SDZ_CTL_mskICDZ) >>
- + SDZ_CTL_offICDZ);
- + } else {
- + return sprint_cache_sdz(page,
- + CACHE_LINE_SIZE(DCACHE) *
- + CACHE_SET(DCACHE), CACHE_WAY(DCACHE),
- + (GET_SDZ_CTL() & SDZ_CTL_mskDCDZ) >>
- + SDZ_CTL_offDCDZ);
- + }
- +}
- +
- +static int proc_write_cache_sdz(struct file *file, const char *buffer,
- + unsigned long count, void *data)
- +{
- +
- + unsigned long mode, saved_gie, saved_cctl;
- + char inbuf[INPUTLEN];
- +
- + if (count > INPUTLEN - 1)
- + count = INPUTLEN - 1;
- +
- + if (copy_from_user(inbuf, buffer, count))
- + return -EFAULT;
- +
- + inbuf[count] = '\0';
- +
- + if (!sscanf(inbuf, "%lu", &mode) || mode > 3)
- + return -EFAULT;
- +
- + GIE_SAVE(&saved_gie);
- +
- + saved_cctl = GET_CACHE_CTL();
- + DEBUG(debug, 1, "saved_gie: %ld, saved_cctl: 0x%08lx\n", saved_gie,
- + saved_cctl);
- +
- + if (!strncmp(data, "ic_sdz", 7)) {
- +
- + DEBUG(debug, 1, "IC_SDZ: mode %ld\n", mode);
- +
- + if (mode == 2 || mode == 3) {
- +
- + if (CACHE_LINE_SIZE(ICACHE) * CACHE_SET(ICACHE) / 2 <
- + 4096) {
- +
- + GIE_RESTORE(saved_gie);
- + DEBUG(debug, 1, "Error: way size < 4096\n");
- + return -1;
- + }
- + }
- +
- + /* turn off and flush cache */
- + DEBUG(debug, 1, "turning off cache\n");
- + SET_CACHE_CTL(saved_cctl & ~CACHE_CTL_mskIC_EN);
- + DEBUG(debug, 1, "flushing cache\n");
- + cpu_icache_inval_all();
- +
- + /* perform down size operation */
- + DEBUG(debug, 1, "downsizing cache\n");
- + SET_SDZ_CTL((GET_SDZ_CTL() & ~SDZ_CTL_mskICDZ) |
- + (mode << SDZ_CTL_offICDZ));
- + } else {
- +
- + DEBUG(debug, 1, "DC_SDZ: mode %ld\n", mode);
- +
- + if (mode == 2 || mode == 3) {
- +
- + if (CACHE_LINE_SIZE(DCACHE) * CACHE_SET(DCACHE) / 2 <
- + 4096) {
- +
- + GIE_RESTORE(saved_gie);
- + DEBUG(debug, 1, "Error: way size < 4096\n");
- + return -1;
- + }
- + }
- +
- + /* turn off and flush cache */
- + DEBUG(debug, 1, "turning off cache\n");
- + SET_CACHE_CTL(saved_cctl & ~CACHE_CTL_mskDC_EN);
- + DEBUG(debug, 1, "flushing cache\n");
- + cpu_dcache_wbinval_all();
- +
- + /* perform down size operation */
- + DEBUG(debug, 1, "downsizing cache\n");
- + SET_SDZ_CTL((GET_SDZ_CTL() & ~SDZ_CTL_mskDCDZ) |
- + (mode << SDZ_CTL_offDCDZ));
- + }
- +
- + /* turn on cache ( if it was enabled) */
- + DEBUG(debug, 1, "restoring saved_cctl : 0x%08lx\n", saved_cctl);
- + SET_CACHE_CTL(saved_cctl);
- +
- + DEBUG(debug, 1, "restoring saved_git: %ld\n", saved_gie);
- + GIE_RESTORE(saved_gie);
- +
- + return count;
- +}
- +
- +struct entry_struct proc_table_cache_sdz[] = {
- +
- + {"ic_sdz", 0644, proc_read_cache_sdz, proc_write_cache_sdz},
- + {"dc_sdz", 0644, proc_read_cache_sdz, proc_write_cache_sdz},
- + {NULL, 0, NULL, NULL}
- +};
- +
- +static struct proc_dir_entry *proc_cctl;
- +
- +static void create_seq_entry(struct entry_struct *e, mode_t mode,
- + struct proc_dir_entry *parent)
- +{
- +
- + struct proc_dir_entry *entry = create_proc_entry(e->name, mode, parent);
- +
- + if (entry) {
- +
- + entry->read_proc = e->readop;
- + entry->write_proc = e->writeop;
- + entry->data = e->name;
- + }
- +}
- +
- +static void install_proc_table(struct entry_struct *table)
- +{
- +
- + while (table->name) {
- +
- + create_seq_entry(table, table->perm, proc_cctl);
- + table++;
- + }
- +}
- +
- +static void remove_proc_table(struct entry_struct *table)
- +{
- +
- + while (table->name) {
- +
- + remove_proc_entry(table->name, proc_cctl);
- + table++;
- + }
- +}
- +
- +static int __init init_cctl(void)
- +{
- +
- + DEBUG(debug, 1, "CCTL module registered\n");
- +
- + proc_cctl = proc_mkdir("cctl", NULL);
- +
- + install_proc_table(proc_table_cache_en);
- + install_proc_table(proc_table_cache_sdz);
- +
- + return 0;
- +}
- +
- +static void __exit cleanup_cctl(void)
- +{
- +
- + remove_proc_table(proc_table_cache_sdz);
- + remove_proc_table(proc_table_cache_en);
- + remove_proc_entry("cctl", NULL);
- +
- + DEBUG(debug, 1, "CCTL module unregistered\n");
- +}
- +
- +module_init(init_cctl);
- +module_exit(cleanup_cctl);
- +
- +MODULE_LICENSE("GPL");
- +MODULE_DESCRIPTION("Userspace Cache Control Module");
- diff -Nur linux-3.4.110.orig/arch/nds32/mm/cctl.h linux-3.4.110/arch/nds32/mm/cctl.h
- --- linux-3.4.110.orig/arch/nds32/mm/cctl.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/mm/cctl.h 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,22 @@
- +#ifndef CCTL_H
- +#define CCTL_H
- +
- +#include <linux/module.h>
- +#include <linux/blkdev.h>
- +#include <linux/proc_fs.h>
- +#include <asm/nds32.h>
- +
- +#define INPUTLEN 32
- +
- +extern void cpu_icache_flush(void);
- +extern void cpu_dcache_flush(void);
- +
- +struct entry_struct{
- +
- + char *name;
- + int perm;
- + read_proc_t *readop;
- + write_proc_t *writeop;
- +};
- +
- +#endif /* CCTL_H */
- diff -Nur linux-3.4.110.orig/arch/nds32/mm/consistent.c linux-3.4.110/arch/nds32/mm/consistent.c
- --- linux-3.4.110.orig/arch/nds32/mm/consistent.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/mm/consistent.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,448 @@
- +/*
- + * linux/arch/nds32/mm/consistent.c
- + *
- + * Copyright (C) 2000-2004 Russell King
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * DMA uncached mapping support.
- + */
- +#include <linux/dma-mapping.h>
- +#include <linux/sched.h>
- +#include <linux/slab.h>
- +#include <asm/cacheflush.h>
- +#include <asm/tlbflush.h>
- +#include <asm/pgtable.h>
- +#include <linux/module.h>
- +
- +/*
- + * This is the page table (2MB) covering uncached, DMA consistent allocations
- + */
- +static pte_t *consistent_pte;
- +static DEFINE_RAW_SPINLOCK(consistent_lock);
- +
- +/*
- + * VM region handling support.
- + *
- + * This should become something generic, handling VM region allocations for
- + * vmalloc and similar (ioremap, module space, etc).
- + *
- + * I envisage vmalloc()'s supporting vm_struct becoming:
- + *
- + * struct vm_struct {
- + * struct vm_region region;
- + * unsigned long flags;
- + * struct page **pages;
- + * unsigned int nr_pages;
- + * unsigned long phys_addr;
- + * };
- + *
- + * get_vm_area() would then call vm_region_alloc with an appropriate
- + * struct vm_region head (eg):
- + *
- + * struct vm_region vmalloc_head = {
- + * .vm_list = LIST_HEAD_INIT(vmalloc_head.vm_list),
- + * .vm_start = VMALLOC_START,
- + * .vm_end = VMALLOC_END,
- + * };
- + *
- + * However, vmalloc_head.vm_start is variable (typically, it is dependent on
- + * the amount of RAM found at boot time.) I would imagine that get_vm_area()
- + * would have to initialise this each time prior to calling vm_region_alloc().
- + */
- +struct arch_vm_region {
- + struct list_head vm_list;
- + unsigned long vm_start;
- + unsigned long vm_end;
- + struct page *vm_pages;
- +};
- +
- +static struct arch_vm_region consistent_head = {
- + .vm_list = LIST_HEAD_INIT(consistent_head.vm_list),
- + .vm_start = CONSISTENT_BASE,
- + .vm_end = CONSISTENT_END,
- +};
- +
- +static struct arch_vm_region *vm_region_alloc(struct arch_vm_region *head,
- + size_t size, int gfp)
- +{
- + unsigned long addr = head->vm_start, end = head->vm_end - size;
- + unsigned long flags;
- + struct arch_vm_region *c, *new;
- +
- + new = kmalloc(sizeof(struct arch_vm_region), gfp);
- + if (!new)
- + goto out;
- +
- + raw_spin_lock_irqsave(&consistent_lock, flags);
- +
- + list_for_each_entry(c, &head->vm_list, vm_list) {
- + if ((addr + size) < addr)
- + goto nospc;
- + if ((addr + size) <= c->vm_start)
- + goto found;
- + addr = c->vm_end;
- + if (addr > end)
- + goto nospc;
- + }
- +
- +found:
- + /*
- + * Insert this entry _before_ the one we found.
- + */
- + list_add_tail(&new->vm_list, &c->vm_list);
- + new->vm_start = addr;
- + new->vm_end = addr + size;
- +
- + raw_spin_unlock_irqrestore(&consistent_lock, flags);
- + return new;
- +
- +nospc:
- + raw_spin_unlock_irqrestore(&consistent_lock, flags);
- + kfree(new);
- +out:
- + return NULL;
- +}
- +
- +static struct arch_vm_region *vm_region_find(struct arch_vm_region *head,
- + unsigned long addr)
- +{
- + struct arch_vm_region *c;
- +
- + list_for_each_entry(c, &head->vm_list, vm_list) {
- + if (c->vm_start == addr)
- + goto out;
- + }
- + c = NULL;
- +out:
- + return c;
- +}
- +
- +#ifdef CONFIG_HUGETLB_PAGE
- +#error ARM Coherent DMA allocator does not (yet) support huge TLB
- +#endif
- +
- +static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t * handle,
- + int gfp, pgprot_t prot)
- +{
- + struct page *page;
- + struct arch_vm_region *c;
- + unsigned long order;
- + unsigned int i;
- + u64 mask = ISA_DMA_THRESHOLD, limit;
- +
- + if (!consistent_pte) {
- + printk(KERN_ERR "%s: not initialised\n", __func__);
- + dump_stack();
- + return NULL;
- + }
- +
- + if (dev) {
- + mask = dev->coherent_dma_mask;
- +
- + /*
- + * Sanity check the DMA mask - it must be non-zero, and
- + * must be able to be satisfied by a DMA allocation.
- + */
- + if (mask == 0) {
- + dev_warn(dev, "coherent DMA mask is unset\n");
- + goto no_page;
- + }
- +
- + if ((~mask) & ISA_DMA_THRESHOLD) {
- + dev_warn(dev, "coherent DMA mask %#llx is smaller "
- + "than system GFP_DMA mask %#llx\n",
- + mask, (unsigned long long)ISA_DMA_THRESHOLD);
- + goto no_page;
- + }
- + }
- +
- + /*
- + * Sanity check the allocation size.
- + */
- + size = PAGE_ALIGN(size);
- + limit = (mask + 1) & ~mask;
- + if ((limit && size >= limit) ||
- + size >= (CONSISTENT_END - CONSISTENT_BASE)) {
- + printk(KERN_WARNING "coherent allocation too big "
- + "(requested %#x mask %#llx)\n", size, mask);
- + goto no_page;
- + }
- +
- + order = get_order(size);
- +
- + if (mask != 0xffffffff)
- + gfp |= GFP_DMA;
- +
- + page = alloc_pages(gfp, order);
- + if (!page)
- + goto no_page;
- +
- + for (i = 1; i < (1 << order); i++)
- + atomic_set(&(page + i)->_count, 1);
- +
- + /*
- + * Invalidate any data that might be lurking in the
- + * kernel direct-mapped region for device DMA.
- + */
- + {
- + unsigned long kaddr = (unsigned long)page_address(page);
- + memset(page_address(page), 0, size);
- + cpu_dma_wbinval_range(kaddr, kaddr + size);
- + }
- +
- + /*
- + * Allocate a virtual address in the consistent mapping region.
- + */
- + c = vm_region_alloc(&consistent_head, size,
- + gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
- + if (c) {
- + pte_t *pte = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
- + struct page *end = page + (1 << order);
- +
- + c->vm_pages = page;
- +
- + /*
- + * Set the "dma handle"
- + */
- + *handle = page_to_dma(dev, page);
- +
- + do {
- + BUG_ON(!pte_none(*pte));
- +
- + /*
- + * x86 does not mark the pages reserved...
- + */
- + SetPageReserved(page);
- + set_pte(pte, mk_pte(page, prot));
- + page++;
- + pte++;
- + } while (size -= PAGE_SIZE);
- +
- + /*
- + * Free the otherwise unused pages.
- + */
- + while (page < end) {
- + __free_page(page);
- + page++;
- + }
- +
- + return (void *)c->vm_start;
- + }
- +
- + if (page)
- + __free_pages(page, order);
- +no_page:
- + *handle = ~0;
- + return NULL;
- +}
- +
- +/*
- + * Allocate DMA-coherent memory space and return both the kernel remapped
- + * virtual and bus address for that space.
- + */
- +void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t * handle,
- + gfp_t gfp)
- +{
- + return __dma_alloc(dev, size, handle, gfp,
- + pgprot_noncached(PAGE_KERNEL));
- +}
- +
- +EXPORT_SYMBOL(dma_alloc_coherent);
- +
- +/*
- + * Allocate a writecombining region, in much the same way as
- + * dma_alloc_coherent above.
- + */
- +void *dma_alloc_writecombine(struct device *dev, size_t size,
- + dma_addr_t * handle, gfp_t gfp)
- +{
- + return __dma_alloc(dev, size, handle, gfp,
- + pgprot_writecombine(PAGE_KERNEL));
- +}
- +
- +EXPORT_SYMBOL(dma_alloc_writecombine);
- +
- +static int dma_mmap(struct device *dev, struct vm_area_struct *vma,
- + void *cpu_addr, dma_addr_t dma_addr, size_t size)
- +{
- + unsigned long flags, user_size, kern_size;
- + struct arch_vm_region *c;
- + int ret = -ENXIO;
- +
- + user_size = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
- +
- + raw_spin_lock_irqsave(&consistent_lock, flags);
- + c = vm_region_find(&consistent_head, (unsigned long)cpu_addr);
- + raw_spin_unlock_irqrestore(&consistent_lock, flags);
- +
- + if (c) {
- + unsigned long off = vma->vm_pgoff;
- +
- + kern_size = (c->vm_end - c->vm_start) >> PAGE_SHIFT;
- +
- + if (off < kern_size && user_size <= (kern_size - off)) {
- + vma->vm_flags |= VM_RESERVED;
- + ret = remap_pfn_range(vma, vma->vm_start,
- + page_to_pfn(c->vm_pages) + off,
- + user_size << PAGE_SHIFT,
- + vma->vm_page_prot);
- + }
- + }
- +
- + return ret;
- +}
- +
- +int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
- + void *cpu_addr, dma_addr_t dma_addr, size_t size)
- +{
- + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- + return dma_mmap(dev, vma, cpu_addr, dma_addr, size);
- +}
- +
- +EXPORT_SYMBOL(dma_mmap_coherent);
- +
- +int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma,
- + void *cpu_addr, dma_addr_t dma_addr, size_t size)
- +{
- + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- + return dma_mmap(dev, vma, cpu_addr, dma_addr, size);
- +}
- +
- +EXPORT_SYMBOL(dma_mmap_writecombine);
- +
- +/*
- + * free a page as defined by the above mapping.
- + */
- +void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
- + dma_addr_t handle)
- +{
- + struct arch_vm_region *c;
- + unsigned long flags, addr;
- + pte_t *ptep;
- +
- + size = PAGE_ALIGN(size);
- +
- + raw_spin_lock_irqsave(&consistent_lock, flags);
- +
- + c = vm_region_find(&consistent_head, (unsigned long)cpu_addr);
- + if (!c)
- + goto no_area;
- +
- + if ((c->vm_end - c->vm_start) != size) {
- + printk(KERN_ERR "%s: freeing wrong coherent size (%ld != %d)\n",
- + __func__, c->vm_end - c->vm_start, size);
- + dump_stack();
- + size = c->vm_end - c->vm_start;
- + }
- +
- + ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
- + addr = c->vm_start;
- + do {
- + pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep);
- + unsigned long pfn;
- +
- + ptep++;
- + addr += PAGE_SIZE;
- +
- + if (!pte_none(pte) && pte_present(pte)) {
- + pfn = pte_pfn(pte);
- +
- + if (pfn_valid(pfn)) {
- + struct page *page = pfn_to_page(pfn);
- +
- + /*
- + * x86 does not mark the pages reserved...
- + */
- + ClearPageReserved(page);
- +
- + __free_page(page);
- + continue;
- + }
- + }
- +
- + printk(KERN_CRIT "%s: bad page in kernel page table\n",
- + __func__);
- + } while (size -= PAGE_SIZE);
- +
- + flush_tlb_kernel_range(c->vm_start, c->vm_end);
- +
- + list_del(&c->vm_list);
- +
- + raw_spin_unlock_irqrestore(&consistent_lock, flags);
- +
- + kfree(c);
- + return;
- +
- +no_area:
- + raw_spin_unlock_irqrestore(&consistent_lock, flags);
- + printk(KERN_ERR "%s: trying to free invalid coherent area: %p\n",
- + __func__, cpu_addr);
- + dump_stack();
- +}
- +
- +EXPORT_SYMBOL(dma_free_coherent);
- +
- +/*
- + * Initialise the consistent memory allocation.
- + */
- +static int __init consistent_init(void)
- +{
- + pgd_t *pgd;
- + pmd_t *pmd;
- + pte_t *pte;
- + int ret = 0;
- +
- + do {
- + pgd = pgd_offset(&init_mm, CONSISTENT_BASE);
- + pmd = pmd_alloc(&init_mm, pgd, CONSISTENT_BASE);
- + if (!pmd) {
- + printk(KERN_ERR "%s: no pmd tables\n", __func__);
- + ret = -ENOMEM;
- + break;
- + }
- + /* The first level mapping may be created in somewhere.
- + * It's not necessary to warn here. */
- + /* WARN_ON(!pmd_none(*pmd)); */
- +
- + pte = pte_alloc_kernel(pmd, CONSISTENT_BASE);
- + if (!pte) {
- + ret = -ENOMEM;
- + break;
- + }
- +
- + consistent_pte = pte;
- + } while (0);
- +
- + return ret;
- +}
- +
- +core_initcall(consistent_init);
- +
- +/*
- + * Make an area consistent for devices.
- + */
- +void consistent_sync(void *vaddr, size_t size, int direction)
- +{
- + unsigned long start = (unsigned long)vaddr;
- + unsigned long end = start + size;
- +
- + switch (direction) {
- + case DMA_FROM_DEVICE: /* invalidate only */
- + cpu_dma_inval_range(start, end);
- + break;
- + case DMA_TO_DEVICE: /* writeback only */
- + cpu_dma_wb_range(start, end);
- + break;
- + case DMA_BIDIRECTIONAL: /* writeback and invalidate */
- + cpu_dma_wbinval_range(start, end);
- + break;
- + default:
- + BUG();
- + }
- +}
- +
- +EXPORT_SYMBOL(consistent_sync);
- diff -Nur linux-3.4.110.orig/arch/nds32/mm/extable.c linux-3.4.110/arch/nds32/mm/extable.c
- --- linux-3.4.110.orig/arch/nds32/mm/extable.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/mm/extable.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,18 @@
- +/*
- + * linux/arch/nds32/mm/extable.c
- + *
- + * Copyright (C) 2009 Andes Technology Corporation
- + */
- +#include <linux/module.h>
- +#include <asm/uaccess.h>
- +
- +int fixup_exception(struct pt_regs *regs)
- +{
- + const struct exception_table_entry *fixup;
- +
- + fixup = search_exception_tables(instruction_pointer(regs));
- + if (fixup)
- + regs->NDS32_ipc = fixup->fixup;
- +
- + return fixup != NULL;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/mm/fault.c linux-3.4.110/arch/nds32/mm/fault.c
- --- linux-3.4.110.orig/arch/nds32/mm/fault.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/mm/fault.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,507 @@
- +/*
- + * linux/arch/arm/mm/fault.c
- + *
- + * Copyright (C) 1995 Linus Torvalds
- + * Modifications for ARM processor (c) 1995-2004 Russell King
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +/* ============================================================================
- + *
- + * linux/arch/nds32/mm/fault.c
- + *
- + * Copyright (C) 2007 Andes Technology Corporation
- + * This file is part of Linux and should be licensed under the GPL.
- + * See the file COPYING for conditions for redistribution.
- + *
- + * Abstract:
- + *
- + * This program is for NDS32 architecture, referred from ARM's
- + * implementation.
- + *
- + * Revision History:
- + *
- + * Nov.26.2007 Initial ported by Tom, Shawn, and Steven,
- + * patched for KGDB and refined code by Harry.
- + *
- + * Note:
- + *
- + * ============================================================================
- + */
- +#include <linux/module.h>
- +#include <linux/signal.h>
- +#include <linux/ptrace.h>
- +#include <linux/mm.h>
- +#include <linux/init.h>
- +#include <linux/hardirq.h>
- +
- +#include <asm/system.h>
- +#include <asm/pgtable.h>
- +#include <asm/tlbflush.h>
- +#include <asm/uaccess.h>
- +
- +#include "fault.h"
- +
- +/*
- + * This is useful to dump out the page tables associated with
- + * 'addr' in mm 'mm'.
- + */
- +void show_pte(struct mm_struct *mm, unsigned long addr)
- +{
- + pgd_t *pgd;
- + if (!mm)
- + mm = &init_mm;
- +
- + printk(KERN_ALERT "pgd = %p\n", mm->pgd);
- + pgd = pgd_offset(mm, addr);
- + printk(KERN_ALERT "[%08lx] *pgd=%08lx", addr, pgd_val(*pgd));
- +
- + do {
- + pmd_t *pmd;
- +
- + if (pgd_none(*pgd))
- + break;
- +
- + if (pgd_bad(*pgd)) {
- + printk("(bad)");
- + break;
- + }
- +
- + pmd = pmd_offset(pgd, addr);
- +#if PTRS_PER_PMD != 1
- + printk(", *pmd=%08lx", pmd_val(*pmd));
- +#endif
- +
- + if (pmd_none(*pmd))
- + break;
- +
- + if (pmd_bad(*pmd)) {
- + printk("(bad)");
- + break;
- + }
- +#ifndef CONFIG_HIGHMEM
- + {
- + pte_t *pte;
- + /* We must not map this if we have highmem enabled */
- + pte = pte_offset_map(pmd, addr);
- + printk(", *pte=%08lx", pte_val(*pte));
- + pte_unmap(pte);
- + }
- +#endif
- + } while (0);
- +
- + printk("\n");
- +}
- +
- +/*
- + * Oops. The kernel tried to access some page that wasn't present.
- + */
- +static void
- +__do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
- + struct pt_regs *regs)
- +{
- + /*
- + * Are we prepared to handle this kernel fault?
- + */
- + if (fixup_exception(regs))
- + return;
- +
- + /*
- + * No handler, we'll have to terminate things with extreme prejudice.
- + */
- + bust_spinlocks(1);
- + printk(KERN_ALERT
- + "__do_kernel_fault: Unable to handle kernel %s at virtual address %08lx\n",
- + (addr < PAGE_SIZE) ? "NULL pointer dereference" :
- + "paging request", addr);
- +
- + show_pte(mm, addr);
- + die("Oops", regs, fsr);
- + bust_spinlocks(0);
- + do_exit(SIGKILL);
- +}
- +
- +/*
- + * Something tried to access memory that isn't in our memory map..
- + * User mode accesses just cause a SIGSEGV
- + */
- +static void
- +__do_user_fault(struct task_struct *tsk, unsigned long addr,
- + unsigned int fsr, int code, struct pt_regs *regs)
- +{
- + struct siginfo si;
- +
- +#ifdef CONFIG_DEBUG_USER
- + if (user_debug & UDBG_SEGV) {
- + printk(KERN_DEBUG
- + "%s: unhandled page fault at 0x%08lx, code 0x%03x\n",
- + tsk->comm, addr, fsr);
- + show_pte(tsk->mm, addr);
- + show_regs(regs);
- + }
- +#endif
- +
- + tsk->thread.address = addr;
- + tsk->thread.error_code = fsr;
- + tsk->thread.trap_no = 14;
- + si.si_signo = SIGSEGV;
- + si.si_errno = 0;
- + si.si_code = code;
- + si.si_addr = (void __user *)addr;
- + force_sig_info(SIGSEGV, &si, tsk);
- +}
- +
- +void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
- +{
- + struct task_struct *tsk = current;
- + struct mm_struct *mm = tsk->active_mm;
- +
- + /*
- + * If we are in kernel mode at this point, we
- + * have no context to handle this fault with.
- + */
- + if (user_mode(regs)) {
- + __do_user_fault(tsk, addr, fsr, SEGV_MAPERR, regs);
- + } else {
- + __do_kernel_fault(mm, addr, fsr, regs);
- + }
- +}
- +
- +#define VM_FAULT_BADMAP 0x010000
- +#define VM_FAULT_BADACCESS 0x020000
- +
- +void do_page_fault(unsigned long entry, unsigned long addr,
- + unsigned int error_code, struct pt_regs *regs)
- +{
- + struct task_struct *tsk;
- + struct mm_struct *mm;
- + struct vm_area_struct *vma;
- + siginfo_t info;
- + int fault;
- + unsigned int mask = VM_READ | VM_WRITE | VM_EXEC;
- + unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
- +
- + error_code = error_code & (ITYPE_mskINST | ITYPE_mskETYPE);
- + tsk = current;
- + mm = tsk->mm;
- + info.si_code = SEGV_MAPERR;
- + /*
- + * We fault-in kernel-space virtual memory on-demand. The
- + * 'reference' page table is init_mm.pgd.
- + *
- + * NOTE! We MUST NOT take any locks for this case. We may
- + * be in an interrupt or a critical region, and should
- + * only copy the information from the master page table,
- + * nothing more.
- + */
- + if (addr >= TASK_SIZE) {
- + if (user_mode(regs))
- + goto bad_area_nosemaphore;
- +
- + if (addr >= TASK_SIZE && addr < VMALLOC_END && (entry == 2))
- + goto vmalloc_fault;
- + else
- + goto no_context;
- + }
- +
- + /*
- + * If we're in an interrupt or have no user
- + * context, we must not take the fault..
- + */
- + if (unlikely(in_atomic() || !mm))
- + goto no_context;
- +
- + /*
- + * As per x86, we may deadlock here. However, since the kernel only
- + * validly references user space from well defined areas of the code,
- + * we can bug out early if this is from code which shouldn't.
- + */
- + if (unlikely(!down_read_trylock(&mm->mmap_sem))) {
- + if (!user_mode(regs) &&
- + !search_exception_tables(instruction_pointer(regs)))
- + goto no_context;
- +retry:
- + down_read(&mm->mmap_sem);
- + } else {
- + /*
- + * The above down_read_trylock() might have succeeded in which
- + * case, we'll have missed the might_sleep() from down_read().
- + */
- + might_sleep();
- +#ifdef CONFIG_DEBUG_VM
- + if (!user_mode(regs) &&
- + !search_exception_tables(instruction_pointer(regs)))
- + goto no_context;
- +#endif
- + }
- +
- + vma = find_vma(mm, addr);
- +
- + if (unlikely(!vma))
- + goto bad_area;
- +
- + if (vma->vm_start <= addr)
- + goto good_area;
- +
- + if (unlikely(!(vma->vm_flags & VM_GROWSDOWN)))
- + goto bad_area;
- +
- + if (unlikely(expand_stack(vma, addr)))
- + goto bad_area;
- +
- + /*
- + * Ok, we have a good vm_area for this memory access, so
- + * we can handle it..
- + */
- +
- +good_area:
- + info.si_code = SEGV_ACCERR;
- +
- + /* first do some preliminary protection checks */
- + if (entry == 2) {
- + if (error_code & ITYPE_mskINST)
- + mask = VM_EXEC;
- + else {
- + mask = VM_READ | VM_WRITE;
- + if (vma->vm_flags & VM_WRITE)
- + flags |= FAULT_FLAG_WRITE;
- + }
- + } else if (entry == 3) {
- + switch (error_code & ITYPE_mskETYPE) {
- + case RD_PROT:
- + mask = VM_READ;
- + break;
- + case WRT_PROT:
- + mask = VM_WRITE;
- + flags |= FAULT_FLAG_WRITE;
- + break;
- + case NOEXEC:
- + mask = VM_EXEC;
- + break;
- + case PAGE_MODIFY:
- + mask = VM_WRITE;
- + flags |= FAULT_FLAG_WRITE;
- + break;
- + case ACC_BIT:
- + BUG();
- + default:
- + break;
- + }
- +
- + }
- + if (!(vma->vm_flags & mask))
- + goto bad_area;
- +
- + /*
- + * If for any reason at all we couldn't handle the fault,
- + * make sure we exit gracefully rather than endlessly redo
- + * the fault.
- + */
- +
- + fault = handle_mm_fault(mm, vma, addr, flags);
- +
- + /*
- + * If we need to retry but a fatal signal is pending, handle the
- + * signal first. We do not need to release the mmap_sem because it
- + * would already be released in __lock_page_or_retry in mm/filemap.c.
- + */
- + if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
- + return;
- +
- + if (unlikely(fault & VM_FAULT_ERROR)) {
- + if (fault & VM_FAULT_OOM)
- + goto out_of_memory;
- + else if (fault & VM_FAULT_SIGBUS)
- + goto do_sigbus;
- + BUG();
- + }
- +
- + /*
- + * Major/minor page fault accounting is only done on the initial
- + * attempt. If we go through a retry, it is extremely likely that the
- + * page will be found in page cache at that point.
- + */
- + if (flags & FAULT_FLAG_ALLOW_RETRY) {
- + if (fault & VM_FAULT_MAJOR)
- + tsk->maj_flt++;
- + else
- + tsk->min_flt++;
- + if (fault & VM_FAULT_RETRY) {
- + flags &= ~FAULT_FLAG_ALLOW_RETRY;
- + flags |= FAULT_FLAG_TRIED;
- +
- + /* No need to up_read(&mm->mmap_sem) as we would
- + * have already released it in __lock_page_or_retry
- + * in mm/filemap.c.
- + */
- + goto retry;
- + }
- + }
- +
- + up_read(&mm->mmap_sem);
- + return;
- +
- + /*
- + * Something tried to access memory that isn't in our memory map..
- + * Fix it, but check if it's kernel or user first..
- + */
- +bad_area:
- + up_read(&mm->mmap_sem);
- +
- +bad_area_nosemaphore:
- +
- + /* User mode accesses just cause a SIGSEGV */
- +
- + if (user_mode(regs)) {
- + tsk->thread.address = addr;
- + tsk->thread.error_code = error_code;
- + tsk->thread.trap_no = 14;
- + info.si_signo = SIGSEGV;
- + info.si_errno = 0;
- + /* info.si_code has been set above */
- + info.si_addr = (void *)addr;
- + force_sig_info(SIGSEGV, &info, tsk);
- + return;
- + }
- +
- +no_context:
- +
- + /* Are we prepared to handle this kernel fault?
- + *
- + * (The kernel has valid exception-points in the source
- + * when it acesses user-memory. When it fails in one
- + * of those points, we find it in a table and do a jump
- + * to some fixup code that loads an appropriate error
- + * code)
- + */
- +
- + {
- + const struct exception_table_entry *entry;
- +
- + if ((entry =
- + search_exception_tables(instruction_pointer(regs))) !=
- + NULL) {
- + /* Adjust the instruction pointer in the stackframe */
- + instruction_pointer(regs) = entry->fixup;
- + return;
- + }
- + }
- +
- + /*
- + * Oops. The kernel tried to access some bad page. We'll have to
- + * terminate things with extreme prejudice.
- + */
- +
- + bust_spinlocks(1);
- + printk(KERN_ALERT
- + "Unable to handle kernel %s at virtual address %08lx\n",
- + (addr < PAGE_SIZE) ? "NULL pointer dereference" :
- + "paging request", addr);
- +
- + show_pte(mm, addr);
- + die("Oops", regs, error_code);
- + bust_spinlocks(0);
- + do_exit(SIGKILL);
- +
- + /* TODO: verify this necessity */
- + return;
- +
- + /*
- + * We ran out of memory, or some other thing happened to us that made
- + * us unable to handle the page fault gracefully.
- + */
- +
- +out_of_memory:
- + up_read(&mm->mmap_sem);
- + if (!user_mode(regs))
- + goto no_context;
- + pagefault_out_of_memory();
- + return;
- +
- +do_sigbus:
- + up_read(&mm->mmap_sem);
- +
- + /* Kernel mode? Handle exceptions or die */
- + if (!user_mode(regs))
- + goto no_context;
- +
- + /*
- + * Send a sigbus
- + */
- + tsk->thread.address = addr;
- + tsk->thread.error_code = error_code;
- + tsk->thread.trap_no = 14;
- + info.si_signo = SIGBUS;
- + info.si_errno = 0;
- + info.si_code = BUS_ADRERR;
- + info.si_addr = (void *)addr;
- + force_sig_info(SIGBUS, &info, tsk);
- +
- + return;
- +
- +vmalloc_fault:
- + {
- + /*
- + * Synchronize this task's top level page-table
- + * with the 'reference' page table.
- + *
- + * Use current_pgd instead of tsk->active_mm->pgd
- + * since the latter might be unavailable if this
- + * code is executed in a misfortunately run irq
- + * (like inside schedule() between switch_mm and
- + * switch_to...).
- + */
- +
- + unsigned int index = pgd_index(addr);
- + pgd_t *pgd, *pgd_k;
- + pud_t *pud, *pud_k;
- + pmd_t *pmd, *pmd_k;
- + pte_t *pte_k;
- +
- + pgd = (pgd_t *) __va(GET_L1_PPTB()) + index;
- + pgd_k = init_mm.pgd + index;
- +
- + if (!pgd_present(*pgd_k))
- + goto no_context;
- +
- + pud = pud_offset(pgd, addr);
- + pud_k = pud_offset(pgd_k, addr);
- + if (!pud_present(*pud_k))
- + goto no_context;
- +
- + pmd = pmd_offset(pud, addr);
- + pmd_k = pmd_offset(pud_k, addr);
- + if (!pmd_present(*pmd_k))
- + goto no_context;
- +
- + if (!pmd_present(*pmd)) {
- + set_pmd(pmd, *pmd_k);
- + /* TODO: need to do a cache flush like arm,
- + * maybe add at header file */
- + } else
- +
- + BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
- +
- + /*
- + * Since the vmalloc area is global, we don't
- + * need to copy individual PTE's, it is enough to
- + * copy the pgd pointer into the pte page of the
- + * root task. If that is there, we'll find our pte if
- + * it exists.
- + */
- +
- + /* Make sure the actual PTE exists as well to
- + * catch kernel vmalloc-area accesses to non-mapped
- + * addres. If we don't do this, this will just
- + * silently loop forever.
- + */
- +
- + pte_k = pte_offset_kernel(pmd_k, addr);
- + if (!pte_present(*pte_k))
- + goto no_context;
- +
- + return;
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/mm/fault.h linux-3.4.110/arch/nds32/mm/fault.h
- --- linux-3.4.110.orig/arch/nds32/mm/fault.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/mm/fault.h 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,5 @@
- +void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
- +
- +void show_pte(struct mm_struct *mm, unsigned long addr);
- +
- +unsigned long search_exception_table(unsigned long addr);
- diff -Nur linux-3.4.110.orig/arch/nds32/mm/highmem.c linux-3.4.110/arch/nds32/mm/highmem.c
- --- linux-3.4.110.orig/arch/nds32/mm/highmem.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/mm/highmem.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,76 @@
- +#include <linux/export.h>
- +#include <linux/highmem.h>
- +#include <linux/sched.h>
- +#include <linux/smp.h>
- +#include <linux/interrupt.h>
- +#include <linux/bootmem.h>
- +#include <asm/fixmap.h>
- +#include <asm/tlbflush.h>
- +
- +void *kmap(struct page *page)
- +{
- + unsigned long vaddr;
- + might_sleep();
- + if (!PageHighMem(page))
- + return page_address(page);
- + vaddr = (unsigned long)kmap_high(page);
- + return (void *)vaddr;
- +}
- +
- +EXPORT_SYMBOL(kmap);
- +
- +void kunmap(struct page *page)
- +{
- + BUG_ON(in_interrupt());
- + if (!PageHighMem(page))
- + return;
- + kunmap_high(page);
- +}
- +
- +EXPORT_SYMBOL(kunmap);
- +
- +/*
- + * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because
- + * no global lock is needed and because the kmap code must perform a global TLB
- + * invalidation when the kmap pool wraps.
- + *
- + * However when holding an atomic kmap is is not legal to sleep, so atomic
- + * kmaps are appropriate for short, tight code paths only.
- + */
- +void *kmap_atomic(struct page *page)
- +{
- + unsigned int idx;
- + unsigned long vaddr, pte;
- + int type;
- +
- + pagefault_disable();
- + if (!PageHighMem(page))
- + return page_address(page);
- +
- + type = kmap_atomic_idx_push();
- +
- + idx = type + KM_TYPE_NR * smp_processor_id();
- + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
- + pte = (page_to_pfn(page) << PAGE_SHIFT) | (PAGE_KERNEL);
- + asm volatile ("mtsr %0, $TLB_VPN\n\t"
- + "dsb\n\t"
- + "tlbop %1, RWLK\n\t"
- + "isb\n\t"
- + ::"r" (vaddr), "r"(pte));
- + return (void *)vaddr;
- +}
- +
- +EXPORT_SYMBOL(kmap_atomic);
- +
- +void __kunmap_atomic(void *kvaddr)
- +{
- + if (kvaddr >= (void *)FIXADDR_START) {
- + kmap_atomic_idx_pop();
- + asm volatile ("tlbop %0, UNLK\n\t"
- + "tlbop %0, INV\n\t"
- + ::"r" (kvaddr));
- + }
- + pagefault_enable();
- +}
- +
- +EXPORT_SYMBOL(__kunmap_atomic);
- diff -Nur linux-3.4.110.orig/arch/nds32/mm/init.c linux-3.4.110/arch/nds32/mm/init.c
- --- linux-3.4.110.orig/arch/nds32/mm/init.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/mm/init.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,438 @@
- +/*
- + * linux/arch/nds32/mm/init.c
- + *
- + * Copyright (C) 1995-2002 Russell King
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +#include <linux/kernel.h>
- +#include <linux/errno.h>
- +#include <linux/swap.h>
- +#include <linux/init.h>
- +#include <linux/bootmem.h>
- +#include <linux/mman.h>
- +#include <linux/nodemask.h>
- +#include <linux/initrd.h>
- +#include <linux/highmem.h>
- +#include <linux/memblock.h>
- +
- +#include <asm/sections.h>
- +#include <asm/mach-types.h>
- +#include <asm/hardware.h>
- +#include <asm/setup.h>
- +#include <asm/tlb.h>
- +#include <asm/page.h>
- +
- +#include <asm/mach/arch.h>
- +#include <asm/mach/map.h>
- +
- +#include "mm.h"
- +#include "../../kernel/signal.h"
- +
- +#define TABLE_SIZE (PTRS_PER_PTE * sizeof(pte_t))
- +
- +DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
- +DEFINE_SPINLOCK(anon_alias_lock);
- +extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
- +extern unsigned long phys_initrd_start;
- +extern unsigned long phys_initrd_size;
- +
- +/*
- + * empty_zero_page is a special page that is used for
- + * zero-initialized data and COW.
- + */
- +struct page *empty_zero_page;
- +
- +void show_mem(unsigned int flags)
- +{
- + int free = 0, total = 0, reserved = 0;
- + int shared = 0, cached = 0, slab = 0, node;
- +
- + printk("Mem-info:\n");
- + show_free_areas(flags);
- + printk("Free swap: %6ldkB\n", nr_swap_pages << (PAGE_SHIFT - 10));
- +
- + for_each_online_node(node) {
- + struct page *page, *end;
- +
- + page = NODE_MEM_MAP(node);
- + end = page + NODE_DATA(node)->node_spanned_pages;
- +
- + do {
- + total++;
- + if (PageReserved(page))
- + reserved++;
- + else if (PageSwapCache(page))
- + cached++;
- + else if (PageSlab(page))
- + slab++;
- + else if (!page_count(page))
- + free++;
- + else
- + shared += page_count(page) - 1;
- + page++;
- + } while (page < end);
- + }
- +
- + printk("%d pages of RAM\n", total);
- + printk("%d free pages\n", free);
- + printk("%d reserved pages\n", reserved);
- + printk("%d slab pages\n", slab);
- + printk("%d pages shared\n", shared);
- + printk("%d pages swap cached\n", cached);
- +}
- +
- +struct node_info {
- + unsigned int start;
- + unsigned int end;
- + int bootmap_pages;
- +};
- +
- +#define O_PFN_DOWN(x) ((x) >> PAGE_SHIFT)
- +#define V_PFN_DOWN(x) O_PFN_DOWN(__pa(x))
- +
- +#define O_PFN_UP(x) (PAGE_ALIGN(x) >> PAGE_SHIFT)
- +#define V_PFN_UP(x) O_PFN_UP(__pa(x))
- +
- +#define PFN_SIZE(x) ((x) >> PAGE_SHIFT)
- +#define PFN_RANGE(s,e) PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \
- + (((unsigned long)(s)) & PAGE_MASK))
- +#ifdef CONFIG_EARLY_PRINTK
- +#include <asm/fixmap.h>
- +
- +/*
- + * Using tlbop to create an early I/O mapping
- + */
- +void __iomem *__init early_io_map(phys_addr_t pa)
- +{
- + unsigned long va;
- + pa &= PAGE_MASK;
- + pa += pgprot_val(PAGE_DEVICE);
- + va = fix_to_virt(FIX_EARLY_DEBUG);
- + /* insert and lock this page to tlb entry directly */
- + asm volatile ("mtsr %0, $TLB_VPN\n\t"
- + "dsb\n\t"
- + "tlbop %1, RWLK\n\t" "isb\n\t"::"r" (va), "r"(pa));
- + return (void __iomem *)va;
- +}
- +
- +int __init early_io_unmap(void)
- +{
- + unsigned long va;
- + va = fix_to_virt(FIX_EARLY_DEBUG);
- + asm volatile ("tlbop %0, UNLK\n\t"
- + "tlbop %0, INV\n\t" "isb\n\t"::"r" (va));
- + return 0;
- +}
- +
- +late_initcall(early_io_unmap);
- +#endif
- +
- +static void __init zone_sizes_init(void)
- +{
- + unsigned long zones_size[MAX_NR_ZONES];
- +
- + /* Clear the zone sizes */
- + memset(zones_size, 0, sizeof(zones_size));
- +
- + zones_size[ZONE_NORMAL] = max_low_pfn;
- +#ifdef CONFIG_HIGHMEM
- + zones_size[ZONE_HIGHMEM] = max_pfn;
- +#endif
- + free_area_init_nodes(zones_size);
- +
- +}
- +
- +/*
- + * Map all physical memory under high_memory into kernel's address space.
- + *
- + * This is explicitly coded for two-level page tables, so if you need
- + * something else then this needs to change.
- + */
- +static void __init map_ram(void)
- +{
- + unsigned long v, p, e;
- + pgd_t *pge;
- + pud_t *pue;
- + pmd_t *pme;
- + pte_t *pte;
- + /* These mark extents of read-only kernel pages...
- + * ...from vmlinux.lds.S
- + */
- +
- + p = (u32) memblock_start_of_DRAM() & PAGE_MASK;
- + e = min((u32) memblock_end_of_DRAM(), (u32) __pa(high_memory));
- +
- + v = (u32) __va(p);
- + pge = pgd_offset_k(v);
- +
- + while (p < e) {
- + int j;
- + pue = pud_offset(pge, v);
- + pme = pmd_offset(pue, v);
- +
- + if ((u32) pue != (u32) pge || (u32) pme != (u32) pge) {
- + panic("%s: Kernel hardcoded for "
- + "two-level page tables", __func__);
- + }
- +
- + /* Alloc one page for holding PTE's... */
- + pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
- + set_pmd(pme, __pmd(__pa(pte) + _PAGE_KERNEL_TABLE));
- +
- + /* Fill the newly allocated page with PTE'S */
- + for (j = 0; p < e && j < PTRS_PER_PTE;
- + v += PAGE_SIZE, p += PAGE_SIZE, j++, pte++) {
- + /* Create mapping between p and v. */
- + /* TODO: more fine grant for page access permission */
- + set_pte(pte, __pte(p + pgprot_val(PAGE_KERNEL)));
- + }
- +
- + pge++;
- + }
- +}
- +
- +static void __init fixedrange_init(void)
- +{
- + unsigned long vaddr, phys, prot;
- + pgd_t *pgd;
- + pud_t *pud;
- + pmd_t *pmd;
- + pte_t *pte;
- +
- + /*
- + * Fixed mappings:
- + */
- + vaddr = __fix_to_virt(__end_of_fixed_addresses - 1);
- + pgd = swapper_pg_dir + pgd_index(vaddr);
- + pud = pud_offset(pgd, vaddr);
- + pmd = pmd_offset(pud, vaddr);
- + pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
- + set_pmd(pmd, __pmd(__pa(pte) + _PAGE_KERNEL_TABLE));
- +
- + /* create return_syscall mapping. */
- + vaddr = __fix_to_virt(FIX_RETURN_SYSCALL);
- + phys = RETURN_SYSCALL_PA_BASE;
- + prot = PAGE_UXKRWX_V2;
- + pte = pte_offset_kernel(pmd, vaddr);
- + set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot));
- +
- +#ifdef CONFIG_HIGHMEM
- + /*
- + * Permanent kmaps:
- + */
- + vaddr = PKMAP_BASE;
- +
- + pgd = swapper_pg_dir + pgd_index(vaddr);
- + pud = pud_offset(pgd, vaddr);
- + pmd = pmd_offset(pud, vaddr);
- + pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
- + set_pmd(pmd, __pmd(__pa(pte) + _PAGE_KERNEL_TABLE));
- + pkmap_page_table = pte;
- +#endif /* CONFIG_HIGHMEM */
- +}
- +
- +/*
- + * paging_init() sets up the page tables, initialises the zone memory
- + * maps, and sets up the zero page, bad page and bad page tables.
- + */
- +void __init paging_init(struct machine_desc *mdesc)
- +{
- + void *zero_page;
- + int i;
- +
- + printk(KERN_INFO "Setting up paging and PTEs.\n");
- +
- +#ifdef CONFIG_BLK_DEV_INITRD
- + if (phys_initrd_size) {
- + /* assume initrd is put on node 0 */
- + reserve_bootmem_node(NODE_DATA(0), phys_initrd_start,
- + phys_initrd_size, BOOTMEM_DEFAULT);
- + initrd_start = __phys_to_virt(phys_initrd_start);
- + initrd_end = initrd_start + phys_initrd_size;
- + printk(KERN_INFO
- + "initrd_start at 0x%08lx, initrd_end at 0x%08lx\n",
- + initrd_start, initrd_end);
- + }
- +#endif
- +
- + /* clear out the init_mm.pgd that will contain the kernel's mappings */
- + for (i = 0; i < PTRS_PER_PGD; i++)
- + swapper_pg_dir[i] = __pgd(1);
- +
- + map_ram();
- +
- + if (mdesc->map_io)
- + mdesc->map_io();
- +
- + fixedrange_init();
- +
- + /* allocate space for empty_zero_page */
- + zero_page = alloc_bootmem_low_pages(PAGE_SIZE);
- + memset(zero_page, 0, PAGE_SIZE);
- +
- + zone_sizes_init();
- +
- + empty_zero_page = virt_to_page(zero_page);
- +#ifdef CONFIG_NO_KERNEL_LARGE_PAGE
- + SET_MMU_CTL(GET_MMU_CTL() & ~0x400);
- +#endif
- +#ifdef CONFIG_SMP
- + cpu_dcache_wbinval_all();
- +#endif
- + flush_dcache_page(empty_zero_page);
- +}
- +
- +static inline int free_area(unsigned long addr, unsigned long end, char *s)
- +{
- + unsigned int size = (end - addr) >> 10;
- + int pages = 0;
- +
- + for (; addr < end; addr += PAGE_SIZE) {
- + struct page *page = virt_to_page(addr);
- + ClearPageReserved(page);
- + init_page_count(page);
- + free_page(addr);
- + totalram_pages++;
- + pages++;
- + }
- +
- + if (size && s)
- + printk(KERN_INFO "free_area: Freeing %s memory: %dK\n", s,
- + size);
- +
- + return pages;
- +}
- +
- +/* Free the reserved page into the buddy system, so it gets managed. */
- +static inline void __free_reserved_page(struct page *page)
- +{
- + ClearPageReserved(page);
- + init_page_count(page);
- + __free_page(page);
- +}
- +
- +#ifdef CONFIG_HIGHMEM
- +void free_highmem_page(struct page *page)
- +{
- + __free_reserved_page(page);
- + totalram_pages++;
- + totalhigh_pages++;
- +}
- +#endif
- +
- +static inline void __init free_highmem(void)
- +{
- +#ifdef CONFIG_HIGHMEM
- + unsigned long pfn;
- + for (pfn = PFN_UP(__pa(high_memory)); pfn < max_pfn; pfn++) {
- + phys_addr_t paddr = (phys_addr_t) pfn << PAGE_SHIFT;
- + if (!memblock_is_reserved(paddr))
- + free_highmem_page(pfn_to_page(pfn));
- + }
- +#endif
- +}
- +
- +static void __init set_max_mapnr_init(void)
- +{
- + max_mapnr = max_pfn;
- +}
- +
- +/*
- + * mem_init() marks the free areas in the mem_map and tells us how much
- + * memory is free. This is done after various parts of the system have
- + * claimed their memory after the kernel image.
- + */
- +void __init mem_init(void)
- +{
- + phys_addr_t memory_start = memblock_start_of_DRAM();
- + BUG_ON(!mem_map);
- + set_max_mapnr_init();
- +
- + free_highmem();
- +
- + /* this will put all low memory onto the freelists */
- + totalram_pages += free_all_bootmem();
- +
- + printk(KERN_INFO "virtual kernel memory layout:\n"
- + " fixmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
- +#ifdef CONFIG_HIGHMEM
- + " pkmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
- +#endif
- + " consist : 0x%08lx - 0x%08lx (%4ld MB)\n"
- + " vmalloc : 0x%08lx - 0x%08lx (%4ld MB)\n"
- + " lowmem : 0x%08lx - 0x%08lx (%4ld MB)\n"
- + " .init : 0x%08lx - 0x%08lx (%4ld kB)\n"
- + " .data : 0x%08lx - 0x%08lx (%4ld kB)\n"
- + " .text : 0x%08lx - 0x%08lx (%4ld kB)\n",
- + FIXADDR_START, FIXADDR_TOP, (FIXADDR_TOP - FIXADDR_START) >> 10,
- +#ifdef CONFIG_HIGHMEM
- + PKMAP_BASE, PKMAP_BASE + LAST_PKMAP * PAGE_SIZE,
- + (LAST_PKMAP * PAGE_SIZE) >> 10,
- +#endif
- + CONSISTENT_BASE, CONSISTENT_END,
- + ((CONSISTENT_END) - (CONSISTENT_BASE)) >> 20, VMALLOC_START,
- + (unsigned long)VMALLOC_END, (VMALLOC_END - VMALLOC_START) >> 20,
- + (unsigned long)__va(memory_start), (unsigned long)high_memory,
- + ((unsigned long)high_memory -
- + (unsigned long)__va(memory_start)) >> 20,
- + (unsigned long)&__init_begin, (unsigned long)&__init_end,
- + ((unsigned long)&__init_end -
- + (unsigned long)&__init_begin) >> 10, (unsigned long)&_etext,
- + (unsigned long)&_edata,
- + ((unsigned long)&_edata - (unsigned long)&_etext) >> 10,
- + (unsigned long)&_text, (unsigned long)&_etext,
- + ((unsigned long)&_etext - (unsigned long)&_text) >> 10);
- +
- + /*
- + * Check boundaries twice: Some fundamental inconsistencies can
- + * be detected at build time already.
- + */
- +#define __FIXADDR_TOP (-PAGE_SIZE)
- +#ifdef CONFIG_HIGHMEM
- + BUILD_BUG_ON(PKMAP_BASE + LAST_PKMAP * PAGE_SIZE > FIXADDR_START);
- + BUILD_BUG_ON((CONSISTENT_END) > PKMAP_BASE);
- +#endif
- + BUILD_BUG_ON(VMALLOC_END > CONSISTENT_BASE);
- +#define high_memory (-128UL << 20)
- + BUILD_BUG_ON(VMALLOC_START >= VMALLOC_END);
- +#undef high_memory
- +#undef __FIXADDR_TOP
- +
- +#ifdef CONFIG_HIGHMEM
- + BUG_ON(PKMAP_BASE + LAST_PKMAP * PAGE_SIZE > FIXADDR_START);
- + BUG_ON(CONSISTENT_END > PKMAP_BASE);
- +#endif
- + BUG_ON(VMALLOC_END > CONSISTENT_BASE);
- + BUG_ON(VMALLOC_START >= VMALLOC_END);
- + BUG_ON((unsigned long)high_memory > VMALLOC_START);
- +
- + return;
- +}
- +
- +void free_initmem(void)
- +{
- + free_area((unsigned long)(&__init_begin),
- + (unsigned long)(&__init_end), "init");
- +}
- +
- +#ifdef CONFIG_BLK_DEV_INITRD
- +static int keep_initrd;
- +
- +void free_initrd_mem(unsigned long start, unsigned long end)
- +{
- + if (!keep_initrd)
- + free_area(start, end, "initrd");
- +}
- +
- +static int __init keepinitrd_setup(char *__unused)
- +{
- + keep_initrd = 1;
- + return 1;
- +}
- +
- +__setup("keepinitrd", keepinitrd_setup);
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/mm/ioremap.c linux-3.4.110/arch/nds32/mm/ioremap.c
- --- linux-3.4.110.orig/arch/nds32/mm/ioremap.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/mm/ioremap.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,89 @@
- +/*
- + * linux/arch/nds32/mm/ioremap.c
- + *
- + * Re-map IO memory to kernel address space so that we can access it.
- + *
- + * (C) Copyright 1995 1996 Linus Torvalds
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * Hacked for ARM by Phil Blundell <philb@gnu.org>
- + * Hacked to allow all architectures to build, and various cleanups
- + * by Russell King
- + *
- + * This allows a driver to remap an arbitrary region of bus memory into
- + * virtual space. One should *only* use readl, writel, memcpy_toio and
- + * so on with such remapped areas.
- + *
- + * Because the ARM only has a 32-bit address space we can't address the
- + * whole of the (physical) PCI space at once. PCI huge-mode addressing
- + * allows us to circumvent this restriction by splitting PCI space into
- + * two 2GB chunks and mapping only one at a time into processor memory.
- + * We use MMU protection domains to trap any attempt to access the bank
- + * that is not currently mapped. (This isn't fully implemented yet.)
- + */
- +#include <linux/module.h>
- +#include <linux/vmalloc.h>
- +#include <linux/io.h>
- +#include <asm/cacheflush.h>
- +
- +/*
- + * Remap an arbitrary physical address space into the kernel virtual
- + * address space. Needed when the kernel wants to access high addresses
- + * directly.
- + *
- + * NOTE! We need to allow non-page-aligned mappings too: we will obviously
- + * have to convert them into an offset in a page-aligned mapping, but the
- + * caller shouldn't need to know that small detail.
- + *
- + * 'flags' are the extra L_PTE_ flags that you want to specify for this
- + * mapping. See include/asm-arm/proc-armv/pgtable.h for more information.
- + */
- +void __iomem *__ioremap(unsigned long phys_addr, size_t size,
- + unsigned long flags, unsigned long align)
- +{
- + struct vm_struct *area;
- + unsigned long addr, offset, last_addr;
- + pgprot_t prot;
- +
- + /* Don't allow wraparound or zero size */
- + last_addr = phys_addr + size - 1;
- + if (!size || last_addr < phys_addr)
- + return NULL;
- +
- + /*
- + * Mappings have to be page-aligned
- + */
- + offset = phys_addr & ~PAGE_MASK;
- + phys_addr &= PAGE_MASK;
- + size = PAGE_ALIGN(last_addr + 1) - phys_addr;
- +
- + /*
- + * Ok, go for it..
- + */
- + area = get_vm_area(size, VM_IOREMAP);
- + if (!area)
- + return NULL;
- +
- + area->phys_addr = phys_addr;
- + addr = (unsigned long)area->addr;
- + /* TODO: verify this value for ioremap */
- + prot = __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D |
- + _PAGE_G | _PAGE_C_DEV | flags);
- + /* TODO: verify this use generic ioremap_page_range instead of
- + * self's remap_area_pages */
- + if (ioremap_page_range(addr, addr + size, phys_addr, prot)) {
- + vunmap((void *)addr);
- + return NULL;
- + }
- + return (__force void __iomem *)(offset + (char *)addr);
- +
- +}
- +
- +EXPORT_SYMBOL(__ioremap);
- +
- +void __iounmap(void __iomem * addr)
- +{
- + vunmap((void *)(PAGE_MASK & (unsigned long)addr));
- +}
- +
- +EXPORT_SYMBOL(__iounmap);
- diff -Nur linux-3.4.110.orig/arch/nds32/mm/Makefile linux-3.4.110/arch/nds32/mm/Makefile
- --- linux-3.4.110.orig/arch/nds32/mm/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/mm/Makefile 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,24 @@
- +#
- +# Makefile for the linux arm-specific parts of the memory manager.
- +#
- +
- +obj-y := consistent.o extable.o \
- + fault.o init.o ioremap.o mmap.o \
- + mm-nds32.o cacheflush.o
- +
- +obj-y += proc-n12.o
- +obj-$(CONFIG_CCTL) += cctl.o
- +obj-$(CONFIG_ALIGNMENT_TRAP) += alignment.o
- +ifneq ($(CONFIG_CPU_NO_CONTEXT_ID), y)
- +obj-y += tlb.o
- +endif
- +gcc_ver :=$(shell $(CC) -E -dM -xc /dev/null | grep __VERSION__ | sed 's/\#define __VERSION__ //')
- +ifeq ($(shell expr `echo $(gcc_ver)` \>= 4.9.2 ), 1)
- +CFLAGS_proc-n12.o += -fomit-frame-pointer
- +else
- +CFLAGS_proc-n12.o += -fomit-frame-pointer -mno-16bit
- +endif
- +obj-$(CONFIG_HIGHMEM) += highmem.o
- +ifdef CONFIG_FUNCTION_TRACER
- +CFLAGS_REMOVE_proc-n12.o = -pg
- +endif
- diff -Nur linux-3.4.110.orig/arch/nds32/mm/mmap.c linux-3.4.110/arch/nds32/mm/mmap.c
- --- linux-3.4.110.orig/arch/nds32/mm/mmap.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/mm/mmap.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,101 @@
- +/*
- + * linux/arch/nds32/mm/mmap.c
- + *
- + * Copyright (C) 2009 Andes Technology Corporation
- + */
- +#include <linux/sched.h>
- +#include <linux/mman.h>
- +#include <linux/shm.h>
- +
- +#define COLOUR_ALIGN(addr,pgoff) \
- + ((((addr)+REALSHMLBA-1)&~(REALSHMLBA-1)) + \
- + (((pgoff)<<PAGE_SHIFT) & (REALSHMLBA-1)))
- +
- +/*
- + * We need to ensure that shared mappings are correctly aligned to
- + * avoid aliasing issues with VIPT caches. We need to ensure that
- + * a specific page of an object is always mapped at a multiple of
- + * SHMLBA bytes.
- + *
- + * We unconditionally provide this function for all cases, however
- + * in the VIVT case, we optimise out the alignment rules.
- + */
- +unsigned long
- +arch_get_unmapped_area(struct file *filp, unsigned long addr,
- + unsigned long len, unsigned long pgoff,
- + unsigned long flags)
- +{
- + struct mm_struct *mm = current->mm;
- + struct vm_area_struct *vma;
- + unsigned long start_addr;
- + int do_align = 0;
- +#ifdef CONFIG_CPU_CACHE_NONALIASING
- + int aliasing = 0;
- +#else
- + int aliasing = 1;
- +#endif
- +
- + /*
- + * We only need to do colour alignment if either the I or D
- + * caches alias.
- + */
- + if (aliasing)
- + do_align = filp || (flags & MAP_SHARED);
- +
- + /*
- + * We should enforce the MAP_FIXED case. However, currently
- + * the generic kernel code doesn't allow us to handle this.
- + */
- + if (flags & MAP_FIXED) {
- + if (aliasing && flags & MAP_SHARED && addr & (REALSHMLBA - 1))
- + return -EINVAL;
- + return addr;
- + }
- +
- + if (len > TASK_SIZE)
- + return -ENOMEM;
- +
- + if (addr) {
- + if (do_align)
- + addr = COLOUR_ALIGN(addr, pgoff);
- + else
- + addr = PAGE_ALIGN(addr);
- +
- + vma = find_vma(mm, addr);
- + if (TASK_SIZE - len >= addr &&
- + (!vma || addr + len <= vma->vm_start))
- + return addr;
- + }
- + start_addr = addr = mm->free_area_cache;
- +
- +full_search:
- + if (do_align)
- + addr = COLOUR_ALIGN(addr, pgoff);
- + else
- + addr = PAGE_ALIGN(addr);
- +
- + for (vma = find_vma(mm, addr);; vma = vma->vm_next) {
- + /* At this point: (!vma || addr < vma->vm_end). */
- + if (TASK_SIZE - len < addr) {
- + /*
- + * Start a new search - just in case we missed
- + * some holes.
- + */
- + if (start_addr != TASK_UNMAPPED_BASE) {
- + start_addr = addr = TASK_UNMAPPED_BASE;
- + goto full_search;
- + }
- + return -ENOMEM;
- + }
- + if (!vma || addr + len <= vma->vm_start) {
- + /*
- + * Remember the place where we stopped the search:
- + */
- + mm->free_area_cache = addr + len;
- + return addr;
- + }
- + addr = vma->vm_end;
- + if (do_align)
- + addr = COLOUR_ALIGN(addr, pgoff);
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/mm/mm.h linux-3.4.110/arch/nds32/mm/mm.h
- --- linux-3.4.110.orig/arch/nds32/mm/mm.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/mm/mm.h 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,19 @@
- +/* the upper-most page table pointer */
- +
- +#ifdef CONFIG_MMU
- +
- +extern pmd_t *top_pmd;
- +
- +#define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
- +
- +static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
- +{
- + return pmd_offset(pgd, virt);
- +}
- +
- +static inline pmd_t *pmd_off_k(unsigned long virt)
- +{
- + return pmd_off(pgd_offset_k(virt), virt);
- +}
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/mm/mm-nds32.c linux-3.4.110/arch/nds32/mm/mm-nds32.c
- --- linux-3.4.110.orig/arch/nds32/mm/mm-nds32.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/mm/mm-nds32.c 2016-04-07 10:20:50.982082572 +0200
- @@ -0,0 +1,267 @@
- +/*
- + * linux/arch/nds32/mm/mm-nds32.c
- + *
- + * Copyright (C) 1998-2002 Russell King
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * Page table sludge for Andes N10/N12 processor architectures.
- + */
- +#include <linux/module.h>
- +#include <linux/mm.h>
- +#include <linux/bootmem.h>
- +#include <linux/init_task.h>
- +
- +#include <asm/pgalloc.h>
- +#include <asm/pgtable.h>
- +#include <asm/setup.h>
- +#include <asm/fixmap.h>
- +
- +#include <asm/mach/map.h>
- +#include "./../kernel/signal.h"
- +
- +extern void _text, _stext, _etext;
- +extern void *high_memory;
- +
- +#define FIRST_KERNEL_PGD_NR (USER_PTRS_PER_PGD)
- +
- +/*
- + * need to get a 4k page for level 1
- + */
- +
- +pgd_t *get_pgd_slow(struct mm_struct *mm)
- +{
- + pgd_t *new_pgd, *init_pgd;
- + int i;
- +
- + new_pgd = (pgd_t *) __get_free_pages(GFP_KERNEL, 0); //M order 0: one page
- + if (!new_pgd)
- + return NULL;
- + for (i = 0; i < PTRS_PER_PGD; i++) {
- + (*new_pgd) = 1;
- + new_pgd++;
- + }
- + new_pgd -= PTRS_PER_PGD;
- +
- + init_pgd = pgd_offset_k(0);
- +
- + memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
- + (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
- +
- + cpu_dcache_wb_range((unsigned long)new_pgd,
- + (unsigned long)new_pgd +
- + PTRS_PER_PGD * sizeof(pgd_t));
- + inc_zone_page_state(virt_to_page((unsigned long *)new_pgd),
- + NR_PAGETABLE);
- +
- + return new_pgd;
- +}
- +
- +void free_pgd_slow(struct mm_struct *mm, pgd_t * pgd)
- +{
- + pmd_t *pmd;
- + struct page *pte;
- +
- + if (!pgd)
- + return;
- +
- + pmd = (pmd_t *) pgd;
- + if (pmd_none(*pmd))
- + goto free;
- + if (pmd_bad(*pmd)) {
- + pmd_ERROR(*pmd);
- + pmd_clear(pmd);
- + goto free;
- + }
- +
- + pte = pmd_page(*pmd);
- + pmd_clear(pmd);
- + dec_zone_page_state(virt_to_page((unsigned long *)pgd), NR_PAGETABLE);
- + pte_free(mm, pte);
- + pmd_free(mm, pmd);
- +free:
- + free_pages((unsigned long)pgd, 0);
- +}
- +
- +/*
- + * Add a PAGE mapping between VIRT and PHYS in domain
- + * DOMAIN with protection PROT. Note that due to the
- + * way we map the PTEs, we must allocate two PTE_SIZE'd
- + * blocks - one for the Linux pte table, and one for
- + * the hardware pte table.
- + */
- +static inline void
- +alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1,
- + pgprot_t prot)
- +{
- + pmd_t *pmdp;
- + pte_t *ptep;
- +
- + pmdp = pmd_offset(pgd_offset_k(virt), virt); //L1PTE
- + if (pmd_none(*pmdp)) { //must not or 0xc0000000
- + ptep = alloc_bootmem_low_pages(PTRS_PER_PTE * sizeof(pte_t));
- + set_pmd(pmdp, __mk_pmd(ptep, 0));
- + }
- + ptep = pte_offset_kernel(pmdp, virt); //L2PTE
- + set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, prot));
- +}
- +
- +/*
- + * Clear any PGD mapping. On a two-level page table system,
- + * the clearance is done by the middle-level functions (pmd)
- + * rather than the top-level (pgd) functions.
- + */
- +static inline void clear_mapping(unsigned long virt)
- +{
- + pmd_clear(pmd_offset(pgd_offset_k(virt), virt));
- +}
- +
- +struct mem_types {
- + unsigned int prot_pte;
- + unsigned int prot_l1;
- +};
- +
- +static struct mem_types mem_types[] __initdata = {
- + [MT_DEVICE] = {
- + .prot_pte = 0x9f, //_KERNPG_TABLE,
- + .prot_l1 = PMD_TYPE_TABLE,
- + },
- + [MT_CACHECLEAN] = {
- + .prot_l1 = PMD_TYPE_TABLE,
- + .prot_pte = 0x0, //_KERNPG_TABLE,
- + },
- + [MT_MINICLEAN] = {
- + .prot_l1 = PMD_TYPE_TABLE,
- + .prot_pte = 0x0, // _KERNPG_TABLE,
- + },
- + [MT_CACHE_L1] = {
- + .prot_pte = PAGE_CACHE_L1,
- + .prot_l1 = PMD_TYPE_TABLE,
- + },
- + [MT_UXKRWX_V1] = {
- + .prot_pte = PAGE_UXKRWX_V1,
- + .prot_l1 = PMD_TYPE_TABLE,
- + },
- + [MT_UXKRWX_V2] = {
- + .prot_pte = PAGE_UXKRWX_V2,
- + .prot_l1 = PMD_TYPE_TABLE,
- + },
- + [MT_MEMORY] = {
- + .prot_pte = PAGE_MEMORY,
- + .prot_l1 = PMD_TYPE_TABLE,
- + },
- + [MT_ROM] = {
- + .prot_l1 = PMD_TYPE_TABLE,
- + .prot_pte = 0x2bb, // _KERNPG_TABLE,
- + },
- + [MT_ILM] = {
- + .prot_l1 = PMD_TYPE_TABLE,
- + .prot_pte = 0x2b7, // _KERNPG_TABLE,
- + },
- + [MT_DLM] = {
- + .prot_l1 = PMD_TYPE_TABLE,
- + .prot_pte = 0x297, // _KERNPG_TABLE,
- + }
- +};
- +
- +/*
- + * Create the page directory entries and any necessary
- + * page tables for the mapping specified by `md'. We
- + * are able to cope here with varying sizes and address
- + * offsets, and we take full advantage of sections.
- + */
- +static void __init create_mapping(struct map_desc *md)
- +{
- + unsigned long virt, length;
- + int prot_l1;
- + pgprot_t prot_pte;
- + long off;
- +
- + printk("virt:0x%08lx,phys:%08lx,size:%08lx,pte:%08x\n",
- + md->virtual, md->physical, md->length,
- + __pgprot(mem_types[md->type].prot_pte));
- +
- + if (md->virtual < TASK_SIZE) {
- + printk(KERN_WARNING "BUG: not creating mapping area for "
- + "0x%08lx at 0x%08lx in user region, next frame\n",
- + md->physical, md->virtual);
- + panic("In :%s, line:%d", __func__, __LINE__);
- + return;
- + }
- +
- + if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
- + md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) {
- + printk(KERN_WARNING "BUG: mapping area for 0x%08lx at 0x%08lx "
- + "overlaps vmalloc space, next frame\n",
- + md->physical, md->virtual);
- + panic("In :%s, line:%d", __func__, __LINE__);
- + }
- +
- + prot_pte = __pgprot(mem_types[md->type].prot_pte);
- + prot_l1 = mem_types[md->type].prot_l1;
- + virt = md->virtual;
- + off = md->physical - virt;
- +
- + length = md->length;
- + if (mem_types[md->type].prot_l1 == 1 &&
- + (virt & 0xfffff || (virt + off) & 0xfffff
- + || (virt + length) & 0xfffff)) {
- + printk(KERN_WARNING
- + "BUG: map area for 0x%08lx at 0x%08lx can not "
- + "be mapped using pages, ignoring. next frame\n",
- + md->physical, md->virtual);
- + panic("In :%s, line:%d", __func__, __LINE__);
- + return;
- + }
- +
- + while (length >= PAGE_SIZE) {
- +#ifdef CONFIG_SMP
- + if (((virt >= (unsigned long)&_text)
- + && (virt < (unsigned long)&_etext))
- + || ((virt >= 0xc0000000) && (virt < 0xc0008000)))
- + prot_pte = __pgprot(mem_types[MT_CACHE_L1].prot_pte);
- +#endif
- + alloc_init_page(virt, virt + off, prot_l1, prot_pte);
- + virt += PAGE_SIZE;
- + length -= PAGE_SIZE;
- + }
- +}
- +
- +/*
- + * In order to soft-boot, we need to insert a 1:1 mapping in place of
- + * the user-mode pages. This will then ensure that we have predictable
- + * results when turning the mmu off
- + */
- +void setup_mm_for_reboot(char mode)
- +{
- + unsigned long pmdval;
- + pgd_t *pgd;
- + pmd_t *pmd;
- + int i;
- +
- + if (current->mm && current->mm->pgd)
- + pgd = current->mm->pgd;
- + else
- + pgd = init_mm.pgd;
- +
- + for (i = 0; i < USER_PTRS_PER_PGD; i++) {
- + pmdval = (i << PGDIR_SHIFT);
- + pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT);
- + set_pmd(pmd, __pmd(pmdval));
- + }
- +}
- +
- +/*
- + * Create the architecture specific mappings
- + */
- +void __init iotable_init(struct map_desc *io_desc, int nr)
- +{
- + int i;
- +
- + for (i = 0; i < nr; i++) {
- + create_mapping(io_desc + i);
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/mm/proc-n12.c linux-3.4.110/arch/nds32/mm/proc-n12.c
- --- linux-3.4.110.orig/arch/nds32/mm/proc-n12.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/mm/proc-n12.c 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,845 @@
- +/*
- + * linux/arch/nds32/mm/proc-nds32.c
- + *
- + * Copyright (C) 2006 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + *
- + * These are the low level assembler for performing cache and TLB
- + * functions on the nds32.
- + *
- + */
- +#include <linux/module.h>
- +#include <linux/sched.h>
- +#include <linux/mm.h>
- +#include <asm/nds32.h>
- +#include <asm/pgtable.h>
- +#include <asm/tlbflush.h>
- +#include <asm/cacheflush.h>
- +#ifdef CONFIG_CACHE_L2
- +#include <asm/l2_cache.h>
- +#endif
- +#include <nds32_intrinsic.h>
- +
- +#include <asm/cache_info.h>
- +extern struct cache_info L1_cache_info[2];
- +
- +#ifdef CONFIG_CACHE_L2
- +void n12_L2cache_inval(void)
- +{
- + unsigned long cmd = CCTL_CMD_L2_IX_INVAL | CCTL_ALL_CMD;
- +
- + L2_CMD_RDY();
- + L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
- + L2_CMD_RDY();
- + L2C_W_REG(L2_CCTL_CMD_OFF, CCTL_CMD_L2_SYNC);
- + L2_CMD_RDY();
- +}
- +
- +void n12_L2cache_wb(void)
- +{
- + unsigned long cmd = CCTL_CMD_L2_IX_WB | CCTL_ALL_CMD;
- +
- + L2_CMD_RDY();
- + L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
- + L2_CMD_RDY();
- + L2C_W_REG(L2_CCTL_CMD_OFF, CCTL_CMD_L2_SYNC);
- + L2_CMD_RDY();
- +}
- +#endif
- +
- +int va_kernel_present(unsigned long addr)
- +{
- + pmd_t *pmd;
- + pte_t *ptep, pte;
- + int ret = 0;
- +
- + pmd = pmd_offset(pgd_offset_k(addr), addr);
- + if (!pmd_none(*pmd)) {
- + ptep = pte_offset_map(pmd, addr);
- + pte = *ptep;
- + if (pte_present(pte))
- + ret = 1;
- + }
- + return ret;
- +}
- +
- +int va_present(struct mm_struct *mm, unsigned long addr)
- +{
- + pgd_t *pgd;
- + pud_t *pud;
- + pmd_t *pmd;
- + pte_t *ptep, pte;
- + int ret = 0;
- +
- + pgd = pgd_offset(mm, addr);
- + if (!pgd_none(*pgd)) {
- + pud = pud_offset(pgd, addr);
- + if (!pud_none(*pud)) {
- + pmd = pmd_offset(pud, addr);
- + if (!pmd_none(*pmd)) {
- + ptep = pte_offset_map(pmd, addr);
- + pte = *ptep;
- + if (pte_present(pte))
- + ret = 1;
- + }
- + }
- + }
- + return ret;
- +
- +}
- +
- +int va_readable(struct pt_regs *regs, unsigned long addr)
- +{
- + struct mm_struct *mm = current->mm;
- + pgd_t *pgd;
- + pud_t *pud;
- + pmd_t *pmd;
- + pte_t *ptep, pte;
- + int ret = 0;
- +
- + if (user_mode(regs)) {
- + /* user mode */
- + pgd = pgd_offset(mm, addr);
- + if (!pgd_none(*pgd)) {
- + pud = pud_offset(pgd, addr);
- + if (!pud_none(*pud)) {
- + pmd = pmd_offset(pud, addr);
- + if (!pmd_none(*pmd)) {
- + ptep = pte_offset_map(pmd, addr);
- + pte = *ptep;
- + if (pte_present(pte) && pte_read(pte))
- + ret = 1;
- + }
- + }
- + }
- + } else {
- + /* superuser mode is always readable, so we can only
- + * check it is present or not*/
- + pmd = pmd_offset(pgd_offset_k(addr), addr);
- + if (!pmd_none(*pmd)) {
- + ptep = pte_offset_map(pmd, addr);
- + pte = *ptep;
- + if (pte_present(pte))
- + ret = 1;
- + }
- + }
- + return ret;
- +}
- +
- +int va_writable(struct pt_regs *regs, unsigned long addr)
- +{
- + struct mm_struct *mm = current->mm;
- + pgd_t *pgd;
- + pud_t *pud;
- + pmd_t *pmd;
- + pte_t *ptep, pte;
- + int ret = 0;
- +
- + if (user_mode(regs)) {
- + /* user mode */
- + pgd = pgd_offset(mm, addr);
- + if (!pgd_none(*pgd)) {
- + pud = pud_offset(pgd, addr);
- + if (!pud_none(*pud)) {
- + pmd = pmd_offset(pud, addr);
- + if (!pmd_none(*pmd)) {
- + ptep = pte_offset_map(pmd, addr);
- + pte = *ptep;
- + if (pte_present(pte) && pte_write(pte))
- + ret = 1;
- + }
- + }
- + }
- + } else {
- + /* superuser mode */
- + pmd = pmd_offset(pgd_offset_k(addr), addr);
- + if (!pmd_none(*pmd)) {
- + ptep = pte_offset_map(pmd, addr);
- + pte = *ptep;
- + if (pte_present(pte) && pte_kernel_write(pte))
- + ret = 1;
- + }
- + }
- + return ret;
- +}
- +
- +#if 0
- +static inline void flush_fill_buffer(void)
- +{
- + unsigned long kaddr, pte, flags;
- +
- + local_irq_save(flags);
- +#define BASE_ADDR2 0xffff4000
- + kaddr = BASE_ADDR2;
- + pte = (0x6000 | _PAGE_V | _PAGE_M_KRW | _PAGE_G | _PAGE_C_DEV);
- + asm("tlbop %0, INV\nisb\n"::"r"(kaddr));
- + asm("mtsr %1, $mr2\ndsb\n"
- + "tlbop %0, RWR\nisb\n"::"r"(pte), "r"(kaddr));
- +asm("lmw.bi $r0, [%0], $r1\n"::"r"(kaddr):"$r0", "$r1");
- + local_irq_restore(flags);
- +}
- +#else
- +static inline void flush_fill_buffer(void)
- +{
- +}
- +#endif
- +
- +/*
- + * All
- + */
- +void n12_icache_inval_all(void)
- +{
- + unsigned long end, line_size;
- +
- + line_size = L1_cache_info[ICACHE].line_size;
- + end =
- + line_size * L1_cache_info[ICACHE].ways * L1_cache_info[ICACHE].sets;
- +
- + do {
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL"::"r" (end));
- + } while (end > 0);
- +}
- +
- +void n12_dcache_inval_all(void)
- +{
- +#ifdef CONFIG_PLAT_AG102
- + __asm__ volatile ("\n\tcctl L1D_INVALALL");
- +#else
- + unsigned long end, line_size;
- +
- + line_size = L1_cache_info[DCACHE].line_size;
- + end =
- + line_size * L1_cache_info[DCACHE].ways * L1_cache_info[DCACHE].sets;
- +
- + do {
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL"::"r" (end));
- + } while (end > 0);
- +#endif
- +}
- +
- +void n12_dcache_wb_all(void)
- +{
- +#ifdef __NDS32_BASELINE_V3
- +#ifdef CONFIG_CACHE_L2
- + __nds32__cctl_l1d_wball_alvl();
- +#else
- + __nds32__cctl_l1d_wball_one_lvl();
- +#endif
- +#else
- +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- + unsigned long end, line_size;
- +
- + line_size = L1_cache_info[DCACHE].line_size;
- + end =
- + line_size * L1_cache_info[DCACHE].ways * L1_cache_info[DCACHE].sets;
- +
- + do {
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1D_IX_WB"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1D_IX_WB"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1D_IX_WB"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1D_IX_WB"::"r" (end));
- + } while (end > 0);
- +#endif
- +#endif
- +}
- +
- +void n12_dcache_wbinval_all(void)
- +{
- + unsigned long end, line_size;
- +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- + unsigned long saved_gie;
- +#endif
- +
- + line_size = L1_cache_info[DCACHE].line_size;
- + end =
- + line_size * L1_cache_info[DCACHE].ways * L1_cache_info[DCACHE].sets;
- +
- +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- + GIE_SAVE(&saved_gie);
- +#endif
- +#ifdef __NDS32_BASELINE_V3
- +#ifdef CONFIG_CACHE_L2
- + __nds32__cctl_l1d_wball_alvl();
- +#else
- + __nds32__cctl_l1d_wball_one_lvl();
- +#endif
- + __nds32__cctl_l1d_invalall();
- +#else
- + do {
- + end -= line_size;
- +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- + __asm__ volatile ("\n\tcctl %0, L1D_IX_WB"::"r" (end));
- +#endif
- +#ifndef CONFIG_PLAT_AG102
- + __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL"::"r" (end));
- +#endif
- + end -= line_size;
- +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- + __asm__ volatile ("\n\tcctl %0, L1D_IX_WB"::"r" (end));
- +#endif
- +#ifndef CONFIG_PLAT_AG102
- + __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL"::"r" (end));
- +#endif
- + end -= line_size;
- +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- + __asm__ volatile ("\n\tcctl %0, L1D_IX_WB"::"r" (end));
- +#endif
- +#ifndef CONFIG_PLAT_AG102
- + __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL"::"r" (end));
- +#endif
- + end -= line_size;
- +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- + __asm__ volatile ("\n\tcctl %0, L1D_IX_WB"::"r" (end));
- +#endif
- +#ifndef CONFIG_PLAT_AG102
- + __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL"::"r" (end));
- +#endif
- + } while (end > 0);
- +#ifdef CONFIG_PLAT_AG102
- + __asm__ volatile ("\n\tcctl L1D_INVALALL");
- +#endif
- +#endif
- +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- + GIE_RESTORE(saved_gie);
- +#endif
- +}
- +
- +/*
- + * Page
- + */
- +void n12_icache_inval_page(unsigned long start)
- +{
- + unsigned long line_size, end;
- +
- + line_size = L1_cache_info[ICACHE].line_size;
- + end = start + PAGE_SIZE;
- +
- + do {
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL"::"r" (end));
- + } while (end != start);
- +}
- +
- +void n12_dcache_inval_page(unsigned long start)
- +{
- + unsigned long line_size, end;
- +
- + line_size = L1_cache_info[DCACHE].line_size;
- + end = start + PAGE_SIZE;
- +
- + flush_fill_buffer();
- + do {
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
- + } while (end != start);
- +}
- +
- +void n12_dcache_wb_page(unsigned long start)
- +{
- +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- + unsigned long line_size, end;
- +
- + line_size = L1_cache_info[DCACHE].line_size;
- + end = start + PAGE_SIZE;
- +
- + flush_fill_buffer();
- + do {
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
- + end -= line_size;
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
- + } while (end != start);
- +#endif
- +}
- +
- +void n12_dcache_wbinval_page(unsigned long start)
- +{
- + unsigned long line_size, end;
- +
- + line_size = L1_cache_info[DCACHE].line_size;
- + end = start + PAGE_SIZE;
- +
- + flush_fill_buffer();
- + do {
- + end -= line_size;
- +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
- +#endif
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
- + end -= line_size;
- +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
- +#endif
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
- + end -= line_size;
- +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
- +#endif
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
- + end -= line_size;
- +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
- +#endif
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
- + } while (end != start);
- +}
- +
- +void n12_cache_wbinval_page(unsigned long page, int flushi)
- +{
- + n12_dcache_wbinval_page(page);
- + if (flushi)
- + n12_icache_inval_page(page);
- +}
- +
- +/* These functions are used to invalidate cache by idx instead of
- + * virtual address. User can use virtual address to do this purpose.
- + * It supports 4way and 32KB cache size with 32bytes cacheline size. */
- +#include <nds32_intrinsic.h>
- +//#define WB_WITH_IDX
- +inline unsigned long va2idx(unsigned long va, unsigned int cache_type,
- + unsigned long *way_offset)
- +{
- + unsigned char set_bits, way_bits, line_bits;
- + unsigned int idx;
- + set_bits = L1_cache_info[cache_type].set_bits;
- + way_bits = L1_cache_info[cache_type].way_bits;
- + line_bits = L1_cache_info[cache_type].line_bits;
- + *way_offset = set_bits + line_bits;
- +
- + idx = (va & (((1 << set_bits) - 1) << line_bits));
- + return idx;
- +}
- +
- +static inline void n12_dcache_inval_idx(unsigned long p)
- +{
- + unsigned long idx, i, way_offset;
- + unsigned char ways;
- + ways = L1_cache_info[DCACHE].ways;
- +
- + /* Unroll loop. Not support 2 ways invalidate. */
- + if (ways == 2)
- + panic("This way size is not supported. ways:%u, %s\n", ways,
- + __func__);
- + idx = va2idx(p, DCACHE, &way_offset);
- + for (i = 0; i < ways / 4; i++) {
- + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL,
- + (idx | i << way_offset));
- + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL,
- + (idx | (i + 1) << way_offset));
- + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL,
- + (idx | (i + 2) << way_offset));
- + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL,
- + (idx | (i + 3) << way_offset));
- + }
- +}
- +
- +static inline void n12_dcache_wb_idx(unsigned long p)
- +{
- + unsigned long idx, i, way_offset;
- + unsigned char ways;
- + ways = L1_cache_info[DCACHE].ways;
- +
- + /* Unroll the loop. Not support 2 ways invalidate. */
- + if (ways == 2)
- + panic("This way size is not supported. ways:%d, %s\n", ways,
- + __func__);
- + idx = va2idx(p, DCACHE, &way_offset);
- + for (i = 0; i < ways / 4; i++) {
- + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_WB,
- + (idx | i << way_offset));
- + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL,
- + (idx | i << way_offset));
- + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_WB,
- + (idx | (i + 1) << way_offset));
- + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL,
- + (idx | (i + 1) << way_offset));
- + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_WB,
- + (idx | (i + 2) << way_offset));
- + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL,
- + (idx | (i + 2) << way_offset));
- + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_WB,
- + (idx | (i + 3) << way_offset));
- + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL,
- + (idx | (i + 3) << way_offset));
- + }
- +}
- +
- +static inline void n12_dcache_wbinval_idx(unsigned long p)
- +{
- + unsigned long idx, i, way_offset;
- + unsigned char ways;
- + ways = L1_cache_info[DCACHE].ways;
- +
- + /* Unroll the loop. Not support 2 ways invalidate. */
- + if (ways == 2)
- + panic("This way size is not supported. ways:%d, %s\n", ways,
- + __func__);
- + idx = va2idx(p, DCACHE, &way_offset);
- + for (i = 0; i < ways / 4; i++) {
- + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_WB,
- + (idx | i << way_offset));
- + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_WB,
- + (idx | (i + 1) << way_offset));
- + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_WB,
- + (idx | (i + 2) << way_offset));
- + __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_WB,
- + (idx | (i + 3) << way_offset));
- + }
- +}
- +
- +/*
- + * Range
- + */
- +void n12_icache_inval_range(unsigned long start, unsigned long end)
- +{
- + unsigned long line_size;
- +
- + line_size = L1_cache_info[ICACHE].line_size;
- +
- + while (end > start) {
- + __asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL"::"r" (start));
- + start += line_size;
- + }
- +}
- +
- +void n12_dcache_inval_range(unsigned long start, unsigned long end)
- +{
- + unsigned long line_size;
- +
- + line_size = L1_cache_info[DCACHE].line_size;
- +
- + flush_fill_buffer();
- + while (end > start) {
- +#ifdef WB_WITH_IDX
- + n12_dcache_inval_idx(start);
- +#else
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (start));
- +#endif
- + start += line_size;
- + }
- +}
- +
- +void n12_dcache_wb_range(unsigned long start, unsigned long end)
- +{
- +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- + unsigned long line_size;
- +
- + line_size = L1_cache_info[DCACHE].line_size;
- +
- + flush_fill_buffer();
- + while (end > start) {
- +#ifdef WB_WITH_IDX
- + n12_dcache_wb_idx(start);
- +#else
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (start));
- +#endif
- + start += line_size;
- + }
- +#endif
- +}
- +
- +void n12_dcache_wbinval_range(unsigned long start, unsigned long end)
- +{
- + unsigned long line_size;
- +
- + line_size = L1_cache_info[DCACHE].line_size;
- +
- + flush_fill_buffer();
- + while (end > start) {
- +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- +#ifdef WB_WITH_IDX
- + n12_dcache_wbinval_idx(start);
- +#else
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (start));
- +#endif
- +#endif
- + __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (start));
- + start += line_size;
- + }
- +}
- +
- +void n12_cache_wbinval_range(unsigned long start, unsigned long end, int flushi)
- +{
- + n12_dcache_wbinval_range(start, end);
- + if (flushi)
- + n12_icache_inval_range(start, end);
- +}
- +
- +void n12_cache_wbinval_range_check(struct vm_area_struct *vma,
- + unsigned long start, unsigned long end)
- +{
- + unsigned long line_size, t_start, t_end;
- + int flushi;
- +
- + flushi = vma->vm_flags & VM_EXEC;
- + line_size = L1_cache_info[DCACHE].line_size;
- + start = start & ~(line_size - 1);
- + end = (end + line_size - 1) & ~(line_size - 1);
- +
- + if ((end - start) > (8 * PAGE_SIZE)) {
- + n12_dcache_wbinval_all();
- + if (flushi)
- + n12_icache_inval_all();
- + return;
- + }
- +
- + t_start = (start + PAGE_SIZE) & PAGE_MASK;
- + t_end = ((end - 1) & PAGE_MASK);
- +
- + if ((start & PAGE_MASK) == t_end) {
- + if (va_present(vma->vm_mm, start))
- + n12_cache_wbinval_range(start, end, flushi);
- + return;
- + }
- +
- + if (va_present(vma->vm_mm, start))
- + n12_cache_wbinval_range(start, t_start, flushi);
- +
- + if (va_present(vma->vm_mm, end - 1))
- + n12_cache_wbinval_range(t_end, end, flushi);
- +
- + while (t_start < t_end) {
- + if (va_present(vma->vm_mm, t_start))
- + n12_cache_wbinval_page(t_start, flushi);
- + t_start += PAGE_SIZE;
- + }
- +}
- +
- +/*
- + * DMA
- + */
- +void n12_dma_wb_range(unsigned long start, unsigned long end)
- +{
- + unsigned long line_size;
- + line_size = L1_cache_info[DCACHE].line_size;
- + start = start & (~(line_size - 1));
- + end = (end + line_size - 1) & (~(line_size - 1));
- + if (unlikely(start == end))
- + return;
- +
- + n12_dcache_wb_range(start, end);
- +
- +#ifdef CONFIG_CACHE_L2
- + {
- + unsigned long p_start = __pa(start);
- + unsigned long p_end = __pa(end);
- + unsigned long cmd;
- + //TODO Can Use PAGE Mode to optimize if range large than PAGE_SIZE
- + line_size = L2_CACHE_LINE_SIZE();
- + cmd =
- + (p_start & ~(line_size - 1)) | CCTL_CMD_L2_PA_WB |
- + CCTL_SINGLE_CMD;
- + do {
- + L2_CMD_RDY();
- + L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
- + cmd += line_size;
- + p_start += line_size;
- + } while (p_end > p_start);
- + cmd = CCTL_CMD_L2_SYNC;
- + L2_CMD_RDY();
- + L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
- + L2_CMD_RDY();
- +
- + }
- +#endif
- +}
- +
- +#ifdef CONFIG_CACHE_L2
- +void n12_l2dcache_wbinval_range(unsigned long start, unsigned long end)
- +{
- + unsigned long p_start;
- + unsigned long p_end;
- + unsigned long cmd;
- + unsigned long line_size;
- +
- + p_start = __pa(start);
- + p_end = __pa(end);
- + //TODO Can Use PAGE Mode to optimize if range large than PAGE_SIZE
- + line_size = L2_CACHE_LINE_SIZE();
- + cmd =
- + (p_start & ~(line_size - 1)) | CCTL_CMD_L2_PA_WBINVAL |
- + CCTL_SINGLE_CMD;
- + do {
- + L2_CMD_RDY();
- + L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
- + cmd += line_size;
- + p_start += line_size;
- + } while (p_end > p_start);
- + cmd = CCTL_CMD_L2_SYNC;
- + L2_CMD_RDY();
- + L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
- + L2_CMD_RDY();
- +
- +}
- +#endif
- +
- +void n12_dma_inval_range(unsigned long start, unsigned long end)
- +{
- + unsigned long line_size;
- + unsigned long old_start = start;
- + unsigned long old_end = end;
- + line_size = L1_cache_info[DCACHE].line_size;
- + start = start & (~(line_size - 1));
- + end = (end + line_size - 1) & (~(line_size - 1));
- + if (unlikely(start == end))
- + return;
- + if (start != old_start) {
- + n12_dcache_wbinval_range(start, start + line_size);
- +#ifdef CONFIG_CACHE_L2
- + n12_l2dcache_wbinval_range(start, start + line_size);
- +#endif
- + }
- + if (end != old_end) {
- + n12_dcache_wbinval_range(end - line_size, end);
- +#ifdef CONFIG_CACHE_L2
- + n12_l2dcache_wbinval_range(end - line_size, end);
- +#endif
- + }
- + n12_dcache_inval_range(start, end);
- +#ifdef CONFIG_CACHE_L2
- + unsigned long p_start = __pa(start);
- + unsigned long p_end = __pa(end);
- + unsigned long cmd;
- + //TODO Can Use PAGE Mode to optimize if range large than PAGE_SIZE
- + line_size = L2_CACHE_LINE_SIZE();
- + cmd =
- + (p_start & ~(line_size - 1)) | CCTL_CMD_L2_PA_INVAL |
- + CCTL_SINGLE_CMD;
- + do {
- + L2_CMD_RDY();
- + L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
- + cmd += line_size;
- + p_start += line_size;
- + } while (p_end > p_start);
- + cmd = CCTL_CMD_L2_SYNC;
- + L2_CMD_RDY();
- + L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
- + L2_CMD_RDY();
- +#endif
- +
- +}
- +
- +void n12_dma_wbinval_range(unsigned long start, unsigned long end)
- +{
- + unsigned long line_size;
- + line_size = L1_cache_info[DCACHE].line_size;
- + start = start & (~(line_size - 1));
- + end = (end + line_size - 1) & (~(line_size - 1));
- + if (unlikely(start == end))
- + return;
- +
- + n12_dcache_wbinval_range(start, end);
- +#ifdef CONFIG_CACHE_L2
- + {
- + unsigned long p_start = __pa(start);
- + unsigned long p_end = __pa(end);
- + unsigned long cmd;
- + //TODO Can Use PAGE Mode to optimize if range large than PAGE_SIZE
- + line_size = L2_CACHE_LINE_SIZE();
- + cmd =
- + (p_start & ~(line_size - 1)) | CCTL_CMD_L2_PA_WBINVAL |
- + CCTL_SINGLE_CMD;
- + do {
- + L2_CMD_RDY();
- + L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
- + cmd += line_size;
- + p_start += line_size;
- + } while (p_end > p_start);
- + cmd = CCTL_CMD_L2_SYNC;
- + L2_CMD_RDY();
- + L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
- + L2_CMD_RDY();
- +
- + }
- +#endif
- +}
- +
- +void n12_proc_init(void)
- +{
- +}
- +
- +void n12_proc_fin(void)
- +{
- +}
- +
- +void n12_do_idle(void)
- +{
- + STANDBY(no_wake_grant);
- +}
- +
- +void n12_reset(unsigned long reset)
- +{
- + GIE_DISABLE();
- + SET_CACHE_CTL(GET_CACHE_CTL() &
- + ~(CACHE_CTL_mskIC_EN | CACHE_CTL_mskDC_EN));
- + n12_dcache_wbinval_all();
- + n12_icache_inval_all();
- +
- + __asm__ __volatile__("jr.toff %0\n\t"::"r"(reset));
- +}
- +
- +void n12_switch_mm(struct mm_struct *mm)
- +{
- + unsigned long cid;
- +#ifndef CONFIG_CPU_NO_CONTEXT_ID
- + cid = GET_TLB_MISC();
- + cid = (cid & ~TLB_MISC_mskCID) | mm->context.id;
- + SET_TLB_MISC(cid);
- +#endif
- + SET_L1_PPTB(__pa(mm->pgd));
- + //workaround N10 single-entry cache flush issue
- + //the following line can be removed once the issue is fixed.
- + __asm__ __volatile__("tlbop %0, INV"::"r"(cid));
- + __nds32__isb();
- +#ifdef CONFIG_CPU_NO_CONTEXT_ID
- + local_flush_tlb_mm(mm);
- +#endif
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/mm/tlb.c linux-3.4.110/arch/nds32/mm/tlb.c
- --- linux-3.4.110.orig/arch/nds32/mm/tlb.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/mm/tlb.c 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,47 @@
- +#include <linux/spinlock_types.h>
- +#include <linux/mm.h>
- +#include <linux/sched.h>
- +#include <asm/nds32.h>
- +#include <nds32_intrinsic.h>
- +
- +unsigned int cpu_last_cid = { TLB_MISC_mskCID + (2 << TLB_MISC_offCID) };
- +
- +DEFINE_SPINLOCK(cid_lock);
- +
- +void local_flush_tlb_range(struct vm_area_struct *vma,
- + unsigned long start, unsigned long end)
- +{
- + unsigned long flags, ocid, ncid;
- +
- + if ((end - start) > 0x400000) {
- + asm("tlbop FLUA");
- + __nds32__isb();
- + return;
- + }
- +
- + spin_lock_irqsave(&cid_lock, flags);
- + ocid = GET_TLB_MISC();
- + ncid = (ocid & ~TLB_MISC_mskCID) | vma->vm_mm->context.id;
- + SET_TLB_MISC(ncid);
- + while (start < end) {
- + asm("tlbop %0, INV"::"r"(start));
- + __nds32__isb();
- + start += PAGE_SIZE;
- + }
- + SET_TLB_MISC(ocid);
- + spin_unlock_irqrestore(&cid_lock, flags);
- +}
- +
- +void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
- +{
- + unsigned long flags, ocid, ncid;
- +
- + spin_lock_irqsave(&cid_lock, flags);
- + ocid = GET_TLB_MISC();
- + ncid = (ocid & ~TLB_MISC_mskCID) | vma->vm_mm->context.id;
- + SET_TLB_MISC(ncid);
- + asm("tlbop %0, INV"::"r"(addr));
- + __nds32__isb();
- + SET_TLB_MISC(ocid);
- + spin_unlock_irqrestore(&cid_lock, flags);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/oprofile/common.c linux-3.4.110/arch/nds32/oprofile/common.c
- --- linux-3.4.110.orig/arch/nds32/oprofile/common.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/oprofile/common.c 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,104 @@
- +/*
- + * This file is subject to the terms and conditions of the GNU General Public
- + * License. See the file "COPYING" in the main directory of this archive
- + * for more details.
- + *
- + * Copyright (C) 2004, 2005 Ralf Baechle
- + * Copyright (C) 2005 MIPS Technologies, Inc.
- + * Copyright (C) 2008 Andes Technology Corporation
- + */
- +#include <linux/errno.h>
- +#include <linux/init.h>
- +#include <linux/oprofile.h>
- +#include <linux/smp.h>
- +
- +#include "op_impl.h"
- +
- +extern struct op_nds32_model op_model_nds32_ops __attribute__ ((weak));
- +
- +static struct op_nds32_model *model;
- +
- +static struct op_counter_config ctr[20];
- +
- +static int op_nds32_setup(void)
- +{
- + /* Pre-compute the values to stuff in the hardware registers. */
- + model->reg_setup(ctr);
- +
- + /* Configure the registers on all cpus. */
- + on_each_cpu(model->cpu_setup, NULL, 1);
- +
- + return 0;
- +}
- +
- +static int op_nds32_create_files(struct super_block *sb, struct dentry *root)
- +{
- + int i;
- +
- + for (i = 0; i < model->num_counters; ++i) {
- + struct dentry *dir;
- + char buf[4];
- +
- + snprintf(buf, sizeof buf, "%d", i);
- + dir = oprofilefs_mkdir(sb, root, buf);
- +
- + oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
- + oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
- + oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count);
- + oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
- + oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
- + oprofilefs_create_ulong(sb, dir, "exl", &ctr[i].exl);
- + /* Dummy. */
- + oprofilefs_create_ulong(sb, dir, "unit_mask",
- + &ctr[i].unit_mask);
- + }
- +
- + return 0;
- +}
- +
- +static int op_nds32_start(void)
- +{
- + on_each_cpu(model->cpu_start, NULL, 1);
- +
- + return 0;
- +}
- +
- +static void op_nds32_stop(void)
- +{
- + /* Disable performance monitoring for all counters. */
- + on_each_cpu(model->cpu_stop, NULL, 1);
- +}
- +
- +int __init oprofile_arch_init(struct oprofile_operations *ops)
- +{
- + struct op_nds32_model *lmodel = NULL;
- + int res;
- +
- + lmodel = &op_model_nds32_ops;
- +
- + if (!lmodel)
- + return -ENODEV;
- +
- + res = lmodel->init();
- + if (res)
- + return res;
- +
- + model = lmodel;
- +
- + ops->create_files = op_nds32_create_files;
- + ops->setup = op_nds32_setup;
- + ops->start = op_nds32_start;
- + ops->stop = op_nds32_stop;
- + ops->cpu_type = lmodel->cpu_type;
- +
- + printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
- + lmodel->cpu_type);
- +
- + return 0;
- +}
- +
- +void oprofile_arch_exit(void)
- +{
- + if (model)
- + model->exit();
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/oprofile/Makefile linux-3.4.110/arch/nds32/oprofile/Makefile
- --- linux-3.4.110.orig/arch/nds32/oprofile/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/oprofile/Makefile 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,11 @@
- +EXTRA_CFLAGS :=
- +
- +obj-$(CONFIG_OPROFILE) += oprofile.o
- +
- +DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
- + oprof.o cpu_buffer.o buffer_sync.o \
- + event_buffer.o oprofile_files.o \
- + oprofilefs.o oprofile_stats.o \
- + timer_int.o )
- +
- +oprofile-y := $(DRIVER_OBJS) common.o op_model_nds32.o
- diff -Nur linux-3.4.110.orig/arch/nds32/oprofile/op_impl.h linux-3.4.110/arch/nds32/oprofile/op_impl.h
- --- linux-3.4.110.orig/arch/nds32/oprofile/op_impl.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/oprofile/op_impl.h 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,42 @@
- +/**
- + * @file arch/alpha/oprofile/op_impl.h
- + *
- + * @remark Copyright 2002 OProfile authors
- + * @remark Read the file COPYING
- + *
- + * @author Richard Henderson <rth@twiddle.net>
- + */
- +
- +#ifndef OP_IMPL_H
- +#define OP_IMPL_H 1
- +
- +struct pt_regs;
- +
- +extern int null_perf_irq(struct pt_regs *regs);
- +extern int (*perf_irq)(struct pt_regs *regs);
- +
- +/* Per-counter configuration as set via oprofilefs. */
- +struct op_counter_config {
- + unsigned long enabled;
- + unsigned long event;
- + unsigned long count;
- + /* Dummies because I am too lazy to hack the userspace tools. */
- + unsigned long kernel;
- + unsigned long user;
- + unsigned long exl;
- + unsigned long unit_mask;
- +};
- +
- +/* Per-architecture configury and hooks. */
- +struct op_nds32_model {
- + void (*reg_setup) (struct op_counter_config *);
- + void (*cpu_setup) (void * dummy);
- + int (*init)(void);
- + void (*exit)(void);
- + void (*cpu_start)(void *args);
- + void (*cpu_stop)(void *args);
- + char *cpu_type;
- + unsigned char num_counters;
- +};
- +
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/oprofile/op_model_nds32.c linux-3.4.110/arch/nds32/oprofile/op_model_nds32.c
- --- linux-3.4.110.orig/arch/nds32/oprofile/op_model_nds32.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/oprofile/op_model_nds32.c 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,400 @@
- +/*
- + * This file is subject to the terms and conditions of the GNU General Public
- + * License. See the file "COPYING" in the main directory of this archive
- + * for more details.
- + *
- + * Copyright (C) 2004, 2005 by Ralf Baechle
- + * Copyright (C) 2005 by MIPS Technologies, Inc.
- + * Copyright (C) 2007 Andes Technology Corporation
- + */
- +#include <linux/oprofile.h>
- +#include <linux/interrupt.h>
- +#include <linux/smp.h>
- +#include <asm/irq_regs.h>
- +#include <asm/nds32.h>
- +#include <asm/uaccess.h>
- +#include <asm/pfm.h>
- +
- +#include "op_impl.h"
- +
- +#ifdef CONFIG_PLAT_AG102
- +#include <asm/amic.h>
- +#define NDS32_PERFCNTR_IRQA 23
- +#define NDS32_PERFCNTR_IRQB 22
- +#else
- +#define NDS32_PERFCNTR_IRQA 10
- +#endif
- +#define NDS32_PERFCTL_EN(num) (1 << num)
- +#define NDS32_PERFCTL_INTEN (1UL << 3)
- +#define NDS32_PERFCTL_OVERFLOW (1UL << 6)
- +#define NDS32_PERFCTL_NOKERNEL (1UL << 9)
- +#define NDS32_PERFCTL_NOUSER (1UL << 12)
- +#define NDS32_PERFCTL_EVENT_0(event) (event << 15)
- +#define NDS32_PERFCTL_EVENT_1(event) (event << 16)
- +#define NDS32_PERFCTL_EVENT_2(event) (event << 22)
- +
- +static unsigned long long ov0, ov1, ov2;
- +static int syscall = 0;
- +
- +struct pmu_counter {
- + volatile unsigned long ovf;
- + unsigned long reset_counter;
- +};
- +
- +enum { PFMC0, PFMC1, PFMC2, MAX_COUNTERS };
- +
- +static struct pmu_counter results[MAX_COUNTERS];
- +
- +static inline unsigned int read_perfcntr(int counter)
- +{
- + switch (counter) {
- + case PFMC0:
- + return GET_PFMC0();
- + break;
- + case PFMC1:
- + return GET_PFMC1();
- + break;
- + case PFMC2:
- + return GET_PFMC2();
- + break;
- + default:
- + printk(KERN_ERR
- + "Oprofile read_perfcntr: CPU has no %d performance counters\n",
- + counter);
- + }
- +
- + return 0;
- +}
- +
- +static inline unsigned int read_perfctrl(void)
- +{
- + return GET_PFM_CTL();
- +}
- +
- +static inline void write_perfcntr(int counter, unsigned int value)
- +{
- + switch (counter) {
- + case PFMC0:
- + SET_PFMC0(value);
- + break;
- + case PFMC1:
- + SET_PFMC1(value);
- + break;
- + case PFMC2:
- + SET_PFMC2(value);
- + break;
- + default:
- + printk(KERN_ERR
- + "Oprofile write_perfcntr: CPU has no %d performance counters\n",
- + counter);
- + }
- +}
- +
- +static inline void write_perfctrl(unsigned int value)
- +{
- + SET_PFM_CTL(value);
- +}
- +
- +struct op_nds32_model op_model_nds32_ops;
- +
- +static struct nds32_register_config {
- + unsigned int control[3];
- + unsigned int counter[3];
- +} reg;
- +
- +/* Compute all of the registers in preparation for enabling profiling. */
- +
- +static void nds32_reg_setup(struct op_counter_config *ctr)
- +{
- + unsigned int counters = op_model_nds32_ops.num_counters;
- + int i;
- +
- + /* Compute the performance counter control word. */
- + /* For now count kernel and user mode */
- + for (i = 0; i < counters; i++) {
- + reg.control[i] = 0;
- + reg.counter[i] = 0;
- +
- + if (!ctr[i].enabled)
- + continue;
- +
- + switch (i) {
- + case 0:
- + reg.control[i] = NDS32_PERFCTL_EVENT_0(ctr[i].event) |
- + (NDS32_PERFCTL_INTEN << i);
- + break;
- + case 1:
- + reg.control[i] = NDS32_PERFCTL_EVENT_1(ctr[i].event) |
- + (NDS32_PERFCTL_INTEN << i);
- + break;
- + case 2:
- + reg.control[i] = NDS32_PERFCTL_EVENT_2(ctr[i].event) |
- + (NDS32_PERFCTL_INTEN << i);
- + break;
- + default:
- + printk(KERN_ERR
- + "Oprofile nds32_reg_setup: CPU has no %d performance counters\n",
- + i);
- + }
- + if (!(ctr[i].kernel))
- + reg.control[i] |= (NDS32_PERFCTL_NOKERNEL << i);
- + if (!(ctr[i].user))
- + reg.control[i] |= (NDS32_PERFCTL_NOUSER << i);
- + reg.counter[i] = -ctr[i].count;
- + }
- +}
- +
- +/* Program all of the registers in preparation for enabling profiling. */
- +
- +static void nds32_cpu_setup(void *args)
- +{
- + unsigned int counters = op_model_nds32_ops.num_counters;
- +
- + switch (counters) {
- + case 3:
- + write_perfcntr(2, reg.counter[2]);
- + case 2:
- + write_perfcntr(1, reg.counter[1]);
- + case 1:
- + write_perfcntr(0, reg.counter[0]);
- + }
- + write_perfctrl(0);
- +}
- +
- +/* Start all counters on current CPU */
- +static void nds32_cpu_start(void *args)
- +{
- + unsigned int counters = op_model_nds32_ops.num_counters;
- + unsigned int value = 0;
- +
- + switch (counters) {
- + case 3:
- + if (reg.control[2])
- + value |= (NDS32_PERFCTL_EN(2) | reg.control[2]);
- + case 2:
- + if (reg.control[1])
- + value |= (NDS32_PERFCTL_EN(1) | reg.control[1]);
- + case 1:
- + if (reg.control[0])
- + value |= (NDS32_PERFCTL_EN(0) | reg.control[0]);
- + }
- + write_perfctrl(value);
- +}
- +
- +/* Stop all counters on current CPU */
- +static void nds32_cpu_stop(void *args)
- +{
- + write_perfctrl(0);
- +}
- +
- +static irqreturn_t nds32_perfcount_handler(int irq, void *dev_id)
- +{
- + unsigned int control, i;
- +
- + control = read_perfctrl();
- + write_perfctrl(0);
- +
- + if (syscall) {
- + if (control & PFM_CTL_mskOVF0)
- + ov0++;
- + if (control & PFM_CTL_mskOVF1)
- + ov1++;
- + if (control & PFM_CTL_mskOVF2)
- + ov2++;
- + } else {
- + for (i = 0; i < MAX_COUNTERS; i++) {
- + if ((control & (NDS32_PERFCTL_INTEN << i))
- + && (control & (NDS32_PERFCTL_OVERFLOW << i))) {
- + oprofile_add_sample(get_irq_regs(), i);
- + write_perfcntr(i, reg.counter[i]);
- + break;
- + }
- + }
- + }
- + write_perfctrl(control);
- +
- + return IRQ_HANDLED;
- +}
- +
- +static inline int n_counters(void)
- +{
- + return 3;
- +}
- +
- +static inline void reset_counters(int counters)
- +{
- + switch (counters) {
- + case 3:
- + write_perfcntr(2, 0);
- + case 2:
- + write_perfcntr(1, 0);
- + case 1:
- + write_perfcntr(0, 0);
- + }
- + write_perfctrl(0);
- +}
- +
- +static int __init nds32_init(void)
- +{
- + int counters, ret;
- +
- + counters = n_counters();
- + if (counters == 0) {
- + printk(KERN_ERR "Oprofile: CPU has no performance counters\n");
- + return -ENODEV;
- + }
- +
- + reset_counters(counters);
- +
- + op_model_nds32_ops.num_counters = counters;
- + op_model_nds32_ops.cpu_type = "nds32";
- +
- + ret =
- + request_irq(NDS32_PERFCNTR_IRQA, nds32_perfcount_handler,
- + IRQF_SHARED, "NDS32 PERFCNTR", (void *)results);
- + if (ret < 0) {
- + printk(KERN_ERR "oprofile: unable to request IRQ%d\n",
- + NDS32_PERFCNTR_IRQA);
- + return ret;
- + }
- +#ifdef CONFIG_PLAT_AG102
- + unsigned int tmp;
- + /* Set NDS32_PERFCNTR_IRQA to bind on core A */
- + tmp =
- + *(volatile unsigned long *)(AMIC_VA_BASE + CPUID0 +
- + ((NDS32_PERFCNTR_IRQA >> 4) << 2));
- + tmp &= ~(0x11 << ((NDS32_PERFCNTR_IRQA & ~0x10) * 2));
- + *(volatile unsigned long *)(AMIC_VA_BASE + CPUID0 +
- + ((NDS32_PERFCNTR_IRQA >> 4) << 2)) = tmp;
- + tmp =
- + (*(volatile unsigned long *)(AMIC_VA_BASE + CPUDC)) & ~(1 <<
- + NDS32_PERFCNTR_IRQA);
- + *(volatile unsigned long *)(AMIC_VA_BASE + CPUDC) = tmp;
- +
- + ret =
- + request_irq(NDS32_PERFCNTR_IRQB, nds32_perfcount_handler,
- + IRQF_SHARED, "NDS32 PERFCNTR", (void *)results);
- + if (ret < 0) {
- + printk(KERN_ERR "oprofile: unable to request IRQ%d\n",
- + NDS32_PERFCNTR_IRQB);
- + return ret;
- + }
- + /* Set NDS32_PERFCNTR_IRQB to bind on core B */
- + tmp =
- + *(volatile unsigned long *)(AMIC_VA_BASE + CPUID0 +
- + ((NDS32_PERFCNTR_IRQB >> 4) << 2));
- + tmp &= ~(0x11 << ((NDS32_PERFCNTR_IRQB & ~0x10) * 2));
- + tmp |= 1 << ((NDS32_PERFCNTR_IRQB & ~0x10) * 2);
- + *(volatile unsigned long *)(AMIC_VA_BASE + CPUID0 +
- + ((NDS32_PERFCNTR_IRQB >> 4) << 2)) = tmp;
- + tmp =
- + (*(volatile unsigned long *)(AMIC_VA_BASE + CPUDC)) & ~(1 <<
- + NDS32_PERFCNTR_IRQB);
- + *(volatile unsigned long *)(AMIC_VA_BASE + CPUDC) = tmp;
- +#endif
- +
- + return 0;
- +}
- +
- +static void nds32_exit(void)
- +{
- + reset_counters(op_model_nds32_ops.num_counters);
- +
- + free_irq(NDS32_PERFCNTR_IRQA, results);
- +#ifdef CONFIG_PLAT_AG102
- + free_irq(NDS32_PERFCNTR_IRQB, results);
- +#endif
- +}
- +
- +void sys_pfmctl(int event0, int event1, int event2, int start)
- +{
- + unsigned int ctl = 0;
- +
- + if (start) {
- + syscall = 1;
- + if (event0 >= 0)
- + ctl |=
- + (NDS32_PERFCTL_EVENT_0(event0) |
- + (NDS32_PERFCTL_INTEN << 0) | NDS32_PERFCTL_EN(0));
- + if (event1 >= 0)
- + ctl |=
- + (NDS32_PERFCTL_EVENT_1(event1) |
- + (NDS32_PERFCTL_INTEN << 1) | NDS32_PERFCTL_EN(1));
- + if (event2 >= 0)
- + ctl |=
- + (NDS32_PERFCTL_EVENT_2(event2) |
- + (NDS32_PERFCTL_INTEN << 2) | NDS32_PERFCTL_EN(2));
- + } else {
- + syscall = 0;
- + if (event0 >= 0)
- + ctl &=
- + ~((NDS32_PERFCTL_INTEN << 0) | NDS32_PERFCTL_EN(0));
- + if (event1 >= 0)
- + ctl &=
- + ~((NDS32_PERFCTL_INTEN << 1) | NDS32_PERFCTL_EN(1));
- + if (event2 >= 0)
- + ctl &=
- + ~((NDS32_PERFCTL_INTEN << 2) | NDS32_PERFCTL_EN(2));
- + }
- +
- + write_perfctrl(ctl);
- +
- +}
- +
- +int sys_getpfm(struct pcounter __user * p)
- +{
- + struct pcounter pfm;
- + unsigned int control;
- +
- + control = read_perfctrl();
- + write_perfctrl(0);
- +
- + pfm.pfm0 = ov0 << 32 | GET_PFMC0();
- + pfm.pfm1 = ov1 << 32 | GET_PFMC1();
- + pfm.pfm2 = ov2 << 32 | GET_PFMC2();
- +
- + if (copy_to_user(p, &pfm, sizeof(pfm)))
- + return -EFAULT;
- +
- + write_perfctrl(control);
- +
- + return 0;
- +}
- +
- +int sys_setpfm(int pfm0, int pfm1, int pfm2, struct pcounter __user * p)
- +{
- + struct pcounter pfm;
- + unsigned int control;
- +
- + control = read_perfctrl();
- + write_perfctrl(0);
- +
- + if (copy_from_user(&pfm, p, sizeof(pfm)))
- + return -EFAULT;
- +
- + if (pfm0) {
- + SET_PFMC0((unsigned int)(pfm.pfm0 & 0xffffffff));
- + ov0 = pfm.pfm0 >> 32;
- + }
- + if (pfm1) {
- + SET_PFMC1((unsigned int)(pfm.pfm1 & 0xffffffff));
- + ov1 = pfm.pfm1 >> 32;
- + }
- + if (pfm2) {
- + SET_PFMC2((unsigned int)(pfm.pfm2 & 0xffffffff));
- + ov2 = pfm.pfm2 >> 32;
- + }
- +
- + write_perfctrl(control);
- +
- + return 0;
- +}
- +
- +struct op_nds32_model op_model_nds32_ops = {
- + .reg_setup = nds32_reg_setup,
- + .cpu_setup = nds32_cpu_setup,
- + .init = nds32_init,
- + .exit = nds32_exit,
- + .cpu_start = nds32_cpu_start,
- + .cpu_stop = nds32_cpu_stop,
- +};
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101/cpu-fcs.c linux-3.4.110/arch/nds32/platforms/ag101/cpu-fcs.c
- --- linux-3.4.110.orig/arch/nds32/platforms/ag101/cpu-fcs.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag101/cpu-fcs.c 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,401 @@
- +/*
- + * linux/arch/nds32/platforms/ag101/cpu-fcs.c
- + *
- + * Copyright (C) 2002,2003 Intrinsyc Software
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + * History:
- + * 31-Jul-2002 : Initial version [FB]
- + * 29-Jan-2003 : added PXA255 support [FB]
- + * 20-Apr-2003 : ported to v2.5 (Dustin McIntire, Sensoria Corp.)
- + * 18-Jun-2008 : ported to NDS32 architecture ( Roy Lee, Andestech Corp.)
- + *
- + * Note:
- + * This driver may change the memory bus clock rate, but will not do any
- + * platform specific access timing changes... for example if you have flash
- + * memory connected to CS0, you will need to register a platform specific
- + * notifier which will adjust the memory access strobes to maintain a
- + * minimum strobe width.
- + *
- + */
- +#include <linux/module.h>
- +#include <linux/cpufreq.h>
- +#include <linux/interrupt.h>
- +
- +#include <asm/hardware.h>
- +#include <asm/localmem.h>
- +#include <asm/system.h>
- +#include <asm/nds32.h>
- +#include <asm/irq_regs.h>
- +
- +#define NDS32_FCS_IRQ 8
- +#define AG101_MIN_FREQ 100000
- +#define AG101_MAX_FREQ 400000
- +#define OSC_KHZ 10000 /* 10 MHz AG101 */
- +
- +#define USE_CACHE 0
- +struct ag101_freq_struct {
- +
- + unsigned int khz; /* cpu_clk in khz */
- + unsigned int pll; /* pll mul */
- + unsigned int div; /* ahb div */
- + unsigned int frange; /* pll1 freq range */
- +};
- +
- +struct ag101_freq_struct ag101_run_freqs[] = {
- +
- + /* khz , pll, div, frange pll/cpu/ahb/apb */
- + {100000, 10, 2, 0}, /* 400/400/050/025 */
- + {200000, 20, 4, 1}, /* 400/400/050/025 */
- + {300000, 30, 6, 2}, /* 400/400/050/025 */
- + {400000, 40, 8, 2}, /* 400/400/050/025 */
- + {500000, 50, 10, 3}, /* 500/500/050/025 */
- + {0,}
- +};
- +
- +#define NUM_RUN_FREQS ARRAY_SIZE( ag101_run_freqs)
- +static struct cpufreq_frequency_table ag101_run_freq_table[NUM_RUN_FREQS + 1];
- +
- +/* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */
- +static struct ag101_freq_struct ag101_turbo_freqs[] = {
- +
- + /* khz , pll, div, frange pll/cpu/ahb/apb */
- + {100000, 10, 2, 0}, /* 400/400/050/025 */
- + {200000, 20, 4, 1}, /* 400/400/050/025 */
- + {300000, 30, 6, 2}, /* 400/400/050/025 */
- + {400000, 40, 8, 2}, /* 400/400/050/025 */
- + {500000, 50, 10, 3}, /* 500/500/050/025 */
- + {0,}
- +};
- +
- +#define NUM_TURBO_FREQS ARRAY_SIZE( ag101_turbo_freqs)
- +static struct cpufreq_frequency_table ag101_turbo_freq_table[NUM_TURBO_FREQS +
- + 1];
- +
- +/* Generic helper function get CPU clocks in kHz */
- +unsigned int ag101_cpufreq_get(unsigned int dummy)
- +{
- +
- + unsigned int mul = (REG32(PMU_FTPMU010_VA_BASE + 0x30) >> 3UL) & 0x01ff; /* pll1 mul */
- + return OSC_KHZ * mul;
- +}
- +
- +/* find a valid frequency point */
- +static int ag101_verify_policy(struct cpufreq_policy *policy)
- +{
- +
- + struct cpufreq_frequency_table *ag101_freqs_table;
- +
- + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
- +
- + ag101_freqs_table = ag101_run_freq_table;
- + } else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) {
- +
- + ag101_freqs_table = ag101_turbo_freq_table;
- + } else {
- + printk
- + ("CPU PXA: Unknown policy found. Using CPUFREQ_POLICY_PERFORMANCE\n");
- + ag101_freqs_table = ag101_run_freq_table;
- + }
- +
- + printk("Verified CPU policy: %dKhz min to %dKhz max\n", policy->min,
- + policy->max);
- +
- + return cpufreq_frequency_table_verify(policy, ag101_freqs_table);
- +}
- +
- +static int cal_edivahbclk(int div)
- +{
- +
- + switch (div) {
- +
- + case 1:
- + case 2:
- + case 3:
- + case 4:
- + case 5:
- + case 6:
- + return --div;
- + case 8:
- + return 8;
- + case 10:
- + return 9;
- + case 12:
- + return 10;
- + case 14:
- + return 11;
- + case 15:
- + return 12;
- + case 18:
- + return 13;
- + case 20:
- + return 14;
- + default:
- + printk("Error: No such CPU/AHB frequency ratio %d", div);
- + }
- +
- + return 9;
- +}
- +
- +void start_fcs(unsigned int pll, unsigned int frange, unsigned int div)
- +{
- +
- + /* PDLLCR0 */
- + REG32(PMU_FTPMU010_VA_BASE + 0x30) &= ~0x00003ff8; /* clear PLL1NS and PLL1FRANG fields */
- + REG32(PMU_FTPMU010_VA_BASE + 0x30) |= (pll << 3); /* set PLL1NS */
- + REG32(PMU_FTPMU010_VA_BASE + 0x30) |= (frange << 12); /* set PLL1FRANG */
- +
- + /* PMODE */
- + REG32(PMU_FTPMU010_VA_BASE + 0x0c) &= ~0x000000ff; /* clear EDIVAHBCLK field */
- + REG32(PMU_FTPMU010_VA_BASE + 0x0c) |= (div << 4); /* set EDIVAHBCLK [7:4] */
- + REG32(PMU_FTPMU010_VA_BASE + 0x0c) |= (1UL << 2); /* [2]: FCS */
- +
- + __asm__ __volatile__("msync all");
- + __asm__ __volatile__("isb");
- + __asm__ __volatile__("standby wake_grant");
- + REG32(PMU_FTPMU010_VA_BASE + 0x30) |= (1UL << 16); /* PDLLCR0 bit[16]==1:disable dll */
- +}
- +
- +void end_fcs(void)
- +{
- +
- + /* Leave this function as a place marker. */
- +}
- +
- +static int nds32_fcs_handler(int irq, void *dev_id)
- +{
- +
- + REG32(PMU_FTPMU010_VA_BASE + 0x20) = (1UL << 17); /* Clear IntFCS PMSR[17] */
- + REG32(PMU_FTPMU010_VA_BASE + 0x0c) &= ~(1UL << 2); /* Power Mode Register */
- +
- + return 1;
- +}
- +
- +static int ag101_speedstep(int idx)
- +{
- +
- + unsigned int pll, frange, div;
- + unsigned long flags = 0;
- + int irq, saved_irq_mask;
- + void (*do_fcs) (unsigned int pll, unsigned int frange,
- + unsigned int div);
- +
- +#if USE_CACHE
- +
- + int i;
- + int line_size = CACHE_LINE_SIZE(ICACHE);
- + unsigned long start = ((unsigned long)start_fcs) & ~(line_size - 1);
- + unsigned long end =
- + (((unsigned long)end_fcs) + line_size) & ~(line_size - 1);
- +
- + printk("&start_fcs(): 0x%08lx, aligned to: 0x%08lx\n",
- + (unsigned long)start_fcs, start);
- + printk("&end_fcs(): 0x%08lx, aligned to: 0x%08lx\n",
- + (unsigned long)end_fcs, end);
- +
- + for (i = start; i <= end; i += CACHE_LINE_SIZE(ICACHE))
- + __asm__ volatile ("\n\tcctl %0, L1I_VA_FILLCK"::
- + "r" (i):"memory");
- +
- + do_fcs = start_fcs;
- +#else
- + unsigned long buf, aligned_buf, len = PAGE_SIZE;
- +
- + buf = (unsigned long)kmalloc(0x100000 + 1000, GFP_KERNEL);
- + if (!buf)
- + printk("Error: kmalloc( base) failed\n");
- +
- + aligned_buf = (buf + 0x100000 - 1) & 0xFFF00000;
- +
- + if (sys_lmmap(LM_ILM, aligned_buf, aligned_buf + 0x1000, 0, NULL)) {
- + printk("Error: lmmap failed, can't scale frequency.\n");
- +#ifdef CONFIG_CPU_FREQ_DEBUG
- + WARN_ON(1);
- +#endif
- + return 0;
- + }
- +
- + if (((GET_ILMB() & ILMB_mskILMSZ) >> ILMB_offILMSZ) == 9)
- + len = 0x400;
- + else if (((GET_ILMB() & ILMB_mskILMSZ) >> ILMB_offILMSZ) == 10)
- + len = 0x800;
- + memcpy((unsigned char *)aligned_buf, (unsigned char *)start_fcs, len);
- +
- + do_fcs = (void *)aligned_buf;
- +#endif
- + pll = ag101_run_freqs[idx].pll;
- + div = cal_edivahbclk(ag101_run_freqs[idx].div);
- + frange = ag101_run_freqs[idx].frange;
- +
- + irq =
- + request_irq(NDS32_FCS_IRQ, nds32_fcs_handler,
- + IRQF_DISABLED | IRQF_TRIGGER_FALLING,
- + "NDS32 Frequency Change Sequence",
- + (void *)ag101_run_freqs);
- + if (irq < 0)
- + printk(KERN_ERR "Error: unable to request FCS IRQ%d\n",
- + NDS32_FCS_IRQ);
- +
- + local_irq_save(flags);
- +
- + saved_irq_mask = REG32(INTC_FTINTC010_VA_BASE + 0x04);
- + REG32(INTC_FTINTC010_VA_BASE + 0x04) = (1UL << NDS32_FCS_IRQ);
- +
- + do_fcs(pll, frange, div);
- +
- + REG32(INTC_FTINTC010_VA_BASE + 0x04) = saved_irq_mask;
- +
- + local_irq_restore(flags);
- + free_irq(NDS32_FCS_IRQ, ag101_run_freqs);
- +
- +#if USE_CACHE
- + for (i = start; i <= end; i += CACHE_LINE_SIZE(ICACHE))
- + __asm__ volatile ("\n\tcctl %0, L1I_VA_ULCK"::"r" (i):"memory");
- +#else
- + if (sys_lmunmap(aligned_buf, 0))
- + printk("Error: lmunmap failed\n");
- +
- + kfree((void *)buf);
- +#endif
- + return 1;
- +}
- +
- +static int ag101_set_target(struct cpufreq_policy *policy,
- + unsigned int target_freq, unsigned int relation)
- +{
- +
- + unsigned int idx;
- + struct cpufreq_frequency_table *ag101_freqs_table;
- + struct ag101_freq_struct *ag101_freq_settings;
- + struct cpufreq_freqs freqs;
- +
- + /* Get the current policy */
- + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
- +
- + ag101_freq_settings = ag101_run_freqs;
- + ag101_freqs_table = ag101_run_freq_table;
- + } else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) {
- +
- + ag101_freq_settings = ag101_turbo_freqs;
- + ag101_freqs_table = ag101_turbo_freq_table;
- + } else {
- + printk
- + ("Unknown FCS policy found. Using CPUFREQ_POLICY_PERFORMANCE\n");
- + ag101_freq_settings = ag101_run_freqs;
- + ag101_freqs_table = ag101_run_freq_table;
- + }
- +
- + /* Lookup the next frequency */
- + if (cpufreq_frequency_table_target
- + (policy, ag101_freqs_table, target_freq, relation, &idx))
- + return -EINVAL;
- +
- + freqs.old = policy->cur;
- + freqs.new = ag101_freq_settings[idx].khz;
- + freqs.cpu = policy->cpu;
- +
- + /*
- + * Tell everyone what we're about to do...
- + * you should add a notify client with any platform specific
- + * Vcc changing capability
- + */
- + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- +
- + if (freqs.new != freqs.old) {
- + if (!ag101_speedstep(idx))
- + return -ENODEV;
- + }
- +
- + /*
- + * Tell everyone what we've just done...
- + * you should add a notify client with any platform specific
- + * SDRAM refresh timer adjustments
- + */
- + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
- +
- + return 0;
- +}
- +
- +static int ag101_cpufreq_init(struct cpufreq_policy *policy)
- +{
- +
- + int i;
- + /* set default policy and cpuinfo */
- + policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
- + policy->policy = CPUFREQ_POLICY_PERFORMANCE;
- + policy->cpuinfo.max_freq = AG101_MAX_FREQ;
- + policy->cpuinfo.min_freq = AG101_MIN_FREQ;
- + policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
- + policy->cur = ag101_cpufreq_get(0); /* current freq */
- + policy->min = policy->max = policy->cur;
- +
- + /* Generate the run cpufreq_frequency_table struct */
- + for (i = 0; i < NUM_RUN_FREQS; i++) {
- +
- + ag101_run_freq_table[i].frequency = ag101_run_freqs[i].khz;
- + ag101_run_freq_table[i].index = i;
- + }
- +
- + ag101_run_freq_table[i].frequency = CPUFREQ_TABLE_END;
- +
- + /* Generate the turbo cpufreq_frequency_table struct */
- + for (i = 0; i < NUM_TURBO_FREQS; i++) {
- +
- + ag101_turbo_freq_table[i].frequency = ag101_turbo_freqs[i].khz;
- + ag101_turbo_freq_table[i].index = i;
- + }
- +
- + ag101_turbo_freq_table[i].frequency = CPUFREQ_TABLE_END;
- +
- + printk("CPU frequency change support initialized\n");
- +
- + return 0;
- +}
- +
- +static struct cpufreq_driver ag101_cpufreq_driver = {
- +
- + .verify = ag101_verify_policy,
- + .target = ag101_set_target,
- + .init = ag101_cpufreq_init,
- + .get = ag101_cpufreq_get,
- + .name = "AG101",
- +};
- +
- +static int __init ag101_cpu_init(void)
- +{
- +
- + if (CPU_IS_N1213_43U1HA0() || CPU_IS_N1213_43U1HB0()) {
- +
- + /* Clear IntFS, IntFCS and irq8 */
- + REG32(PMU_FTPMU010_VA_BASE + 0x20) = (1UL << 16);
- + return cpufreq_register_driver(&ag101_cpufreq_driver);
- + } else
- + return -ENODEV;
- +}
- +
- +static void __exit ag101_cpu_exit(void)
- +{
- +
- + if (CPU_IS_N1213_43U1HA0() || CPU_IS_N1213_43U1HB0())
- + cpufreq_unregister_driver(&ag101_cpufreq_driver);
- +}
- +
- +MODULE_AUTHOR("Andes Technology Corporation");
- +MODULE_DESCRIPTION("CPU frequency changing driver for the AG101 architecture");
- +MODULE_LICENSE("GPL");
- +module_init(ag101_cpu_init);
- +module_exit(ag101_cpu_exit);
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101/devices.c linux-3.4.110/arch/nds32/platforms/ag101/devices.c
- --- linux-3.4.110.orig/arch/nds32/platforms/ag101/devices.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag101/devices.c 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,94 @@
- +#include <linux/serial_8250.h>
- +#include <asm/mach-types.h>
- +#include <asm/sizes.h>
- +#include <asm/mach/arch.h>
- +#include <asm/mach/map.h>
- +#include <asm/spec.h>
- +#include <asm/intc.h>
- +#include <asm/timer.h>
- +
- +const struct map_desc platform_io_desc[] __initdata = {
- + {UART0_VA_BASE, UART0_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {UART1_VA_BASE, UART1_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {INTC_FTINTC010_0_VA_BASE, INTC_FTINTC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {TIMER_FTTMR010_0_VA_BASE, TIMER_FTTMR010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {SSP_FTSSP010_0_VA_BASE, SSP_FTSSP010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {PMU_FTPMU010_0_VA_BASE, PMU_FTPMU010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {MAC_FTMAC100_0_VA_BASE, MAC_FTMAC100_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {SDC_FTSDC010_0_VA_BASE, SDC_FTSDC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {RTC_FTRTC010_0_VA_BASE, RTC_FTRTC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {WDT_FTWDT010_0_VA_BASE, WDT_FTWDT010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {GPIO_FTGPIO010_0_VA_BASE, GPIO_FTGPIO010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {CFC_FTCFC010_0_VA_BASE, CFC_FTCFC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {LCD_FTLCDC100_0_VA_BASE, LCD_FTLCDC100_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {I2C_FTI2C010_0_VA_BASE, I2C_FTI2C010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {DMAC_FTDMAC020_0_VA_BASE, DMAC_FTDMAC020_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {APBBRG_FTAPBBRG020S_0_VA_BASE, APBBRG_FTAPBBRG020S_0_PA_BASE,
- + PAGE_SIZE, MT_DEVICE_NCB},
- + {KMI_FTKBC010_0_VA_BASE, KMI_FTKBC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCNB},
- + {KMI_FTKBC010_1_VA_BASE, KMI_FTKBC010_1_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCNB},
- + {USB_FUSB220_0_VA_BASE, USB_FUSB220_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCNB},
- + {PCIIO_0_VA_BASE, PCIIO_0_PA_BASE, 0x000FF000, MT_DEVICE_NCB},
- + {PCIC_FTPCI100_0_VA_BASE, PCIC_FTPCI100_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {LED_VA_BASE, LED_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {SDMC_FTSDMC021_VA_BASE, SDMC_FTSDMC021_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {L2CC_VA_BASE, L2CC_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB}
- +};
- +
- +static void __init platform_map_io(void)
- +{
- + iotable_init((struct map_desc *)platform_io_desc,
- + ARRAY_SIZE(platform_io_desc));
- +}
- +
- +static struct uart_port uart0 = {
- + .membase = (void __iomem *)UART0_VA_BASE,
- + .irq = UART0_IRQ,
- + .uartclk = CONFIG_UART_CLK,
- + .regshift = 2,
- + .iotype = UPIO_MEM,
- + .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
- + .line = 0,
- + .mapbase = UART0_PA_BASE,
- +};
- +
- +static struct uart_port uart1 = {
- + .membase = (void __iomem *)UART1_VA_BASE,
- + .irq = UART1_IRQ,
- + .uartclk = CONFIG_UART_CLK,
- + .regshift = 2,
- + .iotype = UPIO_MEM,
- + .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
- + .line = 1,
- + .mapbase = UART1_PA_BASE,
- +};
- +
- +void ag101_calc_ahb_clk(void);
- +static void __init soc_init(void)
- +{
- + ag101_calc_ahb_clk();
- + early_serial_setup(&uart0);
- + early_serial_setup(&uart1);
- +}
- +
- +MACHINE_START(FARADAY, PLATFORM_NAME)
- + .param_offset = BOOT_PARAMETER_PA_BASE,.map_io = platform_map_io,.init_irq = platform_init_irq,.timer = &platform_timer, /* defined in timer.c */
- + .init_machine = soc_init, MACHINE_END
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101/fia320.c linux-3.4.110/arch/nds32/platforms/ag101/fia320.c
- --- linux-3.4.110.orig/arch/nds32/platforms/ag101/fia320.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag101/fia320.c 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,103 @@
- +/*
- + * linux/arch/nds32/platforms/ag101/fia320.c
- + *
- + * Faraday A320D Platform Dependent Functions
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + * ChangeLog
- + *
- + * Luke Lee 09/26/2005 Created
- + * Peter Liao 09/29/2005 Port dynamically getting AHB clock
- + */
- +
- +#include <linux/module.h>
- +#include <linux/init.h>
- +#include <linux/pm.h>
- +#include <linux/sched.h>
- +#include <linux/irq.h>
- +
- +#include <asm/hardware.h>
- +#include <asm/spec.h>
- +
- +#ifdef CONFIG_AUTO_SYS_CLK
- +#include <nds32_intrinsic.h>
- +#define AG101B0 (0x0c020003)
- +
- +/*
- + * Table for ahb divisor, PMODE[07:04]
- + */
- +static const int ahb_div[16] = {
- + 1, 2, 3, 4, 5, 6, 3, 5,
- + 8, 10, 12, 14, 15, 18, 20, -1
- +};
- +
- +/* ag101_get_ahb_clk()
- + *
- + * return AHB clock in Hz.
- + */
- +static int ahbclk;
- +void ag101_calc_ahb_clk(void)
- +{
- + /*
- + * FIXME: We should not put AG101 term in here, Harry@Oct.23.2007
- + */
- + const unsigned int osc = 10; // OSC in MHz
- + unsigned int mul, div, cpu, pll;
- + unsigned int ahb = 0; // ahb clk in Hz
- + unsigned int cpu_ver;
- +
- + mul = (REG32(PMU_FTPMU010_0_VA_BASE + 0x30) >> 3) & 0x01ff; // pll1 mul
- + div = (REG32(PMU_FTPMU010_0_VA_BASE + 0x4) >> 8) & 0x000f; // pll1 div
- + ahb = (REG32(PMU_FTPMU010_0_VA_BASE + 0x4) >> 4) & 0x000f; // ahb div
- + div += 1;
- +
- + pll = (osc * mul / div); // depend on OSC.
- +
- + //AG101B0 PLL divider fix
- + cpu_ver = __nds32__mfsr(NDS32_SR_CPU_VER);
- + if (AG101B0 == cpu_ver)
- + pll >>= 1;
- +
- + if (-1 != ahb_div[ahb]) {
- + if ((ahb == 6) || (ahb == 7)) // special cases for 3:2 & 5:2
- + cpu = pll >> 1; // divide by 2
- + else
- + cpu = pll;
- +
- + ahb = pll / ahb_div[ahb]; // become ahb clk in MHz.
- +
- + printk("AG101 auto-detected AHB clock: CPU/AHB=%uMHz/%uMHz\n",
- + cpu, ahb);
- + ahb *= 1000000; // become ahb clk in Hz.
- + ahbclk = (int)ahb;
- + } else {
- + printk("Unknown AHB divisor:0x%x\n", ahb);
- + ahbclk = 0;
- + }
- +
- + ahbclk = (int)ahb;
- +}
- +
- +int ag101_get_ahb_clk(void)
- +{
- + return ahbclk;
- +}
- +
- +EXPORT_SYMBOL(ag101_get_ahb_clk);
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101/freq-scaling.c linux-3.4.110/arch/nds32/platforms/ag101/freq-scaling.c
- --- linux-3.4.110.orig/arch/nds32/platforms/ag101/freq-scaling.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag101/freq-scaling.c 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,367 @@
- +/*
- + * linux/arch/nds32/platforms/ag101/cpu-fcs.c
- + *
- + * Copyright (C) 2002,2003 Intrinsyc Software
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + * History:
- + * 31-Jul-2002 : Initial version [FB]
- + * 29-Jan-2003 : added PXA255 support [FB]
- + * 20-Apr-2003 : ported to v2.5 (Dustin McIntire, Sensoria Corp.)
- + * 18-Jun-2008 : ported to NDS32 architecture ( Roy Lee, Andestech Corp.)
- + *
- + * Note:
- + * This driver may change the memory bus clock rate, but will not do any
- + * platform specific access timing changes... for example if you have flash
- + * memory connected to CS0, you will need to register a platform specific
- + * notifier which will adjust the memory access strobes to maintain a
- + * minimum strobe width.
- + *
- + */
- +#include <linux/module.h>
- +#include <linux/cpufreq.h>
- +#include <linux/interrupt.h>
- +
- +#include <asm/hardware.h>
- +#include <asm/localmem.h>
- +#include <asm/system.h>
- +#include <asm/nds32.h>
- +#include <asm/irq_regs.h>
- +
- +#define NDS32_FCS_IRQ 8
- +#define AG101_MIN_FREQ 70000
- +#define AG101_MAX_FREQ 420000
- +#define OSC_KHZ 10000 /* 10 MHz AG101 */
- +
- +#define USE_CACHE 0
- +struct ag101_freq_struct {
- +
- + unsigned int khz; /* cpu_clk in khz */
- + unsigned int sf; /* scaling factor */
- + unsigned int cr; /* clock ratio */
- +};
- +
- +struct ag101_freq_struct ag101_run_freqs[] = {
- +
- + /* khz , sf, cr pll/cpu/ahb/apb */
- + {AG101_MAX_FREQ / 6, 6, 1}, /* 420/070/070/035 */
- + {AG101_MAX_FREQ / 1, 1, 6}, /* 420/420/070/035 */
- + {0}
- +};
- +
- +#define NUM_RUN_FREQS ARRAY_SIZE( ag101_run_freqs)
- +static struct cpufreq_frequency_table ag101_run_freq_table[NUM_RUN_FREQS + 1];
- +
- +/* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */
- +static struct ag101_freq_struct ag101_turbo_freqs[] = {
- +
- + /* khz , sf, cr pll/cpu/ahb/apb */
- + {AG101_MAX_FREQ / 6, 6, 1}, /* 420/070/070/035 */
- + {AG101_MAX_FREQ / 1, 1, 6}, /* 420/420/070/035 */
- + {0}
- +};
- +
- +#define NUM_TURBO_FREQS ARRAY_SIZE( ag101_turbo_freqs)
- +static struct cpufreq_frequency_table ag101_turbo_freq_table[NUM_TURBO_FREQS +
- + 1];
- +
- +/* Generic helper function get CPU clocks in kHz */
- +unsigned int ag101_cpufreq_get(unsigned int dummy)
- +{
- +
- + unsigned int pll = (REG32(PMU_FTPMU010_VA_BASE + 0x30) >> 3UL) & 0x01ff; /* pll */
- + unsigned int sf = (REG32(PMU_FTPMU010_VA_BASE + 0x0c) >> 8UL) & 0x0f; /* scaling factor */
- +
- + return OSC_KHZ * pll / (sf + 1);
- +}
- +
- +/* find a valid frequency point */
- +static int ag101_verify_policy(struct cpufreq_policy *policy)
- +{
- +
- + struct cpufreq_frequency_table *ag101_freqs_table;
- +
- + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
- +
- + ag101_freqs_table = ag101_run_freq_table;
- + } else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) {
- +
- + ag101_freqs_table = ag101_turbo_freq_table;
- + } else {
- + printk
- + ("CPU PXA: Unknown policy found. Using CPUFREQ_POLICY_PERFORMANCE\n");
- + ag101_freqs_table = ag101_run_freq_table;
- + }
- +
- + printk("Verified CPU policy: %dKhz min to %dKhz max\n", policy->min,
- + policy->max);
- +
- + return cpufreq_frequency_table_verify(policy, ag101_freqs_table);
- +}
- +
- +void start_fcs(unsigned int sf, unsigned cr)
- +{
- +
- + /* set EFSF in PMODE [11:8] */
- + REG32(PMU_FTPMU010_VA_BASE + 0x0c) &= ~(0xfUL << 8);
- + REG32(PMU_FTPMU010_VA_BASE + 0x0c) |= (sf << 8);
- +
- + /* set EDIVAHBCLK [7:4] */
- + REG32(PMU_FTPMU010_VA_BASE + 0x0c) &= ~(0xffUL << 0);
- + REG32(PMU_FTPMU010_VA_BASE + 0x0c) |= (cr << 4);
- +
- + /* PMR[1]: scaling mode */
- + REG32(PMU_FTPMU010_VA_BASE + 0x0c) |= (1UL << 1);
- +
- + __asm__ __volatile__("msync all");
- + __asm__ __volatile__("isb");
- + __asm__ __volatile__("standby wake_grant");
- + // REG32( PMU_FTPMU010_VA_BASE + 0x30) |= ( 1UL << 16); /* PDLLCR0 bit[16]==1:disable dll */
- + REG32(PMU_FTPMU010_VA_BASE + 0x0c) &= ~(1UL << 1); /* Power Mode Register */
- +}
- +
- +void end_fcs(void)
- +{
- +
- + /* Leave this function as a place marker. */
- +}
- +
- +static int cal_edivahbclk(int div)
- +{
- +
- + switch (div) {
- +
- + case 1:
- + case 2:
- + case 3:
- + case 4:
- + case 5:
- + case 6:
- + return --div;
- + case 8:
- + return 8;
- + case 10:
- + return 9;
- + case 12:
- + return 10;
- + case 14:
- + return 11;
- + case 15:
- + return 12;
- + case 18:
- + return 13;
- + case 20:
- + return 14;
- + default:
- + printk("Error: No such CPU/AHB frequency ratio %d", div);
- + }
- +
- + return 9;
- +}
- +
- +static int ag101_speedstep(int idx)
- +{
- +
- + unsigned int sf, cr;
- + unsigned long flags = 0;
- + void (*do_fcs) (unsigned int efsf, unsigned int edivhbaclk);
- +
- +#if USE_CACHE
- +
- + int i;
- + int line_size = CACHE_LINE_SIZE(ICACHE);
- + unsigned long start = ((unsigned long)start_fcs) & ~(line_size - 1);
- + unsigned long end =
- + (((unsigned long)end_fcs) + line_size) & ~(line_size - 1);
- +
- + printk("&start_fcs(): 0x%08lx, aligned to: 0x%08lx\n",
- + (unsigned long)start_fcs, start);
- + printk("&end_fcs(): 0x%08lx, aligned to: 0x%08lx\n",
- + (unsigned long)end_fcs, end);
- +
- + for (i = start; i <= end; i += CACHE_LINE_SIZE(ICACHE))
- + __asm__ volatile ("\n\tcctl %0, L1I_VA_FILLCK"::
- + "r" (i):"memory");
- +
- + do_fcs = start_fcs;
- +#else
- + unsigned long buf, aligned_buf, len = PAGE_SIZE;
- +
- + buf = (unsigned long)kmalloc(0x100000 + 1000, GFP_KERNEL);
- + if (!buf)
- + printk("Error: kmalloc( base) failed\n");
- +
- + aligned_buf = (buf + 0x100000 - 1) & 0xFFF00000;
- +
- + if (sys_lmmap(LM_ILM, aligned_buf, aligned_buf + 0x1000, 0, NULL)) {
- + printk("Error: lmmap failed, can't scale frequency.\n");
- +#ifdef CONFIG_CPU_FREQ_DEBUG
- + WARN_ON(1);
- +#endif
- + return 0;
- + }
- +
- + if (((GET_ILMB() & ILMB_mskILMSZ) >> ILMB_offILMSZ) == 9)
- + len = 0x400;
- + else if (((GET_ILMB() & ILMB_mskILMSZ) >> ILMB_offILMSZ) == 10)
- + len = 0x800;
- + memcpy((unsigned char *)aligned_buf, (unsigned char *)start_fcs, len);
- +
- + do_fcs = (void *)aligned_buf;
- +#endif
- + sf = ag101_run_freqs[idx].sf - 1;
- + cr = cal_edivahbclk(ag101_run_freqs[idx].cr);
- +
- + local_irq_save(flags);
- + do_fcs(sf, cr);
- + local_irq_restore(flags);
- +
- +#if USE_CACHE
- + for (i = start; i <= end; i += CACHE_LINE_SIZE(ICACHE))
- + __asm__ volatile ("\n\tcctl %0, L1I_VA_ULCK"::"r" (i):"memory");
- +#else
- + if (sys_lmunmap(aligned_buf, 0))
- + printk("Error: lmunmap failed\n");
- +
- + kfree((void *)buf);
- +#endif
- + return 1;
- +}
- +
- +static int ag101_set_target(struct cpufreq_policy *policy,
- + unsigned int target_freq, unsigned int relation)
- +{
- +
- + unsigned int idx;
- + struct cpufreq_frequency_table *ag101_freqs_table;
- + struct ag101_freq_struct *ag101_freq_settings;
- + struct cpufreq_freqs freqs;
- +
- + /* Get the current policy */
- + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
- +
- + ag101_freq_settings = ag101_run_freqs;
- + ag101_freqs_table = ag101_run_freq_table;
- + } else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) {
- +
- + ag101_freq_settings = ag101_turbo_freqs;
- + ag101_freqs_table = ag101_turbo_freq_table;
- + } else {
- + printk
- + ("Unknown FCS policy found. Using CPUFREQ_POLICY_PERFORMANCE\n");
- + ag101_freq_settings = ag101_run_freqs;
- + ag101_freqs_table = ag101_run_freq_table;
- + }
- +
- + /* Lookup the next frequency */
- + if (cpufreq_frequency_table_target
- + (policy, ag101_freqs_table, target_freq, relation, &idx))
- + return -EINVAL;
- +
- + freqs.old = policy->cur;
- + freqs.new = ag101_freq_settings[idx].khz;
- + freqs.cpu = policy->cpu;
- +
- + /*
- + * Tell everyone what we're about to do...
- + * you should add a notify client with any platform specific
- + * Vcc changing capability
- + */
- + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- +
- + if (freqs.new != freqs.old) {
- +
- + if (!ag101_speedstep(idx))
- + return -ENODEV;
- + }
- +
- + /*
- + * Tell everyone what we've just done...
- + * you should add a notify client with any platform specific
- + * SDRAM refresh timer adjustments
- + */
- + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
- +
- + return 0;
- +}
- +
- +static int ag101_cpufreq_init(struct cpufreq_policy *policy)
- +{
- +
- + int i;
- + /* set default policy and cpuinfo */
- + policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
- + policy->policy = CPUFREQ_POLICY_PERFORMANCE;
- + policy->cpuinfo.max_freq = AG101_MAX_FREQ;
- + policy->cpuinfo.min_freq = AG101_MIN_FREQ;
- + policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
- + policy->cur = ag101_cpufreq_get(0); /* current freq */
- + policy->min = policy->max = policy->cur;
- +
- + /* Generate the run cpufreq_frequency_table struct */
- + for (i = 0; i < NUM_RUN_FREQS; i++) {
- +
- + ag101_run_freq_table[i].frequency = ag101_run_freqs[i].khz;
- + ag101_run_freq_table[i].index = i;
- + }
- +
- + ag101_run_freq_table[i].frequency = CPUFREQ_TABLE_END;
- +
- + /* Generate the turbo cpufreq_frequency_table struct */
- + for (i = 0; i < NUM_TURBO_FREQS; i++) {
- +
- + ag101_turbo_freq_table[i].frequency = ag101_turbo_freqs[i].khz;
- + ag101_turbo_freq_table[i].index = i;
- + }
- +
- + ag101_turbo_freq_table[i].frequency = CPUFREQ_TABLE_END;
- +
- + printk("CPU frequency change support initialized\n");
- +
- + return 0;
- +}
- +
- +static struct cpufreq_driver ag101_cpufreq_driver = {
- +
- + .verify = ag101_verify_policy,
- + .target = ag101_set_target,
- + .init = ag101_cpufreq_init,
- + .get = ag101_cpufreq_get,
- + .name = "AG101",
- +};
- +
- +static int __init ag101_cpu_init(void)
- +{
- +
- + if (CPU_IS_N1213_43U1HA0() || CPU_IS_N1213_43U1HB0())
- + return cpufreq_register_driver(&ag101_cpufreq_driver);
- + else
- + return -ENODEV;
- +}
- +
- +static void __exit ag101_cpu_exit(void)
- +{
- +
- + if (CPU_IS_N1213_43U1HA0() || CPU_IS_N1213_43U1HB0())
- + cpufreq_unregister_driver(&ag101_cpufreq_driver);
- +}
- +
- +MODULE_AUTHOR("Andes Technology Corporation");
- +MODULE_DESCRIPTION("CPU frequency changing driver for the AG101 architecture");
- +MODULE_LICENSE("GPL");
- +module_init(ag101_cpu_init);
- +module_exit(ag101_cpu_exit);
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101/Kconfig linux-3.4.110/arch/nds32/platforms/ag101/Kconfig
- --- linux-3.4.110.orig/arch/nds32/platforms/ag101/Kconfig 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag101/Kconfig 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,9 @@
- +menu "AG101 Platform Options"
- +
- +config AUTO_SYS_CLK
- + bool "Automatic AHB Clock Detection"
- + default y
- + help
- + Automatic detection of AHB clock
- +
- +endmenu
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101/Makefile linux-3.4.110/arch/nds32/platforms/ag101/Makefile
- --- linux-3.4.110.orig/arch/nds32/platforms/ag101/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag101/Makefile 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,5 @@
- +obj-y = devices.o
- +obj-$(CONFIG_AUTO_SYS_CLK) += fia320.o
- +obj-$(CONFIG_PM) += pm.o sleep.o
- +obj-$(CONFIG_AG101_CPU_FREQ_FCS) += cpu-fcs.o
- +obj-$(CONFIG_AG101_CPU_FREQ_SCALING_MODE) += freq-scaling.o
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101/pm.c linux-3.4.110/arch/nds32/platforms/ag101/pm.c
- --- linux-3.4.110.orig/arch/nds32/platforms/ag101/pm.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag101/pm.c 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,190 @@
- +/*
- + * AG101 Power Management Routines
- + *
- + * Copyright (c) 2007 Harry Pan <harry@andestech.com>
- + *
- + * This program is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU General Public License.
- + *
- + * Abstract:
- + *
- + * This program is for AG101 power management routines.
- + * It is initail referred from 2.6.11 SA1100 PM driver.
- + *
- + * Revision History:
- + *
- + * Jul.13.2007 Initial code by Harry.
- + */
- +#include <linux/init.h>
- +#include <linux/suspend.h>
- +#include <linux/errno.h>
- +#include <linux/time.h>
- +#include <linux/delay.h>
- +
- +#include <asm/hardware.h>
- +#include <asm/memory.h>
- +#include <asm/system.h>
- +#include <asm/mach/time.h>
- +#include <asm/cacheflush.h>
- +
- +extern void ag101_cpu_sleep(void);
- +extern void ag101_cpu_resume(void);
- +extern void ag101_cpu_resume2(void);
- +
- +#include <asm/timer.h>
- +/*
- + * AG101 PMU sleep mode handler.
- + */
- +void ag101_pmu_sleep(void)
- +{
- + int i;
- + static int irq_saves[3];
- +
- + irq_saves[0] = REG32(INTC_FTINTC010_VA_BASE + 0x4);
- + irq_saves[1] = REG32(INTC_FTINTC010_VA_BASE + 0xc);
- + irq_saves[2] = REG32(INTC_FTINTC010_VA_BASE + 0x10);
- +
- + /* save SDRAM settings */
- + for (i = 0; i < 0x30; i += 4)
- + REG32(PMU_FTPMU010_VA_BASE + 0x50 + i) = REG32(SDMC_FTSDMC021_VA_BASE + i); //SDRAMC
- +
- + /* set resume return address */
- + REG32(PMU_FTPMU010_VA_BASE + 0x88) =
- + virt_to_phys(ag101_cpu_resume) | 0x10000000;
- + REG32(PMU_FTPMU010_VA_BASE + 0x8c) = (u32) ag101_cpu_resume2;
- + REG32(PMU_FTPMU010_VA_BASE + 0x80) = GET_L1_PPTB();
- +
- + /* setup wakeup sources */
- + REG32(PMU_FTPMU010_VA_BASE + 0x14) |= -1;
- + REG32(PMU_FTPMU010_VA_BASE + 0x10) |= 0x1fff;
- +
- + cpu_dcache_wbinval_all();
- + cpu_icache_inval_all();
- + SET_CACHE_CTL(GET_CACHE_CTL() & ~CACHE_CTL_mskDC_EN);
- + ag101_cpu_sleep();
- +
- +#ifndef CONFIG_ANDES_PAGE_SIZE_8KB
- +
- + if (CPU_IS_N1213_43U1HA0()) {
- + int tmp = 0;
- + /* Downsize cache to bypass cache aliasing issue */
- +
- + if ((CACHE_SET(ICACHE) * CACHE_LINE_SIZE(ICACHE)) > 4096)
- + tmp = 0x02 << SDZ_CTL_offICDZ;
- +
- + if ((CACHE_SET(DCACHE) * CACHE_LINE_SIZE(DCACHE)) > 4096)
- + tmp |= 0x02 << SDZ_CTL_offDCDZ;
- +
- + SET_SDZ_CTL(tmp);
- + ISB();
- + }
- +#endif
- +
- + SET_CACHE_CTL(GET_CACHE_CTL() | CACHE_CTL_mskDC_EN);
- + REG32(INTC_FTINTC010_VA_BASE + 0x4) = irq_saves[0];
- + REG32(INTC_FTINTC010_VA_BASE + 0xc) = irq_saves[1];
- + REG32(INTC_FTINTC010_VA_BASE + 0x10) = irq_saves[2];
- +}
- +
- +static int ag101_pm_valid(suspend_state_t state)
- +{
- + switch (state) {
- + case PM_SUSPEND_ON:
- + case PM_SUSPEND_STANDBY:
- + case PM_SUSPEND_MEM:
- + return 1;
- +
- + default:
- + return 0;
- + }
- +}
- +
- +static int ag101_pm_begin(suspend_state_t state)
- +{
- + /* TBD if we need it */
- + return 0;
- +}
- +
- +static unsigned long irq_save;
- +static inline void setup_wakeup_event(void)
- +{
- + REG32(GPIO_FTGPIO010_VA_BASE + 0x20) = 1;
- + irq_save = REG32(INTC_FTINTC010_VA_BASE + 0x4);
- + REG32(INTC_FTINTC010_VA_BASE + 0x4) &= ~(1 << 19);
- + REG32(INTC_FTINTC010_VA_BASE + 0x4) |= 1 << 13;
- +}
- +
- +static inline void remove_wakeup_event(void)
- +{
- + REG32(GPIO_FTGPIO010_VA_BASE + 0x30) = 1;
- + REG32(GPIO_FTGPIO010_VA_BASE + 0x20) = 0;
- + REG32(INTC_FTINTC010_VA_BASE + 0x4) = irq_save;
- +}
- +
- +static inline void cpu_standby(void)
- +{
- + asm __volatile__("standby no_wake_grant");
- +}
- +
- +static int ag101_pm_enter(suspend_state_t state)
- +{
- + switch (state) {
- + case PM_SUSPEND_STANDBY:
- + setup_wakeup_event();
- + cpu_standby();
- + remove_wakeup_event();
- + return 0;
- + case PM_SUSPEND_MEM:
- + ag101_pmu_sleep();
- + return 0;
- + default:
- + return -EINVAL;
- + }
- +}
- +
- +/*
- + * Called after processes are frozen, but before we shutdown devices.
- + */
- +static int ag101_pm_prepare(void)
- +{
- + /* TBD if we need it */
- + return 0;
- +}
- +
- +/*
- + * Called after devices are wakeuped, but before processes are thawed.
- + */
- +static void ag101_pm_finish(void)
- +{
- + /* TBD if we need it */
- +}
- +
- +static void ag101_pm_end(void)
- +{
- + /* TBD if we need it */
- +}
- +
- +/*
- + * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
- + */
- +static struct platform_suspend_ops ag101_pm_ops = {
- + .valid = ag101_pm_valid,
- + .begin = ag101_pm_begin,
- + .prepare = ag101_pm_prepare,
- + .enter = ag101_pm_enter,
- + .finish = ag101_pm_finish,
- + .end = ag101_pm_end,
- +};
- +
- +static int __init ag101_pm_init(void)
- +{
- + printk("PM driver init\n");
- + suspend_set_ops(&ag101_pm_ops);
- + REG32(GPIO_FTGPIO010_VA_BASE + 0x30) = 1;
- + REG32(INTC_FTINTC010_VA_BASE + 0x0c) &= ~(1 << 13);
- + REG32(INTC_FTINTC010_VA_BASE + 0x10) &= ~(1 << 13);
- +
- + return 0;
- +}
- +
- +late_initcall(ag101_pm_init);
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101/sleep.S linux-3.4.110/arch/nds32/platforms/ag101/sleep.S
- --- linux-3.4.110.orig/arch/nds32/platforms/ag101/sleep.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag101/sleep.S 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,118 @@
- +/*
- + * AG101 Assembler Sleep/WakeUp Management Routines
- + *
- + * Copyright (c) 2007 Harry Pan <harry@andestech.com>
- + *
- + * This program is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU General Public License.
- + *
- + * Abstract:
- + *
- + * This program is for AG101 suspend/wakeup.
- + *
- + * Revision History:
- + *
- + * Jul.13.2007 Initial code by Harry.
- + */
- +#include <linux/linkage.h>
- +#include <asm/assembler.h>
- +#include <asm/hardware.h>
- +#include <asm/spec.h>
- +
- + .text
- +
- +/* ag101_cpu_suspend()
- + *
- + * Causes AG101 to enter sleep state
- + */
- +
- +ENTRY(ag101_cpu_sleep)
- + pushm $r0, $r30
- + mfusr $r0, $d0.lo ! $d0 lo byte
- + mfusr $r1, $d0.hi ! $d0 hi byte
- + mfusr $r2, $d1.lo ! $d1 lo byte
- + mfusr $r3, $d1.hi ! $d1 hi byte
- + mfsr $r4, $mr0
- + mfsr $r5, $mr1
- + mfsr $r6, $mr4
- + mfsr $r7, $mr6
- + mfsr $r8, $mr7
- + mfsr $r9, $mr8
- + mfsr $r10, $ir0
- + mfsr $r11, $ir1
- + mfsr $r12, $ir2
- + mfsr $r13, $ir3
- + mfsr $r14, $ir9
- + mfsr $r15, $ir10
- + mfsr $r16, $ir12
- + mfsr $r17, $ir13
- + mfsr $r18, $ir14
- + mfsr $r19, $ir15
- + pushm $r0, $r19
- +
- + sethi $r0, hi20(PMU_FTPMU010_0_VA_BASE + 0x84)
- + ori $r2, $r0, lo12(PMU_FTPMU010_0_VA_BASE + 0x84)
- + swi $r31, [$r2]
- +
- + lwi $r2, [$r0+#0x0c] ! sleep mode
- + ori $r2, $r2, #1
- + swi $r2, [$r0+#0x0c] ! sleep mode
- + standby wake_grant
- +1:
- + b 1b ! loop waiting for sleep
- +
- +/* ag101_cpu_resume()
- + *
- + * Entry point from boot code back to kernel.
- + *
- + */
- +
- +ENTRY(ag101_cpu_resume)
- + mfsr $r2, $mr0
- + ori $r2, $r2, #0x6
- +#ifdef CONFIG_ANDES_PAGE_SIZE_8KB
- + ori $r2, $r2, #0x1
- +#endif
- + mtsr $r2, $mr0
- +
- + sethi $r2, hi20(PMU_FTPMU010_0_PA_BASE + 0x80)
- + ori $r2, $r2, lo12(PMU_FTPMU010_0_PA_BASE + 0x80)
- + lwi $r3, [$r2]
- + lwi $r4, [$r2 + 0xc]
- + mtsr $r3, $mr1
- +
- + mfsr $r0, $mr8
- + ori $r0, $r0, #0x1
- + mtsr $r0, $mr8
- +
- + sethi $r2, hi20(AHB_ATFAHBC020S_0_PA_BASE + 0x88)
- + ori $r2, $r2, lo12(AHB_ATFAHBC020S_0_PA_BASE + 0x88)
- + movi $r3, #0x1
- + swi $r3, [$r2]
- +
- + jral.ton $r4, $r4
- +
- +ENTRY(ag101_cpu_resume2)
- + popm $r0, $r19
- + mtusr $r0, $d0.lo ! $d0 lo byte
- + mtusr $r1, $d0.hi ! $d0 hi byte
- + mtusr $r2, $d1.lo ! $d1 lo byte
- + mtusr $r3, $d1.hi ! $d1 hi byte
- + mtsr $r4, $mr0
- + mtsr $r5, $mr1
- + mtsr $r6, $mr4
- + mtsr $r7, $mr6
- + mtsr $r8, $mr7
- + mtsr $r9, $mr8
- + mtsr $r10, $ir0
- + mtsr $r11, $ir1
- + mtsr $r12, $ir2
- + mtsr $r13, $ir3
- + mtsr $r14, $ir9
- + mtsr $r15, $ir10
- + mtsr $r16, $ir12
- + mtsr $r17, $ir13
- + mtsr $r18, $ir14
- + mtsr $r19, $ir15
- + popm $r0, $r30
- + ret
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101p/devices.c linux-3.4.110/arch/nds32/platforms/ag101p/devices.c
- --- linux-3.4.110.orig/arch/nds32/platforms/ag101p/devices.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag101p/devices.c 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,104 @@
- +#include <linux/serial_8250.h>
- +#include <asm/mach-types.h>
- +#include <asm/sizes.h>
- +#include <asm/mach/arch.h>
- +#include <asm/mach/map.h>
- +#include <asm/spec.h>
- +#include <asm/timer.h>
- +
- +const struct map_desc platform_io_desc[] __initdata = {
- + {UART0_VA_BASE, UART0_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {UART1_VA_BASE, UART1_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {INTC_FTINTC010_0_VA_BASE, INTC_FTINTC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {TIMER_FTTMR010_0_VA_BASE, TIMER_FTTMR010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {SSP_FTSSP010_0_VA_BASE, SSP_FTSSP010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {PMU_FTPMU010_0_VA_BASE, PMU_FTPMU010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {MAC_FTMAC100_0_VA_BASE, MAC_FTMAC100_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {SDC_FTSDC010_0_VA_BASE, SDC_FTSDC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {RTC_FTRTC010_0_VA_BASE, RTC_FTRTC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {WDT_FTWDT010_0_VA_BASE, WDT_FTWDT010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {GPIO_FTGPIO010_0_VA_BASE, GPIO_FTGPIO010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {CFC_FTCFC010_0_VA_BASE, CFC_FTCFC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {LCD_FTLCDC100_0_VA_BASE, LCD_FTLCDC100_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {I2C_FTI2C010_0_VA_BASE, I2C_FTI2C010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {DMAC_FTDMAC020_0_VA_BASE, DMAC_FTDMAC020_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {APBBRG_FTAPBBRG020S_0_VA_BASE, APBBRG_FTAPBBRG020S_0_PA_BASE,
- + PAGE_SIZE, MT_DEVICE_NCB},
- + {USB_FOTG2XX_0_VA_BASE, USB_FOTG2XX_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {PCIIO_0_VA_BASE, PCIIO_0_PA_BASE, (0x000FF000 & PAGE_MASK),
- + MT_DEVICE_NCB},
- + {PCIC_FTPCI100_0_VA_BASE, PCIC_FTPCI100_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {AHB_ATFAHBC020S_0_VA_BASE, AHB_ATFAHBC020S_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {LED_VA_BASE, LED_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {SDMC_FTSDMC021_VA_BASE, SDMC_FTSDMC021_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {L2CC_VA_BASE, L2CC_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB}
- +};
- +
- +static void __init platform_map_io(void)
- +{
- + iotable_init((struct map_desc *)platform_io_desc,
- + ARRAY_SIZE(platform_io_desc));
- +}
- +
- +static struct uart_port uart0 = {
- + .membase = (void __iomem *)UART0_VA_BASE,
- + .irq = UART0_IRQ,
- + .uartclk = CONFIG_UART_CLK,
- + .regshift = 2,
- + .iotype = UPIO_MEM,
- + .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
- + .line = 0,
- + .mapbase = UART0_PA_BASE,
- +};
- +
- +static struct uart_port uart1 = {
- + .membase = (void __iomem *)UART1_VA_BASE,
- + .irq = UART1_IRQ,
- + .uartclk = CONFIG_UART_CLK,
- + .regshift = 2,
- + .iotype = UPIO_MEM,
- + .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
- + .line = 1,
- + .mapbase = UART1_PA_BASE,
- +};
- +
- +static void __init soc_init(void)
- +{
- + early_serial_setup(&uart0);
- + early_serial_setup(&uart1);
- +}
- +
- +MACHINE_START(FARADAY, PLATFORM_NAME)
- + .param_offset = BOOT_PARAMETER_PA_BASE,
- + .map_io = platform_map_io,
- + .init_irq = platform_init_irq,
- + .timer = &platform_timer, /* defined in timer.c */
- + .init_machine = soc_init,
- +MACHINE_END static struct platform_device usb_dev_otg_host = {
- + .name = "fotg-ehci",
- +};
- +
- +static int __init fotg_init(void)
- +{
- + platform_device_register(&usb_dev_otg_host);
- + return 0;
- +}
- +
- +device_initcall(fotg_init);
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101p/interrupt-latency.c linux-3.4.110/arch/nds32/platforms/ag101p/interrupt-latency.c
- --- linux-3.4.110.orig/arch/nds32/platforms/ag101p/interrupt-latency.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag101p/interrupt-latency.c 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,197 @@
- +/*
- + * interrupt_latency v1.0 11/25/01
- + * www.embeddedlinuxinterfacing.com
- + *
- + * The original location of this code is
- + * http://www.embeddedlinuxinterfacing.com/chapters/11/
- + *
- + * Copyright (C) 2001 by Craig Hollabaugh
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU Library General Public License as
- + * published by the Free Software Foundation; either version 2 of the
- + * License, or (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful, but
- + * WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- + * Library General Public License for more details.
- + *
- + * You should have received a copy of the GNU Library General Public
- + * License along with this program; if not, write to the
- + * Free Software Foundation, Inc.,
- + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + */
- +
- +/*
- + * interrupt_latency.c is based on procfs_example.c by Erik Mouw.
- + * For more information, please see, The Linux Kernel Procfs Guide, Erik Mouw
- + * http://kernelnewbies.org/documents/kdoc/procfs-guide/lkprocfsguide.html
- + */
- +
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/init.h>
- +#include <linux/proc_fs.h>
- +#include <linux/irq.h>
- +#include <linux/interrupt.h>
- +#include <nds32_intrinsic.h>
- +
- +#define ILT_MODULE_VERSION "1.0"
- +#define MODULE_NAME "interrupt_latency"
- +
- +#define USE_PFM
- +static int interruptcount = 0;
- +#ifdef USE_PFM
- +static unsigned int start_cycle = 0, finish_cycle = 0;
- +static unsigned int start_inst = 0, finish_inst = 0;
- +static unsigned int start_int = 0, finish_int = 0;
- +#else
- +static struct timeval tv1, tv2; /* do_gettimeofday fills these */
- +#endif
- +
- +#define INTERRUPT 9
- +
- +static struct proc_dir_entry *interrupt_latency_file;
- +
- +/*
- + * function interrupt_interrupt_latency
- + * This function is the interrupt handler for interrupt 7. It sets the tv2
- + * structure using do_gettimeofday. It then deasserts D7.
- + */
- +static irqreturn_t interrupt_interrupt_latency(int irq, void *dev_id)
- +{
- + unsigned int ir15, pfm_ctl;
- +#ifdef USE_PFM
- + /* disable counter */
- + pfm_ctl = 0x4410000; //cycles, instructions and icache misses
- + //pfm_ctl = 0x4c0000; //instructions and interrupts
- + //pfm_ctl = 0x4510000; //icache accesses and misses
- + __nds32__mtsr(pfm_ctl, NDS32_SR_PFM_CTL); //instructions and interrupts
- + finish_cycle = __nds32__mfsr(NDS32_SR_PFMC0);
- + finish_inst = __nds32__mfsr(NDS32_SR_PFMC2);
- + finish_int = __nds32__mfsr(NDS32_SR_PFMC1);
- +#else
- + do_gettimeofday(&tv2);
- +#endif
- + /* deassert the interrupt signal */
- + ir15 = __nds32__mfsr(NDS32_SR_INT_PEND);
- + __nds32__mtsr((~0x10000) & ir15, NDS32_SR_INT_PEND);
- + __nds32__dsb();
- +
- + interruptcount++;
- + return IRQ_HANDLED;
- +}
- +
- +/*
- + * function proc_read_interrupt_latency
- + * The kernel executes this function when a read operation occurs on
- + * /proc/interrupt_latency. This function sets the tv1 structure. It asserts
- + * D7 which should immediately cause interrupt 7 to occur. The handler
- + * records tv2 and deasserts D7. This function returns the time differential
- + * between tv2 and tv1.
- + */
- +static int proc_read_interrupt_latency(char *page, char **start, off_t off,
- + int count, int *eof, void *data)
- +{
- + int len;
- + unsigned int ir15, pfm_ctl;
- +#ifdef USE_PFM
- + //pfm_ctl = 0x4c0007;
- + //pfm_ctl = 0x4510007;
- + pfm_ctl = 0x4410007;
- + start_cycle = __nds32__mfsr(NDS32_SR_PFMC0);
- + start_inst = __nds32__mfsr(NDS32_SR_PFMC2);
- + start_int = __nds32__mfsr(NDS32_SR_PFMC1);
- + __nds32__mtsr(pfm_ctl, NDS32_SR_PFM_CTL);
- +#else
- + do_gettimeofday(&tv1);
- +#endif
- + /* assert the interrupt signal */
- + ir15 = __nds32__mfsr(NDS32_SR_INT_PEND);
- + __nds32__mtsr(0x10000 | ir15, NDS32_SR_INT_PEND);
- + __nds32__dsb();
- +
- +#ifdef USE_PFM
- + len =
- + sprintf(page,
- + "Cnt0 %11u Start %11u Finish %11u Cycles %11u\n"
- + "Cnt2 %11u Start %11u Finish %11u icache miss %11u\n"
- + "Cnt1 %11u Start %11u Finish %11u Instructions %11u\n"
- + "Count %11i\n", ((pfm_ctl & 0x8000) >> 15), start_cycle,
- + finish_cycle, (finish_cycle - start_cycle),
- + ((pfm_ctl & 0xfc00000) >> 22), start_inst, finish_inst,
- + (finish_inst - start_inst), ((pfm_ctl & 0x3f0000) >> 16),
- + start_int, finish_int, (finish_int - start_int),
- + interruptcount);
- +#else
- + len = sprintf(page, "Start %9i.%06i\nFinish %9i.%06i\nLatency %17i\n\
- +Count %19i\n", (int)tv1.tv_sec, (int)tv1.tv_usec, (int)tv2.tv_sec, (int)tv2.tv_usec, (int)(tv2.tv_usec - tv1.tv_usec), interruptcount);
- +#endif
- + *eof = 1;
- + return len;
- +}
- +
- +/*
- + * function init_interrupt_latency
- + * This function creates the /proc directory entry interrupt_latency. It
- + * also configures the parallel port then requests interrupt 7 from Linux.
- + */
- +static int __init init_interrupt_latency(void)
- +{
- + int rv = 0;
- + unsigned int ir14;
- +
- + interrupt_latency_file =
- + create_proc_entry("interrupt_latency", 0444, NULL);
- + if (interrupt_latency_file == NULL) {
- + return -ENOMEM;
- + }
- +
- + interrupt_latency_file->data = NULL;
- + interrupt_latency_file->read_proc = &proc_read_interrupt_latency;
- + interrupt_latency_file->write_proc = NULL;
- +
- + /* request interrupt from linux */
- + rv = request_irq(INTERRUPT, interrupt_interrupt_latency, IRQF_DISABLED,
- + "interrupt_latency", (void *)NULL);
- + if (rv) {
- + printk("Can't get interrupt %d\n", INTERRUPT);
- + goto no_interrupt_latency;
- + }
- +
- + /* unmask SWI */
- + ir14 = __nds32__mfsr(NDS32_SR_INT_MASK);
- + __nds32__mtsr((0x10000 | ir14), NDS32_SR_INT_MASK);
- + __nds32__dsb();
- +
- + /* everything initialized */
- + printk(KERN_INFO "%s %s initialized\n", MODULE_NAME,
- + ILT_MODULE_VERSION);
- + return 0;
- +
- + /* remove the proc entry on error */
- +no_interrupt_latency:
- + remove_proc_entry("interrupt_latency", NULL);
- + return 0;
- +}
- +
- +/*
- + * function cleanup_interrupt_latency
- + * This function frees interrupt then removes the /proc directory entry
- + * interrupt_latency.
- + */
- +static void __exit cleanup_interrupt_latency(void)
- +{
- + /* free the interrupt */
- + free_irq(INTERRUPT, (void *)NULL);
- +
- + remove_proc_entry("interrupt_latency", NULL);
- +
- + printk(KERN_INFO "%s %s removed\n", MODULE_NAME, ILT_MODULE_VERSION);
- +}
- +
- +module_init(init_interrupt_latency);
- +module_exit(cleanup_interrupt_latency);
- +
- +MODULE_DESCRIPTION("interrupt_latency proc module");
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101p/Kconfig linux-3.4.110/arch/nds32/platforms/ag101p/Kconfig
- --- linux-3.4.110.orig/arch/nds32/platforms/ag101p/Kconfig 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag101p/Kconfig 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,11 @@
- +menu "AG101P Platform Options"
- +config CACHE_L2
- +bool "Support L2 cache"
- + default n
- +
- +config MEASURE_INTERRUPT_LATENCY
- + bool "Measure interrupt latency"
- + default n
- + help
- + Enable measuring interrupt latency with software interrupt
- +endmenu
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101p/Makefile linux-3.4.110/arch/nds32/platforms/ag101p/Makefile
- --- linux-3.4.110.orig/arch/nds32/platforms/ag101p/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag101p/Makefile 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,2 @@
- +obj-y = devices.o
- +obj-$(CONFIG_MEASURE_INTERRUPT_LATENCY) += interrupt-latency.o
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/ahbclkcal.c linux-3.4.110/arch/nds32/platforms/ag102/ahbclkcal.c
- --- linux-3.4.110.orig/arch/nds32/platforms/ag102/ahbclkcal.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag102/ahbclkcal.c 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,216 @@
- +#include <linux/module.h>
- +#include <linux/init.h>
- +#include <linux/pm.h>
- +#include <linux/sched.h>
- +#include <linux/irq.h>
- +
- +#include <asm/hardware.h>
- +#include <asm/spec.h>
- +#ifdef CONFIG_AUTO_SYS_CLK
- +
- +#define OSCH3_CLK 33000000
- +#define OSCH_CLK 25000000
- +#define MHZ 1000000
- +/*
- + * Table for ahb divisor, PMODE[07:04]
- + */
- +static const int ahb_div[16] = {
- + 1, 2, 3, 4, 5, 6, 3, 5,
- + 8, 10, 12, 14, 15, 18, 20, -1
- +};
- +
- +/* ag102_get_ahb_clk()
- + *
- + * return AHB clock in Hz.
- + */
- +static int ahbclk;
- +void ag102_calc_ahb_clk(void)
- +{
- + unsigned int pcs1_param;
- + unsigned int pcs4_param;
- + unsigned int pcs5_param;
- + unsigned int main_PLL_div;
- + unsigned int main_PLL_out;
- + unsigned int ratio;
- + unsigned int main_PLL_N;
- + unsigned int main_PLL_M = 1;
- + unsigned int F_core0;
- + unsigned int F_core1;
- + unsigned int F_l2cc;
- + unsigned int F_ddr2;
- + unsigned int F_ahb;
- + unsigned int F_apb;
- + unsigned int F_pci;
- +
- + pcs1_param = REG32(PCU_VA_BASE + 0xa4); //pcs1 parameter register, for core/ahb/apb clk ratio setting
- + main_PLL_div = (pcs1_param >> 4) & 0x3;
- + ratio = pcs1_param & 0xf;
- +
- + pcs4_param = REG32(PCU_VA_BASE + 0x104); //pcs4 parameter register, for main PLL setting
- + main_PLL_N = pcs4_param & 0xff;
- + main_PLL_out = (OSCH3_CLK * main_PLL_N / main_PLL_M) >> main_PLL_div;
- +
- + pcs5_param = REG32(PCU_VA_BASE + 0x124); //pcs5 parameter register, for PCI PLL/DLL setting
- +
- + switch (ratio) {
- + case 0:
- + F_core0 = main_PLL_out;
- + F_core1 = F_core0;
- + F_l2cc = F_core0 >> 1;
- + F_ddr2 = F_core0 >> 1;
- + F_ahb = F_core0 >> 2;
- + F_apb = F_ahb >> 1;
- + break;
- +
- + case 1:
- + F_core0 = main_PLL_out;
- + F_core1 = F_core0;
- + F_l2cc = F_core0 >> 1;
- + F_ddr2 = F_core0 >> 1;
- + F_ahb = F_core0 >> 3;
- + F_apb = F_ahb >> 1;
- + break;
- +
- + case 2:
- + F_core0 = main_PLL_out;
- + F_core1 = F_core0 >> 1;
- + F_l2cc = F_core0 >> 1;
- + F_ddr2 = F_core0 >> 1;
- + F_ahb = F_core0 >> 2;
- + F_apb = F_ahb >> 1;
- + break;
- +
- + case 3:
- + F_core0 = main_PLL_out;
- + F_core1 = F_core0 >> 1;
- + F_l2cc = F_core0 >> 1;
- + F_ddr2 = F_core0 >> 1;
- + F_ahb = F_core0 >> 3;
- + F_apb = F_ahb >> 1;
- + break;
- +
- + case 4:
- + F_core0 = main_PLL_out;
- + F_core1 = F_core0 >> 2;
- + F_l2cc = F_core0 >> 2;
- + F_ddr2 = F_core0 >> 1;
- + F_ahb = F_core0 >> 2;
- + F_apb = F_ahb >> 1;
- + break;
- + case 5:
- + F_core0 = main_PLL_out;
- + F_core1 = F_core0 >> 2;
- + F_l2cc = F_core0 >> 2;
- + F_ddr2 = F_core0 >> 1;
- + F_ahb = F_core0 >> 3;
- + F_apb = F_ahb >> 1;
- + break;
- +
- + case 6:
- + F_core0 = main_PLL_out;
- + F_core1 = F_core0;
- + F_l2cc = F_core0;
- + F_ddr2 = F_core0 >> 1;
- + F_ahb = F_core0 >> 2;
- + F_apb = F_ahb >> 1;
- + break;
- +
- + case 7:
- + F_core0 = main_PLL_out;
- + F_core1 = F_core0;
- + F_l2cc = F_core0;
- + F_ddr2 = F_core0 >> 1;
- + F_ahb = F_core0 >> 3;
- + F_apb = F_ahb >> 1;
- + break;
- +
- + case 8:
- + F_core0 = main_PLL_out;
- + F_core1 = F_core0;
- + F_l2cc = F_core0 >> 1;
- + F_ddr2 = OSCH_CLK * 24 / 2;
- + F_ahb = F_core0 >> 2;
- + F_apb = F_ahb >> 1;
- + break;
- +
- + case 9:
- + F_core0 = main_PLL_out;
- + F_core1 = F_core0;
- + F_l2cc = F_core0 >> 1;
- + F_ddr2 = OSCH_CLK * 24 / 2;
- + F_ahb = F_core0 >> 3;
- + F_apb = F_ahb >> 1;
- + break;
- + case 10:
- + F_core0 = main_PLL_out;
- + F_core1 = F_core0 >> 1;
- + F_l2cc = F_core0 >> 1;
- + F_ddr2 = OSCH_CLK * 24 / 2;
- + F_ahb = F_core0 >> 2;
- + F_apb = F_ahb >> 1;
- + break;
- +
- + case 11:
- + F_core0 = main_PLL_out;
- + F_core1 = F_core0 >> 1;
- + F_l2cc = F_core0 >> 1;
- + F_ddr2 = OSCH_CLK * 24 / 2;
- + F_ahb = F_core0 >> 3;
- + F_apb = F_ahb >> 1;
- + break;
- +
- + case 12:
- + F_core0 = main_PLL_out;
- + F_core1 = F_core0 >> 2;
- + F_l2cc = F_core0 >> 2;
- + F_ddr2 = OSCH_CLK * 24 / 2;
- + F_ahb = F_core0 >> 2;
- + F_apb = F_ahb >> 1;
- + break;
- +
- + case 13:
- + F_core0 = main_PLL_out;
- + F_core1 = F_core0 >> 2;
- + F_l2cc = F_core0 >> 2;
- + F_ddr2 = OSCH_CLK * 24 / 2;
- + F_ahb = F_core0 >> 3;
- + F_apb = F_ahb >> 1;
- + break;
- +
- + case 14:
- + F_core0 = main_PLL_out;
- + F_core1 = F_core0;
- + F_l2cc = F_core0;
- + F_ddr2 = F_core0;
- + F_ahb = F_core0;
- + F_apb = F_ahb;
- + break;
- + default: // 15
- + F_core0 = OSCH3_CLK;
- + F_core1 = F_core0;
- + F_l2cc = F_core0;
- + F_ddr2 = F_core0;
- + F_ahb = F_core0;
- + F_apb = F_ahb;
- + break;
- + }
- +
- + F_pci = OSCH_CLK * 24 / 9;
- + if ((pcs5_param & 0x800) == 0)
- + F_pci = F_pci >> 1;
- +
- + ahbclk = (int)F_ahb;
- +}
- +
- +int ag102_get_ahb_clk(void)
- +{
- + //return ahbclk+MHZ;
- + return ahbclk;
- +}
- +
- +EXPORT_SYMBOL(ag102_get_ahb_clk);
- +#else
- +void ag102_calc_ahb_clk(void)
- +{
- +}
- +#endif
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/devices.c linux-3.4.110/arch/nds32/platforms/ag102/devices.c
- --- linux-3.4.110.orig/arch/nds32/platforms/ag102/devices.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag102/devices.c 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,181 @@
- +#include <linux/serial_8250.h>
- +#include <asm/mach-types.h>
- +#include <asm/sizes.h>
- +#include <asm/mach/arch.h>
- +#include <asm/mach/map.h>
- +#include <asm/timer.h>
- +#include <linux/platform_device.h>
- +#include <linux/usb/g_hid.h>
- +
- +extern void amic_init(void);
- +
- +const struct map_desc platform_io_desc[] __initdata = {
- + {UART0_VA_BASE, UART0_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {UART1_VA_BASE, UART1_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {AMIC_VA_BASE, AMIC_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {GMAC_VA_BASE, GMAC_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {APBBR_VA_BASE, APBBR_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {TIMER_VA_BASE, TIMER_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {L2CC_VA_BASE, L2CC_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {PCIIO_0_VA_BASE, PCIIO_0_PA_BASE, 0x0000F000, MT_DEVICE_NCB},
- + {PCIC_FTPCI100_0_VA_BASE, PCIC_FTPCI100_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {SDC_FTSDC010_0_VA_BASE, SDC_FTSDC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {RTC_FTRTC010_0_VA_BASE, RTC_FTRTC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {WDT_FTWDT010_0_VA_BASE, WDT_FTWDT010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {I2C_FTI2C010_0_VA_BASE, I2C_FTI2C010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {GPIO_FTGPIO010_0_VA_BASE, GPIO_FTGPIO010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {PCU_VA_BASE, PCU_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {LPC_IO_VA_BASE, LPC_IO_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {LPC_REG_VA_BASE, LPC_REG_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {DMAC_FTDMAC020_0_VA_BASE, DMAC_FTDMAC020_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {GPU_VA_BASE, GPU_PA_BASE, SZ_64K, MT_DEVICE_NCB},
- + {IDE_FTIDE020_VA_BASE, IDE_FTIDE020_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {USB_FOTG2XX_0_VA_BASE, USB_FOTG2XX_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {CFC_FTCFC010_0_VA_BASE, CFC_FTCFC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {SSP_FTSSP010_0_VA_BASE, SSP_FTSSP010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {SPI_FTSSP010_0_VA_BASE, SPI_FTSSP010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {DDR2C_VA_BASE, DDR2C_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {AHB_ATFAHBC020S_0_VA_BASE, AHB_ATFAHBC020S_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB}
- + //{ GPIO_VA_BASE, GPIO_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB }
- +};
- +
- +/* hid descriptor for a keyboard */
- +static struct hidg_func_descriptor my_hid_data = {
- + .subclass = 0, /* No subclass */
- + .protocol = 1, /* Keyboard */
- + .report_length = 8,
- + .report_desc_length = 63,
- + .report_desc = {
- + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
- + 0x09, 0x06, /* USAGE (Keyboard) */
- + 0xa1, 0x01, /* COLLECTION (Application) */
- + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */
- + 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */
- + 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */
- + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
- + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
- + 0x75, 0x01, /* REPORT_SIZE (1) */
- + 0x95, 0x08, /* REPORT_COUNT (8) */
- + 0x81, 0x02, /* INPUT (Data,Var,Abs) */
- + 0x95, 0x01, /* REPORT_COUNT (1) */
- + 0x75, 0x08, /* REPORT_SIZE (8) */
- + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */
- + 0x95, 0x05, /* REPORT_COUNT (5) */
- + 0x75, 0x01, /* REPORT_SIZE (1) */
- + 0x05, 0x08, /* USAGE_PAGE (LEDs) */
- + 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */
- + 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */
- + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
- + 0x95, 0x01, /* REPORT_COUNT (1) */
- + 0x75, 0x03, /* REPORT_SIZE (3) */
- + 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */
- + 0x95, 0x06, /* REPORT_COUNT (6) */
- + 0x75, 0x08, /* REPORT_SIZE (8) */
- + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
- + 0x25, 0x65, /* LOGICAL_MAXIMUM (101) */
- + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */
- + 0x19, 0x00, /* USAGE_MINIMUM (Reserved) */
- + 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */
- + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */
- + 0xc0 /* END_COLLECTION */
- + }
- +};
- +
- +static struct platform_device my_hid = {
- + .name = "hidg",
- + .id = 0,
- + .num_resources = 0,
- + .resource = 0,
- + .dev.platform_data = &my_hid_data,
- +};
- +
- +static void __init platform_map_io(void)
- +{
- + iotable_init((struct map_desc *)platform_io_desc,
- + ARRAY_SIZE(platform_io_desc));
- +}
- +
- +static struct resource ftgmac100_resources[] = {
- + [0] = {
- + .start = GMAC_PA_BASE,
- + .end = GMAC_PA_BASE + SZ_4K - 1,
- + .flags = IORESOURCE_MEM,
- + },
- + [1] = {
- + .start = GMAC_IRQ,
- + .flags = IORESOURCE_IRQ,
- + },
- +};
- +
- +static struct platform_device ftgmac100_device = {
- + .name = "ftgmac100",
- + .id = 0,
- + .num_resources = ARRAY_SIZE(ftgmac100_resources),
- + .resource = ftgmac100_resources,
- +};
- +
- +static int __init devices_init(void)
- +{
- + platform_device_register(&ftgmac100_device);
- + platform_device_register(&my_hid);
- + return 0;
- +}
- +
- +arch_initcall(devices_init);
- +
- +static struct uart_port uart0 = {
- + .membase = (void __iomem *)UART0_VA_BASE,
- + .irq = UART0_IRQ,
- + .uartclk = CONFIG_UART_CLK,
- + .regshift = 2,
- + .iotype = UPIO_MEM,
- + .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
- + .line = 0,
- + .mapbase = UART0_PA_BASE,
- +};
- +
- +static struct uart_port uart1 = {
- + .membase = (void __iomem *)UART1_VA_BASE,
- + .irq = UART1_IRQ,
- + .uartclk = CONFIG_UART_CLK,
- + .regshift = 2,
- + .iotype = UPIO_MEM,
- + .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
- + .line = 1,
- + .mapbase = UART1_PA_BASE,
- +};
- +
- +void ag102_calc_ahb_clk(void);
- +static void __init soc_init(void)
- +{
- + ag102_calc_ahb_clk();
- + early_serial_setup(&uart0);
- + early_serial_setup(&uart1);
- +}
- +
- +MACHINE_START(FARADAY, PLATFORM_NAME)
- + .param_offset = BOOT_PARAMETER_PA_BASE,.map_io = platform_map_io,.init_irq = amic_init,.timer = &platform_timer, /* defined in timer.c */
- +.init_machine = soc_init,
- + MACHINE_END static struct platform_device usb_dev_otg_host = {
- + .name = "fotg-ehci",
- +};
- +
- +static int __init fotg_init(void)
- +{
- + platform_device_register(&usb_dev_otg_host);
- + return 0;
- +}
- +
- +device_initcall(fotg_init);
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/freq-scaling.c linux-3.4.110/arch/nds32/platforms/ag102/freq-scaling.c
- --- linux-3.4.110.orig/arch/nds32/platforms/ag102/freq-scaling.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag102/freq-scaling.c 2016-04-07 10:20:50.986082726 +0200
- @@ -0,0 +1,512 @@
- +/*
- + * linux/arch/nds32/platforms/ag102/cpu-fcs.c
- + *
- + * Copyright (C) 2002,2003 Intrinsyc Software
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + * History:
- + * 31-Jul-2002 : Initial version [FB]
- + * 29-Jan-2003 : added PXA255 support [FB]
- + * 20-Apr-2003 : ported to v2.5 (Dustin McIntire, Sensoria Corp.)
- + * 18-Jun-2008 : ported to NDS32 architecture ( Roy Lee, Andestech Corp.)
- + * 13-Oct-2010 : ported to NDS32 AG102 architecture(Gavin Guo, Andestech Corp.)
- + *
- + * Note:
- + * This driver may change the memory bus clock rate, but will not do any
- + * platform specific access timing changes... for example if you have flash
- + * memory connected to CS0, you will need to register a platform specific
- + * notifier which will adjust the memory access strobes to maintain a
- + * minimum strobe width.
- + *
- + */
- +#include <linux/module.h>
- +#include <linux/cpufreq.h>
- +#include <linux/interrupt.h>
- +
- +#include <linux/delay.h>
- +#include <asm/hardware.h>
- +#include <asm/localmem.h>
- +#include <asm/system.h>
- +#include <asm/nds32.h>
- +#include <asm/irq_regs.h>
- +#include "pcu.h"
- +
- +void __ddr_fsc_lock_start();
- +void __ddr_fsc_lock_end();
- +#define AG102_MIN_FREQ 200000000
- +#define AG102_MAX_FREQ 1000000000
- +#define OSCH3_CLK 33000000 /* 33MHz AG102 */
- +
- +struct ag102_freq_struct {
- + unsigned int khz; /* cpu_clk in khz */
- + unsigned int sf; /* scaling factor */
- + unsigned int cr; /* clock ratio */
- +};
- +
- +struct ag102_freq_struct ag102_run_freqs[] = {
- + /* khz sf, cr */
- + {OSCH3_CLK * 7, 7, 0}, /* CPUA 231MHz */
- + {OSCH3_CLK * 8, 8, 0}, /* CPUA 264MHz */
- + {OSCH3_CLK * 9, 9, 0},
- + {OSCH3_CLK * 10, 10, 0},
- + {OSCH3_CLK * 11, 11, 0},
- + {OSCH3_CLK * 12, 12, 0},
- + {OSCH3_CLK * 13, 13, 0},
- + {OSCH3_CLK * 14, 14, 0},
- + {OSCH3_CLK * 15, 15, 0},
- + {OSCH3_CLK * 16, 16, 0},
- + /*
- + * {OSCH3_CLK * 17, 17, 0},
- + * {OSCH3_CLK * 18, 18, 0},
- + * {OSCH3_CLK * 19, 19, 0},
- + * {OSCH3_CLK * 20, 20, 0},
- + * {OSCH3_CLK * 21, 21, 0},
- + * {OSCH3_CLK * 22, 22, 0},
- + * {OSCH3_CLK * 23, 23, 0},
- + * {OSCH3_CLK * 24, 24, 0},
- + * {OSCH3_CLK * 25, 25, 0},
- + * {OSCH3_CLK * 26, 26, 0},
- + * {OSCH3_CLK * 27, 27, 0},
- + * {OSCH3_CLK * 28, 28, 0},
- + * {OSCH3_CLK * 29, 29, 0},
- + * {OSCH3_CLK * 30, 30, 0},
- + */
- + {0} /* The last 30 is CPUA 1000MHz */
- +};
- +
- +#define NUM_RUN_FREQS ARRAY_SIZE(ag102_run_freqs)
- +static struct cpufreq_frequency_table ag102_run_freq_table[NUM_RUN_FREQS + 1];
- +
- +/* Generic helper function get CPU clocks in kHz */
- +unsigned int ag102_cpufreq_get(unsigned int dummy)
- +{
- + unsigned int main_PLL_M = 1;
- + unsigned int main_PLL_out;
- + unsigned int main_PLL_div;
- + unsigned int ratio;
- + unsigned int main_PLL_N;
- + unsigned int pcs1_param;
- + unsigned int pcs4_param;
- +
- + pcs1_param = PCU_GET_REG(PCS1_ST2);
- + main_PLL_div = PCU_EXTRACT(PCS1_ST2, DIV, pcs1_param);
- + ratio = PCU_EXTRACT(PCS1_ST2, RATIO, pcs1_param);
- +
- + pcs4_param = PCU_GET_REG(PCS4_ST2);
- + main_PLL_N = PCU_EXTRACT(PCS4_ST2, N_FACTOR, pcs4_param);
- + main_PLL_out = (OSCH3_CLK * main_PLL_N / main_PLL_M) >> main_PLL_div;
- +
- + printk("CPU frequency is %d\n", main_PLL_out);
- + return main_PLL_out;
- +}
- +
- +/* find a valid frequency point */
- +static int ag102_verify_policy(struct cpufreq_policy *policy)
- +{
- + printk("Verified CPU policy: %dKhz min to %dKhz max\n", policy->min,
- + policy->max);
- + return cpufreq_frequency_table_verify(policy, ag102_run_freq_table);
- +}
- +
- +void wakeup_and_ddr_train(void)
- +{
- + unsigned int csr_reg;
- + unsigned long ddr2_va_base = DDR2C_VA_BASE;
- + /* issue standby */
- + /*standby(PCU_STBY_WAIT_DONE); */
- + __asm__ __volatile__("__fcs_stby:");
- + __asm__ __volatile__("standby wait_done");
- + /* Fill the inline assembly codes into Cache to avoid SDRAM access before the data training is done */
- + __asm__ __volatile__("__ddr_fsc_lock_start:\n"
- + "li $p0, %0 \n"
- + "lwi $p1, [$p0 + 0x1f0] \n"
- + "ori $p1, $p1, 0x100 \n"
- + "swi $p1, [$p0 + 0x1f0] ! DLL Reset \n"
- + "msync \n"
- + "isb \n"
- + "1: \n"
- + "lwi $p1, [$p0 + 0x1f0] \n"
- + "andi $p1, $p1, 0x100 \n"
- + "bnez $p1, 1b ! Wait until DLL reset is done\n"
- + "__trigger_dt:\n"
- + "li $p0, %1 \n"
- + "lwi $p1, [$p0] \n"
- + "li $p0, 0x40000000 \n"
- + "or $p1, $p1, $p0 \n"
- + "li $p0, %2 \n"
- + "swi $p1, [$p0] ! Trigger data training\n"
- + "msync \n"
- + "isb \n"
- + "li $p0, %3 \n"
- + "__wait_init_0:\n"
- + "lwi $p1, [$p0 + 0xc] \n"
- + "srli $p1, $p1, 23 \n"
- + "andi $p1, $p1, 0x1 \n"
- + "bnez $p1, __wait_init_0 ! Wait until init bit in CSR == 0\n"
- + "lwi $p1, [$p0 + 0xc] \n"
- + "srli $p1, $p1, 20 \n"
- + "andi $p1, $p1, 0x1 \n"
- + "beqz $p1, __dt_pass ! Monitor data training result\n"
- + "li $p0, 0xff942000 \n"
- + "li $p1, 0x45 \n"
- + "swi $p1, [$p0] ! put 'E' to UART\n"
- + "li $p1, 0x52 \n"
- + "swi $p1, [$p0] ! put 'R' to UART\n"
- + "li $p1, 0x52 \n"
- + "swi $p1, [$p0] ! put 'R' to UART\n"
- + "li $p1, 0x4f \n"
- + "swi $p1, [$p0] ! put 'O' to UART\n"
- + "li $p1, 0x52 \n"
- + "swi $p1, [$p0] ! put 'R' to UART\n"
- + "li $p1, 0xd \n"
- + "swi $p1, [$p0] ! put '\\r' to UART\n"
- + "li $p1, 0xa \n"
- + "swi $p1, [$p0] ! put '\\n' to UART\n"
- + "j __ddr_fsc_lock_end \n"
- + "__dt_pass:\n"
- + "li $p0, 0xff942000 \n"
- + "li $p1, 0x50 \n"
- + "swi $p1, [$p0] ! put 'P' to UART\n"
- + "li $p1, 'A \n"
- + "swi $p1, [$p0] ! put 'A' to UART\n"
- + "li $p1, 0x53 \n"
- + "swi $p1, [$p0] ! put 'S' to UART\n"
- + "li $p1, 0x53 \n"
- + "swi $p1, [$p0] ! put 'S' to UART\n"
- + "li $p1, '\\r \n"
- + "swi $p1, [$p0] ! put '\\r' to UART\n"
- + "li $p1, '\\n \n"
- + "swi $p1, [$p0] ! put '\\n' to UART\n"
- + "__ddr_fsc_lock_end: \n"::
- + "r"
- + (ddr2_va_base),
- + "r"
- + (ddr2_va_base),
- + "r"(ddr2_va_base), "r"(ddr2_va_base));
- +
- + csr_reg = GET_REG(DDR2C_VA_BASE + 0xc);
- + if (csr_reg & 0x100000) {
- + printk("\n###### Data training error ######\nCSR = 0x%x\n\n",
- + csr_reg);
- + }
- +}
- +
- +void check_status()
- +{
- + unsigned int reg_value_tmp;
- +
- + /*
- + * CPU will continue if it is waked up
- + * => check status
- + */
- + reg_value_tmp = PCU_GET_REG(BSM_STATUS);
- + if (PCU_EXTRACT(BSM_STATUS, STS, reg_value_tmp) != PCS_BSM_DONE) {
- + printk("ERROR: BSM status is not expected:0x%x\n",
- + reg_value_tmp);
- + }
- + PCU_SET_REG(BSM_STATUS, 0x0); // write to clear the status
- +
- + /*
- + * Maybe we will need the following code in the future
- + * if (pcs1_used) {
- + * reg_value_tmp = PCU_GET_REG(PCS1_ST1);
- + * if (PCU_EXTRACT(PCS1_ST1, STS, reg_value_tmp) != PCS_STS_DONE) {
- + * printk("ERROR: PCS1 status is not expected:0x%x\n", reg_value_tmp);
- + * printk("DEBUG: PCS1 status 2 is 0x%x\n", PCU_GET_REG(PCS1_ST2));
- + * }
- + * PCU_SET_REG(PCS1_ST1, 0x0); // write to clear the status
- + * pcs1_used = 0;
- + * }
- + */
- +
- + /* if (pcs4_used) { */
- + reg_value_tmp = PCU_GET_REG(PCS4_ST1);
- + if (PCU_EXTRACT(PCS4_ST1, STS, reg_value_tmp) != PCS_STS_DONE) {
- + printk("ERROR: PCS4 status is not expected:0x%x\n",
- + reg_value_tmp);
- + printk("DEBUG: PCS4 status 2 is 0x%x\n", PCU_GET_REG(PCS4_ST2));
- + }
- + PCU_SET_REG(PCS4_ST1, 0x0); /* write to clear the status */
- + /* pcs4_used = 0; */
- + /* } */
- +
- +}
- +
- +void start_fcs(unsigned int pll_n_factor, unsigned org_div_param)
- +{
- + unsigned int pll_range;
- + unsigned int pcs4_prmtr;
- +
- + /*
- + * We must keep the frequency between 266~533.
- + * because this is the frequency having been tested.
- + */
- + if (org_div_param == 0) {
- + if ((pll_n_factor < 7) || (pll_n_factor > 16)) { /* 266~533 */
- + printk("\npll_n_factor:%d, org_div_param:%d\n",
- + pll_n_factor, org_div_param);
- + printk
- + ("The input is not accepted! Please input the other value\n");
- + return;
- + }
- + } else { /* div = 1(the divsior is 2), (pll_n_factor*33MHz/2) */
- + if (pll_n_factor < 16) { /* (533/2~1000/2) */
- + printk("\npll_n_factor:%d, org_div_param:%d\n",
- + pll_n_factor, org_div_param);
- + printk
- + ("The input is not accepted! Please input the other value\n");
- + return;
- + }
- +
- + }
- + /* Setup the pll_range, pcu need to know the frequency which we setup */
- + if (org_div_param == 0) {
- + if (pll_n_factor <= 15) {
- + pll_range = 2;
- + } else
- + pll_range = 3;
- + } else if (org_div_param == 1) {
- + if (pll_n_factor >= 16 && pll_n_factor <= 30) {
- + pll_range = 2;
- + } else
- + pll_range = 3;
- + }
- +
- + printk("\npll_n_factor:%d, org_div_param:%d, pll_range:%d\n",
- + pll_n_factor, org_div_param, pll_range);
- + /* PCS4 */
- + PCU_SET_REG(PCS4_CFG, 0); /* stop */
- + pcs4_prmtr = PCU_PREPARE(PCS4_PARA, IE, 1) | PCU_PREPARE(PCS4_PARA, CMD, PCS_CMD_NOP) | PCU_PREPARE(PCS4_PARA, SYNC, 1) | PCU_PREPARE(PCS4_PARA, PWDN, 0) | PCU_PREPARE(PCS4_PARA, RANGE, pll_range) | /* PLL range */
- + pll_n_factor; /* PLL N factor */
- + PCU_SET_REG(PCS4_PARA, pcs4_prmtr);
- +
- + /* BSM */
- + PCU_SET_REG(BSM_CTRL, PCU_PREPARE(BSM_CTRL, IE, 1) | PCU_PREPARE(BSM_CTRL, CMD, PCS_CMD_SCALING | PCS_CMD_DRAM_SF) | PCU_PREPARE(BSM_CTRL, SYNC, 1) | PCU_PREPARE(BSM_CTRL, LINK0, 4) | /* scaling link start */
- + PCU_PREPARE(BSM_CTRL, LINK1, 0x0)); /* wakeup link start */
- + wakeup_and_ddr_train();
- + check_status();
- +}
- +
- +void end_fcs(void)
- +{
- + /* Leave this function as a place marker. */
- +}
- +
- +#define LPS_PREC 8
- +void calibration()
- +{
- + unsigned long ticks, loopbit, lpj;
- + int lps_precision = LPS_PREC;
- +
- + lpj = (1 << 12);
- +
- + printk(KERN_INFO "Calibrating delay loop... ");
- + while ((lpj <<= 1) != 0) {
- + /* wait for "start of" clock tick */
- + ticks = jiffies;
- + while (ticks == jiffies)
- + /* nothing */ ;
- + /* Go .. */
- + ticks = jiffies;
- + __delay(lpj);
- + ticks = jiffies - ticks;
- + if (ticks)
- + break;
- + }
- +
- + /*
- + * Do a binary approximation to get lpj set to
- + * equal one clock (up to lps_precision bits)
- + */
- + lpj >>= 1;
- + loopbit = lpj;
- + while (lps_precision-- && (loopbit >>= 1)) {
- + lpj |= loopbit;
- + ticks = jiffies;
- + while (ticks == jiffies)
- + /* nothing */ ;
- + ticks = jiffies;
- + __delay(lpj);
- + if (jiffies != ticks) /* longer than 1 tick */
- + lpj &= ~loopbit;
- + }
- +
- + printk(KERN_CONT "%lu.%02lu BogoMIPS modified(lpj=%lu)\n",
- + lpj / (500000 / HZ), (lpj / (5000 / HZ)) % 100, lpj);
- +}
- +
- +static int ag102_speedstep(int idx)
- +{
- + unsigned int j;
- + char ch = 'a';
- + unsigned int sf, cr;
- + unsigned long flags = 0;
- + unsigned long org_div_param;
- + void (*do_fcs) (unsigned int efsf, unsigned int edivhbaclk);
- + int i;
- + int line_size = CACHE_LINE_SIZE(ICACHE);
- + unsigned long start =
- + ((unsigned long)__ddr_fsc_lock_start) & ~(line_size - 1);
- + unsigned long end =
- + (((unsigned long)__ddr_fsc_lock_end) + line_size) & ~(line_size -
- + 1);
- +
- + printk("&__ddr_fsc_lock_start(): 0x%08lx, aligned to: 0x%08lx\n",
- + (unsigned long)__ddr_fsc_lock_start, start);
- + printk("&__ddr_fsc_lock_end(): 0x%08lx, aligned to: 0x%08lx\n",
- + (unsigned long)__ddr_fsc_lock_end, end);
- +
- + for (i = start; i <= end; i += CACHE_LINE_SIZE(ICACHE))
- + __asm__ volatile ("\n\tcctl %0, L1I_VA_FILLCK"::
- + "r" (i):"memory");
- +
- + do_fcs = start_fcs;
- + org_div_param = (PCU_GET_REG(PCS1_ST2) >> 4) & 0x3;
- + sf = ag102_run_freqs[idx].sf;
- + if (org_div_param == 1)
- + sf *= 2;
- +#if 0
- + calibration();
- + printk("pcu read value,before frequency scaling:");
- + ag102_cpufreq_get(0);
- +#endif
- + local_irq_save(flags);
- + do_fcs(sf, org_div_param);
- + local_irq_restore(flags);
- +#if 0
- + printk("\npcu read value,after frequency scaling:");
- + ag102_cpufreq_get(0);
- +#endif
- +
- + for (i = start; i <= end; i += CACHE_LINE_SIZE(ICACHE))
- + __asm__ volatile ("\n\tcctl %0, L1I_VA_ULCK"::"r" (i):"memory");
- +
- + return 1;
- +}
- +
- +static int ag102_set_target(struct cpufreq_policy *policy,
- + unsigned int target_freq, unsigned int relation)
- +{
- + unsigned int idx, i, j;
- + char ch = 'a';
- + struct cpufreq_frequency_table *ag102_freqs_table;
- + struct ag102_freq_struct *ag102_freq_settings;
- + struct cpufreq_freqs freqs;
- +
- + ag102_freq_settings = ag102_run_freqs;
- + ag102_freqs_table = ag102_run_freq_table;
- +
- + if (target_freq > AG102_MAX_FREQ || target_freq < AG102_MIN_FREQ) {
- + printk
- + ("\nThe frequency you input is illegal!!Please enter the frequency between %d ~ %d\n",
- + AG102_MIN_FREQ, AG102_MAX_FREQ);
- + return -EINVAL;
- + }
- +
- + /* Lookup the next frequency */
- + if (cpufreq_frequency_table_target
- + (policy, ag102_freqs_table, target_freq, relation, &idx))
- + return -EINVAL;
- +
- + freqs.old = policy->cur;
- + freqs.new = ag102_freq_settings[idx].khz;
- + freqs.cpu = policy->cpu;
- +
- + /*
- + * Tell everyone what we're about to do...
- + * you should add a notify client with any platform specific
- + * Vcc changing capability
- + */
- + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- +
- + if (freqs.new != freqs.old) {
- +
- + if (!ag102_speedstep(idx))
- + return -ENODEV;
- + }
- +
- + /*
- + * Tell everyone what we've just done...
- + * you should add a notify client with any platform specific
- + * SDRAM refresh timer adjustments
- + */
- + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
- +#if 0
- + printk("After CPUFREQ_POSTCHANGE, scaling:\n");
- + calibration();
- + printk("Speed test...");
- + for (i = 0; i < 26; i++) {
- + for (j = 0; j < 500000000; j++) ;
- + printk("%c", ch);
- + ch += 1;
- + }
- + printk("\n");
- +#endif
- + return 0;
- +}
- +
- +static int ag102_cpufreq_init(struct cpufreq_policy *policy)
- +{
- + int i;
- + /* set default policy and cpuinfo */
- + policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
- + policy->policy = CPUFREQ_POLICY_PERFORMANCE;
- + policy->cpuinfo.max_freq = AG102_MAX_FREQ;
- + policy->cpuinfo.min_freq = AG102_MIN_FREQ;
- + policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
- + policy->cur = ag102_cpufreq_get(0); /* current freq */
- + policy->min = AG102_MIN_FREQ;
- + policy->max = AG102_MAX_FREQ;
- +
- + /* Generate the run cpufreq_frequency_table struct */
- + for (i = 0; i < NUM_RUN_FREQS; i++) {
- +
- + ag102_run_freq_table[i].frequency = ag102_run_freqs[i].khz;
- + ag102_run_freq_table[i].index = i;
- + }
- +
- + ag102_run_freq_table[i].frequency = CPUFREQ_TABLE_END;
- +
- + printk("CPU frequency change support initialized\n");
- +
- + return 0;
- +}
- +
- +static struct cpufreq_driver ag102_cpufreq_driver = {
- +
- + .verify = ag102_verify_policy,
- + .target = ag102_set_target,
- + .init = ag102_cpufreq_init,
- + .get = ag102_cpufreq_get,
- + .name = "AG102",
- +};
- +
- +static int __init ag102_cpu_init(void)
- +{
- + return cpufreq_register_driver(&ag102_cpufreq_driver);
- +}
- +
- +static void __exit ag102_cpu_exit(void)
- +{
- + cpufreq_unregister_driver(&ag102_cpufreq_driver);
- +}
- +
- +MODULE_AUTHOR("Andes Technology Corporation");
- +MODULE_DESCRIPTION("CPU frequency changing driver for the AG102 architecture");
- +MODULE_LICENSE("GPL");
- +module_init(ag102_cpu_init);
- +module_exit(ag102_cpu_exit);
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/gmac.h linux-3.4.110/arch/nds32/platforms/ag102/gmac.h
- --- linux-3.4.110.orig/arch/nds32/platforms/ag102/gmac.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag102/gmac.h 2016-04-07 10:20:51.002083345 +0200
- @@ -0,0 +1,354 @@
- +#ifdef CONFIG_PLAT_AG102
- +#include <asm/spec-ag102.h>
- +#else
- +#include <asm/spec-ag101.h>
- +#endif
- +
- +#ifndef __GMAC_H
- +#define __GMAC_H
- +
- +// ======================================================
- +// GMAC register definition
- +// ======================================================
- +// GMAC register
- +//
- +//#define CPE_GMAC_BASE 0xFF90B000 //VA Base
- +#define CPE_DDR2_MEM_BASE 0x00000000
- +
- +#define BIT_MASK(bit_h, bit_l) ((((UINT32)0x1<<(1+bit_h-bit_l))-(UINT32)0x1)<<bit_l)
- +
- +#define GMAC_REG_ISR (GMAC_VA_BASE+0x0) // interrupt sataus register
- +#define GMAC_REG_IME (GMAC_VA_BASE+0x4) // interrupt enable register
- +#define GMAC_REG_MAC_MADR (GMAC_VA_BASE+0x8) // mac most signification address
- +#define GMAC_REG_MAC_LADR (GMAC_VA_BASE+0xc) // mac least signification address
- +#define GMAC_REG_NPTXPD (GMAC_VA_BASE+0x18) // normal priority poll demand
- +#define GMAC_REG_RXPD (GMAC_VA_BASE+0x1c) // receive poll demand
- +#define GMAC_REG_HPTXPD (GMAC_VA_BASE+0x28) // high priority poll demand
- +#define GMAC_REG_NPTXR_BADR (GMAC_VA_BASE+0x20) // normal proprity tx ring base
- +#define GMAC_REG_RXR_BADR (GMAC_VA_BASE+0x24) // rx ring base
- +#define GMAC_REG_HPTXR_BADR (GMAC_VA_BASE+0x28) // high priority tx ring base
- +#define GMAC_REG_DBLAC (GMAC_VA_BASE+0x38) // DMA burst lenght and arbitration control
- +#define GMAC_REG_DMAFIFOS (GMAC_VA_BASE+0x3c) // DMA FIFO status
- +#define GMAC_REG_REVR (GMAC_VA_BASE+0x40) // revision
- +#define GMAC_REG_FEAR (GMAC_VA_BASE+0x44) // feature register
- +#define GMAC_REG_TPAFCR (GMAC_VA_BASE+0x48) // Tramsmit Prority Arbitration and FIFO control
- +#define GMAC_REG_MACCR (GMAC_VA_BASE+0x50) // mac control register
- +#define GMAC_REG_MACSR (GMAC_VA_BASE+0x54) // mac status register
- +#define GMAC_REG_PHYCR (GMAC_VA_BASE+0x60) // phy control register
- +#define GMAC_REG_PHYDATA (GMAC_VA_BASE+0x64) // phy data register
- +#define GMAC_REG_WOLCR (GMAC_VA_BASE+0x70) // wake-on-lan control register
- +#define GMAC_REG_WOLSR (GMAC_VA_BASE+0x74) // wake-on-lan status register
- +#define GMAC_REG_WFCRC (GMAC_VA_BASE+0x78) // wake-up frame CRC register
- +#define GMAC_REG_WFBM1 (GMAC_VA_BASE+0x80) // wake-up frame byte mask 1st
- +#define GMAC_REG_WFBM2 (GMAC_VA_BASE+0x84) // wake-up frame byte mask 2nd
- +#define GMAC_REG_WFBM3 (GMAC_VA_BASE+0x88) // wake-up frame byte mask 3rd
- +#define GMAC_REG_WFBM4 (GMAC_VA_BASE+0x8c) // wake-up frame byte mask 4th
- +#define GMAC_REG_RXR_PTR (GMAC_VA_BASE+0x98) //
- +#define GMAC_REG_TPKT_CNT (GMAC_VA_BASE+0xa0) // tx packet count
- +#define GMAC_REG_TMCOL_SCOL (GMAC_VA_BASE+0xa4) // tx mcol and scol count
- +#define GMAC_REG_TECOL_FAIL (GMAC_VA_BASE+0xa8) // tx ecol and fail count
- +#define GMAC_REG_TLCOL_URUN (GMAC_VA_BASE+0xac) // tx lcol and urun count
- +#define GMAC_REG_RPKT_CNT (GMAC_VA_BASE+0xb0) // rx packet count
- +#define GMAC_REG_BROPKT_CNT (GMAC_VA_BASE+0xb4) // broad cast packet count
- +#define GMAC_REG_MULPKT_CNT (GMAC_VA_BASE+0xb8) // multicast packet count
- +#define GMAC_REG_RPF_AEP (GMAC_VA_BASE+0xbc) //
- +#define GMAC_REG_RUNT_CNT (GMAC_VA_BASE+0xc0) // rx runt packet
- +#define GMAC_REG_CRCER_FLT (GMAC_VA_BASE+0xc4) // crc error and FLT
- +#define GMAC_REG_RCOL_LOST (GMAC_VA_BASE+0xc8) // rx lost and collision count
- +
- +// interrupt enable
- +#define GMAC_IME_PHY_STS_CHG_MASK (BIT_MASK(9, 9)) //
- +#define GMAC_IME_PHY_STS_CHG_OFFSET (9)
- +#define GMAC_IME_AHB_ERR_MASK (BIT_MASK(8, 8)) //
- +#define GMAC_IME_AHB_ERR_OFFSET (8)
- +#define GMAC_IME_TPKT_LOST_MASK (BIT_MASK(7, 7)) //
- +#define GMAC_IME_TPKT_LOST_OFFSET (7)
- +#define GMAC_IME_TXBUF_UNAVA_MASK (BIT_MASK(6, 6)) //
- +#define GMAC_IME_TXBUF_UNAVA_OFFSET (6)
- +#define GMAC_IME_TPKT2F_MASK (BIT_MASK(5, 5)) //
- +#define GMAC_IME_TPKT2F_OFFSET (5)
- +#define GMAC_IME_TPKT2B_MASK (BIT_MASK(4, 4)) //
- +#define GMAC_IME_TPKT2B_OFFSET (4)
- +#define GMAC_IME_RPKT_LOST_MASK (BIT_MASK(3, 3)) //
- +#define GMAC_IME_RPKT_LOST_OFFSET (3)
- +#define GMAC_IME_RXBUF_UNAVA_MASK (BIT_MASK(2, 2)) //
- +#define GMAC_IME_RXBUF_UNAVA_OFFSET (2)
- +#define GMAC_IME_RPKT2F_MASK (BIT_MASK(1, 1)) //
- +#define GMAC_IME_RPKT2F_OFFSET (1)
- +#define GMAC_IME_RPKT2B_MASK (BIT_MASK(0, 0)) //
- +#define GMAC_IME_RPKT2B_OFFSET (0)
- +
- +
- +// interrupt status
- +#define GMAC_ISR_PHY_STS_CHG_MASK (BIT_MASK(9, 9)) //
- +#define GMAC_ISR_PHY_STS_CHG_OFFSET (9)
- +#define GMAC_ISR_AHB_ERR_MASK (BIT_MASK(8, 8)) //
- +#define GMAC_ISR_AHB_ERR_OFFSET (8)
- +#define GMAC_ISR_TPKT_LOST_MASK (BIT_MASK(7, 7)) //
- +#define GMAC_ISR_TPKT_LOST_OFFSET (7)
- +#define GMAC_ISR_TXBUF_UNAVA_MASK (BIT_MASK(6, 6)) //
- +#define GMAC_ISR_TXBUF_UNAVA_OFFSET (6)
- +#define GMAC_ISR_TPKT2F_MASK (BIT_MASK(5, 5)) //
- +#define GMAC_ISR_TPKT2F_OFFSET (5)
- +#define GMAC_ISR_TPKT2B_MASK (BIT_MASK(4, 4)) //
- +#define GMAC_ISR_TPKT2B_OFFSET (4)
- +#define GMAC_ISR_RPKT_LOST_MASK (BIT_MASK(3, 3)) //
- +#define GMAC_ISR_RPKT_LOST_OFFSET (3)
- +#define GMAC_ISR_RXBUF_UNAVA_MASK (BIT_MASK(2, 2)) //
- +#define GMAC_ISR_RXBUF_UNAVA_OFFSET (2)
- +#define GMAC_ISR_RPKT2F_MASK (BIT_MASK(1, 1)) //
- +#define GMAC_ISR_RPKT2F_OFFSET (1)
- +#define GMAC_ISR_RPKT2B_MASK (BIT_MASK(0, 0)) //
- +#define GMAC_ISR_RPKT2B_OFFSET (0)
- +
- +//bit field for TPAFCR control
- +#define GMAC_TPAFCR_TFIFO_SIZE_MASK (BIT_MASK(29, 27)) //
- +#define GMAC_TPAFCR_TFIFO_SIZE_OFFSET (27)
- +#define GMAC_TPAFCR_RFIFO_SIZE_MASK (BIT_MASK(26, 24)) //
- +#define GMAC_TPAFCR_RFIFO_SIZE_OFFSET (24)
- +#define GMAC_TPAFCR_EARLY_TXTHR_MASK (BIT_MASK(23, 16)) //
- +#define GMAC_TPAFCR_EARLY_TXTHR_OFFSET (16)
- +#define GMAC_TPAFCR_EARLY_RXTHR_MASK (BIT_MASK(15, 8)) //
- +#define GMAC_TPAFCR_EARLY_RXTHR_OFFSET (8)
- +#define GMAC_TPAFCR_HPKT_THR_MASK (BIT_MASK(7, 4)) //
- +#define GMAC_TPAFCR_HPKT_THR_OFFSET (4)
- +#define GMAC_TPAFCR_NPKT_THR_MASK (BIT_MASK(3, 0)) //
- +#define GMAC_TPAFCR_NPKT_THR_OFFSET (0)
- +
- +//bit field for MAC control
- +#define GMAC_MACCR_SW_RST_MASK (BIT_MASK(31, 31)) //
- +#define GMAC_MACCR_SW_RST_OFFSET (31)
- +#define GMAC_MACCR_DIRECT_PATH_MASK (BIT_MASK(21, 21)) //
- +#define GMAC_MACCR_DIRECT_PATH_OFFSET (21)
- +#define GMAC_MACCR_SPEED_MASK (BIT_MASK(19, 19)) //
- +#define GMAC_MACCR_SPEED_OFFSET (19)
- +#define GMAC_MACCR_DISCARD_CRCERR_MASK (BIT_MASK(18, 18)) //
- +#define GMAC_MACCR_DISCARD_CRCERR_OFFSET (18)
- +#define GMAC_MACCR_BROADPKT_EN_MASK (BIT_MASK(17, 17)) //
- +#define GMAC_MACCR_BROADPKT_EN_OFFSET (17)
- +#define GMAC_MACCR_RX_MULTIPKT_EN_MASK (BIT_MASK(16, 16)) //
- +#define GMAC_MACCR_RX_MULTIPKT_EN_OFFSET (16)
- +#define GMAC_MACCR_RX_HT_EN_MASK (BIT_MASK(15, 15)) //
- +#define GMAC_MACCR_RX_HT_EN_OFFSET (15)
- +#define GMAC_MACCR_RX_ALLADR_MASK (BIT_MASK(14, 14)) //
- +#define GMAC_MACCR_RX_ALLADR_OFFSET (14)
- +#define GMAC_MACCR_JUMBO_LF_MASK (BIT_MASK(13, 13)) //
- +#define GMAC_MACCR_JUMBO_LF_OFFSET (13)
- +#define GMAC_MACCR_RX_RUNT_MASK (BIT_MASK(12, 12)) //
- +#define GMAC_MACCR_RX_RUNT_OFFSET (12)
- +#define GMAC_MACCR_CRC_APD_MASK (BIT_MASK(10, 10)) //
- +#define GMAC_MACCR_CRC_APD_OFFSET (10)
- +#define GMAC_MACCR_GMAC_MODE_MASK (BIT_MASK(9, 9)) //
- +#define GMAC_MACCR_GMAC_MODE_OFFSET (9)
- +#define GMAC_MACCR_FULLDUP_MASK (BIT_MASK(8, 8)) //
- +#define GMAC_MACCR_FULLDUP_OFFSET (8)
- +#define GMAC_MACCR_ENRX_IN_HALFTX_MASK (BIT_MASK(7, 7)) //
- +#define GMAC_MACCR_ENRX_IN_HALFTX_OFFSET (7)
- +#define GMAC_MACCR_LOOP_EN_MASK (BIT_MASK(6, 6)) //
- +#define GMAC_MACCR_LOOP_EN_OFFSET (6)
- +#define GMAC_MACCR_HPTXR_EN_MASK (BIT_MASK(5, 5)) //
- +#define GMAC_MACCR_HPTXR_EN_OFFSET (5)
- +#define GMAC_MACCR_REMOVE_VLAN_MASK (BIT_MASK(4, 4)) //
- +#define GMAC_MACCR_REMOVE_VLAN_OFFSET (4)
- +#define GMAC_MACCR_RXMAC_EN_MASK (BIT_MASK(3, 3)) //
- +#define GMAC_MACCR_RXMAC_EN_OFFSET (3)
- +#define GMAC_MACCR_TXMAC_EN_MASK (BIT_MASK(2, 2)) //
- +#define GMAC_MACCR_TXMAC_EN_OFFSET (2)
- +#define GMAC_MACCR_RXDMA_EN_MASK (BIT_MASK(1, 1)) //
- +#define GMAC_MACCR_RXDMA_EN_OFFSET (1)
- +#define GMAC_MACCR_TXDMA_EN_MASK (BIT_MASK(0, 0)) //
- +#define GMAC_MACCR_TXDMA_EN_OFFSET (0)
- +
- +//bit field for PHY control
- +#define GMAC_PHYCR_MIIWR_MASK (BIT_MASK(27, 27)) //
- +#define GMAC_PHYCR_MIIWR_OFFSET (27)
- +#define GMAC_PHYCR_MIIRD_MASK (BIT_MASK(26, 26)) //
- +#define GMAC_PHYCR_MIIRD_OFFSET (26)
- +#define GMAC_PHYCR_REGAD_MASK (BIT_MASK(25, 21)) // register address
- +#define GMAC_PHYCR_REGAD_OFFSET (21)
- +#define GMAC_PHYCR_PHYAD_MASK (BIT_MASK(20, 16)) // phy address
- +#define GMAC_PHYCR_PHYAD_OFFSET (16)
- +#define GMAC_PHYCR_MDC_CYCTHR_MASK (BIT_MASK(5, 0)) // cycle threshold
- +#define GMAC_PHYCR_MDC_CYCTHR_OFFSET (0)
- +
- +//bit field for PHY data
- +#define GMAC_PHYDATA_MIIRDATA_MASK (BIT_MASK(31, 16)) // read data
- +#define GMAC_PHYDATA_MIIRDATA_OFFSET (16)
- +#define GMAC_PHYDATA_MIIWDATA_MASK (BIT_MASK(15, 0)) // write data
- +#define GMAC_PHYDATA_MIIWDATA_OFFSET (0)
- +
- +//bit field for WOLCR
- +#define GMAC_WOLCR_WOL_TYPE_MASK (BIT_MASK(258, 24)) //
- +#define GMAC_WOLCR_WOL_TYPE_OFFSET (24)
- +#define GMAC_WOLCR_SW_PDNPHY_MASK (BIT_MASK(18, 18)) //
- +#define GMAC_WOLCR_SW_PDNPHY_OFFSET (18)
- +#define GMAC_WOLCR_WAKEUP_SEL_MASK (BIT_MASK(17, 16)) //
- +#define GMAC_WOLCR_WAKEUP_SEL_OFFSET (16)
- +#define GMAC_WOLCR_PWRSAV_MASK (BIT_MASK(15, 15)) //
- +#define GMAC_WOLCR_PWRSAV_OFFSET (15)
- +#define GMAC_WOLCR_WAKEUP4_EN_MASK (BIT_MASK(6, 6)) //
- +#define GMAC_WOLCR_WAKEUP4_EN_OFFSET (6)
- +#define GMAC_WOLCR_WAKEUP3_EN_MASK (BIT_MASK(5, 5)) //
- +#define GMAC_WOLCR_WAKEUP3_EN_OFFSET (5)
- +#define GMAC_WOLCR_WAKEUP2_EN_MASK (BIT_MASK(4, 4)) //
- +#define GMAC_WOLCR_WAKEUP2_EN_OFFSET (4)
- +#define GMAC_WOLCR_WAKEUP1_EN_MASK (BIT_MASK(3, 3)) //
- +#define GMAC_WOLCR_WAKEUP1_EN_OFFSET (3)
- +#define GMAC_WOLCR_MAGICPKT_EN_MASK (BIT_MASK(2, 2)) //
- +#define GMAC_WOLCR_MAGICPKT_EN_OFFSET (2)
- +#define GMAC_WOLCR_LINKCHG1_EN_MASK (BIT_MASK(1, 1)) // read data
- +#define GMAC_WOLCR_LINKCHG1_EN_OFFSET (1)
- +#define GMAC_WOLCR_LINKCHG0_EN_MASK (BIT_MASK(0, 0)) // write data
- +#define GMAC_WOLCR_LINKCHG0_EN_OFFSET (0)
- +
- +//bit field for WOLSR
- +#define GMAC_WOLSR_WAKEUP4_STS_MASK (BIT_MASK(6, 6)) //
- +#define GMAC_WOLSR_WAKEUP4_STS_OFFSET (6)
- +#define GMAC_WOLSR_WAKEUP3_STS_MASK (BIT_MASK(5, 5)) //
- +#define GMAC_WOLSR_WAKEUP3_STS_OFFSET (5)
- +#define GMAC_WOLSR_WAKEUP2_STS_MASK (BIT_MASK(4, 4)) //
- +#define GMAC_WOLSR_WAKEUP2_STS_OFFSET (4)
- +#define GMAC_WOLSR_WAKEUP1_STS_MASK (BIT_MASK(3, 3)) //
- +#define GMAC_WOLSR_WAKEUP1_STS_OFFSET (3)
- +#define GMAC_WOLSR_MAGICPKT_STS_MASK (BIT_MASK(2, 2)) //
- +#define GMAC_WOLSR_MAGICPKT_STS_OFFSET (2)
- +#define GMAC_WOLSR_LINKCHG1_STS_MASK (BIT_MASK(1, 1)) // read data
- +#define GMAC_WOLSR_LINKCHG1_STS_OFFSET (1)
- +#define GMAC_WOLSR_LINKCHG0_STS_MASK (BIT_MASK(0, 0)) // write data
- +#define GMAC_WOLSR_LINKCHG0_STS_OFFSET (0)
- +
- +// feature
- +#define GMAC_FEAR_TFIFO_RSIZE_MASK (BIT_MASK(5, 3)) // tx fifo size
- +#define GMAC_FEAR_TFIFO_RSIZE_OFFSET (3)
- +#define GMAC_FEAR_RFIFO_RSIZE_MASK (BIT_MASK(2, 0)) // rx fufo size
- +#define GMAC_FEAR_RFIFO_RSIZE_OFFSET (0)
- +
- +// ======================================================
- +// GMAC access macro
- +// ======================================================
- +#define GMAC_SET_FIELD(reg, field, value) SET_FIELD(GMAC_REG_##reg, GMAC_##reg##_##field##_##MASK, GMAC_##reg##_##field##_##OFFSET, value)
- +#define GMAC_GET_FIELD(reg, field) GET_FIELD(GMAC_REG_##reg, GMAC_##reg##_##field##_##MASK, GMAC_##reg##_##field##_##OFFSET)
- +#define GMAC_TEST_FIELD(reg, field) TEST_FIELD(GMAC_REG_##reg, GMAC_##reg##_##field##_##MASK)
- +
- +#define GMAC_SET_REG(reg, value) SET_REG(GMAC_REG_##reg, value)
- +#define GMAC_GET_REG(reg) GET_REG(GMAC_REG_##reg)
- +#define GMAC_TEST_BIT(reg, field, value) VAR_TEST_BIT(value, GMAC_##reg##_##field##_##MASK)
- +
- +#define GMAC_EXTRACT(reg, field, value) EXTRACT_FIELD(value, GMAC_##reg##_##field##_##MASK, GMAC_##reg##_##field##_##OFFSET )
- +#define GMAC_PREPARE(reg, field, value) PREPARE_FIELD(value, GMAC_##reg##_##field##_##MASK, GMAC_##reg##_##field##_##OFFSET )
- +
- +#define GMAC_DEFAULT(reg, field) PREPARE_FIELD(GMAC_##reg##_##field##_##DEFAULT, GMAC_##reg##_##field##_##MASK, GMAC_##reg##_##field##_##OFFSET )
- +
- +#define GMAC_TEST_SIG(var, sig) VAR_TEST_BIT(var, GMAC_ISR_SIG_##sig)
- +#define GMAC_SET_SIG(var, sig) VAR_SET_BIT(var, GMAC_ISR_SIG_##sig)
- +#define GMAC_CLR_SIG(var, sig) VAR_CLR_BIT(var, GMAC_ISR_SIG_##sig)
- +
- +#define FTGMAC100_MEM_BASE (CPE_DDR2_MEM_BASE + 0x00700000) //new: higher space of RAM
- +#define FTGMAC100_TXR_BASE (FTGMAC100_MEM_BASE) // 2048 des., 4 byte, 4 DWs
- +#define FTGMAC100_RXR_BASE (FTGMAC100_MEM_BASE+ 4096*4*4*2) // offset 2 BASE ADDRESS
- +#define FTGMAC100_TXBUF_BASE (FTGMAC100_MEM_BASE+ 0x100000) // offset 2 SIZE ADDRESS
- +#define FTGMAC100_RXBUF_BASE (FTGMAC100_MEM_BASE+ 0x400000) // offset 3 SIZE ADDRESS
- +
- +#define FTGMAC100_DESCRIPTOR_BYTE 16
- +#define FTGMAC100_RXBUF_SIZE 1024
- +
- +//#define GMAC_DAH (0xef12)
- +//#define GMAC_DAL (0x3456789a)
- +#define GMAC_DAH (0x5555)
- +#define GMAC_DAL (0x55555555)
- +
- +// ======================================================
- +// DAVICOM DM9161A PHY register definition
- +// ======================================================
- +#define DVC_PHY_ID (0x0181b8a0)
- +#define DVC_PHY_ADDR (0x0)
- +#define DVC_PHY_REG_CTL (0)
- +#define DVC_PHY_REG_STS (1)
- +#define DVC_PHY_REG_CFG (17)
- +#define DVC_PHY_REG_CTL_SW_RST (0x1<<15)
- +#define DVC_PHY_REG_CTL_AN_EN (0x1<<12)
- +#define DVC_PHY_REG_CTL_AN_RST (0x1<<9)
- +#define DVC_PHY_REG_CTL_LOOPBACK (0x1<<14)
- +
- +// ======================================================
- +// Marvell 88E1119R GPHY register definition
- +// ======================================================
- +#define MAR_GPHY_ID (0x01410e80)
- +#define MAR_GPHY_ADDR (0x1f)
- +#define MAR_GPHY_REG_CTL (0)
- +#define MAR_GPHY_REG_STS (1)
- +#define MAR_GPHY_REG_ID0 (2)
- +#define MAR_GPHY_REG_ID1 (3)
- +#define MAR_GPHY_REG_LPA (5)
- +#define MAR_GPHY_REG_COP_CTL (16) // page 0
- +#define MAR_GPHY_REG_MAC1 (16) // page 2
- +#define MAR_GPHY_REG_LED_CTL (16) // page 3
- +#define MAR_GPHY_REG_PKT_GEN (16) // page 6
- +#define MAR_GPHY_REG_COP_STS1 (17) // page 0
- +#define MAR_GPHY_REG_LED_POLAR (17) // page 3
- +#define MAR_GPHY_REG_COP_STS2 (19) // page 0
- +#define MAR_GPHY_REG_MAC2 (21) // page 2
- +#define MAR_GPHY_REG_MAC_INT_EN (18) // page 0
- +#define MAR_GPHY_REG_MAC_STS (19) // page 2
- +#define MAR_GPHY_REG_PAGE (22)
- +
- +#define MAR_GPHY_REG_CTL_SW_RST (0x1<<15)
- +#define MAR_GPHY_REG_CTL_AN_EN (0x1<<12)
- +#define MAR_GPHY_REG_CTL_START_AN (0x1<<9)
- +#define MAR_GPHY_REG_CTL_FULL_DUP (0x1<<8)
- +#define MAR_GPHY_REG_CTL_LOOPBACK (0x1<<14)
- +#define MAR_GPHY_REG_CTL_SPEED ((0x1<<13)|(0x1<<6))
- +#define MAR_GPHY_REG_CTL_SPEED_1000M (0x1<<6)
- +#define MAR_GPHY_REG_CTL_SPEED_100M (0x1<<13)
- +#define MAR_GPHY_REG_CTL_SPEED_10M (0x0)
- +#define MAR_GPHY_REG_STS_AN_COMPLETE (0x1<<5)
- +#define MAR_GPHY_REG_MAC1_CLK125_DIS (0x1<<2)
- +#define MAR_GPHY_REG_MAC2_SPEED (0x7)
- +#define MAR_GPHY_REG_MAC2_SPEED_1000M (0x6)
- +#define MAR_GPHY_REG_MAC2_SPEED_100M (0x1) //(0x5)
- +#define MAR_GPHY_REG_MAC2_SPEED_10M (0x4)
- +#define MAR_GPHY_REG_MAC2_LINE_LOOPBACK (0x1<<14)
- +#define MAR_GPHY_REG_EN_STUB (0x1<<5)
- +
- +typedef struct {
- + UINT8 speed; // 0=10Mbps, 1=100Mbps, 2=1000Mbps
- + UINT8 duplex; // 0=half, 1=full
- +} ETH_PHY_STAT;
- +
- +
- +INT32 gmac_test_main();
- +INT32 gmac_stress_main(UINT32 test_item, UINT32 test_cnt);
- +INT32 gmac_phy_check();
- +INT32 gmac_phy_pwr_ctl(UINT32 pwr);
- +
- +void eth_mac_init(ETH_PHY_STAT *phy_stat);
- +void eth_mac_config(UINT32 type);
- +void eth_mac_register_dump();
- +INT32 eth_mac_interrupt_setup();
- +
- +INT32 eth_phy_detect(UINT32* phy_addr, UINT32* phy_id);
- +INT32 eth_phy_hook_driver (UINT32 phy_id);
- +
- +void eth_phy_init_mar(UINT32 phy_addr);
- +void eth_phy_init_dvc(UINT32 phy_addr);
- +//typedef void (*FP_ETH_PHY_INIT)(UINT32 phy_addr);
- +
- +void eth_phy_config_dvc(UINT32 type, UINT32 phy_addr);
- +void eth_phy_config_mar(UINT32 type, UINT32 phy_addr);
- +//typedef void (*FP_ETH_PHY_CONFIG)(UINT32 type, UINT32 phy_addr);
- +
- +UINT32 eth_phy_stat_dvc(UINT32 phy_addr, ETH_PHY_STAT *phy_stat);
- +UINT32 eth_phy_stat_mar(UINT32 phy_addr, ETH_PHY_STAT *phy_stat);
- +//typedef UINT32 (*FP_ETH_PHY_STAT)(UINT32 phy_addr, ETH_PHY_STAT *phy_stat);
- +
- +//typedef UINT32 (*FP_ETH_PHY_REG_READ)(UINT32 phy_addr, UINT32 phy_page, UINT32 phy_reg, UINT32 *phy_data);
- +//typedef UINT32 (*FP_ETH_PHY_REG_WRITE)(UINT32 phy_addr, UINT32 phy_page, UINT32 phy_reg, UINT32 phy_data);
- +
- +//extern FP_ETH_PHY_CONFIG eth_phy_config;
- +//extern FP_ETH_PHY_INIT eth_phy_init;
- +//extern FP_ETH_PHY_STAT eth_phy_stat;
- +//extern FP_ETH_PHY_REG_WRITE eth_phy_reg_write;
- +//extern FP_ETH_PHY_REG_READ eth_phy_reg_read;
- +
- +
- +#endif // __GMAC_H
- \ No newline at end of file
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/Kconfig linux-3.4.110/arch/nds32/platforms/ag102/Kconfig
- --- linux-3.4.110.orig/arch/nds32/platforms/ag102/Kconfig 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag102/Kconfig 2016-04-07 10:20:51.002083345 +0200
- @@ -0,0 +1,16 @@
- +menu "AG102 Platform Options"
- +
- +config CACHE_L2
- + bool "Support L2 cache"
- + default y
- +
- +config LPC
- + bool "LPC support"
- +
- +config AUTO_SYS_CLK
- + bool "Automatic AHB Clock Detection"
- + default y
- + help
- + Automatic detection of AHB clock
- +
- +endmenu
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/lpc.c linux-3.4.110/arch/nds32/platforms/ag102/lpc.c
- --- linux-3.4.110.orig/arch/nds32/platforms/ag102/lpc.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag102/lpc.c 2016-04-07 10:20:51.002083345 +0200
- @@ -0,0 +1,230 @@
- +#include <linux/irq.h>
- +#include <linux/interrupt.h>
- +#include <linux/delay.h>
- +
- +#include <asm/spec.h>
- +
- +#define LPC_REG_SCR 0x10
- +#define LPC_REG_SIR 0x14
- +#define LPC_REG_SIMR 0x18
- +
- +/*
- + * Level trigger IRQ chip methods
- + */
- +
- +static void lpc_level_unmask_irq(unsigned int irq)
- +{
- + unsigned int val;
- +// *(volatile unsigned int *) (LPC_REG_BASE + LPC_REG_SIR) =
- +// 1 << (irq - PLATFORM_LPC_IRQ_BASE);
- + val = *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIMR);
- + val &= ~(1 << (irq - PLATFORM_LPC_IRQ_BASE));
- + *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIMR) = val;
- +}
- +
- +static void lpc_level_mask_irq(unsigned int irq)
- +{
- + unsigned int val;
- + val = *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIMR);
- + val |= 1 << (irq - PLATFORM_LPC_IRQ_BASE);
- + *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIMR) = val;
- +}
- +
- +static void lpc_level_ack_irq(unsigned int irq)
- +{
- + *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIR) =
- + 1 << (irq - PLATFORM_LPC_IRQ_BASE);
- +}
- +
- +static struct irq_chip lpc_simple_chip = {
- + .ack = lpc_level_ack_irq,
- + .mask = lpc_level_mask_irq,
- + .unmask = lpc_level_unmask_irq,
- +};
- +
- +void lpc_irq_rounter(unsigned int irq, struct irq_desc *desc)
- +{
- + unsigned int lpc_status;
- + unsigned int lpc_mask;
- + unsigned int lpc_irq;
- + int i;
- + struct irq_desc *lpc_desc;
- +
- + desc->chip->mask(irq);
- + desc->chip->ack(irq);
- +
- + lpc_status = *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIR);
- + lpc_mask = *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIMR);
- + *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIMR) = 0xffffffff;
- + for (i = 0; i < PLATFORM_LPC_IRQ_TOTALCOUNT; i++) {
- + if (!(~lpc_mask & (1 << i) & lpc_status))
- + continue;
- + lpc_irq = PLATFORM_LPC_IRQ_BASE + i;
- + lpc_desc = irq_desc + lpc_irq;
- + lpc_desc->handle_irq(lpc_irq, lpc_desc);
- + *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIR) =
- + 1 << i;
- + }
- + *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIMR) = lpc_mask;
- +
- + desc->chip->unmask(irq);
- +}
- +
- +int __init lpc_init_irq(void)
- +{
- + int i;
- +
- + *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SCR) = 0x1f3;
- + /* Register all IRQ */
- + for (i = PLATFORM_LPC_IRQ_BASE;
- + i < PLATFORM_LPC_IRQ_BASE + PLATFORM_LPC_IRQ_TOTALCOUNT; i++) {
- + // level trigger
- + set_irq_chip(i, &lpc_simple_chip);
- + set_irq_handler(i, handle_simple_irq);
- +
- + }
- + set_irq_chained_handler(LPC_IRQ, lpc_irq_rounter);
- +
- + return 0;
- +}
- +
- +device_initcall(lpc_init_irq);
- +
- +#define ITE_ADDR 0x2e
- +#define ITE_DATA 0x2f
- +void outlpc(unsigned int addr, unsigned int data)
- +{
- + *(volatile unsigned int *)(LPC_IO_VA_BASE + 4 * addr) = data;
- +}
- +
- +unsigned int inlpc(unsigned int addr)
- +{
- + return *(volatile unsigned int *)(LPC_IO_VA_BASE + 4 * addr);
- +}
- +
- +int __init ite8717_init(void)
- +{
- + unsigned char data1, data2;
- + unsigned int count;
- + /* enter configure mode */
- + outlpc(ITE_ADDR, 0x87);
- + outlpc(ITE_ADDR, 0x01);
- + outlpc(ITE_ADDR, 0x55);
- + outlpc(ITE_ADDR, 0x55);
- + /* check chip */
- + outlpc(ITE_ADDR, 0x20);
- + data1 = inlpc(ITE_DATA);
- + outlpc(ITE_ADDR, 0x21);
- + data2 = inlpc(ITE_DATA);
- + if ((data1 != 0x87) && (data2 != 0x17))
- + goto not_found;
- + /* earlyio program */
- + outlpc(ITE_ADDR, 0x07); // LDN=0 -> FDC
- + outlpc(ITE_DATA, 0x00);
- + outlpc(ITE_ADDR, 0x30); // Enable FDC
- + outlpc(ITE_DATA, 0x01);
- + outlpc(ITE_ADDR, 0xf1); // Set (Index 0F1h) = 90h
- + outlpc(ITE_DATA, 0x80);
- +
- + outlpc(0x64, 0xaa); // Send KBC self-test command
- + count = 0;
- + do {
- + if (count++ > 0x10000)
- + break;
- + data1 = ~inlpc(0x64);
- + } while (data1 & 0x01);
- + data2 = inlpc(0x60);
- + outlpc(0x64, 0xcb); // Set PS2 mode
- + count = 0;
- + do {
- + if (count++ > 0x10000)
- + break;
- + data1 = inlpc(0x64);
- + } while (data1 & 0x02);
- + outlpc(0x60, 0x01);
- + count = 0;
- + do {
- + if (count++ > 0x10000)
- + break;
- + data1 = inlpc(0x64);
- + } while (data1 & 0x02);
- + outlpc(0x64, 0x60); // 60h = write 8042 command byte
- + count = 0;
- + do {
- + if (count++ > 0x10000)
- + break;
- + data1 = inlpc(0x64);
- + } while (data1 & 0x02);
- + outlpc(0x60, 0x45); // AT interface, keyboard enabled, system flag
- + count = 0;
- + do {
- + if (count++ > 0x10000)
- + break;
- + data1 = inlpc(0x64);
- + } while (data1 & 0x02);
- + outlpc(0x64, 0xae);
- + count = 0;
- + do {
- + if (count++ > 0x10000)
- + break;
- + data1 = ~inlpc(0x64);
- + } while (data1 & 0x01);
- + outlpc(ITE_ADDR, 0x23);
- + outlpc(ITE_DATA, 0x00);
- +
- + outlpc(ITE_ADDR, 0x07);
- + outlpc(ITE_DATA, 0x04);
- + outlpc(ITE_ADDR, 0xf0);
- + data1 = inlpc(ITE_DATA);
- + data1 &= 0x18;
- + data1 |= 0x0;
- + outlpc(ITE_DATA, data1);
- + outlpc(ITE_ADDR, 0xf2);
- + data1 = inlpc(ITE_DATA);
- + data1 &= 0x2e;
- + data1 |= 0xa;
- + outlpc(ITE_DATA, data1);
- + outlpc(ITE_ADDR, 0xf4);
- + data1 = inlpc(ITE_DATA);
- + data1 &= 0xaf;
- + data1 |= 0x80;
- + outlpc(ITE_DATA, data1);
- + outlpc(ITE_ADDR, 0xf5);
- + data1 = inlpc(ITE_DATA);
- + data1 &= 0x3f;
- + data1 |= 0x0;
- + outlpc(ITE_DATA, data1);
- + /* initialize all device */
- + outlpc(ITE_ADDR, 0x07);
- + outlpc(ITE_DATA, 0x04);
- + outlpc(ITE_ADDR, 0x30);
- + outlpc(ITE_DATA, 0x01);
- +#if 1
- + outlpc(ITE_ADDR, 0x07);
- + outlpc(ITE_DATA, 0x05);
- + outlpc(ITE_ADDR, 0xf0);
- + outlpc(ITE_DATA, 0x4e);
- + outlpc(ITE_ADDR, 0x71);
- + outlpc(ITE_DATA, 0x01);
- +#endif
- + outlpc(ITE_ADDR, 0x07);
- + outlpc(ITE_DATA, 0x06);
- + outlpc(ITE_ADDR, 0x30);
- + outlpc(ITE_DATA, 0x01);
- +#if 1
- + outlpc(ITE_ADDR, 0xf0);
- + outlpc(ITE_DATA, 0x01);
- + outlpc(ITE_ADDR, 0x71);
- + outlpc(ITE_DATA, 0x01);
- +#endif
- +
- + /* exit configure mode */
- + outlpc(ITE_ADDR, 0x02);
- + outlpc(ITE_DATA, 0x02);
- + return 0;
- +not_found:
- + printk("ITE8717 not found\n");
- + return -1;
- +}
- +
- +subsys_initcall(ite8717_init);
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/Makefile linux-3.4.110/arch/nds32/platforms/ag102/Makefile
- --- linux-3.4.110.orig/arch/nds32/platforms/ag102/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag102/Makefile 2016-04-07 10:20:51.002083345 +0200
- @@ -0,0 +1,5 @@
- +obj-y += devices.o ahbclkcal.o
- +obj-$(CONFIG_LPC) += lpc.o
- +obj-$(CONFIG_PM) += pm.o sleep.o
- +obj-$(CONFIG_AG102_CPU_FREQ_FCS) += cpu-fcs.o
- +obj-$(CONFIG_AG102_CPU_FREQ_SCALING_MODE) += freq-scaling.o
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/pcu.h linux-3.4.110/arch/nds32/platforms/ag102/pcu.h
- --- linux-3.4.110.orig/arch/nds32/platforms/ag102/pcu.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag102/pcu.h 2016-04-07 10:20:51.002083345 +0200
- @@ -0,0 +1,1887 @@
- +#ifndef __PCU_H
- +#define __PCU_H
- +#include <asm/spec.h>
- +#define CPE_PCU_BASE PCU_VA_BASE
- +//Data type
- +typedef enum Bool {
- + FALSE,
- + TRUE
- +} BOOL;
- +
- +typedef enum {
- + SUCCESS=0,
- + FAIL
- +} STATUS;
- +
- +typedef unsigned char UINT8;
- +typedef char INT8;
- +typedef unsigned short UINT16;
- +typedef short INT16;
- +typedef unsigned int UINT32;
- +typedef int INT32;
- +typedef unsigned long long UINT64;
- +typedef long long INT64;
- +
- +//Registion IO operation macro
- +#define REG32(a) (*(volatile UINT32 *)(a))
- +#define REG16(a) (*(volatile UINT16 *)(a))
- +#define REG8(a) (*(volatile UINT8 *)(a))
- +
- +#define inb(a) REG8(a)
- +#define inhw(a) REG16(a)
- +#define inw(a) REG32(a)
- +
- +#define outb(a, v) (REG8(a) = (UINT8)(v))
- +#define outhw(a, v) (REG16(a) = (UINT16)(v))
- +#define outw(a, v) (REG32(a) = (UINT32)(v))
- +
- +
- +// Register bit operation macro
- +#define ANDES_BIT_MASK(bit_h, bit_l) ((((UINT32)0x1<<(1+bit_h-bit_l))-(UINT32)0x1)<<bit_l)
- +
- +
- +#define SET_BIT(addr, bit) do { outw(addr, (inw(addr) | (0x1<<(bit)))); } while(0)
- +#define CLR_BIT(addr, bit) do { outw(addr, (inw(addr) & (~(0x1<<(bit))))); } while(0)
- +
- +#define SET_FIELD(addr, mask, offset, value) do {\
- + outw(addr, ((inw(addr) & (~mask)) | (((value) << (offset)) &(mask)))); \
- + } while (0)
- +#define GET_FIELD(addr, mask, offset) ((inw(addr)&(mask))>> (offset))
- +
- +#define TEST_FIELD(addr, mask) (inw(addr)&(mask))
- +
- +#define SET_REG(addr, value) do { outw(addr, value); } while (0)
- +#define GET_REG(addr) (inw(addr))
- +
- +#define CHECK_FIELD(value, mask) ( (value)&(mask) )
- +#define EXTRACT_FIELD(value, mask, offset) ( ((value)&(mask))>>(offset) )
- +#define PREPARE_FIELD(value, mask, offset) ( ((value)<<(offset))&(mask) )
- +
- +
- +// Variable bit operation macro
- +#define VAR_TEST_BIT(var, sig) ((var)&(sig))
- +#define VAR_SET_BIT(var, sig) ((var) = (var)|(sig))
- +#define VAR_CLR_BIT(var, sig) ((var) = (var)&(~(sig)))
- +// ============================
- +// PCU register definition
- +// ============================
- +#define PCU_REG_VER (CPE_PCU_BASE+0x000) //version
- +#define PCU_REG_SPINFO (CPE_PCU_BASE+0x004) //scartch pad information
- +#define PCU_REG_SOCID (CPE_PCU_BASE+0x010) //SoC ID
- +#define PCU_REG_AHB_CFG (CPE_PCU_BASE+0x014) //AHB device configuration
- +#define PCU_REG_APB_CFG (CPE_PCU_BASE+0x018) //APB device configuration
- +#define PCU_REG_DCSR0 (CPE_PCU_BASE+0x020) //driving capability and slew rate control 0
- +#define PCU_REG_DCSR1 (CPE_PCU_BASE+0x024) //driving capability and slew rate control 1
- +#define PCU_REG_DCSR2 (CPE_PCU_BASE+0x028) //driving capability and slew rate control 2
- +#define PCU_REG_MFPS0 (CPE_PCU_BASE+0x030) //multi-function port setting 0
- +#define PCU_REG_MFPS1 (CPE_PCU_BASE+0x034) //multi-function port setting 1
- +#define PCU_REG_DMA_SEL (CPE_PCU_BASE+0x038) //dma engin selection
- +#define PCU_REG_OSC_CTRL (CPE_PCU_BASE+0x040) //OSC control register
- +#define PCU_REG_PWM_DIV (CPE_PCU_BASE+0x044) //PWM clock divider value
- +#define PCU_REG_MISC (CPE_PCU_BASE+0x048) //misc register
- +#define PCU_REG_BSM_CTRL (CPE_PCU_BASE+0x080) //BSM control register
- +#define PCU_REG_BSM_STATUS (CPE_PCU_BASE+0x084) //BSM status
- +#define PCU_REG_WAKEUP_SEN (CPE_PCU_BASE+0x088) //wakeup event signal sensitivity
- +#define PCU_REG_WAKEUP_STATUS (CPE_PCU_BASE+0x08c) //wakeup event status
- +#define PCU_REG_RESET_TIMER (CPE_PCU_BASE+0x090) //reset timer register
- +#define PCU_REG_INTR (CPE_PCU_BASE+0x094) //interrup register
- +#define PCU_REG_PCS1_CFG (CPE_PCU_BASE+0x0a0)
- +#define PCU_REG_PCS1_PARA (CPE_PCU_BASE+0x0a4)
- +#define PCU_REG_PCS1_ST1 (CPE_PCU_BASE+0x0a8)
- +#define PCU_REG_PCS1_ST2 (CPE_PCU_BASE+0x0ac)
- +#define PCU_REG_PCS1_PDD (CPE_PCU_BASE+0x0b0)
- +#define PCU_REG_PCS2_CFG (CPE_PCU_BASE+0x0c0)
- +#define PCU_REG_PCS2_PARA (CPE_PCU_BASE+0x0c4)
- +#define PCU_REG_PCS2_ST1 (CPE_PCU_BASE+0x0c8)
- +#define PCU_REG_PCS2_ST2 (CPE_PCU_BASE+0x0cc)
- +#define PCU_REG_PCS2_PDD (CPE_PCU_BASE+0x0d0)
- +#define PCU_REG_PCS3_CFG (CPE_PCU_BASE+0x0e0)
- +#define PCU_REG_PCS3_PARA (CPE_PCU_BASE+0x0e4)
- +#define PCU_REG_PCS3_ST1 (CPE_PCU_BASE+0x0e8)
- +#define PCU_REG_PCS3_ST2 (CPE_PCU_BASE+0x0ec)
- +#define PCU_REG_PCS3_PDD (CPE_PCU_BASE+0x0f0)
- +#define PCU_REG_PCS4_CFG (CPE_PCU_BASE+0x100)
- +#define PCU_REG_PCS4_PARA (CPE_PCU_BASE+0x104)
- +#define PCU_REG_PCS4_ST1 (CPE_PCU_BASE+0x108)
- +#define PCU_REG_PCS4_ST2 (CPE_PCU_BASE+0x10c)
- +#define PCU_REG_PCS4_PDD (CPE_PCU_BASE+0x110)
- +#define PCU_REG_PCS5_CFG (CPE_PCU_BASE+0x120)
- +#define PCU_REG_PCS5_PARA (CPE_PCU_BASE+0x124)
- +#define PCU_REG_PCS5_ST1 (CPE_PCU_BASE+0x128)
- +#define PCU_REG_PCS5_ST2 (CPE_PCU_BASE+0x12c)
- +#define PCU_REG_PCS5_PDD (CPE_PCU_BASE+0x130)
- +#define PCU_REG_PCS6_CFG (CPE_PCU_BASE+0x140)
- +#define PCU_REG_PCS6_PARA (CPE_PCU_BASE+0x144)
- +#define PCU_REG_PCS6_ST1 (CPE_PCU_BASE+0x148)
- +#define PCU_REG_PCS6_ST2 (CPE_PCU_BASE+0x14c)
- +#define PCU_REG_PCS6_PDD (CPE_PCU_BASE+0x150)
- +#define PCU_REG_PCS7_CFG (CPE_PCU_BASE+0x160)
- +#define PCU_REG_PCS7_PARA (CPE_PCU_BASE+0x164)
- +#define PCU_REG_PCS7_ST1 (CPE_PCU_BASE+0x168)
- +#define PCU_REG_PCS7_ST2 (CPE_PCU_BASE+0x16c)
- +#define PCU_REG_PCS7_PDD (CPE_PCU_BASE+0x170)
- +#define PCU_REG_PCS8_CFG (CPE_PCU_BASE+0x180)
- +#define PCU_REG_PCS8_PARA (CPE_PCU_BASE+0x184)
- +#define PCU_REG_PCS8_ST1 (CPE_PCU_BASE+0x188)
- +#define PCU_REG_PCS8_ST2 (CPE_PCU_BASE+0x18c)
- +#define PCU_REG_PCS8_PDD (CPE_PCU_BASE+0x190)
- +#define PCU_REG_PCS9_CFG (CPE_PCU_BASE+0x1a0)
- +#define PCU_REG_PCS9_PARA (CPE_PCU_BASE+0x1a4)
- +#define PCU_REG_PCS9_ST1 (CPE_PCU_BASE+0x1a8)
- +#define PCU_REG_PCS9_ST2 (CPE_PCU_BASE+0x1ac)
- +#define PCU_REG_PCS9_PDD (CPE_PCU_BASE+0x1b0)
- +
- +#define PCU_SCRATCH_OFFSET_SHIFT (8)
- +#define PCU_SCRATCH_SIZE_SHIFT (2) // in byte, 2 means (1<<2) = 4 bytes
- +#define PCU_REG_SCRATCH_MEM (CPE_PCU_BASE+ (PCU_SPINFO_OFFSET_DEFAULT<<PCU_SCRATCH_OFFSET_SHIFT) )
- +
- +// revision register
- +#define PCU_VER_VER_MASK (ANDES_BIT_MASK(31, 16))
- +#define PCU_VER_VER_OFFSET (16)
- +#define PCU_VER_VER_DEFAULT (0x1)
- +#define PCU_VER_PCSNO_MASK (ANDES_BIT_MASK(7, 0))
- +#define PCU_VER_PCSNO_OFFSET (0)
- +#define PCU_VER_PCSNO_DEFAULT (0x9)
- +#define PCU_VER_DEFAULT ((PCU_VER_VER_DEFAULT << PCU_VER_VER_OFFSET ) |\
- + (PCU_VER_PCSNO_DEFAULT << PCU_VER_PCSNO_OFFSET))
- +
- +//scratch pad info
- +#define PCU_SPINFO_OFFSET_MASK (ANDES_BIT_MASK(11, 8))
- +#define PCU_SPINFO_OFFSET_OFFSET (8)
- +#define PCU_SPINFO_OFFSET_DEFAULT (0x4)
- +#define PCU_SPINFO_SIZE_MASK (ANDES_BIT_MASK(7, 0))
- +#define PCU_SPINFO_SIZE_OFFSET (0)
- +#define PCU_SPINFO_SIZE_DEFAULT (0x40)
- +#define PCU_SPINFO_DEFAULT ((PCU_SPINFO_OFFSET_DEFAULT << PCU_SPINFO_OFFSET_OFFSET) |\
- + (PCU_SPINFO_SIZE_DEFAULT << PCU_SPINFO_SIZE_OFFSET ))
- +
- +// revision register
- +#define PCU_SOCID_DEV_MASK (ANDES_BIT_MASK(31, 16))
- +#define PCU_SOCID_DEV_OFFSET (16)
- +#define PCU_SOCID_DEV_DEFAULT (0x102)
- +#define PCU_SOCID_MAJ_MASK (ANDES_BIT_MASK(15, 4))
- +#define PCU_SOCID_MAJ_OFFSET (4)
- +#define PCU_SOCID_MAJ_DEFAULT (0x1)
- +#define PCU_SOCID_MIN_MASK (ANDES_BIT_MASK(3, 0))
- +#define PCU_SOCID_MIN_OFFSET (0)
- +#define PCU_SOCID_MIN_DEFAULT (0x0)
- +#define PCU_SOCID_DEFAULT ((PCU_SOCID_DEV_DEFAULT << PCU_SOCID_DEV_OFFSET) |\
- + (PCU_SOCID_MAJ_DEFAULT << PCU_SOCID_MAJ_OFFSET) |\
- + (PCU_SOCID_MIN_DEFAULT << PCU_SOCID_MIN_OFFSET))
- +
- +// AHB configuration
- +#define PCU_AHB_CFG_AHB2AHB_MEM3_MASK (ANDES_BIT_MASK(31, 31))
- +#define PCU_AHB_CFG_AHB2AHB_MEM3_OFFSET (31)
- +#define PCU_AHB_CFG_AHB2AHB_MEM3_DEFAULT (0x1)
- +#define PCU_AHB_CFG_AHB2AHB_MEM2_MASK (ANDES_BIT_MASK(30, 30))
- +#define PCU_AHB_CFG_AHB2AHB_MEM2_OFFSET (30)
- +#define PCU_AHB_CFG_AHB2AHB_MEM2_DEFAULT (0x1)
- +#define PCU_AHB_CFG_AHB2AHB_MEM1_MASK (ANDES_BIT_MASK(29, 29))
- +#define PCU_AHB_CFG_AHB2AHB_MEM1_OFFSET (29)
- +#define PCU_AHB_CFG_AHB2AHB_MEM1_DEFAULT (0x1)
- +#define PCU_AHB_CFG_AHB2AHB_MEM0_MASK (ANDES_BIT_MASK(28, 28))
- +#define PCU_AHB_CFG_AHB2AHB_MEM0_OFFSET (28)
- +#define PCU_AHB_CFG_AHB2AHB_MEM0_DEFAULT (0x1)
- +#define PCU_AHB_CFG_AHB2AHB_REG_MASK (ANDES_BIT_MASK(27, 27))
- +#define PCU_AHB_CFG_AHB2AHB_REG_OFFSET (27)
- +#define PCU_AHB_CFG_AHB2AHB_REG_DEFAULT (0x1)
- +#define PCU_AHB_CFG_L2CC_MASK (ANDES_BIT_MASK(20, 20))
- +#define PCU_AHB_CFG_L2CC_OFFSET (20)
- +#define PCU_AHB_CFG_L2CC_DEFAULT (0x1)
- +#define PCU_AHB_CFG_PCI_MEM_MASK (ANDES_BIT_MASK(19, 19))
- +#define PCU_AHB_CFG_PCI_MEM_OFFSET (19)
- +#define PCU_AHB_CFG_PCI_MEM_DEFAULT (0x1)
- +#define PCU_AHB_CFG_PCI_IO_MASK (ANDES_BIT_MASK(18, 18))
- +#define PCU_AHB_CFG_PCI_IO_OFFSET (18)
- +#define PCU_AHB_CFG_PCI_IO_DEFAULT (0x1)
- +#define PCU_AHB_CFG_LPC_REG_MASK (ANDES_BIT_MASK(17, 17))
- +#define PCU_AHB_CFG_LPC_REG_OFFSET (17)
- +#define PCU_AHB_CFG_LPC_REG_DEFAULT (0x1)
- +#define PCU_AHB_CFG_LPC_IO_MASK (ANDES_BIT_MASK(16, 16))
- +#define PCU_AHB_CFG_LPC_IO_OFFSET (16)
- +#define PCU_AHB_CFG_LPC_IO_DEFAULT (0x1)
- +#define PCU_AHB_CFG_INTC_MASK (ANDES_BIT_MASK(15, 15))
- +#define PCU_AHB_CFG_INTC_OFFSET (15)
- +#define PCU_AHB_CFG_INTC_DEFAULT (0x1)
- +#define PCU_AHB_CFG_USB_MASK (ANDES_BIT_MASK(14, 14))
- +#define PCU_AHB_CFG_USB_OFFSET (14)
- +#define PCU_AHB_CFG_USB_DEFAULT (0x1)
- +#define PCU_AHB_CFG_IDE_MASK (ANDES_BIT_MASK(13, 13))
- +#define PCU_AHB_CFG_IDE_OFFSET (13)
- +#define PCU_AHB_CFG_IDE_DEFAULT (0x1)
- +#define PCU_AHB_CFG_GMAC_MASK (ANDES_BIT_MASK(12, 12))
- +#define PCU_AHB_CFG_GMAC_OFFSET (12)
- +#define PCU_AHB_CFG_GMAC_DEFAULT (0x1)
- +#define PCU_AHB_CFG_GPU_MASK (ANDES_BIT_MASK(9, 9))
- +#define PCU_AHB_CFG_GPU_OFFSET (9)
- +#define PCU_AHB_CFG_GPU_DEFAULT (0x1)
- +#define PCU_AHB_CFG_DLM2_MASK (ANDES_BIT_MASK(8, 8))
- +#define PCU_AHB_CFG_DLM2_OFFSET (8)
- +#define PCU_AHB_CFG_DLM2_DEFAULT (0x1)
- +#define PCU_AHB_CFG_DMAC_MASK (ANDES_BIT_MASK(7, 7))
- +#define PCU_AHB_CFG_DMAC_OFFSET (7)
- +#define PCU_AHB_CFG_DMAC_DEFAULT (0x1)
- +#define PCU_AHB_CFG_DDR2_MEM_MASK (ANDES_BIT_MASK(6, 6))
- +#define PCU_AHB_CFG_DDR2_MEM_OFFSET (6)
- +#define PCU_AHB_CFG_DDR2_MEM_DEFAULT (0x1)
- +#define PCU_AHB_CFG_DDR2C_MASK (ANDES_BIT_MASK(5, 5))
- +#define PCU_AHB_CFG_DDR2C_OFFSET (5)
- +#define PCU_AHB_CFG_DDR2C_DEFAULT (0x1)
- +#define PCU_AHB_CFG_SPI_MASK (ANDES_BIT_MASK(4, 4))
- +#define PCU_AHB_CFG_SPI_OFFSET (4)
- +#define PCU_AHB_CFG_SPI_DEFAULT (0x1)
- +#define PCU_AHB_CFG_DLM1_MASK (ANDES_BIT_MASK(3, 3))
- +#define PCU_AHB_CFG_DLM1_OFFSET (3)
- +#define PCU_AHB_CFG_DLM1_DEFAULT (0x1)
- +#define PCU_AHB_CFG_APB_MASK (ANDES_BIT_MASK(2, 2))
- +#define PCU_AHB_CFG_APB_OFFSET (2)
- +#define PCU_AHB_CFG_APB_DEFAULT (0x1)
- +#define PCU_AHB_CFG_APBREG_MASK (ANDES_BIT_MASK(1, 1))
- +#define PCU_AHB_CFG_APBREG_OFFSET (1)
- +#define PCU_AHB_CFG_APBREG_DEFAULT (0x1)
- +#define PCU_AHB_CFG_AHBC_MASK (ANDES_BIT_MASK(0, 0))
- +#define PCU_AHB_CFG_AHBC_OFFSET (0)
- +#define PCU_AHB_CFG_AHBC_DEFAULT (0x1)
- +#define PCU_AHB_CFG_DEFAULT ((PCU_AHB_CFG_AHB2AHB_MEM3_DEFAULT << PCU_AHB_CFG_AHB2AHB_MEM3_OFFSET) |\
- + (PCU_AHB_CFG_AHB2AHB_MEM2_DEFAULT << PCU_AHB_CFG_AHB2AHB_MEM2_OFFSET) |\
- + (PCU_AHB_CFG_AHB2AHB_MEM1_DEFAULT << PCU_AHB_CFG_AHB2AHB_MEM1_OFFSET) |\
- + (PCU_AHB_CFG_AHB2AHB_MEM0_DEFAULT << PCU_AHB_CFG_AHB2AHB_MEM0_OFFSET) |\
- + (PCU_AHB_CFG_AHB2AHB_REG_DEFAULT << PCU_AHB_CFG_AHB2AHB_REG_OFFSET ) |\
- + (PCU_AHB_CFG_L2CC_DEFAULT << PCU_AHB_CFG_L2CC_OFFSET ) |\
- + (PCU_AHB_CFG_PCI_MEM_DEFAULT << PCU_AHB_CFG_PCI_MEM_OFFSET ) |\
- + (PCU_AHB_CFG_PCI_IO_DEFAULT << PCU_AHB_CFG_PCI_IO_OFFSET ) |\
- + (PCU_AHB_CFG_LPC_REG_DEFAULT << PCU_AHB_CFG_LPC_REG_OFFSET ) |\
- + (PCU_AHB_CFG_LPC_IO_DEFAULT << PCU_AHB_CFG_LPC_IO_OFFSET ) |\
- + (PCU_AHB_CFG_INTC_DEFAULT << PCU_AHB_CFG_INTC_OFFSET ) |\
- + (PCU_AHB_CFG_USB_DEFAULT << PCU_AHB_CFG_USB_OFFSET ) |\
- + (PCU_AHB_CFG_IDE_DEFAULT << PCU_AHB_CFG_IDE_OFFSET ) |\
- + (PCU_AHB_CFG_GMAC_DEFAULT << PCU_AHB_CFG_GMAC_OFFSET ) |\
- + (PCU_AHB_CFG_GPU_DEFAULT << PCU_AHB_CFG_GPU_OFFSET ) |\
- + (PCU_AHB_CFG_DLM2_DEFAULT << PCU_AHB_CFG_DLM2_OFFSET ) |\
- + (PCU_AHB_CFG_DMAC_DEFAULT << PCU_AHB_CFG_DMAC_OFFSET ) |\
- + (PCU_AHB_CFG_DDR2_MEM_DEFAULT << PCU_AHB_CFG_DDR2_MEM_OFFSET ) |\
- + (PCU_AHB_CFG_DDR2C_DEFAULT << PCU_AHB_CFG_DDR2C_OFFSET ) |\
- + (PCU_AHB_CFG_SPI_DEFAULT << PCU_AHB_CFG_SPI_OFFSET ) |\
- + (PCU_AHB_CFG_DLM1_DEFAULT << PCU_AHB_CFG_DLM1_OFFSET ) |\
- + (PCU_AHB_CFG_APB_DEFAULT << PCU_AHB_CFG_APB_OFFSET ) |\
- + (PCU_AHB_CFG_APBREG_DEFAULT << PCU_AHB_CFG_APBREG_OFFSET ) |\
- + (PCU_AHB_CFG_AHBC_DEFAULT << PCU_AHB_CFG_AHBC_OFFSET ))
- +
- +// APB configuration
- +#define PCU_APB_CFG_PWM_MASK (ANDES_BIT_MASK(23, 23))
- +#define PCU_APB_CFG_PWM_OFFSET (23)
- +#define PCU_APB_CFG_PWM_DEFAULT (0x1)
- +#define PCU_APB_CFG_I2C_MASK (ANDES_BIT_MASK(22, 22))
- +#define PCU_APB_CFG_I2C_OFFSET (22)
- +#define PCU_APB_CFG_I2C_DEFAULT (0x1)
- +#define PCU_APB_CFG_GPIO_MASK (ANDES_BIT_MASK(20, 20))
- +#define PCU_APB_CFG_GPIO_OFFSET (20)
- +#define PCU_APB_CFG_GPIO_DEFAULT (0x1)
- +#define PCU_APB_CFG_RTC_MASK (ANDES_BIT_MASK(19, 19))
- +#define PCU_APB_CFG_RTC_OFFSET (19)
- +#define PCU_APB_CFG_RTC_DEFAULT (0x1)
- +#define PCU_APB_CFG_WDT_MASK (ANDES_BIT_MASK(18, 18))
- +#define PCU_APB_CFG_WDT_OFFSET (18)
- +#define PCU_APB_CFG_WDT_DEFAULT (0x1)
- +#define PCU_APB_CFG_TMR_MASK (ANDES_BIT_MASK(17, 17))
- +#define PCU_APB_CFG_TMR_OFFSET (17)
- +#define PCU_APB_CFG_TMR_DEFAULT (0x1)
- +#define PCU_APB_CFG_PCU_MASK (ANDES_BIT_MASK(16, 16))
- +#define PCU_APB_CFG_PCU_OFFSET (16)
- +#define PCU_APB_CFG_PCU_DEFAULT (0x1)
- +#define PCU_APB_CFG_UART2_MASK (ANDES_BIT_MASK(8, 8))
- +#define PCU_APB_CFG_UART2_OFFSET (8)
- +#define PCU_APB_CFG_UART2_DEFAULT (0x1)
- +#define PCU_APB_CFG_AC97I2C_MASK (ANDES_BIT_MASK(6, 6))
- +#define PCU_APB_CFG_AC97I2C_OFFSET (6)
- +#define PCU_APB_CFG_AC97I2C_DEFAULT (0x1)
- +#define PCU_APB_CFG_SDC_MASK (ANDES_BIT_MASK(5, 5))
- +#define PCU_APB_CFG_SDC_OFFSET (5)
- +#define PCU_APB_CFG_SDC_DEFAULT (0x1)
- +#define PCU_APB_CFG_UART1_MASK (ANDES_BIT_MASK(3, 3))
- +#define PCU_APB_CFG_UART1_OFFSET (3)
- +#define PCU_APB_CFG_UART1_DEFAULT (0x1)
- +#define PCU_APB_CFG_SSP_MASK (ANDES_BIT_MASK(2, 2))
- +#define PCU_APB_CFG_SSP_OFFSET (2)
- +#define PCU_APB_CFG_SSP_DEFAULT (0x1)
- +#define PCU_APB_CFG_CFC_MASK (ANDES_BIT_MASK(1, 1))
- +#define PCU_APB_CFG_CFC_OFFSET (1)
- +#define PCU_APB_CFG_CFC_DEFAULT (0x1)
- +#define PCU_APB_CFG_DEFAULT ((PCU_APB_CFG_PWM_DEFAULT << PCU_APB_CFG_PWM_OFFSET ) |\
- + (PCU_APB_CFG_I2C_DEFAULT << PCU_APB_CFG_I2C_OFFSET ) |\
- + (PCU_APB_CFG_GPIO_DEFAULT << PCU_APB_CFG_GPIO_OFFSET ) |\
- + (PCU_APB_CFG_RTC_DEFAULT << PCU_APB_CFG_RTC_OFFSET ) |\
- + (PCU_APB_CFG_WDT_DEFAULT << PCU_APB_CFG_WDT_OFFSET ) |\
- + (PCU_APB_CFG_TMR_DEFAULT << PCU_APB_CFG_TMR_OFFSET ) |\
- + (PCU_APB_CFG_PCU_DEFAULT << PCU_APB_CFG_PCU_OFFSET ) |\
- + (PCU_APB_CFG_UART2_DEFAULT << PCU_APB_CFG_UART2_OFFSET ) |\
- + (PCU_APB_CFG_AC97I2C_DEFAULT << PCU_APB_CFG_AC97I2C_OFFSET) |\
- + (PCU_APB_CFG_SDC_DEFAULT << PCU_APB_CFG_SDC_OFFSET ) |\
- + (PCU_APB_CFG_UART1_DEFAULT << PCU_APB_CFG_UART1_OFFSET ) |\
- + (PCU_APB_CFG_SSP_DEFAULT << PCU_APB_CFG_SSP_OFFSET ) |\
- + (PCU_APB_CFG_CFC_DEFAULT << PCU_APB_CFG_CFC_OFFSET ))
- +
- +// Driving Capability and Slew Rate
- +#define PCU_DCSR0_GPU_MASK (ANDES_BIT_MASK(22, 20))
- +#define PCU_DCSR0_GPU_OFFSET (20)
- +#define PCU_DCSR0_GPU_DEFAULT (0xb)
- +#define PCU_DCSR0_GMAC_MASK (ANDES_BIT_MASK(19, 16))
- +#define PCU_DCSR0_GMAC_OFFSET (16)
- +#define PCU_DCSR0_GMAC_DEFAULT (0x3)
- +#define PCU_DCSR0_ULPI_MASK (ANDES_BIT_MASK(15, 12))
- +#define PCU_DCSR0_ULPI_OFFSET (12)
- +#define PCU_DCSR0_ULPI_DEFAULT (0xb)
- +#define PCU_DCSR0_LPC_MASK (ANDES_BIT_MASK(11, 8))
- +#define PCU_DCSR0_LPC_OFFSET (8)
- +#define PCU_DCSR0_LPC_DEFAULT (0xb)
- +#define PCU_DCSR0_PCIAHB_MASK (ANDES_BIT_MASK(4, 0))
- +#define PCU_DCSR0_PCIAHB_OFFSET (0)
- +#define PCU_DCSR0_PCIAHB_DEFAULT (0xb)
- +#define PCU_DCSR1_I2C_MASK (ANDES_BIT_MASK(3, 0))
- +#define PCU_DCSR1_I2C_OFFSET (0)
- +#define PCU_DCSR1_I2C_DEFAULT (0x9)
- +#define PCU_DCSR2_PCU_MASK (ANDES_BIT_MASK(31, 28))
- +#define PCU_DCSR2_PCU_OFFSET (28)
- +#define PCU_DCSR2_PCU_DEFAULT (0x3)
- +#define PCU_DCSR2_GPIO_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_DCSR2_GPIO_OFFSET (24)
- +#define PCU_DCSR2_GPIO_DEFAULT (0x9)
- +#define PCU_DCSR2_CFC_MASK (ANDES_BIT_MASK(23, 20))
- +#define PCU_DCSR2_CFC_OFFSET (20)
- +#define PCU_DCSR2_CFC_DEFAULT (0xb)
- +#define PCU_DCSR2_SD_MASK (ANDES_BIT_MASK(19, 16))
- +#define PCU_DCSR2_SD_OFFSET (16)
- +#define PCU_DCSR2_SD_DEFAULT (0xb)
- +#define PCU_DCSR2_SPI_MASK (ANDES_BIT_MASK(15, 12))
- +#define PCU_DCSR2_SPI_OFFSET (12)
- +#define PCU_DCSR2_SPI_DEFAULT (0x9)
- +#define PCU_DCSR2_AC97_MASK (ANDES_BIT_MASK(11, 8))
- +#define PCU_DCSR2_AC97_OFFSET (8)
- +#define PCU_DCSR2_AC97_DEFAULT (0xb)
- +#define PCU_DCSR2_UART2_MASK (ANDES_BIT_MASK(7, 4))
- +#define PCU_DCSR2_UART2_OFFSET (4)
- +#define PCU_DCSR2_UART2_DEFAULT (0x9)
- +#define PCU_DCSR2_UART1_MASK (ANDES_BIT_MASK(3, 0))
- +#define PCU_DCSR2_UART1_OFFSET (0)
- +#define PCU_DCSR2_UART1_DEFAULT (0x9)
- +#define PCU_DCSR0_DEFAULT ((PCU_DCSR0_GPU_DEFAULT << PCU_DCSR0_GPU_OFFSET ) |\
- + (PCU_DCSR0_GMAC_DEFAULT << PCU_DCSR0_GMAC_OFFSET ) |\
- + (PCU_DCSR0_ULPI_DEFAULT << PCU_DCSR0_ULPI_OFFSET ) |\
- + (PCU_DCSR0_LPC_DEFAULT << PCU_DCSR0_LPC_OFFSET ) |\
- + (PCU_DCSR0_PCIAHB_DEFAULT << PCU_DCSR0_PCIAHB_OFFSET))
- +#define PCU_DCSR0_DFT_MASK ((PCU_DCSR0_GPU_MASK ) |\
- + (PCU_DCSR0_GMAC_MASK ) |\
- + (PCU_DCSR0_ULPI_MASK ) |\
- + (PCU_DCSR0_LPC_MASK ) |\
- + (PCU_DCSR0_PCIAHB_MASK))
- +
- +#define PCU_DCSR1_DEFAULT (PCU_DCSR1_I2C_DEFAULT << PCU_DCSR1_I2C_OFFSET )
- +#define PCU_DCSR1_DFT_MASK (PCU_DCSR1_I2C_MASK)
- +
- +#define PCU_DCSR2_DEFAULT ((PCU_DCSR2_PCU_DEFAULT << PCU_DCSR2_PCU_OFFSET ) |\
- + (PCU_DCSR2_GPIO_DEFAULT << PCU_DCSR2_GPIO_OFFSET ) |\
- + (PCU_DCSR2_CFC_DEFAULT << PCU_DCSR2_CFC_OFFSET ) |\
- + (PCU_DCSR2_SD_DEFAULT << PCU_DCSR2_SD_OFFSET ) |\
- + (PCU_DCSR2_SPI_DEFAULT << PCU_DCSR2_SPI_OFFSET ) |\
- + (PCU_DCSR2_AC97_DEFAULT << PCU_DCSR2_AC97_OFFSET ) |\
- + (PCU_DCSR2_UART2_DEFAULT << PCU_DCSR2_UART2_OFFSET ) |\
- + (PCU_DCSR2_UART1_DEFAULT << PCU_DCSR2_UART1_OFFSET ))
- +#define PCU_DCSR2_DFT_MASK ((PCU_DCSR2_PCU_MASK ) |\
- + (PCU_DCSR2_GPIO_MASK ) |\
- + (PCU_DCSR2_CFC_MASK ) |\
- + (PCU_DCSR2_SD_MASK ) |\
- + (PCU_DCSR2_SPI_MASK ) |\
- + (PCU_DCSR2_AC97_MASK ) |\
- + (PCU_DCSR2_UART2_MASK) |\
- + (PCU_DCSR2_UART1_MASK))
- +
- +//multi function port setting
- +#define PCU_MFPS0_ENDIAN_MASK (ANDES_BIT_MASK(31, 31))
- +#define PCU_MFPS0_ENDIAN_OFFSET (31)
- +//#define PCU_MFPS0_ENDIAN_DEFAULT (0x)
- +#define PCU_MFPS0_IVB_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_MFPS0_IVB_OFFSET (28)
- +//#define PCU_MFPS0_IVB_DEFAULT (0x)
- +#define PCU_MFPS0_AHBTARGET_MASK (ANDES_BIT_MASK(4, 4))
- +#define PCU_MFPS0_AHBTARGET_OFFSET (4)
- +//#define PCU_MFPS0_AHBTARGET_DEFAULT (0x)
- +#define PCU_MFPS0_AHBDBG_MASK (ANDES_BIT_MASK(3, 3))
- +#define PCU_MFPS0_AHBDBG_OFFSET (3)
- +//#define PCU_MFPS0_AHBDBG_DEFAULT (0x)
- +#define PCU_MFPS0_MINI_MASK (ANDES_BIT_MASK(2, 2))
- +#define PCU_MFPS0_MINI_OFFSET (2)
- +//#define PCU_MFPS0_MINI_DEFAULT (0x)
- +#define PCU_MFPS0_IDE_MASK (ANDES_BIT_MASK(1, 1))
- +#define PCU_MFPS0_IDE_OFFSET (1)
- +//#define PCU_MFPS0_IDE_DEFAULT (0x)
- +#define PCU_MFPS0_PCI_MASK (ANDES_BIT_MASK(0, 0))
- +#define PCU_MFPS0_PCI_OFFSET (0)
- +//#define PCU_MFPS0_PCI_DEFAULT (0x)
- +
- +#define PCU_MFPS1_EXT_INT_MASK (ANDES_BIT_MASK(31, 31))
- +#define PCU_MFPS1_EXT_INT_OFFSET (31)
- +#define PCU_MFPS1_EXT_INT_DEFAULT (0x0)
- +#define PCU_MFPS1_AHB_FAST_REQ_MASK (ANDES_BIT_MASK(30, 30))
- +#define PCU_MFPS1_AHB_FAST_REQ_OFFSET (30)
- +#define PCU_MFPS1_AHB_FAST_REQ_DEFAULT (0x1)
- +#define PCU_MFPS1_HSMP_FAST_REQ_MASK (ANDES_BIT_MASK(29, 29))
- +#define PCU_MFPS1_HSMP_FAST_REQ_OFFSET (29)
- +#define PCU_MFPS1_HSMP_FAST_REQ_DEFAULT (0x1)
- +#define PCU_MFPS1_DVO_MASK (ANDES_BIT_MASK(28, 28))
- +#define PCU_MFPS1_DVO_OFFSET (28)
- +#define PCU_MFPS1_DVO_DEFAULT (0x0)
- +#define PCU_MFPS1_SD_GPIO_MASK (ANDES_BIT_MASK(10, 10))
- +#define PCU_MFPS1_SD_GPIO_OFFSET (10)
- +#define PCU_MFPS1_SD_GPIO_DEFAULT (0x1)
- +#define PCU_MFPS1_SPI_GPIO_MASK (ANDES_BIT_MASK(9, 9))
- +#define PCU_MFPS1_SPI_GPIO_OFFSET (9)
- +#define PCU_MFPS1_SPI_GPIO_DEFAULT (0x1)
- +#define PCU_MFPS1_UART2_GPIO_MASK (ANDES_BIT_MASK(8, 8))
- +#define PCU_MFPS1_UART2_GPIO_OFFSET (8)
- +#define PCU_MFPS1_UART2_GPIO_DEFAULT (0x1)
- +#define PCU_MFPS1_UART1_GPIO_MASK (ANDES_BIT_MASK(7, 7))
- +#define PCU_MFPS1_UART1_GPIO_OFFSET (7)
- +#define PCU_MFPS1_UART1_GPIO_DEFAULT (0x1)
- +#define PCU_MFPS1_I2C_GPIO_MASK (ANDES_BIT_MASK(6, 6))
- +#define PCU_MFPS1_I2C_GPIO_OFFSET (6)
- +#define PCU_MFPS1_I2C_GPIO_DEFAULT (0x1)
- +#define PCU_MFPS1_PME_GPIO_MASK (ANDES_BIT_MASK(5, 5))
- +#define PCU_MFPS1_PME_GPIO_OFFSET (5)
- +#define PCU_MFPS1_PME_GPIO_DEFAULT (0x1)
- +#define PCU_MFPS1_PWEN_GPIO_MASK (ANDES_BIT_MASK(4, 4))
- +#define PCU_MFPS1_PWEN_GPIO_OFFSET (4)
- +#define PCU_MFPS1_PWEN_GPIO_DEFAULT (0x1)
- +#define PCU_MFPS1_AC97_GPIO_MASK (ANDES_BIT_MASK(3, 3))
- +#define PCU_MFPS1_AC97_GPIO_OFFSET (3)
- +#define PCU_MFPS1_AC97_GPIO_DEFAULT (0x0)
- +#define PCU_MFPS1_PWM1_GPIO_MASK (ANDES_BIT_MASK(2, 2))
- +#define PCU_MFPS1_PWM1_GPIO_OFFSET (2)
- +#define PCU_MFPS1_PWM1_GPIO_DEFAULT (0x0)
- +#define PCU_MFPS1_PWM0_GPIO_MASK (ANDES_BIT_MASK(1, 1))
- +#define PCU_MFPS1_PWM0_GPIO_OFFSET (1)
- +#define PCU_MFPS1_PWM0_GPIO_DEFAULT (0x0)
- +#define PCU_MFPS1_SUSPEND_GPIO_MASK (ANDES_BIT_MASK(0, 0))
- +#define PCU_MFPS1_SUSPEND_GPIO_OFFSET (0)
- +#define PCU_MFPS1_SUSPEND_GPIO_DEFAULT (0x0)
- +#define PCU_MFPS1_DEFAULT ((PCU_MFPS1_EXT_INT_DEFAULT << PCU_MFPS1_EXT_INT_OFFSET )|\
- + (PCU_MFPS1_AHB_FAST_REQ_DEFAULT << PCU_MFPS1_AHB_FAST_REQ_OFFSET )|\
- + (PCU_MFPS1_HSMP_FAST_REQ_DEFAULT << PCU_MFPS1_HSMP_FAST_REQ_OFFSET)|\
- + (PCU_MFPS1_DVO_DEFAULT << PCU_MFPS1_DVO_OFFSET )|\
- + (PCU_MFPS1_SD_GPIO_DEFAULT << PCU_MFPS1_SD_GPIO_OFFSET )|\
- + (PCU_MFPS1_SPI_GPIO_DEFAULT << PCU_MFPS1_SPI_GPIO_OFFSET )|\
- + (PCU_MFPS1_UART2_GPIO_DEFAULT << PCU_MFPS1_UART2_GPIO_OFFSET )|\
- + (PCU_MFPS1_UART1_GPIO_DEFAULT << PCU_MFPS1_UART1_GPIO_OFFSET )|\
- + (PCU_MFPS1_I2C_GPIO_DEFAULT << PCU_MFPS1_I2C_GPIO_OFFSET )|\
- + (PCU_MFPS1_PME_GPIO_DEFAULT << PCU_MFPS1_PME_GPIO_OFFSET )|\
- + (PCU_MFPS1_PWEN_GPIO_DEFAULT << PCU_MFPS1_PWEN_GPIO_OFFSET )|\
- + (PCU_MFPS1_AC97_GPIO_DEFAULT << PCU_MFPS1_AC97_GPIO_OFFSET )|\
- + (PCU_MFPS1_PWM1_GPIO_DEFAULT << PCU_MFPS1_PWM1_GPIO_OFFSET )|\
- + (PCU_MFPS1_PWM0_GPIO_DEFAULT << PCU_MFPS1_PWM0_GPIO_OFFSET )|\
- + (PCU_MFPS1_SUSPEND_GPIO_DEFAULT << PCU_MFPS1_SUSPEND_GPIO_OFFSET ))
- +#define PCU_MFPS1_DFT_MASK ((PCU_MFPS1_EXT_INT_MASK )|\
- + (PCU_MFPS1_AHB_FAST_REQ_MASK )|\
- + (PCU_MFPS1_HSMP_FAST_REQ_MASK)|\
- + (PCU_MFPS1_DVO_MASK )|\
- + (PCU_MFPS1_SD_GPIO_MASK )|\
- + (PCU_MFPS1_SPI_GPIO_MASK )|\
- + (PCU_MFPS1_UART2_GPIO_MASK )|\
- + (PCU_MFPS1_UART1_GPIO_MASK )|\
- + (PCU_MFPS1_I2C_GPIO_MASK )|\
- + (PCU_MFPS1_PME_GPIO_MASK )|\
- + (PCU_MFPS1_PWEN_GPIO_MASK )|\
- + (PCU_MFPS1_AC97_GPIO_MASK )|\
- + (PCU_MFPS1_PWM1_GPIO_MASK )|\
- + (PCU_MFPS1_PWM0_GPIO_MASK )|\
- + (PCU_MFPS1_SUSPEND_GPIO_MASK ))
- +
- +//DMA engine selection
- +#define PCU_DMA_SEL_CFC_MASK (ANDES_BIT_MASK(9, 9))
- +#define PCU_DMA_SEL_CFC_OFFSET (9)
- +#define PCU_DMA_SEL_CFC_DEFAULT (0x0)
- +#define PCU_DMA_SEL_SD_MASK (ANDES_BIT_MASK(9, 9))
- +#define PCU_DMA_SEL_SD_OFFSET (9)
- +#define PCU_DMA_SEL_SD_DEFAULT (0x0)
- +#define PCU_DMA_SEL_UART2_TX_MASK (ANDES_BIT_MASK(9, 9))
- +#define PCU_DMA_SEL_UART2_TX_OFFSET (9)
- +#define PCU_DMA_SEL_UART2_TX_DEFAULT (0x0)
- +#define PCU_DMA_SEL_UART2_RX_MASK (ANDES_BIT_MASK(9, 9))
- +#define PCU_DMA_SEL_UART2_RX_OFFSET (9)
- +#define PCU_DMA_SEL_UART2_RX_DEFAULT (0x0)
- +#define PCU_DMA_SEL_UART1_TX_MASK (ANDES_BIT_MASK(9, 9))
- +#define PCU_DMA_SEL_UART1_TX_OFFSET (9)
- +#define PCU_DMA_SEL_UART1_TX_DEFAULT (0x0)
- +#define PCU_DMA_SEL_UART1_RX_MASK (ANDES_BIT_MASK(9, 9))
- +#define PCU_DMA_SEL_UART1_RX_OFFSET (9)
- +#define PCU_DMA_SEL_UART1_RX_DEFAULT (0x0)
- +#define PCU_DMA_SEL_AC97_TX_MASK (ANDES_BIT_MASK(9, 9))
- +#define PCU_DMA_SEL_AC97_TX_OFFSET (9)
- +#define PCU_DMA_SEL_AC97_TX_DEFAULT (0x0)
- +#define PCU_DMA_SEL_AC97_RX_MASK (ANDES_BIT_MASK(9, 9))
- +#define PCU_DMA_SEL_AC97_RX_OFFSET (9)
- +#define PCU_DMA_SEL_AC97_RX_DEFAULT (0x0)
- +#define PCU_DMA_SEL_DEFAULT ((PCU_DMA_SEL_CFC_DEFAULT << PCU_DMA_SEL_CFC_OFFSET ) |\
- + (PCU_DMA_SEL_SD_DEFAULT << PCU_DMA_SEL_SD_OFFSET ) |\
- + (PCU_DMA_SEL_UART2_TX_DEFAULT << PCU_DMA_SEL_UART2_TX_OFFSET) |\
- + (PCU_DMA_SEL_UART2_RX_DEFAULT << PCU_DMA_SEL_UART2_RX_OFFSET) |\
- + (PCU_DMA_SEL_UART1_TX_DEFAULT << PCU_DMA_SEL_UART1_TX_OFFSET) |\
- + (PCU_DMA_SEL_UART1_RX_DEFAULT << PCU_DMA_SEL_UART1_RX_OFFSET) |\
- + (PCU_DMA_SEL_AC97_TX_DEFAULT << PCU_DMA_SEL_AC97_TX_OFFSET ) |\
- + (PCU_DMA_SEL_AC97_RX_DEFAULT << PCU_DMA_SEL_AC97_RX_OFFSET ) )
- +#define PCU_DMA_SEL_DFT_MASK ((PCU_DMA_SEL_CFC_MASK ) |\
- + (PCU_DMA_SEL_SD_MASK ) |\
- + (PCU_DMA_SEL_UART2_TX_MASK) |\
- + (PCU_DMA_SEL_UART2_RX_MASK) |\
- + (PCU_DMA_SEL_UART1_TX_MASK) |\
- + (PCU_DMA_SEL_UART1_RX_MASK) |\
- + (PCU_DMA_SEL_AC97_TX_MASK ) |\
- + (PCU_DMA_SEL_AC97_RX_MASK ) )
- +
- +// OSC control
- +#define PCU_OSC_CTRL_OSCH3RAN_MASK (ANDES_BIT_MASK(9, 8))
- +#define PCU_OSC_CTRL_OSCH3RAN_OFFSET (8)
- +//#define PCU_OSC_CTRL_OSCH3RAN_DEFAULT (0x0)
- +#define PCU_OSC_CTRL_OSCH2RAN_MASK (ANDES_BIT_MASK(7, 6))
- +#define PCU_OSC_CTRL_OSCH2RAN_OFFSET (6)
- +#define PCU_OSC_CTRL_OSCH2RAN_DEFAULT (0x2)
- +#define PCU_OSC_CTRL_OSCH1RAN_MASK (ANDES_BIT_MASK(5, 4))
- +#define PCU_OSC_CTRL_OSCH1RAN_OFFSET (4)
- +//#define PCU_OSC_CTRL_OSCH1RAN_DEFAULT (0x0)
- +#define PCU_OSC_CTRL_OSCHTRI_MASK (ANDES_BIT_MASK(2, 2))
- +#define PCU_OSC_CTRL_OSCHTRI_OFFSET (2)
- +#define PCU_OSC_CTRL_OSCHTRI_DEFAULT (0x0)
- +#define PCU_OSC_CTRL_OSCHSTABLE_MASK (ANDES_BIT_MASK(1, 1))
- +#define PCU_OSC_CTRL_OSCHSTABLE_OFFSET (1)
- +//#define PCU_OSC_CTRL_OSCHSTABLE_DEFAULT (0x0)
- +#define PCU_OSC_CTRL_OSCHOFF_MASK (ANDES_BIT_MASK(0, 0))
- +#define PCU_OSC_CTRL_OSCHOFF_OFFSET (0)
- +//#define PCU_OSC_CTRL_OSCHOFF_DEFAULT (0x0)
- +#define PCU_OSC_CTRL_DEFAULT (PCU_OSC_CTRL_OSCH2RAN_DEFAULT << PCU_OSC_CTRL_OSCH2RAN_OFFSET )
- +#define PCU_OSC_CTRL_DFT_MASK (PCU_OSC_CTRL_OSCH2RAN_MASK )
- +
- +// PWM divider
- +#define PCU_PWM_DIV_DIV_MASK (ANDES_BIT_MASK(3, 0))
- +#define PCU_PWM_DIV_DIV_OFFSET (0)
- +#define PCU_PWM_DIV_DIV_DEFAULT (0x0)
- +#define PCU_PWM_DIV_DEFAULT (PCU_PWM_DIV_DIV_DEFAULT<<PCU_PWM_DIV_DIV_OFFSET)
- +#define PCU_PWM_DIV_DFT_MASK (PCU_PWM_DIV_DIV_MASK)
- +
- +// MISC
- +#define PCU_MISC_HW_RST_MASK (ANDES_BIT_MASK(31, 31))
- +#define PCU_MISC_HW_RST_OFFSET (31)
- +#define PCU_MISC_HW_RST_DEFAULT (0x0)
- +#define PCU_MISC_WD_RST_MASK (ANDES_BIT_MASK(30, 30))
- +#define PCU_MISC_WD_RST_OFFSET (30)
- +#define PCU_MISC_WD_RST_DEFAULT (0x0)
- +#define PCU_MISC_CPUB_SRST_MASK (ANDES_BIT_MASK(29, 29))
- +#define PCU_MISC_CPUB_SRST_OFFSET (29)
- +#define PCU_MISC_CPUB_SRST_DEFAULT (0x0)
- +#define PCU_MISC_CPUA_SRST_MASK (ANDES_BIT_MASK(28, 28))
- +#define PCU_MISC_CPUA_SRST_OFFSET (28)
- +#define PCU_MISC_CPUA_SRST_DEFAULT (0x0)
- +#define PCU_MISC_PW_FAIL_MASK (ANDES_BIT_MASK(27, 27))
- +#define PCU_MISC_PW_FAIL_OFFSET (27)
- +#define PCU_MISC_PW_FAIL_DEFAULT (0x0)
- +#define PCU_MISC_PW_DAILY_MASK (ANDES_BIT_MASK(26, 26))
- +#define PCU_MISC_PW_DAILY_OFFSET (26)
- +#define PCU_MISC_PW_DAILY_DEFAULT (0x0)
- +#define PCU_MISC_PW_LPC_MASK (ANDES_BIT_MASK(25, 25))
- +#define PCU_MISC_PW_LPC_OFFSET (25)
- +#define PCU_MISC_PW_LPC_DEFAULT (0x0)
- +#define PCU_MISC_PW_PCI_MASK (ANDES_BIT_MASK(24, 24))
- +#define PCU_MISC_PW_PCI_OFFSET (24)
- +#define PCU_MISC_PW_PCI_DEFAULT (0x0)
- +#define PCU_MISC_PW_RTC_MASK (ANDES_BIT_MASK(23, 23))
- +#define PCU_MISC_PW_RTC_OFFSET (23)
- +#define PCU_MISC_PW_RTC_DEFAULT (0x0)
- +#define PCU_MISC_PW_WOL_MASK (ANDES_BIT_MASK(22, 22))
- +#define PCU_MISC_PW_WOL_OFFSET (2)
- +#define PCU_MISC_PW_WOL_DEFAULT (0x0)
- +#define PCU_MISC_PW_GPIO5_MASK (ANDES_BIT_MASK(21, 21))
- +#define PCU_MISC_PW_GPIO5_OFFSET (21)
- +#define PCU_MISC_PW_GPIO5_DEFAULT (0x0)
- +#define PCU_MISC_PW_GPIO4_MASK (ANDES_BIT_MASK(20, 20))
- +#define PCU_MISC_PW_GPIO4_OFFSET (20)
- +#define PCU_MISC_PW_GPIO4_DEFAULT (0x0)
- +#define PCU_MISC_PW_GPIO3_MASK (ANDES_BIT_MASK(19, 19))
- +#define PCU_MISC_PW_GPIO3_OFFSET (19)
- +#define PCU_MISC_PW_GPIO3_DEFAULT (0x0)
- +#define PCU_MISC_PW_GPIO2_MASK (ANDES_BIT_MASK(18, 18))
- +#define PCU_MISC_PW_GPIO2_OFFSET (18)
- +#define PCU_MISC_PW_GPIO2_DEFAULT (0x0)
- +#define PCU_MISC_PW_GPIO1_MASK (ANDES_BIT_MASK(17, 17))
- +#define PCU_MISC_PW_GPIO1_OFFSET (17)
- +#define PCU_MISC_PW_GPIO1_DEFAULT (0x0)
- +#define PCU_MISC_PW_GPIO0_MASK (ANDES_BIT_MASK(16, 16))
- +#define PCU_MISC_PW_GPIO0_OFFSET (16)
- +#define PCU_MISC_PW_GPIO0_DEFAULT (0x0)
- +#define PCU_MISC_EN_CPUB_MASK (ANDES_BIT_MASK(15, 15))
- +#define PCU_MISC_EN_CPUB_OFFSET (15)
- +#define PCU_MISC_EN_CPUB_DEFAULT (0x0)
- +#define PCU_MISC_EN_CPUA_MASK (ANDES_BIT_MASK(14, 14))
- +#define PCU_MISC_EN_CPUA_OFFSET (14)
- +#define PCU_MISC_EN_CPUA_DEFAULT (0x1)
- +#define PCU_MISC_DDR_DLL_TEST_MASK (ANDES_BIT_MASK(12, 12))
- +#define PCU_MISC_DDR_DLL_TEST_OFFSET (12)
- +#define PCU_MISC_DDR_DLL_TEST_DEFAULT (0x0)
- +#define PCU_MISC_DDR_DDQ_TEST_MASK (ANDES_BIT_MASK(11, 11))
- +#define PCU_MISC_DDR_DDQ_TEST_OFFSET (11)
- +#define PCU_MISC_DDR_DDQ_TEST_DEFAULT (0x0)
- +#define PCU_MISC_DDR_DLL_SRST_MASK (ANDES_BIT_MASK(10, 10))
- +#define PCU_MISC_DDR_DLL_SRST_OFFSET (10)
- +#define PCU_MISC_DDR_DLL_SRST_DEFAULT (0x0)
- +#define PCU_MISC_DDR_PLL_BYPASS_MASK (ANDES_BIT_MASK(9, 9))
- +#define PCU_MISC_DDR_PLL_BYPASS_OFFSET (9)
- +#define PCU_MISC_DDR_PLL_BYPASS_DEFAULT (0x0)
- +#define PCU_MISC_400MHZ_SEL_MASK (ANDES_BIT_MASK(8, 8))
- +#define PCU_MISC_400MHZ_SEL_OFFSET (8)
- +#define PCU_MISC_400MHZ_SEL_DEFAULT (0x0)
- +#define PCU_MISC_EXLM_WAIT_B_MASK (ANDES_BIT_MASK(7, 6))
- +#define PCU_MISC_EXLM_WAIT_B_OFFSET (6)
- +#define PCU_MISC_EXLM_WAIT_B_DEFAULT (0x0)
- +#define PCU_MISC_EXLM_WAIT_A_MASK (ANDES_BIT_MASK(5, 4))
- +#define PCU_MISC_EXLM_WAIT_A_OFFSET (4)
- +#define PCU_MISC_EXLM_WAIT_A_DEFAULT (0x0)
- +#define PCU_MISC_USB_WAKE_MASK (ANDES_BIT_MASK(3, 3))
- +#define PCU_MISC_USB_WAKE_OFFSET (3)
- +#define PCU_MISC_USB_WAKE_DEFAULT (0x0)
- +#define PCU_MISC_RST_PCI_MASK (ANDES_BIT_MASK(2, 2))
- +#define PCU_MISC_RST_PCI_OFFSET (2)
- +#define PCU_MISC_RST_PCI_DEFAULT (0x0)
- +#define PCU_MISC_RST_CPUB_MASK (ANDES_BIT_MASK(1, 1))
- +#define PCU_MISC_RST_CPUB_OFFSET (1)
- +#define PCU_MISC_RST_CPUB_DEFAULT (0x0)
- +#define PCU_MISC_RST_CPUA_MASK (ANDES_BIT_MASK(0, 0))
- +#define PCU_MISC_RST_CPUA_OFFSET (0)
- +#define PCU_MISC_RST_CPUA_DEFAULT (0x0)
- +#define PCU_MISC_DEFAULT (/*(PCU_MISC_EN_CPUB_DEFAULT << PCU_MISC_EN_CPUB_OFFSET )|*/\
- + (PCU_MISC_EN_CPUA_DEFAULT << PCU_MISC_EN_CPUA_OFFSET )|\
- + (PCU_MISC_DDR_DLL_TEST_DEFAULT << PCU_MISC_DDR_DLL_TEST_OFFSET )|\
- + (PCU_MISC_DDR_DDQ_TEST_DEFAULT << PCU_MISC_DDR_DDQ_TEST_OFFSET )|\
- + (PCU_MISC_DDR_DLL_SRST_DEFAULT << PCU_MISC_DDR_DLL_SRST_OFFSET )|\
- + (PCU_MISC_DDR_PLL_BYPASS_DEFAULT << PCU_MISC_DDR_PLL_BYPASS_OFFSET )|\
- + (PCU_MISC_400MHZ_SEL_DEFAULT << PCU_MISC_400MHZ_SEL_OFFSET )|\
- + (PCU_MISC_EXLM_WAIT_B_DEFAULT << PCU_MISC_EXLM_WAIT_B_OFFSET )|\
- + (PCU_MISC_EXLM_WAIT_A_DEFAULT << PCU_MISC_EXLM_WAIT_A_OFFSET )|\
- + (PCU_MISC_USB_WAKE_DEFAULT << PCU_MISC_USB_WAKE_OFFSET )|\
- + (PCU_MISC_RST_PCI_DEFAULT << PCU_MISC_RST_PCI_OFFSET )|\
- + (PCU_MISC_RST_CPUB_DEFAULT << PCU_MISC_RST_CPUB_OFFSET )|\
- + (PCU_MISC_RST_CPUA_DEFAULT << PCU_MISC_RST_CPUA_OFFSET ))
- +#define PCU_MISC_DFT_MASK (/*(PCU_MISC_EN_CPUB_MASK )|*/\
- + (PCU_MISC_EN_CPUA_MASK )|\
- + (PCU_MISC_DDR_DLL_TEST_MASK )|\
- + (PCU_MISC_DDR_DDQ_TEST_MASK )|\
- + (PCU_MISC_DDR_DLL_SRST_MASK )|\
- + (PCU_MISC_DDR_PLL_BYPASS_MASK)|\
- + (PCU_MISC_400MHZ_SEL_MASK )|\
- + (PCU_MISC_EXLM_WAIT_B_MASK )|\
- + (PCU_MISC_EXLM_WAIT_A_MASK )|\
- + (PCU_MISC_USB_WAKE_MASK )|\
- + (PCU_MISC_RST_PCI_MASK )|\
- + (PCU_MISC_RST_CPUB_MASK )|\
- + (PCU_MISC_RST_CPUA_MASK ))
- +#define PCU_MISC_W1C_MASK ((PCU_MISC_HW_RST_MASK )|\
- + (PCU_MISC_WD_RST_MASK )|\
- + (PCU_MISC_CPUB_SRST_MASK)|\
- + (PCU_MISC_CPUA_SRST_MASK))
- +
- +// BSM control and status
- +#define PCU_BSM_CTRL_IE_MASK (ANDES_BIT_MASK(31, 31))
- +#define PCU_BSM_CTRL_IE_OFFSET (31)
- +#define PCU_BSM_CTRL_IE_DEFAULT (0x0)
- +#define PCU_BSM_CTRL_CMD_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_BSM_CTRL_CMD_OFFSET (28)
- +#define PCU_BSM_CTRL_CMD_DEFAULT (0x0)
- +#define PCU_BSM_CTRL_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_BSM_CTRL_SYNC_OFFSET (24)
- +#define PCU_BSM_CTRL_SYNC_DEFAULT (0x3)
- +#define PCU_BSM_CTRL_LINK1_MASK (ANDES_BIT_MASK(7, 4))
- +#define PCU_BSM_CTRL_LINK1_OFFSET (4)
- +#define PCU_BSM_CTRL_LINK1_DEFAULT (0x0)
- +#define PCU_BSM_CTRL_LINK0_MASK (ANDES_BIT_MASK(3, 0))
- +#define PCU_BSM_CTRL_LINK0_OFFSET (0)
- +#define PCU_BSM_CTRL_LINK0_DEFAULT (0x0)
- +#define PCU_BSM_CTRL_DEFAULT ((PCU_BSM_CTRL_IE_DEFAULT << PCU_BSM_CTRL_IE_OFFSET ) |\
- + (PCU_BSM_CTRL_CMD_DEFAULT << PCU_BSM_CTRL_CMD_OFFSET ) |\
- + (PCU_BSM_CTRL_SYNC_DEFAULT << PCU_BSM_CTRL_SYNC_OFFSET ) |\
- + (PCU_BSM_CTRL_LINK1_DEFAULT << PCU_BSM_CTRL_LINK1_OFFSET) |\
- + (PCU_BSM_CTRL_LINK0_DEFAULT << PCU_BSM_CTRL_LINK0_OFFSET))
- +
- +#define PCU_BSM_STATUS_STS_MASK (ANDES_BIT_MASK(31, 28))
- +#define PCU_BSM_STATUS_STS_OFFSET (28)
- +#define PCU_BSM_STATUS_STS_DEFAULT (0x0)
- +#define PCU_BSM_STATUS_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_BSM_STATUS_SYNC_OFFSET (24)
- +#define PCU_BSM_STATUS_SYNC_DEFAULT (0x0)
- +#define PCU_BSM_STATUS_CI1_MASK (ANDES_BIT_MASK(7, 4))
- +#define PCU_BSM_STATUS_CI1_OFFSET (4)
- +#define PCU_BSM_STATUS_CI1_DEFAULT (0x0)
- +#define PCU_BSM_STATUS_CI0_MASK (ANDES_BIT_MASK(3, 0))
- +#define PCU_BSM_STATUS_CI0_OFFSET (0)
- +#define PCU_BSM_STATUS_CI0_DEFAULT (0x0)
- +#define PCU_BSM_STATUS_DEFAULT ((PCU_BSM_STATUS_STS_DEFAULT << PCU_BSM_STATUS_STS_OFFSET) |\
- + (PCU_BSM_STATUS_CI1_DEFAULT << PCU_BSM_STATUS_CI1_OFFSET) |\
- + (PCU_BSM_STATUS_CI0_DEFAULT << PCU_BSM_STATUS_CI0_OFFSET))
- +
- +//wakeup event sensitivity
- +#define PCU_WAKEUP_SEN_POL15_MASK (ANDES_BIT_MASK(15, 15))
- +#define PCU_WAKEUP_SEN_POL15_OFFSET (15)
- +#define PCU_WAKEUP_SEN_POL15_DEFAULT (0x0)
- +#define PCU_WAKEUP_SEN_POL14_MASK (ANDES_BIT_MASK(14, 14))
- +#define PCU_WAKEUP_SEN_POL14_OFFSET (14)
- +#define PCU_WAKEUP_SEN_POL14_DEFAULT (0x0)
- +#define PCU_WAKEUP_SEN_POL13_MASK (ANDES_BIT_MASK(13, 13))
- +#define PCU_WAKEUP_SEN_POL13_OFFSET (13)
- +#define PCU_WAKEUP_SEN_POL13_DEFAULT (0x0)
- +#define PCU_WAKEUP_SEN_POL12_MASK (ANDES_BIT_MASK(12, 12))
- +#define PCU_WAKEUP_SEN_POL12_OFFSET (12)
- +#define PCU_WAKEUP_SEN_POL12_DEFAULT (0x0)
- +#define PCU_WAKEUP_SEN_POL11_MASK (ANDES_BIT_MASK(11, 11))
- +#define PCU_WAKEUP_SEN_POL11_OFFSET (11)
- +#define PCU_WAKEUP_SEN_POL11_DEFAULT (0x0)
- +#define PCU_WAKEUP_SEN_POL10_MASK (ANDES_BIT_MASK(10, 10))
- +#define PCU_WAKEUP_SEN_POL10_OFFSET (10)
- +#define PCU_WAKEUP_SEN_POL10_DEFAULT (0x0)
- +#define PCU_WAKEUP_SEN_POL9_MASK (ANDES_BIT_MASK(9, 9))
- +#define PCU_WAKEUP_SEN_POL9_OFFSET (9)
- +#define PCU_WAKEUP_SEN_POL9_DEFAULT (0x0)
- +#define PCU_WAKEUP_SEN_POL8_MASK (ANDES_BIT_MASK(8, 8))
- +#define PCU_WAKEUP_SEN_POL8_OFFSET (8)
- +#define PCU_WAKEUP_SEN_POL8_DEFAULT (0x1)
- +#define PCU_WAKEUP_SEN_POL7_MASK (ANDES_BIT_MASK(7, 7))
- +#define PCU_WAKEUP_SEN_POL7_OFFSET (7)
- +#define PCU_WAKEUP_SEN_POL7_DEFAULT (0x1)
- +#define PCU_WAKEUP_SEN_POL6_MASK (ANDES_BIT_MASK(6, 6))
- +#define PCU_WAKEUP_SEN_POL6_OFFSET (6)
- +#define PCU_WAKEUP_SEN_POL6_DEFAULT (0x1)
- +#define PCU_WAKEUP_SEN_POL5_MASK (ANDES_BIT_MASK(5, 5))
- +#define PCU_WAKEUP_SEN_POL5_OFFSET (5)
- +#define PCU_WAKEUP_SEN_POL5_DEFAULT (0x0)
- +#define PCU_WAKEUP_SEN_POL4_MASK (ANDES_BIT_MASK(4, 4))
- +#define PCU_WAKEUP_SEN_POL4_OFFSET (4)
- +#define PCU_WAKEUP_SEN_POL4_DEFAULT (0x0)
- +#define PCU_WAKEUP_SEN_POL3_MASK (ANDES_BIT_MASK(3, 3))
- +#define PCU_WAKEUP_SEN_POL3_OFFSET (3)
- +#define PCU_WAKEUP_SEN_POL3_DEFAULT (0x0)
- +#define PCU_WAKEUP_SEN_POL2_MASK (ANDES_BIT_MASK(2, 2))
- +#define PCU_WAKEUP_SEN_POL2_OFFSET (2)
- +#define PCU_WAKEUP_SEN_POL2_DEFAULT (0x0)
- +#define PCU_WAKEUP_SEN_POL1_MASK (ANDES_BIT_MASK(1, 1))
- +#define PCU_WAKEUP_SEN_POL1_OFFSET (1)
- +#define PCU_WAKEUP_SEN_POL1_DEFAULT (0x0)
- +#define PCU_WAKEUP_SEN_POL0_MASK (ANDES_BIT_MASK(0, 0))
- +#define PCU_WAKEUP_SEN_POL0_OFFSET (0)
- +#define PCU_WAKEUP_SEN_POL0_DEFAULT (0x0)
- +#define PCU_WAKEUP_SEN_POL_MASK (ANDES_BIT_MASK(15, 0))
- +#define PCU_WAKEUP_SEN_POL_OFFSET (0)
- +#define PCU_WAKEUP_SEN_POL_DEFAULT ((PCU_WAKEUP_SEN_POL15_DEFAULT << PCU_WAKEUP_SEN_POL15_OFFSET) |\
- + (PCU_WAKEUP_SEN_POL14_DEFAULT << PCU_WAKEUP_SEN_POL14_OFFSET) |\
- + (PCU_WAKEUP_SEN_POL13_DEFAULT << PCU_WAKEUP_SEN_POL13_OFFSET) |\
- + (PCU_WAKEUP_SEN_POL12_DEFAULT << PCU_WAKEUP_SEN_POL12_OFFSET) |\
- + (PCU_WAKEUP_SEN_POL11_DEFAULT << PCU_WAKEUP_SEN_POL11_OFFSET) |\
- + (PCU_WAKEUP_SEN_POL10_DEFAULT << PCU_WAKEUP_SEN_POL10_OFFSET) |\
- + (PCU_WAKEUP_SEN_POL9_DEFAULT << PCU_WAKEUP_SEN_POL9_OFFSET ) |\
- + (PCU_WAKEUP_SEN_POL8_DEFAULT << PCU_WAKEUP_SEN_POL8_OFFSET ) |\
- + (PCU_WAKEUP_SEN_POL7_DEFAULT << PCU_WAKEUP_SEN_POL7_OFFSET ) |\
- + (PCU_WAKEUP_SEN_POL6_DEFAULT << PCU_WAKEUP_SEN_POL6_OFFSET ) |\
- + (PCU_WAKEUP_SEN_POL5_DEFAULT << PCU_WAKEUP_SEN_POL5_OFFSET ) |\
- + (PCU_WAKEUP_SEN_POL4_DEFAULT << PCU_WAKEUP_SEN_POL4_OFFSET ) |\
- + (PCU_WAKEUP_SEN_POL3_DEFAULT << PCU_WAKEUP_SEN_POL3_OFFSET ) |\
- + (PCU_WAKEUP_SEN_POL2_DEFAULT << PCU_WAKEUP_SEN_POL3_OFFSET ) |\
- + (PCU_WAKEUP_SEN_POL1_DEFAULT << PCU_WAKEUP_SEN_POL2_OFFSET ) |\
- + (PCU_WAKEUP_SEN_POL0_DEFAULT << PCU_WAKEUP_SEN_POL0_OFFSET ) )
- +#define PCU_WAKEUP_SEN_DEFAULT (PCU_WAKEUP_SEN_POL_DEFAULT)
- +#define PCU_WAKEUP_SEN_DFT_MASK (PCU_WAKEUP_SEN_POL_MASK)
- +
- +#define PCU_WAKEUP_SEN_GPIO0_POL_MASK PCU_WAKEUP_SEN_POL0_MASK
- +#define PCU_WAKEUP_SEN_GPIO0_POL_OFFSET PCU_WAKEUP_SEN_POL0_OFFSET
- +#define PCU_WAKEUP_SEN_GPIO0_POL_DEFAULT PCU_WAKEUP_SEN_POL0_DEFAULT
- +#define PCU_WAKEUP_SEN_GPIO1_POL_MASK PCU_WAKEUP_SEN_POL1_MASK
- +#define PCU_WAKEUP_SEN_GPIO1_POL_OFFSET PCU_WAKEUP_SEN_POL1_OFFSET
- +#define PCU_WAKEUP_SEN_GPIO1_POL_DEFAULT PCU_WAKEUP_SEN_POL1_DEFAULT
- +#define PCU_WAKEUP_SEN_GPIO2_POL_MASK PCU_WAKEUP_SEN_POL2_MASK
- +#define PCU_WAKEUP_SEN_GPIO2_POL_OFFSET PCU_WAKEUP_SEN_POL2_OFFSET
- +#define PCU_WAKEUP_SEN_GPIO2_POL_DEFAULT PCU_WAKEUP_SEN_POL2_DEFAULT
- +#define PCU_WAKEUP_SEN_GPIO3_POL_MASK PCU_WAKEUP_SEN_POL3_MASK
- +#define PCU_WAKEUP_SEN_GPIO3_POL_OFFSET PCU_WAKEUP_SEN_POL3_OFFSET
- +#define PCU_WAKEUP_SEN_GPIO3_POL_DEFAULT PCU_WAKEUP_SEN_POL3_DEFAULT
- +#define PCU_WAKEUP_SEN_GPIO4_POL_MASK PCU_WAKEUP_SEN_POL4_MASK
- +#define PCU_WAKEUP_SEN_GPIO4_POL_OFFSET PCU_WAKEUP_SEN_POL4_OFFSET
- +#define PCU_WAKEUP_SEN_GPIO4_POL_DEFAULT PCU_WAKEUP_SEN_POL4_DEFAULT
- +#define PCU_WAKEUP_SEN_GPIO5_POL_MASK PCU_WAKEUP_SEN_POL5_MASK
- +#define PCU_WAKEUP_SEN_GPIO5_POL_OFFSET PCU_WAKEUP_SEN_POL5_OFFSET
- +#define PCU_WAKEUP_SEN_GPIO5_POL_DEFAULT PCU_WAKEUP_SEN_POL5_DEFAULT
- +#define PCU_WAKEUP_SEN_WOL_POL_MASK PCU_WAKEUP_SEN_POL6_MASK
- +#define PCU_WAKEUP_SEN_WOL_POL_OFFSET PCU_WAKEUP_SEN_POL6_OFFSET
- +#define PCU_WAKEUP_SEN_WOL_POL_DEFAULT PCU_WAKEUP_SEN_POL6_DEFAULT
- +#define PCU_WAKEUP_SEN_RTC_POL_MASK PCU_WAKEUP_SEN_POL7_MASK
- +#define PCU_WAKEUP_SEN_RTC_POL_OFFSET PCU_WAKEUP_SEN_POL7_OFFSET
- +#define PCU_WAKEUP_SEN_RTC_POL_DEFAULT PCU_WAKEUP_SEN_POL7_DEFAULT
- +#define PCU_WAKEUP_SEN_DAY_POL_OFFSET PCU_WAKEUP_SEN_POL8_OFFSET
- +#define PCU_WAKEUP_SEN_DAY_POL_DEFAULT PCU_WAKEUP_SEN_POL8_DEFAULT
- +#define PCU_WAKEUP_SEN_DBG_POL_MASK PCU_WAKEUP_SEN_POL9_MASK
- +#define PCU_WAKEUP_SEN_DBG_POL_OFFSET PCU_WAKEUP_SEN_POL9_OFFSET
- +#define PCU_WAKEUP_SEN_DBG_POL_DEFAULT PCU_WAKEUP_SEN_POL9_DEFAULT
- +#define PCU_WAKEUP_SEN_PCI_POL_MASK PCU_WAKEUP_SEN_POL10_MASK
- +#define PCU_WAKEUP_SEN_PCI_POL_OFFSET PCU_WAKEUP_SEN_POL10_OFFSET
- +#define PCU_WAKEUP_SEN_PCI_POL_DEFAULT PCU_WAKEUP_SEN_POL10_DEFAULT
- +#define PCU_WAKEUP_SEN_LPC_POL_MASK PCU_WAKEUP_SEN_POL11_MASK
- +#define PCU_WAKEUP_SEN_LPC_POL_OFFSET PCU_WAKEUP_SEN_POL11_OFFSET
- +#define PCU_WAKEUP_SEN_LPC_POL_DEFAULT PCU_WAKEUP_SEN_POL11_DEFAULT
- +
- +// wakeup event status register
- +#define PCU_WAKEUP_STATUS_SIG_MASK (ANDES_BIT_MASK(15, 0))
- +#define PCU_WAKEUP_STATUS_SIG_OFFSET (0)
- +#define PCU_WAKEUP_STATUS_SIG_DEFAULT (0x0)
- +#define PCU_WAKEUP_STATUS_DEFAULT (PCU_WAKEUP_STATUS_SIG_DEFAULT << PCU_WAKEUP_STATUS_SIG_OFFSET)
- +#define PCU_WAKEUP_STATUS_DFT_MASK (PCU_WAKEUP_STATUS_SIG_MASK)
- +
- +//reset timing
- +#define PCU_RESET_TIMER_RG3_MASK (ANDES_BIT_MASK(31, 24))
- +#define PCU_RESET_TIMER_RG3_OFFSET (24)
- +#define PCU_RESET_TIMER_RG3_DEFAULT PCU_RESET_TIMER_RG3_CNT_DEFAULT // in rtl fast reset, this will be 0x2
- +#define PCU_RESET_TIMER_RG3_SRC_MASK (ANDES_BIT_MASK(31, 31))
- +#define PCU_RESET_TIMER_RG3_SRC_OFFSET (31)
- +#define PCU_RESET_TIMER_RG3_SRC_DEFAULT (0x0)
- +#define PCU_RESET_TIMER_RG3_CNT_MASK (ANDES_BIT_MASK(30, 24))
- +#define PCU_RESET_TIMER_RG3_CNT_OFFSET (24)
- +#define PCU_RESET_TIMER_RG3_CNT_DEFAULT (0x4)
- +#define PCU_RESET_TIMER_RG2_MASK (ANDES_BIT_MASK(23, 16))
- +#define PCU_RESET_TIMER_RG2_OFFSET (16)
- +#define PCU_RESET_TIMER_RG2_DEFAULT PCU_RESET_TIMER_RG2_CNT_DEFAULT // in rtl fast reset, this will be 0x2
- +#define PCU_RESET_TIMER_RG2_SRC_MASK (ANDES_BIT_MASK(23, 23))
- +#define PCU_RESET_TIMER_RG2_SRC_OFFSET (23)
- +#define PCU_RESET_TIMER_RG2_SRC_DEFAULT (0x0)
- +#define PCU_RESET_TIMER_RG2_CNT_MASK (ANDES_BIT_MASK(22, 16))
- +#define PCU_RESET_TIMER_RG2_CNT_OFFSET (16)
- +#define PCU_RESET_TIMER_RG2_CNT_DEFAULT (0x4)
- +#define PCU_RESET_TIMER_RG1_MASK (ANDES_BIT_MASK(15, 8))
- +#define PCU_RESET_TIMER_RG1_OFFSET (8)
- +#define PCU_RESET_TIMER_RG1_DEFAULT PCU_RESET_TIMER_RG1_CNT_DEFAULT // in rtl fast reset, this will be 0x2
- +#define PCU_RESET_TIMER_RG1_SRC_MASK (ANDES_BIT_MASK(15, 15))
- +#define PCU_RESET_TIMER_RG1_SRC_OFFSET (15)
- +#define PCU_RESET_TIMER_RG1_SRC_DEFAULT (0x0)
- +#define PCU_RESET_TIMER_RG1_CNT_MASK (ANDES_BIT_MASK(14, 8))
- +#define PCU_RESET_TIMER_RG1_CNT_OFFSET (8)
- +#define PCU_RESET_TIMER_RG1_CNT_DEFAULT (0x4)
- +#define PCU_RESET_TIMER_RG0_MASK (ANDES_BIT_MASK(7, 0))
- +#define PCU_RESET_TIMER_RG0_OFFSET (0)
- +#define PCU_RESET_TIMER_RG0_DEFAULT PCU_RESET_TIMER_RG0_CNT_DEFAULT // in rtl fast reset, this will be 0x2
- +#define PCU_RESET_TIMER_RG0_SRC_MASK (ANDES_BIT_MASK(7, 7))
- +#define PCU_RESET_TIMER_RG0_SRC_OFFSET (7)
- +#define PCU_RESET_TIMER_RG0_SRC_DEFAULT (0x0)
- +#define PCU_RESET_TIMER_RG0_CNT_MASK (ANDES_BIT_MASK(6, 0))
- +#define PCU_RESET_TIMER_RG0_CNT_OFFSET (0)
- +#define PCU_RESET_TIMER_RG0_CNT_DEFAULT (0x4)
- +
- +#define PCU_RESET_TIMER_DEFAULT 0x0 /*((PCU_RESET_TIMER_RG3_DEFAULT << PCU_RESET_TIMER_RG3_OFFSET)|\
- + (PCU_RESET_TIMER_RG2_DEFAULT << PCU_RESET_TIMER_RG2_OFFSET)|\
- + (PCU_RESET_TIMER_RG1_DEFAULT << PCU_RESET_TIMER_RG1_OFFSET)|\
- + (PCU_RESET_TIMER_RG0_DEFAULT << PCU_RESET_TIMER_RG0_OFFSET))*/
- +#define PCU_RESET_TIMER_DFT_MASK 0x0 /*((PCU_RESET_TIMER_RG3_MASK)|\
- + (PCU_RESET_TIMER_RG2_MASK)|\
- + (PCU_RESET_TIMER_RG1_MASK)|\
- + (PCU_RESET_TIMER_RG0_MASK))*/
- +#define PCU_RST_TIMER_SRC_500US (0x1)
- +#define PCU_RST_TIMER_SRC_30US (0x0)
- +
- +// interrupt
- +#define PCU_INTR_GPIOSEC_MASK (ANDES_BIT_MASK(11, 11))
- +#define PCU_INTR_PWRLOW_MASK (ANDES_BIT_MASK(10, 10))
- +#define PCU_INTR_PCS9_MASK (ANDES_BIT_MASK(9, 9))
- +#define PCU_INTR_PCS9_OFFSET (9)
- +#define PCU_INTR_PCS9_DEFAULT (0x0)
- +#define PCU_INTR_PCS8_MASK (ANDES_BIT_MASK(8, 8))
- +#define PCU_INTR_PCS8_OFFSET (8)
- +#define PCU_INTR_PCS8_DEFAULT (0x0)
- +#define PCU_INTR_PCS7_MASK (ANDES_BIT_MASK(7, 7))
- +#define PCU_INTR_PCS7_OFFSET (7)
- +#define PCU_INTR_PCS7_DEFAULT (0x0)
- +#define PCU_INTR_PCS6_MASK (ANDES_BIT_MASK(6, 6))
- +#define PCU_INTR_PCS6_OFFSET (6)
- +#define PCU_INTR_PCS6_DEFAULT (0x0)
- +#define PCU_INTR_PCS5_MASK (ANDES_BIT_MASK(5, 5))
- +#define PCU_INTR_PCS5_OFFSET (5)
- +#define PCU_INTR_PCS5_DEFAULT (0x0)
- +#define PCU_INTR_PCS4_MASK (ANDES_BIT_MASK(4, 4))
- +#define PCU_INTR_PCS4_OFFSET (4)
- +#define PCU_INTR_PCS4_DEFAULT (0x0)
- +#define PCU_INTR_PCS3_MASK (ANDES_BIT_MASK(3, 3))
- +#define PCU_INTR_PCS3_OFFSET (3)
- +#define PCU_INTR_PCS3_DEFAULT (0x0)
- +#define PCU_INTR_PCS2_MASK (ANDES_BIT_MASK(2, 2))
- +#define PCU_INTR_PCS2_OFFSET (2)
- +#define PCU_INTR_PCS2_DEFAULT (0x0)
- +#define PCU_INTR_PCS1_MASK (ANDES_BIT_MASK(1, 1))
- +#define PCU_INTR_PCS1_OFFSET (1)
- +#define PCU_INTR_PCS1_DEFAULT (0x0)
- +#define PCU_INTR_BSM_MASK (ANDES_BIT_MASK(0, 0))
- +#define PCU_INTR_BSM_OFFSET (0)
- +#define PCU_INTR_BSM_DEFAULT (0x0)
- +#define PCU_INTR_DEFAULT (0x0)
- +
- +// bits field for PCS1 registers
- +#define PCU_PCS1_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS1_CFG_TYPE_OFFSET (28)
- +#define PCU_PCS1_CFG_TYPE_DEFAULT (0x1)
- +#define PCU_PCS1_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
- +#define PCU_PCS1_CFG_WR_OFFSET (27)
- +#define PCU_PCS1_CFG_WR_DEFAULT (0x0)
- +#define PCU_PCS1_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
- +#define PCU_PCS1_CFG_SR_OFFSET (0)
- +#define PCU_PCS1_CFG_SR_DEFAULT (0x0)
- +#define PCU_PCS1_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
- +#define PCU_PCS1_CFG_LS_OFFSET (20)
- +#define PCU_PCS1_CFG_LS_DEFAULT (0x0)
- +#define PCU_PCS1_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
- +#define PCU_PCS1_CFG_LW_OFFSET (16)
- +#define PCU_PCS1_CFG_LW_DEFAULT (0x0)
- +#define PCU_PCS1_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
- +#define PCU_PCS1_CFG_WKEN_OFFSET (0)
- +#define PCU_PCS1_CFG_WKEN_DEFAULT (0x0)
- +#define PCU_PCS1_CFG_DEFAULT ((PCU_PCS1_CFG_TYPE_DEFAULT << PCU_PCS1_CFG_TYPE_OFFSET)|\
- + (PCU_PCS1_CFG_WR_DEFAULT << PCU_PCS1_CFG_WR_OFFSET )|\
- + (PCU_PCS1_CFG_SR_DEFAULT << PCU_PCS1_CFG_SR_OFFSET )|\
- + (PCU_PCS1_CFG_LS_DEFAULT << PCU_PCS1_CFG_LS_OFFSET )|\
- + (PCU_PCS1_CFG_LW_DEFAULT << PCU_PCS1_CFG_LW_OFFSET )|\
- + (PCU_PCS1_CFG_WKEN_DEFAULT << PCU_PCS1_CFG_WKEN_OFFSET))
- +
- +#define PCU_PCS1_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
- +#define PCU_PCS1_PARA_IE_OFFSET (31)
- +#define PCU_PCS1_PARA_IE_DEFAULT (0x0)
- +#define PCU_PCS1_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS1_PARA_CMD_OFFSET (28)
- +#define PCU_PCS1_PARA_CMD_DEFAULT (0x0)
- +#define PCU_PCS1_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS1_PARA_SYNC_OFFSET (24)
- +#define PCU_PCS1_PARA_SYNC_DEFAULT (0x3)
- +#define PCU_PCS1_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
- +#define PCU_PCS1_PARA_NXTPAR_OFFSET (0)
- +#define PCU_PCS1_PARA_NXTPAR_DEFAULT (0x1)
- +#define PCU_PCS1_PARA_DIV_MASK (ANDES_BIT_MASK(5, 4))
- +#define PCU_PCS1_PARA_DIV_OFFSET (4)
- +//#define PCU_PCS1_PARA_DIV_DEFAULT (0x0) //jumper setting
- +#define PCU_PCS1_PARA_RATIO_MASK (ANDES_BIT_MASK(3, 0))
- +#define PCU_PCS1_PARA_RATIO_OFFSET (0)
- +//#define PCU_PCS1_PARA_RATIO_DEFAULT (0x0) //jumper setting
- +#define PCU_PCS1_PARA_DEFAULT ((PCU_PCS1_PARA_IE_DEFAULT << PCU_PCS1_PARA_IE_OFFSET )|\
- + (PCU_PCS1_PARA_CMD_DEFAULT << PCU_PCS1_PARA_CMD_OFFSET )|\
- + (PCU_PCS1_PARA_SYNC_DEFAULT << PCU_PCS1_PARA_SYNC_OFFSET))
- +#define PCU_PCS1_PARA_DFT_MASK ((PCU_PCS1_PARA_IE_MASK )|\
- + (PCU_PCS1_PARA_CMD_MASK )|\
- + (PCU_PCS1_PARA_SYNC_MASK))
- +
- +#define PCU_PCS1_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS1_ST1_STS_OFFSET (28)
- +#define PCU_PCS1_ST1_STS_DEFAULT (0x0)
- +#define PCU_PCS1_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
- +#define PCU_PCS1_ST1_ERR_OFFSET (0)
- +#define PCU_PCS1_ST1_ERR_DEFAULT (0x0)
- +#define PCU_PCS1_ST1_DEFAULT ((PCU_PCS1_ST1_STS_DEFAULT << PCU_PCS1_ST1_STS_OFFSET )|\
- + (PCU_PCS1_ST1_ERR_DEFAULT << PCU_PCS1_ST1_ERR_OFFSET ))
- +
- +#define PCU_PCS1_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS1_ST2_SYNC_OFFSET (24)
- +#define PCU_PCS1_ST2_SYNC_DEFAULT (0x0)
- +#define PCU_PCS1_ST2_CURPAR_MASK (ANDES_BIT_MASK(23, 0))
- +#define PCU_PCS1_ST2_CURPAR_OFFSET (0)
- +//#define PCU_PCS1_ST2_CURPAR_DEFAULT (0x0)
- +#define PCU_PCS1_ST2_DIV_MASK (ANDES_BIT_MASK(5, 4))
- +#define PCU_PCS1_ST2_DIV_OFFSET (4)
- +//#define PCU_PCS1_ST2_DIV_DEFAULT (0x0) //jumper setting
- +#define PCU_PCS1_ST2_RATIO_MASK (ANDES_BIT_MASK(3, 0))
- +#define PCU_PCS1_ST2_RATIO_OFFSET (0)
- +//#define PCU_PCS1_ST2_RATIO_DEFAULT (0x0) //jumper setting
- +#define PCU_PCS1_ST2_DEFAULT (PCU_PCS1_ST2_SYNC_DEFAULT << PCU_PCS1_ST2_SYNC_OFFSET)
- +#define PCU_PCS1_ST2_DFT_MASK (PCU_PCS1_ST2_SYNC_MASK)
- +
- +
- +// bits field for PCS2 registers
- +#define PCU_PCS2_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS2_CFG_TYPE_OFFSET (28)
- +#define PCU_PCS2_CFG_TYPE_DEFAULT (0x2)
- +#define PCU_PCS2_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
- +#define PCU_PCS2_CFG_WR_OFFSET (27)
- +#define PCU_PCS2_CFG_WR_DEFAULT (0x0)
- +#define PCU_PCS2_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
- +#define PCU_PCS2_CFG_SR_OFFSET (0)
- +#define PCU_PCS2_CFG_SR_DEFAULT (0x0)
- +#define PCU_PCS2_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
- +#define PCU_PCS2_CFG_LS_OFFSET (20)
- +#define PCU_PCS2_CFG_LS_DEFAULT (0x0)
- +#define PCU_PCS2_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
- +#define PCU_PCS2_CFG_LW_OFFSET (16)
- +#define PCU_PCS2_CFG_LW_DEFAULT (0x0)
- +#define PCU_PCS2_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
- +#define PCU_PCS2_CFG_WKEN_OFFSET (0)
- +#define PCU_PCS2_CFG_WKEN_DEFAULT (0x0)
- +#define PCU_PCS2_CFG_DEFAULT ((PCU_PCS2_CFG_TYPE_DEFAULT << PCU_PCS2_CFG_TYPE_OFFSET)|\
- + (PCU_PCS2_CFG_WR_DEFAULT << PCU_PCS2_CFG_WR_OFFSET )|\
- + (PCU_PCS2_CFG_SR_DEFAULT << PCU_PCS2_CFG_SR_OFFSET )|\
- + (PCU_PCS2_CFG_LS_DEFAULT << PCU_PCS2_CFG_LS_OFFSET )|\
- + (PCU_PCS2_CFG_LW_DEFAULT << PCU_PCS2_CFG_LW_OFFSET )|\
- + (PCU_PCS2_CFG_WKEN_DEFAULT << PCU_PCS2_CFG_WKEN_OFFSET))
- +
- +#define PCU_PCS2_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
- +#define PCU_PCS2_PARA_IE_OFFSET (31)
- +#define PCU_PCS2_PARA_IE_DEFAULT (0x0)
- +#define PCU_PCS2_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS2_PARA_CMD_OFFSET (28)
- +#define PCU_PCS2_PARA_CMD_DEFAULT (0x0)
- +#define PCU_PCS2_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS2_PARA_SYNC_OFFSET (24)
- +#define PCU_PCS2_PARA_SYNC_DEFAULT (0x3)
- +#define PCU_PCS2_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
- +#define PCU_PCS2_PARA_NXTPAR_OFFSET (0)
- +#define PCU_PCS2_PARA_NXTPAR_DEFAULT (0x0)
- +#define PCU_PCS2_PARA_DEFAULT ((PCU_PCS2_PARA_IE_DEFAULT << PCU_PCS2_PARA_IE_OFFSET )|\
- + (PCU_PCS2_PARA_CMD_DEFAULT << PCU_PCS2_PARA_CMD_OFFSET )|\
- + (PCU_PCS2_PARA_SYNC_DEFAULT << PCU_PCS2_PARA_SYNC_OFFSET )|\
- + (PCU_PCS2_PARA_NXTPAR_DEFAULT << PCU_PCS2_PARA_NXTPAR_OFFSET))
- +#define PCU_PCS2_PARA_DFT_MASK ((PCU_PCS2_PARA_IE_MASK )|\
- + (PCU_PCS2_PARA_CMD_MASK )|\
- + (PCU_PCS2_PARA_SYNC_MASK )|\
- + (PCU_PCS2_PARA_NXTPAR_MASK))
- +
- +#define PCU_PCS2_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS2_ST1_STS_OFFSET (28)
- +#define PCU_PCS2_ST1_STS_DEFAULT (0x0)
- +#define PCU_PCS2_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
- +#define PCU_PCS2_ST1_ERR_OFFSET (0)
- +#define PCU_PCS2_ST1_ERR_DEFAULT (0x0)
- +#define PCU_PCS2_ST1_DEFAULT ((PCU_PCS2_ST1_STS_DEFAULT << PCU_PCS2_ST1_STS_OFFSET )|\
- + (PCU_PCS2_ST1_ERR_DEFAULT << PCU_PCS2_ST1_ERR_OFFSET ))
- +
- +#define PCU_PCS2_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS2_ST2_SYNC_OFFSET (24)
- +#define PCU_PCS2_ST2_SYNC_DEFAULT (0x0)
- +#define PCU_PCS2_ST2_CURPAR_MASK (ANDES_BIT_MASK(23, 0))
- +#define PCU_PCS2_ST2_CURPAR_OFFSET (0)
- +#define PCU_PCS2_ST2_CURPAR_DEFAULT (0x0)
- +#define PCU_PCS2_ST2_DEFAULT ((PCU_PCS2_ST2_SYNC_DEFAULT << PCU_PCS2_ST2_SYNC_OFFSET )|\
- + (PCU_PCS2_ST2_CURPAR_DEFAULT << PCU_PCS2_ST2_CURPAR_OFFSET))
- +#define PCU_PCS2_ST2_DFT_MASK ((PCU_PCS2_ST2_SYNC_MASK )|\
- + (PCU_PCS2_ST2_CURPAR_MASK))
- +
- +// bits field for PCS3 registers
- +#define PCU_PCS3_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS3_CFG_TYPE_OFFSET (28)
- +#define PCU_PCS3_CFG_TYPE_DEFAULT (0x2)
- +#define PCU_PCS3_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
- +#define PCU_PCS3_CFG_WR_OFFSET (27)
- +#define PCU_PCS3_CFG_WR_DEFAULT (0x0)
- +#define PCU_PCS3_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
- +#define PCU_PCS3_CFG_SR_OFFSET (0)
- +#define PCU_PCS3_CFG_SR_DEFAULT (0x0)
- +#define PCU_PCS3_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
- +#define PCU_PCS3_CFG_LS_OFFSET (20)
- +#define PCU_PCS3_CFG_LS_DEFAULT (0x0)
- +#define PCU_PCS3_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
- +#define PCU_PCS3_CFG_LW_OFFSET (16)
- +#define PCU_PCS3_CFG_LW_DEFAULT (0x0)
- +#define PCU_PCS3_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
- +#define PCU_PCS3_CFG_WKEN_OFFSET (0)
- +#define PCU_PCS3_CFG_WKEN_DEFAULT (0x0)
- +#define PCU_PCS3_CFG_DEFAULT ((PCU_PCS3_CFG_TYPE_DEFAULT << PCU_PCS3_CFG_TYPE_OFFSET)|\
- + (PCU_PCS3_CFG_WR_DEFAULT << PCU_PCS3_CFG_WR_OFFSET )|\
- + (PCU_PCS3_CFG_SR_DEFAULT << PCU_PCS3_CFG_SR_OFFSET )|\
- + (PCU_PCS3_CFG_LS_DEFAULT << PCU_PCS3_CFG_LS_OFFSET )|\
- + (PCU_PCS3_CFG_LW_DEFAULT << PCU_PCS3_CFG_LW_OFFSET )|\
- + (PCU_PCS3_CFG_WKEN_DEFAULT << PCU_PCS3_CFG_WKEN_OFFSET))
- +
- +#define PCU_PCS3_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
- +#define PCU_PCS3_PARA_IE_OFFSET (31)
- +#define PCU_PCS3_PARA_IE_DEFAULT (0x0)
- +#define PCU_PCS3_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS3_PARA_CMD_OFFSET (28)
- +#define PCU_PCS3_PARA_CMD_DEFAULT (0x0)
- +#define PCU_PCS3_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS3_PARA_SYNC_OFFSET (24)
- +#define PCU_PCS3_PARA_SYNC_DEFAULT (0x3)
- +#define PCU_PCS3_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
- +#define PCU_PCS3_PARA_NXTPAR_OFFSET (0)
- +#define PCU_PCS3_PARA_NXTPAR_DEFAULT (0x0)
- +#define PCU_PCS3_PARA_DEFAULT ((PCU_PCS3_PARA_IE_DEFAULT << PCU_PCS3_PARA_IE_OFFSET )|\
- + (PCU_PCS3_PARA_CMD_DEFAULT << PCU_PCS3_PARA_CMD_OFFSET )|\
- + (PCU_PCS3_PARA_SYNC_DEFAULT << PCU_PCS3_PARA_SYNC_OFFSET )|\
- + (PCU_PCS3_PARA_NXTPAR_DEFAULT << PCU_PCS3_PARA_NXTPAR_OFFSET))
- +#define PCU_PCS3_PARA_DFT_MASK ((PCU_PCS3_PARA_IE_MASK )|\
- + (PCU_PCS3_PARA_CMD_MASK )|\
- + (PCU_PCS3_PARA_SYNC_MASK )|\
- + (PCU_PCS3_PARA_NXTPAR_MASK))
- +
- +#define PCU_PCS3_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS3_ST1_STS_OFFSET (28)
- +#define PCU_PCS3_ST1_STS_DEFAULT (0x0)
- +#define PCU_PCS3_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
- +#define PCU_PCS3_ST1_ERR_OFFSET (0)
- +#define PCU_PCS3_ST1_ERR_DEFAULT (0x0)
- +#define PCU_PCS3_ST1_DEFAULT ((PCU_PCS3_ST1_STS_DEFAULT << PCU_PCS3_ST1_STS_OFFSET )|\
- + (PCU_PCS3_ST1_ERR_DEFAULT << PCU_PCS3_ST1_ERR_OFFSET ))
- +
- +#define PCU_PCS3_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS3_ST2_SYNC_OFFSET (24)
- +#define PCU_PCS3_ST2_SYNC_DEFAULT (0x0)
- +#define PCU_PCS3_ST2_CURPAR_MASK (ANDES_BIT_MASK(23, 0))
- +#define PCU_PCS3_ST2_CURPAR_OFFSET (0)
- +#define PCU_PCS3_ST2_CURPAR_DEFAULT (0x0)
- +#define PCU_PCS3_ST2_DEFAULT ((PCU_PCS3_ST2_SYNC_DEFAULT << PCU_PCS3_ST2_SYNC_OFFSET )|\
- + (PCU_PCS3_ST2_CURPAR_DEFAULT << PCU_PCS3_ST2_CURPAR_OFFSET))
- +#define PCU_PCS3_ST2_DFT_MASK ((PCU_PCS3_ST2_SYNC_MASK )|\
- + (PCU_PCS3_ST2_CURPAR_MASK))
- +
- +// bits field for PCS4 registers
- +#define PCU_PCS4_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS4_CFG_TYPE_OFFSET (28)
- +#define PCU_PCS4_CFG_TYPE_DEFAULT (0x0)
- +#define PCU_PCS4_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
- +#define PCU_PCS4_CFG_WR_OFFSET (27)
- +#define PCU_PCS4_CFG_WR_DEFAULT (0x0)
- +#define PCU_PCS4_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
- +#define PCU_PCS4_CFG_SR_OFFSET (0)
- +#define PCU_PCS4_CFG_SR_DEFAULT (0x0)
- +#define PCU_PCS4_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
- +#define PCU_PCS4_CFG_LS_OFFSET (20)
- +#define PCU_PCS4_CFG_LS_DEFAULT (0x0)
- +#define PCU_PCS4_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
- +#define PCU_PCS4_CFG_LW_OFFSET (16)
- +#define PCU_PCS4_CFG_LW_DEFAULT (0x0)
- +#define PCU_PCS4_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
- +#define PCU_PCS4_CFG_WKEN_OFFSET (0)
- +#define PCU_PCS4_CFG_WKEN_DEFAULT (0x0)
- +#define PCU_PCS4_CFG_DEFAULT ((PCU_PCS4_CFG_TYPE_DEFAULT << PCU_PCS4_CFG_TYPE_OFFSET)|\
- + (PCU_PCS4_CFG_WR_DEFAULT << PCU_PCS4_CFG_WR_OFFSET )|\
- + (PCU_PCS4_CFG_SR_DEFAULT << PCU_PCS4_CFG_SR_OFFSET )|\
- + (PCU_PCS4_CFG_LS_DEFAULT << PCU_PCS4_CFG_LS_OFFSET )|\
- + (PCU_PCS4_CFG_LW_DEFAULT << PCU_PCS4_CFG_LW_OFFSET )|\
- + (PCU_PCS4_CFG_WKEN_DEFAULT << PCU_PCS4_CFG_WKEN_OFFSET))
- +
- +#define PCU_PCS4_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
- +#define PCU_PCS4_PARA_IE_OFFSET (31)
- +#define PCU_PCS4_PARA_IE_DEFAULT (0x0)
- +#define PCU_PCS4_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS4_PARA_CMD_OFFSET (28)
- +#define PCU_PCS4_PARA_CMD_DEFAULT (0x0)
- +#define PCU_PCS4_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS4_PARA_SYNC_OFFSET (24)
- +#define PCU_PCS4_PARA_SYNC_DEFAULT (0x3)
- +#define PCU_PCS4_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
- +#define PCU_PCS4_PARA_NXTPAR_OFFSET (0)
- +#define PCU_PCS4_PARA_NXTPAR_DEFAULT (0x4)
- +#define PCU_PCS4_PARA_PWDN_MASK (ANDES_BIT_MASK(23, 23))
- +#define PCU_PCS4_PARA_PWDN_OFFSET (23)
- +#define PCU_PCS4_PARA_PWDN_DEFAULT (0x0)
- +#define PCU_PCS4_PARA_RANGE_MASK (ANDES_BIT_MASK(17, 16))
- +#define PCU_PCS4_PARA_RANGE_OFFSET (16)
- +#define PCU_PCS4_PARA_RANGE_DEFAULT (0x0)
- +#define PCU_PCS4_PARA_N_FACTOR_MASK (ANDES_BIT_MASK(7, 0))
- +#define PCU_PCS4_PARA_N_FACTOR_OFFSET (0)
- +#define PCU_PCS4_PARA_N_FACTOR_DEFAULT (0x4)
- +#define PCU_PCS4_PARA_DEFAULT ((PCU_PCS4_PARA_IE_DEFAULT << PCU_PCS4_PARA_IE_OFFSET )|\
- + (PCU_PCS4_PARA_CMD_DEFAULT << PCU_PCS4_PARA_CMD_OFFSET )|\
- + (PCU_PCS4_PARA_SYNC_DEFAULT << PCU_PCS4_PARA_SYNC_OFFSET)|\
- + (PCU_PCS4_PARA_PWDN_DEFAULT << PCU_PCS4_PARA_PWDN_OFFSET))
- +#define PCU_PCS4_PARA_DFT_MASK ((PCU_PCS4_PARA_IE_MASK )|\
- + (PCU_PCS4_PARA_CMD_MASK )|\
- + (PCU_PCS4_PARA_SYNC_MASK)|\
- + (PCU_PCS4_PARA_PWDN_MASK))
- +
- +#define PCU_PCS4_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS4_ST1_STS_OFFSET (28)
- +#define PCU_PCS4_ST1_STS_DEFAULT (0x0)
- +#define PCU_PCS4_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
- +#define PCU_PCS4_ST1_ERR_OFFSET (0)
- +#define PCU_PCS4_ST1_ERR_DEFAULT (0x0)
- +#define PCU_PCS4_ST1_DEFAULT ((PCU_PCS4_ST1_STS_DEFAULT << PCU_PCS4_ST1_STS_OFFSET )|\
- + (PCU_PCS4_ST1_ERR_DEFAULT << PCU_PCS4_ST1_ERR_OFFSET ))
- +
- +#define PCU_PCS4_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS4_ST2_SYNC_OFFSET (24)
- +#define PCU_PCS4_ST2_SYNC_DEFAULT (0x0)
- +#define PCU_PCS4_ST2_CURPAR_MASK (ANDES_BIT_MASK(23, 0))
- +#define PCU_PCS4_ST2_CURPAR_OFFSET (0)
- +//#define PCU_PCS4_ST2_CURPAR_DEFAULT (0x0)
- +#define PCU_PCS4_ST2_PWDN_MASK PCU_PCS4_PARA_PWDN_MASK
- +#define PCU_PCS4_ST2_PWDN_OFFSET PCU_PCS4_PARA_PWDN_OFFSET
- +#define PCU_PCS4_ST2_PWDN_DEFAULT PCU_PCS4_PARA_PWDN_DEFAULT
- +#define PCU_PCS4_ST2_RANGE_MASK PCU_PCS4_PARA_RANGE_MASK
- +#define PCU_PCS4_ST2_RANGE_OFFSET PCU_PCS4_PARA_RANGE_OFFSET
- +//#define PCU_PCS4_ST2_RANGE_DEFAULT PCU_PCS4_PARA_RANGE_DEFAULT
- +#define PCU_PCS4_ST2_N_FACTOR_MASK PCU_PCS4_PARA_N_FACTOR_MASK
- +#define PCU_PCS4_ST2_N_FACTOR_OFFSET PCU_PCS4_PARA_N_FACTOR_OFFSET
- +//#define PCU_PCS4_ST2_N_FACTOR_DEFAULT PCU_PCS4_PARA_N_FACTOR_DEFAULT
- +#define PCU_PCS4_ST2_DEFAULT ((PCU_PCS4_ST2_SYNC_DEFAULT << PCU_PCS4_ST2_SYNC_OFFSET)|\
- + (PCU_PCS4_ST2_PWDN_DEFAULT << PCU_PCS4_ST2_PWDN_OFFSET))
- +#define PCU_PCS4_ST2_DFT_MASK ((PCU_PCS4_ST2_SYNC_MASK)|\
- + (PCU_PCS4_ST2_PWDN_MASK))
- +
- +// bits field for PCS5 registers
- +#define PCU_PCS5_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS5_CFG_TYPE_OFFSET (28)
- +#define PCU_PCS5_CFG_TYPE_DEFAULT (0x0)
- +#define PCU_PCS5_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
- +#define PCU_PCS5_CFG_WR_OFFSET (27)
- +#define PCU_PCS5_CFG_WR_DEFAULT (0x0)
- +#define PCU_PCS5_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
- +#define PCU_PCS5_CFG_SR_OFFSET (0)
- +#define PCU_PCS5_CFG_SR_DEFAULT (0x0)
- +#define PCU_PCS5_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
- +#define PCU_PCS5_CFG_LS_OFFSET (20)
- +#define PCU_PCS5_CFG_LS_DEFAULT (0x0)
- +#define PCU_PCS5_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
- +#define PCU_PCS5_CFG_LW_OFFSET (16)
- +#define PCU_PCS5_CFG_LW_DEFAULT (0x0)
- +#define PCU_PCS5_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
- +#define PCU_PCS5_CFG_WKEN_OFFSET (0)
- +#define PCU_PCS5_CFG_WKEN_DEFAULT (0x0)
- +#define PCU_PCS5_CFG_DEFAULT ((PCU_PCS5_CFG_TYPE_DEFAULT << PCU_PCS5_CFG_TYPE_OFFSET)|\
- + (PCU_PCS5_CFG_WR_DEFAULT << PCU_PCS5_CFG_WR_OFFSET )|\
- + (PCU_PCS5_CFG_SR_DEFAULT << PCU_PCS5_CFG_SR_OFFSET )|\
- + (PCU_PCS5_CFG_LS_DEFAULT << PCU_PCS5_CFG_LS_OFFSET )|\
- + (PCU_PCS5_CFG_LW_DEFAULT << PCU_PCS5_CFG_LW_OFFSET )|\
- + (PCU_PCS5_CFG_WKEN_DEFAULT << PCU_PCS5_CFG_WKEN_OFFSET))
- +
- +#define PCU_PCS5_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
- +#define PCU_PCS5_PARA_IE_OFFSET (31)
- +#define PCU_PCS5_PARA_IE_DEFAULT (0x0)
- +#define PCU_PCS5_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS5_PARA_CMD_OFFSET (28)
- +#define PCU_PCS5_PARA_CMD_DEFAULT (0x0)
- +#define PCU_PCS5_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS5_PARA_SYNC_OFFSET (24)
- +#define PCU_PCS5_PARA_SYNC_DEFAULT (0x3)
- +#define PCU_PCS5_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
- +#define PCU_PCS5_PARA_NXTPAR_OFFSET (0)
- +#define PCU_PCS5_PARA_NXTPAR_DEFAULT (0x0)
- +#define PCU_PCS5_PARA_DLL_PWDN_MASK (ANDES_BIT_MASK(23, 23))
- +#define PCU_PCS5_PARA_DLL_PWDN_OFFSET (23)
- +#define PCU_PCS5_PARA_DLL_PWDN_DEFAULT (0x0)
- +#define PCU_PCS5_PARA_PLL_PWDN_MASK (ANDES_BIT_MASK(22, 22))
- +#define PCU_PCS5_PARA_PLL_PWDN_OFFSET (22)
- +#define PCU_PCS5_PARA_PLL_PWDN_DEFAULT (0x0)
- +#define PCU_PCS5_PARA_DLL_BYPASS_MASK (ANDES_BIT_MASK(16, 16))
- +#define PCU_PCS5_PARA_DLL_BYPASS_OFFSET (16)
- +#define PCU_PCS5_PARA_DLL_BYPASS_DEFAULT (0x0)
- +#define PCU_PCS5_PARA_DLL_DELAY_MASK (ANDES_BIT_MASK(15, 12))
- +#define PCU_PCS5_PARA_DLL_DELAY_OFFSET (12)
- +#define PCU_PCS5_PARA_DLL_DELAY_DEFAULT (0x0)
- +#define PCU_PCS5_PARA_66MHZ_MASK (ANDES_BIT_MASK(11, 11))
- +#define PCU_PCS5_PARA_66MHZ_OFFSET (11)
- +//#define PCU_PCS5_PARA_66MHZ_DEFAULT (0x0) /dumper setting
- +#define PCU_PCS5_PARA_DEFAULT ((PCU_PCS5_PARA_IE_DEFAULT << PCU_PCS5_PARA_IE_OFFSET )|\
- + (PCU_PCS5_PARA_CMD_DEFAULT << PCU_PCS5_PARA_CMD_OFFSET )|\
- + (PCU_PCS5_PARA_SYNC_DEFAULT << PCU_PCS5_PARA_SYNC_OFFSET )|\
- + (PCU_PCS5_PARA_PLL_PWDN_DEFAULT << PCU_PCS5_PARA_PLL_PWDN_OFFSET )|\
- + (PCU_PCS5_PARA_DLL_DELAY_DEFAULT << PCU_PCS5_PARA_DLL_DELAY_OFFSET ))
- +#define PCU_PCS5_PARA_DFT_MASK ((PCU_PCS5_PARA_IE_MASK )|\
- + (PCU_PCS5_PARA_CMD_MASK )|\
- + (PCU_PCS5_PARA_SYNC_MASK )|\
- + (PCU_PCS5_PARA_PLL_PWDN_MASK )|\
- + (PCU_PCS5_PARA_DLL_DELAY_MASK ))
- +
- +#define PCU_PCS5_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS5_ST1_STS_OFFSET (28)
- +#define PCU_PCS5_ST1_STS_DEFAULT (0x0)
- +#define PCU_PCS5_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
- +#define PCU_PCS5_ST1_ERR_OFFSET (0)
- +#define PCU_PCS5_ST1_ERR_DEFAULT (0x0)
- +#define PCU_PCS5_ST1_DEFAULT ((PCU_PCS5_ST1_STS_DEFAULT << PCU_PCS5_ST1_STS_OFFSET )|\
- + (PCU_PCS5_ST1_ERR_DEFAULT << PCU_PCS5_ST1_ERR_OFFSET ))
- +
- +#define PCU_PCS5_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS5_ST2_SYNC_OFFSET (24)
- +#define PCU_PCS5_ST2_SYNC_DEFAULT (0x0)
- +#define PCU_PCS5_ST2_CURPAR_MASK (ANDES_BIT_MASK(23, 0))
- +#define PCU_PCS5_ST2_CURPAR_OFFSET (0)
- +//#define PCU_PCS5_ST2_CURPAR_DEFAULT (0x0) //no default
- +#define PCU_PCS5_ST2_DLL_PWDN_MASK PCU_PCS5_PARA_DLL_PWDN_MASK
- +#define PCU_PCS5_ST2_DLL_PWDN_OFFSET PCU_PCS5_PARA_DLL_PWDN_OFFSET
- +#define PCU_PCS5_ST2_DLL_PWDN_DEFAULT PCU_PCS5_PARA_DLL_PWDN_DEFAULT
- +#define PCU_PCS5_ST2_PLL_PWDN_MASK PCU_PCS5_PARA_PLL_PWDN_MASK
- +#define PCU_PCS5_ST2_PLL_PWDN_OFFSET PCU_PCS5_PARA_PLL_PWDN_OFFSET
- +#define PCU_PCS5_ST2_PLL_PWDN_DEFAULT PCU_PCS5_PARA_PLL_PWDN_DEFAULT
- +#define PCU_PCS5_ST2_DLL_BYPASS_MASK PCU_PCS5_PARA_DLL_BYPASS_MASK
- +#define PCU_PCS5_ST2_DLL_BYPASS_OFFSET PCU_PCS5_PARA_DLL_BYPASS_OFFSET
- +#define PCU_PCS5_ST2_DLL_BYPASS_DEFAULT PCU_PCS5_PARA_DLL_BYPASS_DEFAULT
- +#define PCU_PCS5_ST2_DLL_DELAY_MASK PCU_PCS5_PARA_DLL_DELAY_MASK
- +#define PCU_PCS5_ST2_DLL_DELAY_OFFSET PCU_PCS5_PARA_DLL_DELAY_OFFSET
- +#define PCU_PCS5_ST2_DLL_DELAY_DEFAULT PCU_PCS5_PARA_DLL_DELAY_DEFAULT
- +#define PCU_PCS5_ST2_DEFAULT ((PCU_PCS5_ST2_SYNC_DEFAULT << PCU_PCS5_ST2_SYNC_OFFSET )|\
- + (PCU_PCS5_ST2_PLL_PWDN_DEFAULT << PCU_PCS5_ST2_PLL_PWDN_OFFSET )|\
- + (PCU_PCS5_ST2_DLL_DELAY_DEFAULT << PCU_PCS5_ST2_DLL_DELAY_OFFSET ))
- +#define PCU_PCS5_ST2_DFT_MASK ((PCU_PCS5_ST2_SYNC_MASK )|\
- + (PCU_PCS5_ST2_PLL_PWDN_MASK )|\
- + (PCU_PCS5_ST2_DLL_DELAY_MASK ))
- +
- +// bits field for PCS6 registers
- +#define PCU_PCS6_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS6_CFG_TYPE_OFFSET (28)
- +#define PCU_PCS6_CFG_TYPE_DEFAULT (0x0)
- +#define PCU_PCS6_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
- +#define PCU_PCS6_CFG_WR_OFFSET (27)
- +#define PCU_PCS6_CFG_WR_DEFAULT (0x0)
- +#define PCU_PCS6_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
- +#define PCU_PCS6_CFG_SR_OFFSET (0)
- +#define PCU_PCS6_CFG_SR_DEFAULT (0x0)
- +#define PCU_PCS6_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
- +#define PCU_PCS6_CFG_LS_OFFSET (20)
- +#define PCU_PCS6_CFG_LS_DEFAULT (0x0)
- +#define PCU_PCS6_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
- +#define PCU_PCS6_CFG_LW_OFFSET (16)
- +#define PCU_PCS6_CFG_LW_DEFAULT (0x0)
- +#define PCU_PCS6_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
- +#define PCU_PCS6_CFG_WKEN_OFFSET (0)
- +#define PCU_PCS6_CFG_WKEN_DEFAULT (0x0)
- +#define PCU_PCS6_CFG_DEFAULT ((PCU_PCS6_CFG_TYPE_DEFAULT << PCU_PCS6_CFG_TYPE_OFFSET)|\
- + (PCU_PCS6_CFG_WR_DEFAULT << PCU_PCS6_CFG_WR_OFFSET )|\
- + (PCU_PCS6_CFG_SR_DEFAULT << PCU_PCS6_CFG_SR_OFFSET )|\
- + (PCU_PCS6_CFG_LS_DEFAULT << PCU_PCS6_CFG_LS_OFFSET )|\
- + (PCU_PCS6_CFG_LW_DEFAULT << PCU_PCS6_CFG_LW_OFFSET )|\
- + (PCU_PCS6_CFG_WKEN_DEFAULT << PCU_PCS6_CFG_WKEN_OFFSET))
- +
- +#define PCU_PCS6_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
- +#define PCU_PCS6_PARA_IE_OFFSET (31)
- +#define PCU_PCS6_PARA_IE_DEFAULT (0x0)
- +#define PCU_PCS6_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS6_PARA_CMD_OFFSET (28)
- +#define PCU_PCS6_PARA_CMD_DEFAULT (0x0)
- +#define PCU_PCS6_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS6_PARA_SYNC_OFFSET (24)
- +#define PCU_PCS6_PARA_SYNC_DEFAULT (0x3)
- +#define PCU_PCS6_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
- +#define PCU_PCS6_PARA_NXTPAR_OFFSET (0)
- +#define PCU_PCS6_PARA_NXTPAR_DEFAULT (0x0)
- +#define PCU_PCS6_PARA_PWDN_MASK (ANDES_BIT_MASK(23, 23))
- +#define PCU_PCS6_PARA_PWDN_OFFSET (23)
- +#define PCU_PCS6_PARA_PWDN_DEFAULT (0x0)
- +#define PCU_PCS6_PARA_DEFAULT ((PCU_PCS6_PARA_IE_DEFAULT << PCU_PCS6_PARA_IE_OFFSET )|\
- + (PCU_PCS6_PARA_CMD_DEFAULT << PCU_PCS6_PARA_CMD_OFFSET )|\
- + (PCU_PCS6_PARA_SYNC_DEFAULT << PCU_PCS6_PARA_SYNC_OFFSET)|\
- + (PCU_PCS6_PARA_PWDN_DEFAULT << PCU_PCS6_PARA_PWDN_OFFSET))
- +#define PCU_PCS6_PARA_DFT_MASK ((PCU_PCS6_PARA_IE_MASK )|\
- + (PCU_PCS6_PARA_CMD_MASK )|\
- + (PCU_PCS6_PARA_SYNC_MASK)|\
- + (PCU_PCS6_PARA_PWDN_MASK))
- +
- +#define PCU_PCS6_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS6_ST1_STS_OFFSET (28)
- +#define PCU_PCS6_ST1_STS_DEFAULT (0x0)
- +#define PCU_PCS6_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
- +#define PCU_PCS6_ST1_ERR_OFFSET (0)
- +#define PCU_PCS6_ST1_ERR_DEFAULT (0x0)
- +#define PCU_PCS6_ST1_DEFAULT ((PCU_PCS6_ST1_STS_DEFAULT << PCU_PCS6_ST1_STS_OFFSET )|\
- + (PCU_PCS6_ST1_ERR_DEFAULT << PCU_PCS6_ST1_ERR_OFFSET ))
- +
- +#define PCU_PCS6_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS6_ST2_SYNC_OFFSET (24)
- +#define PCU_PCS6_ST2_SYNC_DEFAULT (0x0)
- +#define PCU_PCS6_ST2_CURPAR_MASK (ANDES_BIT_MASK(23, 0))
- +#define PCU_PCS6_ST2_CURPAR_OFFSET (0)
- +//#define PCU_PCS6_ST2_CURPAR_DEFAULT (0x0) //no default
- +#define PCU_PCS6_ST2_PWDN_MASK PCU_PCS6_PARA_PWDN_MASK
- +#define PCU_PCS6_ST2_PWDN_OFFSET PCU_PCS6_PARA_PWDN_OFFSET
- +#define PCU_PCS6_ST2_PWDN_DEFAULT PCU_PCS6_PARA_PWDN_DEFAULT
- +#define PCU_PCS6_ST2_DEFAULT ((PCU_PCS6_ST2_SYNC_DEFAULT << PCU_PCS6_ST2_SYNC_OFFSET)|\
- + (PCU_PCS6_ST2_PWDN_DEFAULT << PCU_PCS6_ST2_PWDN_OFFSET))
- +#define PCU_PCS6_ST2_DFT_MASK ((PCU_PCS6_ST2_SYNC_MASK)|\
- + (PCU_PCS6_ST2_PWDN_MASK))
- +
- +// bits field for PCS7 registers
- +#define PCU_PCS7_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS7_CFG_TYPE_OFFSET (28)
- +#define PCU_PCS7_CFG_TYPE_DEFAULT (0x0)
- +#define PCU_PCS7_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
- +#define PCU_PCS7_CFG_WR_OFFSET (27)
- +#define PCU_PCS7_CFG_WR_DEFAULT (0x0)
- +#define PCU_PCS7_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
- +#define PCU_PCS7_CFG_SR_OFFSET (0)
- +#define PCU_PCS7_CFG_SR_DEFAULT (0x0)
- +#define PCU_PCS7_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
- +#define PCU_PCS7_CFG_LS_OFFSET (20)
- +#define PCU_PCS7_CFG_LS_DEFAULT (0x0)
- +#define PCU_PCS7_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
- +#define PCU_PCS7_CFG_LW_OFFSET (16)
- +#define PCU_PCS7_CFG_LW_DEFAULT (0x0)
- +#define PCU_PCS7_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
- +#define PCU_PCS7_CFG_WKEN_OFFSET (0)
- +#define PCU_PCS7_CFG_WKEN_DEFAULT (0x0)
- +#define PCU_PCS7_CFG_DEFAULT ((PCU_PCS7_CFG_TYPE_DEFAULT << PCU_PCS7_CFG_TYPE_OFFSET)|\
- + (PCU_PCS7_CFG_WR_DEFAULT << PCU_PCS7_CFG_WR_OFFSET )|\
- + (PCU_PCS7_CFG_SR_DEFAULT << PCU_PCS7_CFG_SR_OFFSET )|\
- + (PCU_PCS7_CFG_LS_DEFAULT << PCU_PCS7_CFG_LS_OFFSET )|\
- + (PCU_PCS7_CFG_LW_DEFAULT << PCU_PCS7_CFG_LW_OFFSET )|\
- + (PCU_PCS7_CFG_WKEN_DEFAULT << PCU_PCS7_CFG_WKEN_OFFSET))
- +
- +#define PCU_PCS7_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
- +#define PCU_PCS7_PARA_IE_OFFSET (31)
- +#define PCU_PCS7_PARA_IE_DEFAULT (0x0)
- +#define PCU_PCS7_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS7_PARA_CMD_OFFSET (28)
- +#define PCU_PCS7_PARA_CMD_DEFAULT (0x0)
- +#define PCU_PCS7_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS7_PARA_SYNC_OFFSET (24)
- +#define PCU_PCS7_PARA_SYNC_DEFAULT (0x3)
- +#define PCU_PCS7_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
- +#define PCU_PCS7_PARA_NXTPAR_OFFSET (0)
- +#define PCU_PCS7_PARA_NXTPAR_DEFAULT (0x0)
- +#define PCU_PCS7_PARA_PWDN_MASK (ANDES_BIT_MASK(23, 23))
- +#define PCU_PCS7_PARA_PWDN_OFFSET (23)
- +#define PCU_PCS7_PARA_PWDN_DEFAULT (0x0)
- +#define PCU_PCS7_PARA_DEFAULT ((PCU_PCS7_PARA_IE_DEFAULT << PCU_PCS7_PARA_IE_OFFSET )|\
- + (PCU_PCS7_PARA_CMD_DEFAULT << PCU_PCS7_PARA_CMD_OFFSET )|\
- + (PCU_PCS7_PARA_SYNC_DEFAULT << PCU_PCS7_PARA_SYNC_OFFSET)|\
- + (PCU_PCS7_PARA_PWDN_DEFAULT << PCU_PCS7_PARA_PWDN_OFFSET))
- +#define PCU_PCS7_PARA_DFT_MASK ((PCU_PCS7_PARA_IE_MASK )|\
- + (PCU_PCS7_PARA_CMD_MASK )|\
- + (PCU_PCS7_PARA_SYNC_MASK)|\
- + (PCU_PCS7_PARA_PWDN_MASK))
- +
- +#define PCU_PCS7_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS7_ST1_STS_OFFSET (28)
- +#define PCU_PCS7_ST1_STS_DEFAULT (0x0)
- +#define PCU_PCS7_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
- +#define PCU_PCS7_ST1_ERR_OFFSET (0)
- +#define PCU_PCS7_ST1_ERR_DEFAULT (0x0)
- +#define PCU_PCS7_ST1_DEFAULT ((PCU_PCS7_ST1_STS_DEFAULT << PCU_PCS7_ST1_STS_OFFSET )|\
- + (PCU_PCS7_ST1_ERR_DEFAULT << PCU_PCS7_ST1_ERR_OFFSET ))
- +
- +#define PCU_PCS7_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS7_ST2_SYNC_OFFSET (24)
- +#define PCU_PCS7_ST2_SYNC_DEFAULT (0x0)
- +#define PCU_PCS7_ST2_CURPAR_MASK (ANDES_BIT_MASK(23, 0))
- +#define PCU_PCS7_ST2_CURPAR_OFFSET (0)
- +//#define PCU_PCS7_ST2_CURPAR_DEFAULT (0x0) //no default
- +#define PCU_PCS7_ST2_PWDN_MASK PCU_PCS7_PARA_PWDN_MASK
- +#define PCU_PCS7_ST2_PWDN_OFFSET PCU_PCS7_PARA_PWDN_OFFSET
- +#define PCU_PCS7_ST2_PWDN_DEFAULT PCU_PCS7_PARA_PWDN_DEFAULT
- +#define PCU_PCS7_ST2_DEFAULT ((PCU_PCS7_ST2_SYNC_DEFAULT << PCU_PCS7_ST2_SYNC_OFFSET)|\
- + (PCU_PCS7_ST2_PWDN_DEFAULT << PCU_PCS7_ST2_PWDN_OFFSET))
- +#define PCU_PCS7_ST2_DFT_MASK ((PCU_PCS7_ST2_SYNC_MASK)|\
- + (PCU_PCS7_ST2_PWDN_MASK))
- +
- +// bits field for PCS8 registers
- +#define PCU_PCS8_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS8_CFG_TYPE_OFFSET (28)
- +#define PCU_PCS8_CFG_TYPE_DEFAULT (0x4)
- +#define PCU_PCS8_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
- +#define PCU_PCS8_CFG_WR_OFFSET (27)
- +#define PCU_PCS8_CFG_WR_DEFAULT (0x0)
- +#define PCU_PCS8_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
- +#define PCU_PCS8_CFG_SR_OFFSET (0)
- +#define PCU_PCS8_CFG_SR_DEFAULT (0x0)
- +#define PCU_PCS8_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
- +#define PCU_PCS8_CFG_LS_OFFSET (20)
- +#define PCU_PCS8_CFG_LS_DEFAULT (0x0)
- +#define PCU_PCS8_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
- +#define PCU_PCS8_CFG_LW_OFFSET (16)
- +#define PCU_PCS8_CFG_LW_DEFAULT (0x0)
- +#define PCU_PCS8_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
- +#define PCU_PCS8_CFG_WKEN_OFFSET (0)
- +#define PCU_PCS8_CFG_WKEN_DEFAULT (0x0)
- +#define PCU_PCS8_CFG_DEFAULT ((PCU_PCS8_CFG_TYPE_DEFAULT << PCU_PCS8_CFG_TYPE_OFFSET)|\
- + (PCU_PCS8_CFG_WR_DEFAULT << PCU_PCS8_CFG_WR_OFFSET )|\
- + (PCU_PCS8_CFG_SR_DEFAULT << PCU_PCS8_CFG_SR_OFFSET )|\
- + (PCU_PCS8_CFG_LS_DEFAULT << PCU_PCS8_CFG_LS_OFFSET )|\
- + (PCU_PCS8_CFG_LW_DEFAULT << PCU_PCS8_CFG_LW_OFFSET )|\
- + (PCU_PCS8_CFG_WKEN_DEFAULT << PCU_PCS8_CFG_WKEN_OFFSET))
- +
- +#define PCU_PCS8_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
- +#define PCU_PCS8_PARA_IE_OFFSET (31)
- +#define PCU_PCS8_PARA_IE_DEFAULT (0x0)
- +#define PCU_PCS8_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS8_PARA_CMD_OFFSET (28)
- +#define PCU_PCS8_PARA_CMD_DEFAULT (0x0)
- +#define PCU_PCS8_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS8_PARA_SYNC_OFFSET (24)
- +#define PCU_PCS8_PARA_SYNC_DEFAULT (0x3)
- +#define PCU_PCS8_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
- +#define PCU_PCS8_PARA_NXTPAR_OFFSET (0)
- +#define PCU_PCS8_PARA_NXTPAR_DEFAULT (0x0)
- +#define PCU_PCS8_PARA_STOP_MASK (ANDES_BIT_MASK(13, 13))
- +#define PCU_PCS8_PARA_STOP_OFFSET (13)
- +#define PCU_PCS8_PARA_STOP_DEFAULT (0x0)
- +#define PCU_PCS8_PARA_START_MASK (ANDES_BIT_MASK(12, 12))
- +#define PCU_PCS8_PARA_START_OFFSET (12)
- +#define PCU_PCS8_PARA_START_DEFAULT (0x0)
- +#define PCU_PCS8_PARA_BYTES_MASK (ANDES_BIT_MASK(10, 8))
- +#define PCU_PCS8_PARA_BYTES_OFFSET (8)
- +#define PCU_PCS8_PARA_BYTES_DEFAULT (0x0)
- +#define PCU_PCS8_PARA_ADDR_MASK (ANDES_BIT_MASK(7, 1))
- +#define PCU_PCS8_PARA_ADDR_OFFSET (1)
- +#define PCU_PCS8_PARA_ADDR_DEFAULT (0x0)
- +#define PCU_PCS8_PARA_READ_MASK (ANDES_BIT_MASK(0, 0))
- +#define PCU_PCS8_PARA_READ_OFFSET (0)
- +#define PCU_PCS8_PARA_READ_DEFAULT (0x0)
- +#define PCU_PCS8_PARA_DEFAULT ((PCU_PCS8_PARA_IE_DEFAULT << PCU_PCS8_PARA_IE_OFFSET )|\
- + (PCU_PCS8_PARA_CMD_DEFAULT << PCU_PCS8_PARA_CMD_OFFSET )|\
- + (PCU_PCS8_PARA_SYNC_DEFAULT << PCU_PCS8_PARA_SYNC_OFFSET )|\
- + (PCU_PCS8_PARA_NXTPAR_DEFAULT << PCU_PCS8_PARA_NXTPAR_OFFSET))
- +
- +
- +#define PCU_PCS8_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS8_ST1_STS_OFFSET (28)
- +#define PCU_PCS8_ST1_STS_DEFAULT (0x0)
- +#define PCU_PCS8_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
- +#define PCU_PCS8_ST1_ERR_OFFSET (0)
- +#define PCU_PCS8_ST1_ERR_DEFAULT (0x0)
- +#define PCU_PCS8_ST1_DEFAULT ((PCU_PCS8_ST1_STS_DEFAULT << PCU_PCS8_ST1_STS_OFFSET )|\
- + (PCU_PCS8_ST1_ERR_DEFAULT << PCU_PCS8_ST1_ERR_OFFSET ))
- +
- +#define PCU_PCS8_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS8_ST2_SYNC_OFFSET (24)
- +#define PCU_PCS8_ST2_SYNC_DEFAULT (0x0)
- +#define PCU_PCS8_ST2_CURPAR_MASK PCU_PCS8_PARA_NXTPAR_MASK
- +#define PCU_PCS8_ST2_CURPAR_OFFSET PCU_PCS8_PARA_NXTPAR_OFFSET
- +#define PCU_PCS8_ST2_CURPAR_DEFAULT PCU_PCS8_PARA_NXTPAR_DEFAULT
- +#define PCU_PCS8_ST2_DEFAULT ((PCU_PCS8_ST2_SYNC_DEFAULT << PCU_PCS8_ST2_SYNC_OFFSET )|\
- + (PCU_PCS8_ST2_CURPAR_DEFAULT << PCU_PCS8_ST2_CURPAR_OFFSET))
- +
- +
- +#define PCU_PCS8_PDD_4TH_BYTE_MASK (ANDES_BIT_MASK(31, 24))
- +#define PCU_PCS8_PDD_4TH_BYTE_OFFSET (24)
- +#define PCU_PCS8_PDD_4TH_BYTE_DEFAULT (0x0)
- +#define PCU_PCS8_PDD_3RD_BYTE_MASK (ANDES_BIT_MASK(23, 16))
- +#define PCU_PCS8_PDD_3RD_BYTE_OFFSET (16)
- +#define PCU_PCS8_PDD_3RD_BYTE_DEFAULT (0x0)
- +#define PCU_PCS8_PDD_2ND_BYTE_MASK (ANDES_BIT_MASK(15, 8))
- +#define PCU_PCS8_PDD_2ND_BYTE_OFFSET (8)
- +#define PCU_PCS8_PDD_2ND_BYTE_DEFAULT (0x0)
- +#define PCU_PCS8_PDD_1ST_BYTE_MASK (ANDES_BIT_MASK(7, 0))
- +#define PCU_PCS8_PDD_1ST_BYTE_OFFSET (0)
- +#define PCU_PCS8_PDD_1ST_BYTE_DEFAULT (0x0)
- +#define PCU_PCS8_PDD_DEFAULT ((PCU_PCS8_PDD_4TH_BYTE_DEFAULT << PCU_PCS8_PDD_4TH_BYTE_OFFSET)|\
- + (PCU_PCS8_PDD_3RD_BYTE_DEFAULT << PCU_PCS8_PDD_3RD_BYTE_OFFSET)|\
- + (PCU_PCS8_PDD_2ND_BYTE_DEFAULT << PCU_PCS8_PDD_2ND_BYTE_OFFSET)|\
- + (PCU_PCS8_PDD_1ST_BYTE_DEFAULT << PCU_PCS8_PDD_1ST_BYTE_OFFSET))
- +
- +// bits field for PCS9 registers
- +#define PCU_PCS9_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS9_CFG_TYPE_OFFSET (28)
- +#define PCU_PCS9_CFG_TYPE_DEFAULT (0x6)
- +#define PCU_PCS9_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
- +#define PCU_PCS9_CFG_WR_OFFSET (27)
- +#define PCU_PCS9_CFG_WR_DEFAULT (0x0)
- +#define PCU_PCS9_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
- +#define PCU_PCS9_CFG_SR_OFFSET (0)
- +#define PCU_PCS9_CFG_SR_DEFAULT (0x0)
- +#define PCU_PCS9_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
- +#define PCU_PCS9_CFG_LS_OFFSET (20)
- +#define PCU_PCS9_CFG_LS_DEFAULT (0x0)
- +#define PCU_PCS9_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
- +#define PCU_PCS9_CFG_LW_OFFSET (16)
- +#define PCU_PCS9_CFG_LW_DEFAULT (0x0)
- +#define PCU_PCS9_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
- +#define PCU_PCS9_CFG_WKEN_OFFSET (0)
- +#define PCU_PCS9_CFG_WKEN_DEFAULT (0x0)
- +#define PCU_PCS9_CFG_DEFAULT ((PCU_PCS9_CFG_TYPE_DEFAULT << PCU_PCS9_CFG_TYPE_OFFSET)|\
- + (PCU_PCS9_CFG_WR_DEFAULT << PCU_PCS9_CFG_WR_OFFSET )|\
- + (PCU_PCS9_CFG_SR_DEFAULT << PCU_PCS9_CFG_SR_OFFSET )|\
- + (PCU_PCS9_CFG_LS_DEFAULT << PCU_PCS9_CFG_LS_OFFSET )|\
- + (PCU_PCS9_CFG_LW_DEFAULT << PCU_PCS9_CFG_LW_OFFSET )|\
- + (PCU_PCS9_CFG_WKEN_DEFAULT << PCU_PCS9_CFG_WKEN_OFFSET))
- +
- +#define PCU_PCS9_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
- +#define PCU_PCS9_PARA_IE_OFFSET (31)
- +#define PCU_PCS9_PARA_IE_DEFAULT (0x0)
- +#define PCU_PCS9_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS9_PARA_CMD_OFFSET (28)
- +#define PCU_PCS9_PARA_CMD_DEFAULT (0x0)
- +#define PCU_PCS9_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS9_PARA_SYNC_OFFSET (24)
- +#define PCU_PCS9_PARA_SYNC_DEFAULT (0x3)
- +#define PCU_PCS9_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
- +#define PCU_PCS9_PARA_NXTPAR_OFFSET (0)
- +#define PCU_PCS9_PARA_NXTPAR_DEFAULT (0x0)
- +#define PCU_PCS9_PARA_TEST_MASK (PCS_POWER_GPU_AND_DAC |\
- + PCS_POWER_CPUB )
- +
- +#define PCU_PCS9_PARA_TEST PCU_PCS9_PARA_TEST_MASK
- +
- +#define PCU_PCS9_PARA_DEFAULT ((PCU_PCS9_PARA_IE_DEFAULT << PCU_PCS9_PARA_IE_OFFSET )|\
- + (PCU_PCS9_PARA_CMD_DEFAULT << PCU_PCS9_PARA_CMD_OFFSET )|\
- + (PCU_PCS9_PARA_SYNC_DEFAULT << PCU_PCS9_PARA_SYNC_OFFSET )|\
- + (PCU_PCS9_PARA_NXTPAR_DEFAULT << PCU_PCS9_PARA_NXTPAR_OFFSET))
- +
- +#define PCU_PCS9_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
- +#define PCU_PCS9_ST1_STS_OFFSET (28)
- +#define PCU_PCS9_ST1_STS_DEFAULT (0x0)
- +#define PCU_PCS9_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
- +#define PCU_PCS9_ST1_ERR_OFFSET (0)
- +#define PCU_PCS9_ST1_ERR_DEFAULT (0x0)
- +#define PCU_PCS9_ST1_DEFAULT ((PCU_PCS9_ST1_STS_DEFAULT << PCU_PCS9_ST1_STS_OFFSET )|\
- + (PCU_PCS9_ST1_ERR_DEFAULT << PCU_PCS9_ST1_ERR_OFFSET ))
- +
- +#define PCU_PCS9_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
- +#define PCU_PCS9_ST2_SYNC_OFFSET (24)
- +#define PCU_PCS9_ST2_SYNC_DEFAULT (0x0)
- +#define PCU_PCS9_ST2_CURPAR_MASK PCU_PCS9_PARA_NXTPAR_MASK
- +#define PCU_PCS9_ST2_CURPAR_OFFSET PCU_PCS9_PARA_NXTPAR_OFFSET
- +#define PCU_PCS9_ST2_CURPAR_DEFAULT (0x1f)
- +#define PCU_PCS9_ST2_DEFAULT ((PCU_PCS9_ST2_SYNC_DEFAULT << PCU_PCS9_ST2_SYNC_OFFSET )|\
- + (PCU_PCS9_ST2_CURPAR_DEFAULT << PCU_PCS9_ST2_CURPAR_OFFSET))
- +
- +#define PCU_PCS9_PDD_CLR_PWOFF_FLAG_MASK (ANDES_BIT_MASK(31, 31))
- +#define PCU_PCS9_PDD_CLR_PWOFF_FLAG_OFFSET (31)
- +#define PCU_PCS9_PDD_CLR_PWOFF_FLAG_DEFAULT (0x0)
- +#define PCU_PCS9_PDD_SUSP2RAM_MASK (ANDES_BIT_MASK(30, 30))
- +#define PCU_PCS9_PDD_SUSP2RAM_OFFSET (30)
- +#define PCU_PCS9_PDD_SUSP2RAM_DEFAULT (0x0)
- +#define PCU_PCS9_PDD_PWR_OFF_TIME_MASK (ANDES_BIT_MASK(29, 28))
- +#define PCU_PCS9_PDD_PWR_OFF_TIME_OFFSET (28)
- +#define PCU_PCS9_PDD_PWR_OFF_TIME_DEFAULT (0x3)
- +#define PCU_PCS9_PDD_TICK_MASK (ANDES_BIT_MASK(24, 24))
- +#define PCU_PCS9_PDD_TICK_OFFSET (24)
- +#define PCU_PCS9_PDD_TICK_DEFAULT (0x1)
- +#define PCU_PCS9_PDD_TIMER4_MASK (ANDES_BIT_MASK(23, 18))
- +#define PCU_PCS9_PDD_TIMER4_OFFSET (18)
- +#define PCU_PCS9_PDD_TIMER4_DEFAULT (0x20)
- +#define PCU_PCS9_PDD_TIMER3_MASK (ANDES_BIT_MASK(17, 12))
- +#define PCU_PCS9_PDD_TIMER3_OFFSET (12)
- +#define PCU_PCS9_PDD_TIMER3_DEFAULT (0x20)
- +#define PCU_PCS9_PDD_TIMER2_MASK (ANDES_BIT_MASK(11, 6))
- +#define PCU_PCS9_PDD_TIMER2_OFFSET (6)
- +#define PCU_PCS9_PDD_TIMER2_DEFAULT (0x20)
- +#define PCU_PCS9_PDD_TIMER1_MASK (ANDES_BIT_MASK(5, 0))
- +#define PCU_PCS9_PDD_TIMER1_OFFSET (0)
- +#define PCU_PCS9_PDD_TIMER1_DEFAULT (0x20)
- +
- +#define PCU_PCS9_PDD_DEFAULT ((PCU_PCS9_PDD_CLR_PWOFF_FLAG_DEFAULT << PCU_PCS9_PDD_CLR_PWOFF_FLAG_OFFSET)|\
- + (PCU_PCS9_PDD_SUSP2RAM_DEFAULT << PCU_PCS9_PDD_SUSP2RAM_OFFSET )|\
- + (PCU_PCS9_PDD_PWR_OFF_TIME_DEFAULT << PCU_PCS9_PDD_PWR_OFF_TIME_OFFSET )|\
- + (PCU_PCS9_PDD_TICK_DEFAULT << PCU_PCS9_PDD_TICK_OFFSET )|\
- + (PCU_PCS9_PDD_TIMER4_DEFAULT << PCU_PCS9_PDD_TIMER4_OFFSET )|\
- + (PCU_PCS9_PDD_TIMER3_DEFAULT << PCU_PCS9_PDD_TIMER3_OFFSET )|\
- + (PCU_PCS9_PDD_TIMER2_DEFAULT << PCU_PCS9_PDD_TIMER2_OFFSET )|\
- + (PCU_PCS9_PDD_TIMER1_DEFAULT << PCU_PCS9_PDD_TIMER1_OFFSET ))
- +
- +// ======================================================
- +// PCU definitaion macro
- +// ======================================================
- +#define PCS_TYPE_PLL 0
- +#define PCS_TYPE_DIVIDER 1
- +#define PCS_TYPE_CLK_GATING 2
- +#define PCS_TYPE_I2C 4
- +#define PCS_TYPE_PMBUS 5
- +
- +#define PCS_WKEN0 (0x1<<0)
- +#define PCS_WKEN1 (0x1<<1)
- +#define PCS_WKEN2 (0x1<<2)
- +#define PCS_WKEN3 (0x1<<3)
- +#define PCS_WKEN4 (0x1<<4)
- +#define PCS_WKEN5 (0x1<<5)
- +#define PCS_WKEN6 (0x1<<6)
- +#define PCS_WKEN7 (0x1<<7)
- +#define PCS_WKEN8 (0x1<<8)
- +#define PCS_WKEN9 (0x1<<9)
- +#define PCS_WKEN10 (0x1<<10)
- +#define PCS_WKEN11 (0x1<<11)
- +#define PCS_WKEN12 (0x1<<12)
- +#define PCS_WKEN13 (0x1<<13)
- +#define PCS_WKEN14 (0x1<<14)
- +#define PCS_WKEN15 (0x1<<15)
- +
- +#define PCS_WKEN_GPIO0 PCS_WKEN0
- +#define PCS_WKEN_GPIO1 PCS_WKEN1
- +#define PCS_WKEN_GPIO2 PCS_WKEN2
- +#define PCS_WKEN_GPIO3 PCS_WKEN3
- +#define PCS_WKEN_GPIO4 PCS_WKEN4
- +#define PCS_WKEN_GPIO5 PCS_WKEN5
- +#define PCS_WKEN_WOL PCS_WKEN6
- +#define PCS_WKEN_RTC PCS_WKEN7
- +#define PCS_WKEN_DAY PCS_WKEN8
- +#define PCS_WKEN_DBG PCS_WKEN9
- +#define PCS_WKEN_PCI PCS_WKEN10
- +#define PCS_WKEN_LPC PCS_WKEN11
- +#define PCS_WKEN_SRC_CNT 12 // wakeup source number
- +#define PCS_WKEN_SRC_MASK ((1<<PCS_WKEN_SRC_CNT)-1)
- +
- +#define PCS_CMD_NOP 0x0
- +#define PCS_CMD_SCALING 0x1
- +#define PCS_CMD_PW_DOWN 0x2
- +#define PCS_CMD_DRAM_SF 0x4 // DRAM self-refresh
- +
- +#define PCS_SYNC_CPUA_STBY 0x1
- +#define PCS_SYNC_CPUB_STBY 0x2
- +
- +#if ((!defined(CORE0_IDLE)) && (!defined(CORE1_IDLE)))
- + #define PCS_SYNC_SRC PCS_SYNC_CPUA_STBY
- +#elif (!defined(CORE0_IDLE))
- + #define PCS_SYNC_SRC PCS_SYNC_CPUA_STBY
- +#else //(!defined(CORE1_IDLE))
- + #define PCS_SYNC_SRC PCS_SYNC_CPUB_STBY
- +#endif
- +
- +#define PCS_PLL_DIVIDE1 0
- +#define PCS_PLL_DIVIDE2 1
- +#define PCS_PLL_DIVIDE4 2
- +#define PCS_PLL_DIVIDE8 3
- +
- +#define PCS_RATIO_44221H 0 // h(alf): stands for 0.5,
- +#define PCS_RATIO_4422HQ 1 // q(uarter) stands for 0.25,
- +#define PCS_RATIO_42221H 2 // f(ixed) stands for fixed 400Mhz
- +#define PCS_RATIO_4222HQ 3
- +#define PCS_RATIO_41121H 4
- +#define PCS_RATIO_4112HQ 5
- +#define PCS_RATIO_44421H 6
- +#define PCS_RATIO_4442HQ 7
- +#define PCS_RATIO_442F1H 8
- +#define PCS_RATIO_442FHQ 9
- +#define PCS_RATIO_422F1H 10
- +#define PCS_RATIO_422FHQ 11
- +#define PCS_RATIO_411F1H 12
- +#define PCS_RATIO_411FHQ 13
- +#define PCS_RATIO_111111e 14 // enable pll
- +#define PCS_RATIO_111111d 15 // disable pll
- +#define PCS_RATIO_MAX PCS_RATIO_111111d
- +#define PCS_RATIO_CNT (PCS_RATIO_MAX+1)
- +
- +#define PCS_GATING_DDR2_HCLK (0x1<<2 )
- +#define PCS_GATING_AHB2AHB_HCLK (0x1<<3 )
- +#define PCS_GATING_DMAC_HCLK (0x1<<4 )
- +#define PCS_GATING_L2CC_HCLK (0x1<<5 )
- +#define PCS_GATING_LPC_HCLK (0x1<<6 )
- +#define PCS_GATING_I2C_HCLK (0x1<<7 )
- +#define PCS_GATING_IDE_HCLK (0x1<<8 )
- +#define PCS_GATING_GPU_HCLK (0x1<<9)
- +#define PCS_GATING_GMAC_HCLK (0x1<<10)
- +#define PCS_GATING_USB_HCLK (0x1<<11)
- +#define PCS_GATING_PCI_HCLK (0x1<<12)
- +#define PCS_GATING_HCLK_CNT (16)
- +#define PCS_GATING_HCLK_VALID (PCS_GATING_DDR2_HCLK |\
- + PCS_GATING_AHB2AHB_HCLK|\
- + PCS_GATING_DMAC_HCLK |\
- + PCS_GATING_L2CC_HCLK |\
- + PCS_GATING_LPC_HCLK |\
- + PCS_GATING_I2C_HCLK |\
- + PCS_GATING_IDE_HCLK |\
- + PCS_GATING_GPU_HCLK |\
- + PCS_GATING_GMAC_HCLK |\
- + PCS_GATING_USB_HCLK |\
- + PCS_GATING_PCI_HCLK )
- +
- +#define PCS_GATING_NO_PCLK (0x0)
- +#define PCS_GATING_SPI_PCLK (0x1<<0 )
- +#define PCS_GATING_CFC_PCLK (0x1<<1 )
- +#define PCS_GATING_SDC_PCLK (0x1<<2 )
- +#define PCS_GATING_WDT_PCLK (0x1<<3 )
- +#define PCS_GATING_TMR_PCLK (0x1<<4 )
- +#define PCS_GATING_GPIO_PCLK (0x1<<5 )
- +#define PCS_GATING_PWM_PCLK (0x1<<6 )
- +#define PCS_GATING_I2C_PCLK (0x1<<7 )
- +#define PCS_GATING_AC97I2S_PCLK (0x1<<8)
- +#define PCS_GATING_UART1_PCLK (0x1<<9)
- +#define PCS_GATING_UART2_PCLK (0x1<<10)
- +#define PCS_GATING_PCLK_CNT (16)
- +
- +#define PCS_MAIN_PLL_FREF (33) // reference frequency in MHz
- +#define PCS_MAIN_PLL_M_FACTOR (1) // fixed M factor of Main PLL
- +#define PCS_MAIN_PLL_50MHZ_H (66)
- +#define PCS_MAIN_PLL_125MHZ_L (99)
- +#define PCS_MAIN_PLL_125MHZ_H (132)
- +#define PCS_MAIN_PLL_250MHZ_L (231)
- +#define PCS_MAIN_PLL_250MHZ_H (264)
- +#define PCS_MAIN_PLL_500MHZ_L (495)
- +#define PCS_MAIN_PLL_500MHZ_H (528)
- +#define PCS_MAIN_PLL_830MHZ_L (825)
- +//#define PCS_MAIN_PLL_800MHZ_H ()
- +//#define PCS_MAIN_PLL_1000MHZ_L ()
- +//#define PCS_MAIN_PLL_1000MHZ_H ()
- +#define PCS_MAIN_PLL_CNT (4)
- +#define PCS_PLL_50to125MHZ (0x0)
- +#define PCS_PLL_125to250MHZ (0x1)
- +#define PCS_PLL_250to500MHZ (0x2)
- +#define PCS_PLL_500to1000MHZ (0x3)
- +
- +#define PCU_PLL_N_FACTOR(seed, F_ref, M_factor, F_low, F_high) \
- + (((seed)%( 1+ (F_high)*(M_factor)/(F_ref) - (F_low)*(M_factor)/(F_ref))) + ((F_low)*(M_factor)/(F_ref)))
- +#define PCS_MAIN_PLL_N_FACTOR(seed, F_low, F_high) \
- + PCU_PLL_N_FACTOR(seed, PCS_MAIN_PLL_FREF, PCS_MAIN_PLL_M_FACTOR, F_low, F_high)
- +#define PCS_MAIN_PLL_CLOCK(n_factor) ((n_factor/PCS_MAIN_PLL_M_FACTOR)*PCS_MAIN_PLL_FREF)
- +
- +#define PCS_POWER_GPU_AND_DAC (0x1<<1)
- +#define PCS_POWER_CPUB (0x1<<2)
- +#define PCS_POWER_CNT (5)
- +
- +#define PCS_TICK_OSCH 0x0
- +#define PCS_TICK_OSCL 0x1
- +
- +//
- +#define PCS_STS_NORMAL 0x0
- +#define PCS_STS_READY 0x1
- +#define PCS_STS_SEQUENCE 0x2
- +#define PCS_STS_DONE 0x4
- +#define PCS_STS_WAKEN 0x6
- +
- +#define PCS_ERR_NONE 0x0
- +#define PCS_ERR_ILLEGAL 0x1
- +#define PCS_ERR_SYNC_TIMEOUT 0x2
- +#define PCS_ERR_UPDATE_TIMEOUT 0x3
- +
- +//
- +#define PCS_BSM_IDLE 0x0
- +#define PCS_BSM_SCALING 0x1
- +#define PCS_BSM_DONE 0x3
- +#define PCS_BSM_PWDN 0x4
- +#define PCS_BSM_ERROR 0x7
- +#define PCS_BSM_WAKEN 0x8
- +
- +#define PCS_BSM_VALID_NO_MAX 9
- +
- +//
- +#define PCS_SCALING_WITH_WAIT_DOWN 0
- +#define PCS_SCALING_WITH_WAKE_GRANT 1
- +#define PCS_PW_DOWN_WITH_WAIT_DOWN 2
- +#define PCS_PW_DOWN_WAKE_GRANT 3
- +
- +#define PCS_WAKE_WITH_SCALING_CNT (PCS_SCALING_WITH_WAKE_GRANT+1)
- +#define PCS_WAKE_WITH_PWDnSCL_CNT (PCS_PW_DOWN_WAKE_GRANT+1)
- +
- +// standby mode define macro
- +#define PCU_STBY_NO_WAKE_GRANT 0
- +#define PCU_STBY_WAKE_GRANT 1
- +#define PCU_STBY_WAIT_DONE 2
- +
- +
- +// PCU interrupt service routine signal
- +#define PCU_ISR_SIG_NONE 0x0
- +#define PCU_ISR_SIG_BSM PCU_INTR_BSM_MASK
- +#define PCU_ISR_SIG_PCS1 PCU_INTR_PCS1_MASK
- +#define PCU_ISR_SIG_PCS2 PCU_INTR_PCS2_MASK
- +#define PCU_ISR_SIG_PCS3 PCU_INTR_PCS3_MASK
- +#define PCU_ISR_SIG_PCS4 PCU_INTR_PCS4_MASK
- +#define PCU_ISR_SIG_PCS5 PCU_INTR_PCS5_MASK
- +#define PCU_ISR_SIG_PCS6 PCU_INTR_PCS6_MASK
- +#define PCU_ISR_SIG_PCS7 PCU_INTR_PCS7_MASK
- +#define PCU_ISR_SIG_PCS8 PCU_INTR_PCS8_MASK
- +#define PCU_ISR_SIG_PCS9 PCU_INTR_PCS9_MASK
- +
- +// ======================================================
- +// PCU access macro
- +// ======================================================
- +#define PCU_SET_FIELD(reg, field, value) SET_FIELD(PCU_REG_##reg, PCU_##reg##_##field##_##MASK, PCU_##reg##_##field##_##OFFSET, value)
- +#define PCU_GET_FIELD(reg, field) GET_FIELD(PCU_REG_##reg, PCU_##reg##_##field##_##MASK, PCU_##reg##_##field##_##OFFSET)
- +#define PCU_TEST_FIELD(reg, field) TEST_FIELD(PCU_REG_##reg, PCU_##reg##_##field##_##MASK)
- +
- +#define PCU_SET_REG(reg, value) SET_REG(PCU_REG_##reg, value)
- +#define PCU_GET_REG(reg) GET_REG(PCU_REG_##reg)
- +#define PCU_TEST_BIT(reg, field, value) VAR_TEST_BIT(value, PCU_##reg##_##field##_##MASK)
- +
- +#define PCU_CHECK(reg, field, value) CHECK_FIELD (value, PCU_##reg##_##field##_##MASK)
- +#define PCU_EXTRACT(reg, field, value) EXTRACT_FIELD(value, PCU_##reg##_##field##_##MASK, PCU_##reg##_##field##_##OFFSET )
- +#define PCU_PREPARE(reg, field, value) PREPARE_FIELD(value, PCU_##reg##_##field##_##MASK, PCU_##reg##_##field##_##OFFSET )
- +
- +#define PCU_DEFAULT(reg, field) ( PCU_##reg##_##field##_##DEFAULT )
- +
- +#define PCU_TEST_SIG(var, sig) VAR_TEST_BIT(var, PCU_ISR_SIG_##sig)
- +#define PCU_SET_SIG(var, sig) VAR_SET_BIT(var, PCU_ISR_SIG_##sig)
- +#define PCU_CLR_SIG(var, sig) VAR_CLR_BIT(var, PCU_ISR_SIG_##sig)
- +
- +// ======================================================
- +// PCU access function prototype
- +// ======================================================
- +#if __STDC__ || defined(__cplusplus)
- +#define PROTO_PARAMS(s) s
- +#else
- +#define PROTO_PARAMS(s) ()
- +#endif
- +
- +#endif //__PCU_H
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/pm.c linux-3.4.110/arch/nds32/platforms/ag102/pm.c
- --- linux-3.4.110.orig/arch/nds32/platforms/ag102/pm.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag102/pm.c 2016-04-07 10:20:51.002083345 +0200
- @@ -0,0 +1,1614 @@
- +/*
- + * AG101 Power Management Routines
- + *
- + * Copyright (c) 2010 Gavin Guo <gavinguo@andestech.com>
- + *
- + * This program is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU General Public License.
- + *
- + * Abstract:
- + *
- + * This program is for AG102 power management routines.
- + *
- + * Revision History:
- + *
- + * Jul.19.2010 Initial code by Gavin.
- + */
- +#include <linux/init.h>
- +#include <linux/suspend.h>
- +#include <linux/errno.h>
- +#include <linux/time.h>
- +#include <linux/delay.h>
- +/*
- + * the following include file is for testing device node
- + */
- +#include <linux/device.h>
- +#include <linux/fs.h>
- +#include <asm/uaccess.h>
- +/*************************/
- +#include <asm/hardware.h>
- +#include <asm/memory.h>
- +#include <asm/system.h>
- +#include <asm/mach/time.h>
- +#include <asm/cacheflush.h>
- +#include <asm/timer.h>
- +#include <asm/io.h>
- +#include <asm/amic.h>
- +
- +#include "pcu.h"
- +#include "gmac.h"
- +
- +#ifdef CONFIG_PLAT_AG102
- +#include <asm/spec-ag102.h>
- +#endif
- +
- +#define ANDES_PCU_STRING "andes_pcu"
- +static int andes_pcu_major;
- +static struct class *andes_pcu_class;
- +extern void ag102_cpu_sleep(void);
- +extern void ag102_cpu_resume(void);
- +extern void ag102_cpu_resume2(void);
- +extern void __SELF_REFRESH_LOCK_START();
- +extern void __SELF_REFRESH_LOCK_END();
- +extern void ftpci_postinit(void /**sysdata*/ );
- +UINT32 mac_dah, mac_dal;
- +
- +// ADD by river 2010.12.07 for WOL
- +
- +UINT32 eth_phy_reg_read(UINT32 phy_addr, UINT32 phy_page, UINT32 phy_reg,
- + UINT32 * phy_data)
- +{
- + UINT32 cycthr = GMAC_GET_FIELD(PHYCR, MDC_CYCTHR);
- + UINT32 wdata;
- + UINT32 rdata;
- + //TIMER_P timer;
- +
- + printk(">>>>> GMAC : Calling eth_phy_reg_read()...\n");
- +
- + wdata = GMAC_PREPARE(PHYCR, MIIRD, 0x1) |
- + GMAC_PREPARE(PHYCR, PHYAD, phy_addr) |
- + GMAC_PREPARE(PHYCR, REGAD, phy_reg) | cycthr;
- +
- + printk(">>>>> GMAC : wdata = [0x%08x]\n", wdata);
- +
- + GMAC_SET_REG(PHYCR, wdata);
- +
- + // wait phy data read
- + //TIMER_INIT(timer, 10000); // trigger timer & wait until finish of data read
- + //while ( (!TIMER_IS_TIMEOUT(timer)) && (GMAC_GET_FIELD(PHYCR, MIIRD))) {
- + // TIMER_TICK(timer);
- + //}
- +
- + while (GMAC_GET_FIELD(PHYCR, MIIRD)) {
- + mdelay(50);
- + }
- +
- + if (GMAC_GET_FIELD(PHYCR, MIIRD)) {
- + printk("ERR: GPHY read reg[%x] timeout!\n", phy_reg);
- + return 1;
- + } else {
- + rdata = GMAC_GET_FIELD(PHYDATA, MIIRDATA);
- + *phy_data = rdata;
- + printk("GPHY read [%x] \n", rdata);
- + return 0;
- + }
- +}
- +
- +UINT32 eth_phy_reg_write(UINT32 phy_addr, UINT32 phy_page, UINT32 phy_reg,
- + UINT32 phy_data)
- +{
- + UINT32 wdata;
- + //TIMER_P timer;
- +
- + printk(">>>>> GMAC : Calling eth_phy_reg_write()...\n");
- +
- + GMAC_SET_FIELD(PHYDATA, MIIWDATA, phy_data);
- + wdata = GMAC_PREPARE(PHYCR, MIIWR, 0x1) | GMAC_PREPARE(PHYCR, PHYAD, phy_addr) | GMAC_PREPARE(PHYCR, REGAD, phy_reg) | 0x34; //cycthr;
- + GMAC_SET_REG(PHYCR, wdata);
- +
- + // wait phy data write
- + //TIMER_INIT(timer, 10000); // trigger timer & wait until finish of data write
- + //while ( (!TIMER_IS_TIMEOUT(timer)) && (GMAC_GET_FIELD(PHYCR, MIIWR))) {
- + // TIMER_TICK(timer);
- + //}
- +
- + while (GMAC_GET_FIELD(PHYCR, MIIWR)) {
- + mdelay(50);
- + }
- +
- + if (GMAC_GET_FIELD(PHYCR, MIIWR)) {
- + printk("ERR: GPHY write reg[%x] = %x timeout!\n", phy_reg,
- + phy_data);
- + return 1;
- + } else {
- + return 0;
- + }
- +}
- +
- +INT32 eth_phy_detect(UINT32 * phy_addr, UINT32 * phy_id)
- +{
- + UINT32 i, find, data1, data2;
- +
- + printk(">>>>> GMAC : Calling eth_phy_detect()...\n");
- +
- + for (i = 0, find = 0; i <= 0x1f; i++) {
- + eth_phy_reg_read(i, 0, 2, &data1);
- + if ((data1 != 0) && (data1 != 0xffff)) {
- + find = 1;
- + break;
- + }
- + }
- +
- + if (find == 0) {
- + printk("Err: no valid phy found!\n");
- + *phy_id = 0;
- + return (-1);
- + }
- +
- + eth_phy_reg_read(i, 0, 2, &data1);
- + eth_phy_reg_read(i, 0, 3, &data2);
- + *phy_id = (data1 << 16) | (data2 & 0xffff);
- + *phy_addr = i;
- + printk("Info: phy id = 0x%08x!\n", *phy_id);
- + return 0;
- +}
- +
- +void eth_phy_init(UINT32 phy_addr)
- +{
- + UINT32 data, i;
- + //TIMER_P timer;
- + //phy_addr = DVC_PHY_ADDR;
- +
- + printk(">>>>> GMAC : Calling eth_phy_init()...\n");
- + // GPHY SW reset
- + eth_phy_reg_read(phy_addr, 0, DVC_PHY_REG_CTL, &data);
- + data |=
- + DVC_PHY_REG_CTL_SW_RST | DVC_PHY_REG_CTL_AN_EN |
- + DVC_PHY_REG_CTL_AN_RST;
- + eth_phy_reg_write(phy_addr, 0, DVC_PHY_REG_CTL, data);
- + for (i = 0; i < 10000; i++) { // must delay enough for phy to get ready
- + //eth_mdelay(2000);
- + mdelay(2);
- + eth_phy_reg_read(phy_addr, 0, DVC_PHY_REG_CTL, &data);
- + if ((data & 0x8000) == 0)
- + break;
- + }
- + if ((data & 0x8000) != 0) {
- + printk("Err: phy sw reset timeout!!!\n");
- + }
- + eth_phy_reg_read(phy_addr, 0, DVC_PHY_REG_CTL, &data);
- + printk("phy control = 0x%x\n", data);
- + eth_phy_reg_read(phy_addr, 0, DVC_PHY_REG_STS, &data);
- + printk("phy status = 0x%x\n", data);
- +
- + return;
- +}
- +
- +// initialize MAC setting
- +void eth_mac_init(ETH_PHY_STAT * phy_stat)
- +{
- + UINT32 i, wdata, rdata;
- + UINT32 duplex, speed, gmac;
- + //UINT32 mac_dah, mac_dal;
- + printk(">>>>> GMAC : Calling eth_mac_init()...\n");
- +
- + wdata = GMAC_PREPARE(MACCR, SW_RST, 0x1);
- + GMAC_SET_REG(MACCR, wdata);
- + for (i = 0; i < 1000; i++) { // must delay enough for phy to get ready
- + //eth_mdelay(8000); // delay should be enough
- + mdelay(8);
- + rdata = GMAC_GET_REG(FEAR);
- + if ((rdata >> 31) == 0)
- + break;
- + }
- + if ((rdata >> 31) != 0) {
- + printk("Err: mac sw reset timeout!!!\n");
- + }
- + if (phy_stat->speed == 2) { //giga
- + gmac = 0x1;
- + speed = 0x1;
- + } else if (phy_stat->speed == 1) { //100 Mbps
- + gmac = 0x0;
- + speed = 0x1;
- + } else { //10 Mbps
- + gmac = 0x0;
- + speed = 0x0;
- + }
- + duplex = phy_stat->duplex;
- + GMAC_SET_REG(ISR, 0xffff); // Interrupt Status, write 1 to clear
- + GMAC_SET_REG(IME, 0xffff); // Interrupt Enable, enabling all interrupts
- + GMAC_SET_REG(MAC_MADR, mac_dah);
- + GMAC_SET_REG(MAC_LADR, mac_dal);
- + rdata = GMAC_GET_REG(FEAR);
- + GMAC_SET_FIELD(TPAFCR, TFIFO_SIZE,
- + GMAC_EXTRACT(FEAR, TFIFO_RSIZE, rdata));
- + GMAC_SET_FIELD(TPAFCR, RFIFO_SIZE,
- + GMAC_EXTRACT(FEAR, RFIFO_RSIZE, rdata));
- +
- + wdata = GMAC_PREPARE(MACCR, RX_MULTIPKT_EN, 0x1) |
- + GMAC_PREPARE(MACCR, BROADPKT_EN, 0x1) |
- + GMAC_PREPARE(MACCR, RX_ALLADR, 0x1) |
- + GMAC_PREPARE(MACCR, CRC_APD, 0x1) |
- + GMAC_PREPARE(MACCR, FULLDUP, duplex) |
- + GMAC_PREPARE(MACCR, RX_RUNT, 0x1) |
- + GMAC_PREPARE(MACCR, SPEED, speed) |
- + GMAC_PREPARE(MACCR, GMAC_MODE, gmac) |
- + GMAC_PREPARE(MACCR, RXMAC_EN, 0x1) |
- + GMAC_PREPARE(MACCR, TXMAC_EN, 0x1) |
- + GMAC_PREPARE(MACCR, RXDMA_EN, 0x1) |
- + GMAC_PREPARE(MACCR, TXDMA_EN, 0x1);
- + GMAC_SET_REG(MACCR, wdata);
- +
- +#ifdef AHBC_NO_REMAP
- + GMAC_SET_REG(NPTXR_BADR, FTGMAC100_TXR_BASE | 0x40000000);
- + GMAC_SET_REG(RXR_BADR, FTGMAC100_RXR_BASE | 0x40000000);
- +#else
- + GMAC_SET_REG(NPTXR_BADR, FTGMAC100_TXR_BASE);
- + GMAC_SET_REG(RXR_BADR, FTGMAC100_RXR_BASE);
- +#endif
- + return;
- +}
- +
- +UINT32 eth_phy_stat(UINT32 phy_addr, ETH_PHY_STAT * phy_stat)
- +{
- +
- + phy_stat->speed = 0x1;
- + phy_stat->duplex = 0x1;
- +
- + return 0;
- +}
- +
- +void gmac_set_wol()
- +{
- + UINT32 wdata;
- +
- + // Set Rx Wake-up Frame
- + // write 1 clear register before enable power saving mode
- + GMAC_SET_REG(WOLSR, 0xffffffff); // clear wol status
- +
- + // set wakeup_sel and power saving mode enable
- + wdata = GMAC_PREPARE(WOLCR, MAGICPKT_EN, 0x1) |
- + GMAC_PREPARE(WOLCR, PWRSAV, 0x1);
- +
- + GMAC_SET_REG(WOLCR, wdata);
- +
- + return;
- +}
- +
- +// End ADD by river 2010.12.07 for WOL
- +
- +//////////////////////////////// LPC wake up ///////////////////////////////////////////////////
- +#define CPE_LPCIO_BASE LPC_IO_VA_BASE //VA Base
- +#define CPE_LPCREG_BASE LPC_REG_VA_BASE //VA Base
- +#define CPE_IC_BASE AMIC_VA_BASE
- +
- +#define ITE_ADDR 0x2e
- +#define ITE_DATA 0x2f
- +
- +#define KBC_CMD 0x64
- +#define KBC_STATUS KBC_CMD
- +#define KBC_DATA 0x60
- +
- +#define BIT_OBF 0x01
- +#define BIT_IBF 0x02
- +
- +#define LPC_REG_SCR 0x10
- +#define LPC_REG_SIR 0x14
- +#define LPC_REG_SIMR 0x18
- +
- +#define SIRQ_KB 1
- +#define SIRQ_MS 12
- +
- +//#define outlpc(addr, data) outb(data, CPE_LPCIO_BASE + 4 * addr)
- +//#define inlpc(addr) inb(CPE_LPCIO_BASE + 4 * addr)
- +#define inlpc(addr) REG32(CPE_LPCIO_BASE + 4 * addr)
- +
- +#define IRQ_LPC 29
- +#define LEVEL 0
- +#define H_ACTIVE 0
- +#define L_ACTIVE 1
- +#define IRQ_MASK 0x80
- +#define IRQ_MODE 0x20
- +#define IRQ_LEVEL 0x24
- +
- +UINT32 IRQSources = 0; //define the current irq source for debug
- +
- +static inline void outlpc(unsigned long addr, unsigned long data)
- +{
- + REG32(CPE_LPCIO_BASE + 4 * addr) = data;
- +}
- +
- +static void kbc_cmd(UINT8 cmd)
- +{
- + int loop_limit = 1000;
- + int i;
- + UINT8 tmpc;
- +
- + // wait until the input buffer is empty
- + for (i = 0; i < loop_limit; i++) {
- + tmpc = inlpc(KBC_STATUS);
- + if ((tmpc & BIT_IBF) == 0)
- + break;
- + }
- +
- + outlpc(KBC_CMD, cmd);
- +}
- +
- +static void kbc_wdata(UINT8 wdata)
- +{
- + int loop_limit = 1000;
- + int i;
- + UINT8 tmpc;
- +
- + // wait until the input buffer is empty
- + for (i = 0; i < loop_limit; i++) {
- + tmpc = inlpc(KBC_STATUS);
- + if ((tmpc & BIT_IBF) == 0)
- + break;
- + }
- +
- + outlpc(KBC_DATA, wdata);
- +}
- +
- +static UINT8 kbc_rdata(void)
- +{
- + int loop_limit = 1000;
- + int i;
- + UINT8 rdata;
- + UINT8 tmpc;
- +
- + // wait until the output buffer is not empty
- + for (i = 0; i < loop_limit; i++) {
- + tmpc = inlpc(KBC_STATUS);
- + if (tmpc & BIT_OBF)
- + break;
- + }
- +
- + rdata = inlpc(KBC_DATA);
- + return (rdata);
- +}
- +
- +static void delay_loop(int max_no)
- +{
- + int i;
- +
- + for (i = 0; i < max_no; i++) ;
- +}
- +
- +static UINT8 get_response(void)
- +{
- + UINT8 tmpc;
- +
- + delay_loop(200000);
- + tmpc = kbc_rdata();
- + return (tmpc);
- +}
- +
- +int it8718f_init(void)
- +{
- + static int initialized = 0;
- + UINT8 tmpc;
- + unsigned int chip_id;
- +
- + if (initialized == 1)
- + return (0);
- +
- + // Enter the configuration mode
- + outlpc(ITE_ADDR, 0x87);
- + outlpc(ITE_ADDR, 0x01);
- + outlpc(ITE_ADDR, 0x55);
- + outlpc(ITE_ADDR, 0x55);
- +
- + // Check the chip ID
- + printk("Check IT8718F chip ID => ");
- + outlpc(ITE_ADDR, 0x20);
- + tmpc = inlpc(ITE_DATA);
- + chip_id = (tmpc & 0xff) << 8;
- + outlpc(ITE_ADDR, 0x21);
- + tmpc = inlpc(ITE_DATA);
- + chip_id |= tmpc & 0xff;
- +
- + if (chip_id != 0x8718) {
- + printk("FAILED with chip ID = 0x%C%C.\n", (chip_id >> 8) & 0xff,
- + chip_id & 0xff);
- + return (1);
- + } else
- + printk("PASSED\n");
- +
- + // KBC Self Test
- + printk("KBC self-test => ");
- + kbc_cmd(0xaa);
- + tmpc = kbc_rdata();
- + if (tmpc != 0x55) {
- + printk("FAILED with code = 0x%C\n", tmpc & 0xff);
- + return (2);
- + } else
- + printk("PASSED\n");
- +
- + // KBC Interface Test
- + printk("KBC interface test => ");
- + kbc_cmd(0xab);
- + tmpc = kbc_rdata();
- + switch (tmpc) {
- + case 0:
- + printk("PASSED\n");
- + break;
- +
- + case 1:
- + printk("FAILED as the clock is stuck low\n");
- + return (3);
- +
- + case 2:
- + printk("FAILED as the clock is stuck high\n");
- + return (3);
- +
- + case 3:
- + printk("FAILED as the data is stuck low\n");
- + return (3);
- +
- + case 4:
- + printk("FAILED as the data is stuck high\n");
- + return (3);
- +
- + default:
- + printk("FAILED with unknown error\n");
- + return (3);
- + break;
- + }
- +
- + // Read the KBC mode
- + kbc_cmd(0xca);
- + tmpc = kbc_rdata();
- +
- + // Set KBC to the PS/2 mode
- + tmpc |= 0x01;
- + kbc_cmd(0xcb);
- + kbc_wdata(tmpc);
- +
- + // Enable keyboard
- + kbc_wdata(0xf4);
- + tmpc = get_response();
- + printk("@@@@@ : Response of enabling keyboard = 0x%x\n", tmpc & 0xff);
- +
- + // Enable mouse
- + kbc_cmd(0xd4);
- + kbc_wdata(0xf4);
- + tmpc = get_response();
- + //outmsg("Response of enabling mouse = 0x%C\n", tmpc & 0xff);
- +
- + // bit 6: translate
- + // bit 5: mouse enable
- + // bit 4: keyboard enable
- + // bit 3: ignore keyboard lock
- + // bit 2: system flag
- + // bit 1: mouse interrupt enable
- + // bit 0: Keyboard interrupt enable
- + kbc_cmd(0x60);
- + kbc_wdata(0x47);
- +
- + // Set repeat rate and delay
- + kbc_wdata(0xf3);
- + kbc_wdata(0x00);
- + tmpc = get_response();
- +
- + // Set LDN = 5 (Keyboard)
- + outlpc(ITE_ADDR, 0x07);
- + outlpc(ITE_DATA, 0x05);
- +
- + // KBC clock = 8MHz, Key lock enabled, interrupt type can be changed
- + outlpc(ITE_ADDR, 0xf0);
- + outlpc(ITE_DATA, 0x4e);
- +
- + // Low-level triggered interrupt
- + outlpc(ITE_ADDR, 0x71);
- + outlpc(ITE_DATA, 0x01);
- +
- + // Set LDN = 6 (Mouse)
- + outlpc(ITE_ADDR, 0x07);
- + outlpc(ITE_DATA, 0x06);
- +
- + // Enable mouse
- + outlpc(ITE_ADDR, 0x30);
- + outlpc(ITE_DATA, 0x01);
- +
- + // Interrupt type can be changed
- + outlpc(ITE_ADDR, 0xf0);
- + outlpc(ITE_DATA, 0x01);
- +
- + // Low-level triggered interrupt
- + outlpc(ITE_ADDR, 0x71);
- + outlpc(ITE_DATA, 0x01);
- +
- + // Exit the configuration mode
- + outlpc(ITE_ADDR, 0x02);
- + outlpc(ITE_DATA, 0x02);
- +
- + initialized = 1;
- + return (0);
- +}
- +
- +//INT for lpc
- +/* Turn the interrupt source on. */
- +void UnmaskIRQ(UINT32 IRQ)
- +{
- + volatile UINT32 *IRQBase;
- +
- + IRQBase = (UINT32 *) CPE_IC_BASE;
- +
- + IRQBase[(IRQ_MASK / sizeof(UINT32))] |= (1 << IRQ);
- +}
- +
- +void EnableIRQ()
- +{
- +
- + __asm__ volatile ("setgie.d\n\t"
- + "isb\n\t"
- + "mfsr $r1, $INT_MASK\n\t"
- + "ori $r1, $r1, #0x3f\n\t"
- + "mtsr $r1, $INT_MASK\n\t"
- + "setgie.e\n\t" "isb\n\t");
- +
- +}
- +
- +void SetIRQmode(UINT32 IRQ, UINT32 edge)
- +{
- + volatile UINT32 *IRQBase;
- +
- + IRQBase = (UINT32 *) CPE_IC_BASE;
- +
- + if (edge)
- + IRQBase[(IRQ_MODE / sizeof(UINT32))] |= (1 << IRQ);
- + else
- + IRQBase[(IRQ_MODE / sizeof(UINT32))] &= ~(1 << IRQ);
- +}
- +
- +void SetIRQlevel(UINT32 IRQ, UINT32 low)
- +{
- + volatile UINT32 *IRQBase;
- +
- + IRQBase = (UINT32 *) CPE_IC_BASE;
- +
- + if (low)
- + IRQBase[(IRQ_LEVEL / sizeof(UINT32))] |= (1 << IRQ);
- + else
- + IRQBase[(IRQ_LEVEL / sizeof(UINT32))] &= ~(1 << IRQ);
- +}
- +
- +BOOL SetIntTrig(UINT32 intNum, int intMode, int intLevel)
- +{
- + if (intNum >= 32) {
- + printk("ERROR: The interrupt number %d is incorrect\n", intNum);
- + return FALSE;
- + } else {
- + SetIRQmode(intNum, intMode);
- + SetIRQlevel(intNum, intLevel);
- + return TRUE;
- + }
- +}
- +
- +BOOL EnableInt(UINT32 intNum)
- +{
- +
- + if (intNum >= 32) {
- + printk("ERROR: The interrupt number %d is incorrect\n", intNum);
- + return FALSE;
- + } else {
- + IRQSources |= 1 << intNum;
- + UnmaskIRQ(intNum);
- + EnableIRQ();
- + return TRUE;
- + }
- +}
- +
- +//End INT for lpc
- +
- +void enable_sirq(void)
- +{
- + UINT32 data;
- +
- + // Unmask SERIRQs of Keyboard and Mouse
- + data = inw(CPE_LPCREG_BASE + LPC_REG_SIMR);
- + data &= ~((1 << SIRQ_KB) | (1 << SIRQ_MS));
- + outw(CPE_LPCREG_BASE + LPC_REG_SIMR, data);
- +
- + // Enable SERIRQ
- + data = inw(CPE_LPCREG_BASE + LPC_REG_SCR);
- + data |= 0x1;
- + outw(CPE_LPCREG_BASE + LPC_REG_SCR, data);
- +}
- +
- +void ite_set_pme()
- +{
- +
- + UINT8 tmpc;
- + unsigned int chip_id;
- + // Enter the configuration mode
- + outlpc(ITE_ADDR, 0x87);
- + outlpc(ITE_ADDR, 0x01);
- + outlpc(ITE_ADDR, 0x55);
- + outlpc(ITE_ADDR, 0x55);
- +
- + // Check the chip ID
- + printk("@@@@@ : Check IT8718F chip ID in get_lpc_value => \n");
- + outlpc(ITE_ADDR, 0x20);
- + tmpc = inlpc(ITE_DATA);
- + chip_id = (tmpc & 0xff) << 8;
- + outlpc(ITE_ADDR, 0x21);
- + tmpc = inlpc(ITE_DATA);
- + chip_id |= tmpc & 0xff;
- +
- + printk("@@@@@ : chip_id = 0x%08x\n", chip_id);
- + if (chip_id != 0x8718) {
- + printk("FAILED with chip ID = 0x%C%C.\n", (chip_id >> 8) & 0xff,
- + chip_id & 0xff);
- + return (1);
- + } else
- + printk("@@@@@ : PASSED\n");
- +
- + // Set LDN = 5
- + outlpc(ITE_ADDR, 0x07);
- + outlpc(ITE_DATA, 0x05);
- +
- + //Read index 30
- + outlpc(ITE_ADDR, 0x30);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x30] = 0x%x\n", tmpc);
- + //Set index 30 bit0 = 0;
- + outlpc(ITE_ADDR, 0x30);
- + outlpc(ITE_DATA, tmpc & 0xFE);
- +
- + // Set LDN = 6
- + outlpc(ITE_ADDR, 0x07);
- + outlpc(ITE_DATA, 0x06);
- +
- + //Read index 30
- + outlpc(ITE_ADDR, 0x30);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x30] = 0x%x\n", tmpc);
- + //Set index 30 bit0 = 0;
- + outlpc(ITE_ADDR, 0x30);
- + outlpc(ITE_DATA, tmpc & 0xFE);
- +
- + // Set LDN = 4 for PME
- + outlpc(ITE_ADDR, 0x07);
- + outlpc(ITE_DATA, 0x04);
- +
- + //Read index F0
- + outlpc(ITE_ADDR, 0xF0);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xF0] = 0x%x\n", tmpc);
- + //Set index F0 BIT[4:3]=1;
- + outlpc(ITE_ADDR, 0xF0);
- + outlpc(ITE_DATA, tmpc | 0x18);
- +
- + //PME output enable
- + //Read index F2
- + outlpc(ITE_ADDR, 0xF2);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xF2] = 0x%x\n", tmpc);
- + //Set index F2 bit6=0;
- + outlpc(ITE_ADDR, 0xF2);
- + outlpc(ITE_DATA, tmpc & 0xBF);
- +
- + // Exit the configuration mode
- + outlpc(ITE_ADDR, 0x02);
- + outlpc(ITE_DATA, 0x02);
- +}
- +
- +void get_keyboard_status()
- +{
- +
- + printk("Getting keyboard status....\n");
- +
- + UINT8 tmpc;
- + unsigned int chip_id;
- +
- + // Enter the configuration mode
- + outlpc(ITE_ADDR, 0x87);
- + outlpc(ITE_ADDR, 0x01);
- + outlpc(ITE_ADDR, 0x55);
- + outlpc(ITE_ADDR, 0x55);
- +
- + // Check the chip ID
- + //printk("@@@@@ : Check IT8718F chip ID in get_lpc_value => \n");
- + outlpc(ITE_ADDR, 0x20);
- + tmpc = inlpc(ITE_DATA);
- + chip_id = (tmpc & 0xff) << 8;
- + outlpc(ITE_ADDR, 0x21);
- + tmpc = inlpc(ITE_DATA);
- + chip_id |= tmpc & 0xff;
- +
- + //printk("@@@@@ : chip_id = 0x%08x\n", chip_id);
- + if (chip_id != 0x8718) {
- + printk("FAILED with chip ID = 0x%C%C.\n", (chip_id >> 8) & 0xff,
- + chip_id & 0xff);
- + return (1);
- + }
- + // Set LDN = 4 for PME
- + outlpc(ITE_ADDR, 0x07);
- + outlpc(ITE_DATA, 0x04);
- +
- + ///////// Dump configuration register
- + outlpc(ITE_ADDR, 0xf1);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xf1] = 0x%x\n", tmpc);
- +
- + ///////// Dump configuration register
- + outlpc(ITE_ADDR, 0xf0);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xf0] = 0x%x\n", tmpc);
- +
- +}
- +
- +void get_lpc_value()
- +{
- + UINT8 tmpc;
- + unsigned int chip_id;
- +
- + // Enter the configuration mode
- + outlpc(ITE_ADDR, 0x87);
- + outlpc(ITE_ADDR, 0x01);
- + outlpc(ITE_ADDR, 0x55);
- + outlpc(ITE_ADDR, 0x55);
- +
- + // Check the chip ID
- + printk("@@@@@ : Check IT8718F chip ID in get_lpc_value => \n");
- + outlpc(ITE_ADDR, 0x20);
- + tmpc = inlpc(ITE_DATA);
- + chip_id = (tmpc & 0xff) << 8;
- + outlpc(ITE_ADDR, 0x21);
- + tmpc = inlpc(ITE_DATA);
- + chip_id |= tmpc & 0xff;
- +
- + printk("@@@@@ : chip_id = 0x%08x\n", chip_id);
- + if (chip_id != 0x8718) {
- + printk("FAILED with chip ID = 0x%C%C.\n", (chip_id >> 8) & 0xff,
- + chip_id & 0xff);
- + return (1);
- + } else
- + printk("@@@@@ : PASSED\n");
- +
- + printk("=================== Get Values ==================\n");
- + //////////// Environment Controller configuration register
- + printk("@@@@@ : Environment Controller configuration register\n");
- + // Set LDN = 4 for PME
- + outlpc(ITE_ADDR, 0x07);
- + outlpc(ITE_DATA, 0x04);
- +
- + printk("@@@@@ : LDN = 4\n");
- +
- + ///////// Dump configuration register
- + outlpc(ITE_ADDR, 0x30);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x30] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x60);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x60] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x61);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x61] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x62);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x62] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x63);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x63] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x70);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x70] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xf0);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xf0] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xf1);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xf1] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xf2);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xf2] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xf3);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xf3] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xf4);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xf4] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xf5);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xf5] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xf6);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xf6] = 0x%x\n", tmpc);
- +
- + //////////// Keyboard configuration register
- + printk("@@@@@ : Keyboard configuration register\n");
- + // Set LDN = 5
- + outlpc(ITE_ADDR, 0x07);
- + outlpc(ITE_DATA, 0x05);
- +
- + printk("@@@@@ : LDN = 5\n");
- +
- + outlpc(ITE_ADDR, 0x30);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x30] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x60);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x60] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x61);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x61] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x62);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x62] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x63);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x63] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x70);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x70] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x71);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x71] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xf0);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xf0] = 0x%x\n", tmpc);
- +
- + //////////// GPIO configuration register
- + printk("@@@@@ : GPIO configuration register\n");
- + // Set LDN = 7 for GPIO
- + outlpc(ITE_ADDR, 0x07);
- + outlpc(ITE_DATA, 0x07);
- +
- + printk("@@@@@ : LDN = 7\n");
- +
- + outlpc(ITE_ADDR, 0x60);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x60] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x62);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x62] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x63);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x63] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x64);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x64] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x65);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x65] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x70);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x70] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x71);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x71] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x72);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x72] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x73);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x73] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0x74);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0x74] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xB0);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xB0] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xB1);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xB1] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xB2);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xB2] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xB3);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xB3] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xB4);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xB4] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xB5);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xB5] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xB8);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xB8] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xBA);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xBA] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xBB);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xBB] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xBC);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xBC] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xBD);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xBD] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xC0);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xC0] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xC1);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xC1] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xC2);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xC2] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xC3);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xC3] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xC4);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xC4] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xC5);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xC5] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xC8);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xC8] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xC9);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xC9] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xCA);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xCA] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xCB);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xCB] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xCC);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xCC] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xCD);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xCD] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xE0);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xE0] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xE1);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xE1] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xE2);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xE2] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xE3);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xE3] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xE4);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xE4] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xE5);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xE5] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xE6);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xE6] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xF0);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xF0] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xF1);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xF1] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xF2);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xF2] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xF3);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xF3] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xF4);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xF4] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xF5);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xF5] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xF6);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xF6] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xF7);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xF7] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xF8);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xF8] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xF9);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xF9] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xFA);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xFA] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xFB);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xFB] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xFC);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xFC] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xFD);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xFD] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xFE);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xFE] = 0x%x\n", tmpc);
- +
- + outlpc(ITE_ADDR, 0xFF);
- + tmpc = inlpc(ITE_DATA);
- + printk("[0xFF] = 0x%x\n", tmpc);
- +
- + printk("=================== End Get Values ==================\n");
- +
- +}
- +
- +/////////////////////////////// End LPC wake up ///////////////////////////////////////////////
- +
- +/*
- + * AG102 PMU sleep mode handler.
- + */
- +void andes_suspend_to_ram()
- +{
- + int i, k, l, checksum, checksuma;
- + unsigned int addr, reg;
- + static int irq_saves[3];
- + unsigned int tmp;
- + pgd_t *pgdv;
- + pud_t *pudv;
- + pmd_t *pmdv;
- + pte_t *ptev;
- + unsigned int resume_addr /*, resume_temp */ ;
- + //unsigned int *resume_tempaddr;
- + __asm__ volatile ("mfsr %0, $ir14\n\t":"=&r" (tmp));
- + //printk("\nag102_cpu_resume:0x%x\n", ag102_cpu_resume);
- + //printk( KERN_WARNING "\nag102_cpu_resume2:0x%x\n", ag102_cpu_resume2);
- + pgdv =
- + (pgd_t *) __va((GET_L1_PPTB() & L1_PPTB_mskBASE)) +
- + pgd_index((unsigned int)ag102_cpu_resume);
- + pudv = pud_offset(pgdv, (unsigned int)ag102_cpu_resume);
- + pmdv = pmd_offset(pudv, (unsigned int)ag102_cpu_resume);
- + ptev = pte_offset_map(pmdv, (unsigned int)ag102_cpu_resume);
- + //printk("ag102_cpu_resume pte:0x%x\n", ptev);
- + resume_addr =
- + ((*ptev) & TLB_DATA_mskPPN) | ((unsigned int)ag102_cpu_resume &
- + 0x00000fff);
- + printk("resume_addr using Page Table :0x%08x\n", resume_addr);
- +
- + //ADD by river 2010.09.23
- + printk("@@@@@ resume_addr(VA):0x%08x\n", ag102_cpu_resume);
- + printk("@@@@@ resume_addr2(VA):0x%08x\n", ag102_cpu_resume2);
- + printk("@@@@@ resume_addr(PA) using virt_to_phys :0x%08x\n",
- + virt_to_phys(ag102_cpu_resume));
- + printk("@@@@@ resume_addr2(PA):0x%08x\n",
- + virt_to_phys(ag102_cpu_resume2));
- + printk("@@@@@ AHB Controller for ROM :0x%08x\n",
- + REG32(AHB_ATFAHBC020S_0_VA_BASE + 0x10));
- + printk("@@@@@ AHB Controller for RAM :0x%08x\n",
- + REG32(AHB_ATFAHBC020S_0_VA_BASE + 0x18));
- + //End ADD by river 2010.09.23
- +
- + /* trigger mode regs */
- + irq_saves[0] = REG32(AMIC_VA_BASE + 0x20);
- + /* trigger level regs */
- + irq_saves[1] = REG32(AMIC_VA_BASE + 0x24);
- + /* interrupt enable regs */
- + irq_saves[2] = REG32(AMIC_VA_BASE + 0x80);
- + /* save SDRAM settings */
- +
- + /* set resume return address */
- + //REG32(PCU_VA_BASE + 0x400) = (resume_addr);
- + REG32(PCU_VA_BASE + 0x400) = (resume_addr) | 0x80000000;
- + REG32(PCU_VA_BASE + 0x404) = (u32) ag102_cpu_resume2;
- + REG32(PCU_VA_BASE + 0x410) = GET_L1_PPTB();
- + //ADD by river 2010.12.02 for reserve kernel remap
- + REG32(PCU_VA_BASE + 0x418) = REG32(AHB_ATFAHBC020S_0_VA_BASE + 0x10);
- + REG32(PCU_VA_BASE + 0x41C) = REG32(AHB_ATFAHBC020S_0_VA_BASE + 0x18);
- + //End ADD by river 2010.12.02 for reserve kernel remap
- + printk("L1_PPTB (PA) =0x%08x\n", GET_L1_PPTB());
- + printk("L1_PPTB (VA) in virtual address =0x%08x\n",
- + phys_to_virt(GET_L1_PPTB()));
- +
- + //ADD by river 2010.12.07
- + UINT32 phy_id, phy_addr;
- + ETH_PHY_STAT phy_stat;
- +
- + if (eth_phy_detect(&phy_addr, &phy_id) != 0) {
- + printk("ERR: fail to detect known PHY!!!\n");
- + return;
- + }
- + //TEST by river 2010.12.10
- + eth_phy_init(phy_addr);
- + eth_phy_stat(phy_addr, &phy_stat);
- + eth_mac_init(&phy_stat);
- + //End TEST by river 2010.12.10
- + gmac_set_wol();
- + //End ADD by river 2010.12.07
- +
- + /////////// ADD by river 2010.12.20 for LPC wakeup /////////////////////////////
- + if (it8718f_init() != 0)
- + return;
- +
- + //INTC setup
- + SetIntTrig(IRQ_LPC, LEVEL, H_ACTIVE);
- + EnableInt(IRQ_LPC); // including INT_MASK and GIE in Core
- +
- + enable_sirq();
- +
- + //__asm__ volatile ("1:\n\t");
- + //__asm__ volatile ("b 1b\n\t");
- +
- + printk("Calling ite_set_pme() YAYAYA....\n");
- + ite_set_pme();
- +
- + printk("Get Value..... YAYAYA....1\n");
- + get_lpc_value();
- +
- + /////////// End ADD by river 2010.12.20 for LPC wakeup /////////////////////////////
- +
- + //set GPIO[2] as suspend2dram power control pin
- + PCU_SET_FIELD(MFPS1, SUSPEND_GPIO, 0x1);
- + PCU_SET_FIELD(PCS9_PDD, SUSP2RAM, 0x1);
- + //ADD by river 2010.12.07
- + PCU_SET_REG(PCS9_CFG, PCU_PREPARE(PCS9_CFG, WKEN, PCS_WKEN_WOL | PCS_WKEN_LPC | PCS_WKEN_RTC)); // use only gpio0 and wol
- + //PCU_SET_REG(PCS9_CFG, PCU_PREPARE(PCS9_CFG, WKEN, PCS_WKEN_LPC)); // use lpc
- +
- + //End ADD by river 2010.12.07
- +
- + /* set pwoer status */
- + //int par = PCS_POWER_GPU_AND_DAC|PCS_POWER_CPUB;
- + int reg_tmp = PCU_PREPARE(PCS9_PARA, IE, 0x1) |
- + PCU_PREPARE(PCS9_PARA, CMD,
- + PCS_CMD_PW_DOWN /*PCS_CMD_SCALING|PCS_CMD_DRAM_SF */ ) |
- + PCU_PREPARE(PCS9_PARA, SYNC, PCS_SYNC_SRC) | PCU_PREPARE(PCS9_PARA, NXTPAR, 0 /*par */ ); // change power status
- + PCU_SET_REG(PCS9_PARA, reg_tmp);
- +
- + //PCU_SET_FIELD(MFPS1, SUSPEND_GPIO, 0x1);
- + /* setup wakeup sources */
- + /*
- + k = PCU_PREPARE(WAKEUP_SEN, GPIO0_POL, 0x1) |
- + PCU_PREPARE(WAKEUP_SEN, GPIO1_POL, 0x1) |
- + PCU_PREPARE(WAKEUP_SEN, GPIO2_POL, 0x1) |
- + PCU_PREPARE(WAKEUP_SEN, GPIO3_POL, 0x1) |
- + PCU_PREPARE(WAKEUP_SEN, GPIO4_POL, 0x1) |
- + PCU_PREPARE(WAKEUP_SEN, GPIO5_POL, 0x1) |
- + PCU_PREPARE(WAKEUP_SEN, WOL_POL, 0x1) |
- + PCU_PREPARE(WAKEUP_SEN, LPC_POL, 0x1);
- + l = ~k; //set polarity
- + //l = 0x1c0;
- + PCU_SET_REG(WAKEUP_SEN, l);
- + PCU_SET_REG(PCS9_CFG, PCU_PREPARE(PCS9_CFG, WKEN, k));
- + */
- + /* Set PDD register and set suspend_to_ram */
- + //PCU_SET_FIELD(PCS9_PDD, SUSP2RAM, 0x1);
- +
- + cpu_dcache_wbinval_all();
- + cpu_icache_inval_all();
- + SET_CACHE_CTL(GET_CACHE_CTL() & ~CACHE_CTL_mskDC_EN);
- +
- + /* lock self-refresh code to L1 cache */
- +
- + addr = (unsigned int)__SELF_REFRESH_LOCK_START;
- + reg = (((unsigned int)__SELF_REFRESH_LOCK_END - (unsigned int)__SELF_REFRESH_LOCK_START) >> 5) + 1; //
- +
- + for (i = 0; i < reg; i++) {
- + __asm__ volatile ("li $p0, 0x0\n\t"
- + "add $p0, $p0, %0\n\t"
- + "cctl $p0, L1I_VA_FILLCK\n\t"
- + "isb\n\t"::"r" (addr));
- +
- + addr += 32;
- + }
- +
- + unsigned char *ptr;
- + //ADD by river 2010.11.19
- + printk("The resume address's content is :\n");
- + ptr = (unsigned char *)ag102_cpu_resume;
- + for (i = 0; i < 20; i++) {
- + printk("0x%02x - ", *ptr++);
- + }
- +
- + printk("Get Value..... YAYAYA....2\n");
- + get_lpc_value();
- +
- + //End ADD by river 2010.11.19
- + ag102_cpu_sleep();
- + printk("return success-1..........\n");
- + /* wakeup and ckeck */
- + /*
- + reg_tmp = PCU_GET_REG(PCS9_ST2);// check Status-2
- + if (PCU_EXTRACT(PCS9_ST2, CURPAR, reg_tmp) != par)
- + printk("Parameter setup is not the same!\n");
- +
- + reg_tmp = PCU_GET_REG(PCS9_ST1); // check Status-1
- + if (PCU_EXTRACT(PCS9_ST1, STS, reg_tmp) != PCS_STS_DONE)
- + printk("The work is not done?!\n");
- + if (PCU_EXTRACT(PCS9_ST1, ERR, reg_tmp) != PCS_ERR_NONE)
- + printk("Some error happened!!\n");
- + PCU_SET_REG(PCS9_ST1, 0x0); //clear status
- +
- + */
- + ftpci_postinit();
- + SET_CACHE_CTL(GET_CACHE_CTL() | CACHE_CTL_mskDC_EN);
- + /* trigger mode regs */
- + REG32(AMIC_VA_BASE + 0x20) = irq_saves[0];
- + /* trigger level regs */
- + REG32(AMIC_VA_BASE + 0x24) = irq_saves[1];
- + /* interrupt enable regs */
- + REG32(AMIC_VA_BASE + 0x80) = irq_saves[2];
- + __asm__ volatile ("mtsr %0, $ir14\n\t"::"r" (tmp));
- +
- + printk("return success-2..........\n");
- + dump_stack();
- +
- +}
- +
- +static int ag102_pm_valid(suspend_state_t state)
- +{
- + switch (state) {
- + case PM_SUSPEND_ON:
- + case PM_SUSPEND_STANDBY:
- + case PM_SUSPEND_MEM:
- + return 1;
- +
- + default:
- + return 0;
- + }
- +}
- +
- +static int ag102_pm_begin(suspend_state_t state)
- +{
- + /* TBD if we need it */
- + return 0;
- +}
- +
- +static void andes_suspend_cpu(void)
- +{
- + unsigned int irq_save;
- + /* setup GPIO interrupt enable regs to enable GPIO0 */
- + REG32(GPIO_VA_BASE + 0x20) = 1;
- + /* save interrupt enable regs */
- + irq_save = REG32(AMIC_VA_BASE + 0x80);
- + /* accept all interrupts to wake up except timer interrupt */
- + REG32(AMIC_VA_BASE + 0x80) &= ~(1 << 19);
- + /* enable UART0 interrupt */
- + REG32(AMIC_VA_BASE + 0x80) |= 1 << 13;
- +
- + /*
- + * for more IRQ info, please refer to
- + * arch/nds32/include/asm/spec.h&spec-ag102.h
- + */
- +
- + __asm__ volatile ("standby no_wake_grant\n\t");
- + /* clear GPIO interrupt */
- + REG32(GPIO_VA_BASE + 0x30) = 1;
- + /* disable GPIO interrupt */
- + REG32(GPIO_VA_BASE + 0x20) = 0;
- + /* restore GPIO enable regs */
- + REG32(AMIC_VA_BASE + 0x80) = irq_save;
- +}
- +
- +static int ag102_pm_enter(suspend_state_t state)
- +{
- + switch (state) {
- + case PM_SUSPEND_STANDBY:
- + andes_suspend_cpu();
- + return 0;
- + case PM_SUSPEND_MEM:
- + printk("@@@@@@@@@@ : ag102_pm_enter()... from gavin.......\n");
- + andes_suspend_to_ram();
- + return 0;
- + default:
- + return -EINVAL;
- + }
- +}
- +
- +/*
- + * Called after processes are frozen, but before we shutdown devices.
- + */
- +static int ag102_pm_prepare(void)
- +{
- + /* TBD if we need it */
- + return 0;
- +}
- +
- +/*
- + * Called after devices are wakeuped, but before processes are thawed.
- + */
- +static void ag102_pm_finish(void)
- +{
- + /* TBD if we need it */
- +}
- +
- +static void ag102_pm_end(void)
- +{
- + /* TBD if we need it */
- +#if 0
- + class_destroy(andes_pcu_class);
- + unregister_chrdev(andes_pcu_major, ANDES_PCU_STRING);
- +#endif
- + printk("pm_exit\n");
- +}
- +
- +static int andes_pcu_ioctl(struct inode *inode, struct file *file,
- + unsigned int cmd, unsigned long arg)
- +{
- + return 0;
- +}
- +
- +static int andes_pcu_open(struct inode *inode, struct file *file)
- +{
- + return 0;
- +}
- +
- +static ssize_t andes_pcu_write(struct file *filp, const char *buff,
- + size_t count, loff_t * ppos)
- +{
- + char data;
- + get_user(data, buff);
- + switch (data) {
- + case 's':
- + printk("Just suspend cpu\n");
- + andes_suspend_cpu();
- + break;
- + case 'm':
- + printk("Suspend to ram\n");
- + andes_suspend_to_ram();
- + break;
- + }
- + return 0;
- +}
- +
- +static int andes_pcu_release(struct inode *inode, struct file *file)
- +{
- + return 0;
- +}
- +
- +static struct file_operations andes_pcu_fops = {
- + .owner = THIS_MODULE,
- + .ioctl = andes_pcu_ioctl,
- + .open = andes_pcu_open,
- + .write = andes_pcu_write,
- + .release = andes_pcu_release,
- +};
- +
- +static struct platform_suspend_ops ag102_pm_ops = {
- + .valid = ag102_pm_valid,
- + .begin = ag102_pm_begin,
- + .prepare = ag102_pm_prepare,
- + .enter = ag102_pm_enter,
- + .finish = ag102_pm_finish,
- + .end = ag102_pm_end,
- +};
- +
- +//PCU power-off workaround {
- +#undef IRQ_LEVEL
- +#include <linux/interrupt.h>
- +#include <linux/irq.h>
- +
- +//#define PM_DEBUG
- +#ifdef PM_DEBUG
- +#define PRINTK printk
- +#else
- +#define PRINTK(...)
- +#endif
- +
- +static volatile int pcuirq = 0;
- +
- +static inline void poweroff_pcu(void)
- +{
- + PRINTK(KERN_INFO "[kernel] poweroff_pcu()");
- + REG32(PCU_VA_BASE + 0x1a4) = (2 << 28) | (1 << 24) | (6 << 0); //power-down, sync CPUA, domain GPU+CPUB
- + __asm__ volatile ("standby wait_done\n");
- + REG32(PCU_VA_BASE + 0x1a8) = 0x0; //PCS9 status normal, no error
- +}
- +
- +static inline void clear_pcu_status(void)
- +{
- + PRINTK(KERN_INFO "[kernel] clear_pcu_status()");
- + REG32(PCU_VA_BASE + 0x1b0) |= (1 << 31); //clear poweroff flag
- + asm("msync store\nisb");
- +}
- +
- +static irqreturn_t gpio0_isr(int irq, void *dev_id)
- +{
- + PRINTK(KERN_INFO "[kernel] gpio0_isr(irq=%d)\n", irq);
- +
- + // is GPIO0 IRQ
- + if (REG32(GPIO_VA_BASE + 0x28) & (1 << 0)) {
- + PRINTK(KERN_INFO "GPIO#0 ASSERT!\n");
- +
- + pcuirq = 0;
- +
- + //disable GPIO0 IRQ
- + REG32(GPIO_VA_BASE + 0x2c) |= (1 << 0); //GPIO0 IRQ mask, level mode AMIC.GPIO#0 also cleared
- +
- +// REG32(AMIC_VA_BASE + 0x84) = (1<<13); //AMIC clear GPIO interrupt
- +
- + return IRQ_HANDLED;
- + }
- +
- + return IRQ_NONE;
- +}
- +
- +#define GPIO_SEC (1<<11)
- +static irqreturn_t pcu_isr(int irq, void *dev_id)
- +{
- + UINT32 status = REG32(PCU_VA_BASE + 0x94);
- + PRINTK(KERN_INFO "[kernel] pcu_isr(irq=%d) status=0x%08x\n", irq,
- + status);
- + if (0 == (GPIO_SEC & status))
- + return IRQ_NONE;
- +
- + PRINTK(KERN_INFO "[kernel] GPIO_SEC\n");
- + clear_pcu_status(); //clear PCS9 IRQ (level mode => AMIC.PCU also cleared)
- + pcuirq++;
- + if (1 == pcuirq) {
- + //enable GPIO0 IRQ
- + REG32(GPIO_VA_BASE + 0x30) = (1 << 0); //GPIO0 IRQ cleared
- +// REG32(AMIC_VA_BASE + 0x84) = (1 << 13); //AMIC clear GPIO interrupt
- +// enable_irq(GPIO_FTGPIO010_IRQ);
- + REG32(AMIC_VA_BASE + 0x80) |= (1 << 13); //AMIC enable GPIO IRQ
- + REG32(GPIO_VA_BASE + 0x2c) &= ~(1 << 0); //GPIO0 IRQ unmask
- + } else if (5 == pcuirq) {
- + poweroff_pcu();
- + }
- +// REG32(AMIC_VA_BASE + 0x84) = (1 << 8); //PCU IRQ clear
- +
- + return IRQ_HANDLED;
- +}
- +
- +//PCU power-off workaround }
- +
- +static int __init ag102_pm_init(void)
- +{
- + int ret = 0;
- + struct device *temp_class;
- + printk("PM driver init\n");
- + suspend_set_ops(&ag102_pm_ops);
- +
- + andes_pcu_major = register_chrdev(0, ANDES_PCU_STRING, &andes_pcu_fops);
- +
- + printk("@@@@@ : andes_pcu_major = 0x%08x\n", andes_pcu_major);
- + if (andes_pcu_major < 0) {
- + printk("Unable to get a major for andes pcu driver!\n");
- + return andes_pcu_major;
- + }
- +
- + andes_pcu_class = class_create(THIS_MODULE, ANDES_PCU_STRING);
- +
- + if (IS_ERR(andes_pcu_class)) {
- + printk(KERN_ERR "Error creating andes pcu class.\n");
- + ret = PTR_ERR(andes_pcu_class);
- + goto err_out1;
- + }
- +
- + temp_class = device_create(andes_pcu_class, NULL,
- + MKDEV(andes_pcu_major, 0),
- + NULL, ANDES_PCU_STRING);
- +
- + if (IS_ERR(temp_class)) {
- + printk(KERN_ERR "Error creating andes pcu class device.\n");
- + ret = PTR_ERR(temp_class);
- + goto err_out2;
- + }
- +
- + mac_dah = GMAC_GET_REG(MAC_MADR);
- + mac_dal = GMAC_GET_REG(MAC_LADR);
- +
- + //poweroff workaround
- + {
- + if (request_irq
- + (PCU_IRQ, pcu_isr, IRQF_SHARED, "PCU_POWEROFF", pcu_isr)) {
- + printk("Failed to request PCU interrupt.\n");
- + }
- +
- + if (request_irq
- + (GPIO_FTGPIO010_IRQ, gpio0_isr, IRQF_SHARED,
- + "GPIO0_FOR_PCU", gpio0_isr)) {
- + printk("Failed to request GPIO0 interrupt.\n");
- + }
- +
- + REG32(PCU_VA_BASE + 0x1b0) |= (3 << 28); //poweroff in 5s
- +
- + //AMIC setup
- + // PCU IRQ default edge trigger, rising edge
- + // GPIO_FTGPIO010_IRQ default edge trigger, rising edge
- +// REG32(AMIC_VA_BASE + 0x20) &= ~(1 << 8); //PCU IRQ level trigger
- +// REG32(AMIC_VA_BASE + 0x24) &= ~(1 << 8); //PCU IRQ active-high
- +// REG32(AMIC_VA_BASE + 0x20) &= ~(1 << 13); //GPIO IRQ level trigger
- +
- + //GPIO #0 setup
- + REG32(GPIO_VA_BASE + 0x08) &= ~(1 << 0); //GPIO0 input
- + REG32(GPIO_VA_BASE + 0x18) &= ~(1 << 0); //GPIO0 not pulled (external pull-high)
- + REG32(GPIO_VA_BASE + 0x2c) |= (1 << 0); //GPIO0 IRQ masked
- + REG32(GPIO_VA_BASE + 0x34) |= (1 << 0); //GPIO0 IRQ level trigger
- +// REG32(GPIO_VA_BASE + 0x38) &= ~(1<<0); //GPIO0 IRQ single edge
- + REG32(GPIO_VA_BASE + 0x3c) &= ~(1 << 0); //GPIO0 IRQ high-active
- + REG32(GPIO_VA_BASE + 0x40) |= (1 << 0); //GPIO0 enable bounce
- + REG32(GPIO_VA_BASE + 0x40) = 0xffff; //GPIO bounce time = x/PCLK
- +// REG32(GPIO_VA_BASE + 0x30) = (1<<0); //GPIO0 IRQ cleared
- + REG32(GPIO_VA_BASE + 0x20) |= (1 << 0); //GPIO0 IRQ enable
- +
- +// enable_irq(PCU_IRQ);
- + REG32(AMIC_VA_BASE + 0x80) |= (1 << 8); //IRQ enabled
- + }
- +
- + printk("pm_init\n");
- + return 0;
- +err_out2:
- + class_destroy(andes_pcu_class);
- +err_out1:
- + unregister_chrdev(andes_pcu_major, ANDES_PCU_STRING);
- + return 1;
- +}
- +
- +//static void resume_to_ccode(void)
- +//{
- +// printk("Resume to C code successfully....\n");
- +//}
- +
- +late_initcall(ag102_pm_init);
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/sleep.S linux-3.4.110/arch/nds32/platforms/ag102/sleep.S
- --- linux-3.4.110.orig/arch/nds32/platforms/ag102/sleep.S 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ag102/sleep.S 2016-04-07 10:20:51.002083345 +0200
- @@ -0,0 +1,465 @@
- +#include <asm/spec-ag102.h>
- +.text
- +
- +.globl ag102_cpu_sleep
- +.globl ag102_cpu_resume
- +.globl ag102_cpu_resume2
- +.globl __SELF_REFRESH_LOCK_START
- +.globl __SELF_REFRESH_LOCK_END
- +
- +#! 0x94200000; keep r0, r1, r2
- + .macro putch ch
- + li $r0, #0x94200000
- + move $r2, \ch
- +88:
- + lwi $r1, [$r0+#0x14]
- + srli $r1, $r1, #5
- + andi $r1, $r1, #0x1
- + beqz $r1, 88b
- + swi $r2, [$r0]
- + .endm
- +#! 0x94200000; keep r3, r4
- + .macro hex2asc val
- + addi \val, \val, -10
- + bltz \val, 1f
- + addi \val, \val, 0x41
- + j 2f
- +1:
- + addi \val, \val, 0x3a
- +2:
- + .endm
- +
- + .macro print_hex mhex
- + move $r3, \mhex
- +
- + srli $r4, $r3, #28
- + andi $r4, $r4, 0xf
- + hex2asc $r4
- + putch $r4
- + srli $r4, $r3, #24
- + andi $r4, $r4, 0xf
- + hex2asc $r4
- + putch $r4
- + srli $r4, $r3, #20
- + andi $r4, $r4, 0xf
- + hex2asc $r4
- + putch $r4
- + srli $r4, $r3, #16
- + andi $r4, $r4, 0xf
- + hex2asc $r4
- + putch $r4
- + srli $r4, $r3, #12
- + andi $r4, $r4, 0xf
- + hex2asc $r4
- + putch $r4
- + srli $r4, $r3, #8
- + andi $r4, $r4, 0xf
- + hex2asc $r4
- + putch $r4
- + srli $r4, $r3, #4
- + andi $r4, $r4, 0xf
- + hex2asc $r4
- + putch $r4
- + move $r4, $r3
- + andi $r4, $r4, 0xf
- + hex2asc $r4
- + putch $r4
- + .endm
- +
- +ag102_cpu_resume2:
- +/*1:
- +b 1b*/
- + //MOD by river 2010.10.13
- + popm $r0, $r19
- + mtusr $r0, $d0.lo ! $d0 lo byte
- + mtusr $r1, $d0.hi ! $d0 hi byte
- + mtusr $r2, $d1.lo ! $d1 lo byte
- + mtusr $r3, $d1.hi ! $d1 hi byte
- + mtsr $r4, $mr0
- + mtsr $r5, $mr1
- + mtsr $r6, $mr4
- + mtsr $r7, $mr6
- + mtsr $r8, $mr7
- + mtsr $r9, $mr8
- + mtsr $r10, $ir0
- + mtsr $r11, $ir1
- + mtsr $r12, $ir2
- + mtsr $r13, $ir3
- + mtsr $r14, $ir9
- + mtsr $r15, $ir10
- + mtsr $r16, $ir12
- + mtsr $r17, $ir13
- + mtsr $r18, $ir14
- + mtsr $r19, $ir15
- + //End MOD by river 2010.10.13
- + popm $r0, $r30
- + ret
- +
- +ag102_cpu_sleep:
- +
- + pushm $r0, $r30
- + //MOD by river 2010.10.13
- + mfusr $r0, $d0.lo ! $d0 lo byte
- + mfusr $r1, $d0.hi ! $d0 hi byte
- + mfusr $r2, $d1.lo ! $d1 lo byte
- + mfusr $r3, $d1.hi ! $d1 hi byte
- + mfsr $r4, $mr0
- + mfsr $r5, $mr1
- + mfsr $r6, $mr4
- + mfsr $r7, $mr6
- + mfsr $r8, $mr7
- + mfsr $r9, $mr8
- + mfsr $r10, $ir0
- + mfsr $r11, $ir1
- + mfsr $r12, $ir2
- + mfsr $r13, $ir3
- + mfsr $r14, $ir9
- + mfsr $r15, $ir10
- + mfsr $r16, $ir12
- + mfsr $r17, $ir13
- + mfsr $r18, $ir14
- + mfsr $r19, $ir15
- + pushm $r0, $r19
- + //End MOD by river 2010.10.13
- +
- + /* store $sp to 0x408 scratch pad */
- + sethi $r0, hi20(PCU_VA_BASE + 0x408)
- + ori $r2, $r0, lo12(PCU_VA_BASE + 0x408)
- + swi $r31, [$r2]
- +
- + /* set signaure "SUSP" to 0x40c */
- + li $r0, (PCU_VA_BASE + 0x40c)
- + li $r1, 0x53555350 ! set signature "SUSP" to scratch pad register offset 0x40c
- + swi $r1, [$r0]
- +
- + /*
- + * store 8 bytes from 16mb to pcu scratch pad resgister
- + * due to data training process will destroy it
- + */
- + li $r0, 0x10000
- + li $r2, (PCU_VA_BASE + 0x414)
- + lwi $r1, [$r0]
- + swi $r1, [$r2]
- + lwi $r1, [$r0 + 0x4]
- + swi $r1, [$r2 + 0x4]
- +
- + /* ADD by river 2010.09.23 */
- + /* Save PSW in PCU_VA_BASE + 0x420 */
- + li $r0, (PCU_VA_BASE + 0x420)
- + mfsr $r1, $ir0
- + swi $r1, [$r0]
- + /* Save $mr0 in PCU_VA_BASE + 0x424 */
- + li $r0, (PCU_VA_BASE + 0x424)
- + mfsr $r1, $mr0
- + swi $r1, [$r0]
- + /* Save $mr1 in PCU_VA_BASE + 0x428 */
- + li $r0, (PCU_VA_BASE + 0x428)
- + mfsr $r1, $mr1
- + swi $r1, [$r0]
- + /* Save $mr2 in PCU_VA_BASE + 0x42c */
- + li $r0, (PCU_VA_BASE + 0x42c)
- + mfsr $r1, $mr2
- + swi $r1, [$r0]
- + /* Save $mr3 in PCU_VA_BASE + 0x430 */
- + li $r0, (PCU_VA_BASE + 0x430)
- + mfsr $r1, $mr3
- + swi $r1, [$r0]
- + /* Save $mr4 in PCU_VA_BASE + 0x434 */
- + li $r0, (PCU_VA_BASE + 0x434)
- + mfsr $r1, $mr4
- + swi $r1, [$r0]
- + /* Save $mr5 in PCU_VA_BASE + 0x438 */
- + //li $r0, (PCU_VA_BASE + 0x438)
- + //mfsr $r1, $mr5
- + //swi $r1, [$r0]
- + /* Save $mr6 in PCU_VA_BASE + 0x43c */
- + li $r0, (PCU_VA_BASE + 0x43c)
- + mfsr $r1, $mr6
- + swi $r1, [$r0]
- + /* Save $mr7 in PCU_VA_BASE + 0x440 */
- + li $r0, (PCU_VA_BASE + 0x440)
- + mfsr $r1, $mr7
- + swi $r1, [$r0]
- + /* Save $mr8 in PCU_VA_BASE + 0x444 */
- + li $r0, (PCU_VA_BASE + 0x444)
- + mfsr $r1, $mr8
- + swi $r1, [$r0]
- +
- + /* Save $ir3 in PCU_VA_BASE + 0x450 */
- + li $r0, (PCU_VA_BASE + 0x450)
- + mfsr $r1, $ir3
- + swi $r1, [$r0]
- +
- + /* Save $ir14 in PCU_VA_BASE + 0x454 */
- + li $r0, (PCU_VA_BASE + 0x454)
- + mfsr $r1, $ir14
- + swi $r1, [$r0]
- +
- + /* Save $ir15 in PCU_VA_BASE + 0x458 */
- + li $r0, (PCU_VA_BASE + 0x458)
- + mfsr $r1, $ir15
- + swi $r1, [$r0]
- +
- + tlbop FlushAll
- + isb
- + /* End ADD by river 2010.09.23 */
- +
- + //Trace by river 2010.12.01
- + /*1:
- + b 1b*/
- + //End Trace by river 2010.12.01
- +.p2align 5
- +__SELF_REFRESH_LOCK_START:
- + /*sethi $r0, hi20(0x900005cc)
- + ori $r0, $r0, lo12(0x900005cc)
- + sethi $r1, hi20(DDR2C_VA_BASE)
- + swi $r0, [$r1+0x4]
- +
- + msync
- + isb
- +
- + standby wake_grant
- + .p2align 5*/
- + sethi $r0, hi20(DDR2C_VA_BASE)
- + lwi $r1, [$r0+0x4]
- + li $r2, 0x07ffefff
- + and $r1, $r2, $r1
- + li $r2, 0x90001000
- + or $r1, $r2, $r1
- + swi $r1, [$r0+0x4]
- +
- + msync
- + isb
- +
- + standby wake_grant
- + .p2align
- +
- +__SELF_REFRESH_LOCK_END:
- +
- +ag102_cpu_resume:
- + /* TRACE by river 2010.12.02 */
- + /*1:
- + b 1b*/
- + /* End TRACE by river 2010.12.02 */
- + mfsr $r2, $mr0
- + ori $r2, $r2, #0x6
- +#ifdef CONFIG_ANDES_PAGE_SIZE_8KB
- + ori $r2, $r2, #0x1
- +#endif
- + mtsr $r2, $mr0
- +
- + /* ADD by river 2010.09.23 */
- + li $r3, 'C
- + putch $r3
- + li $r3, '\r
- + putch $r3
- + li $r3, '\n
- + putch $r3
- + li $r3, 'P
- + putch $r3
- + li $r3, '\r
- + putch $r3
- + li $r3, '\n
- + putch $r3
- + li $r3, 'U
- + putch $r3
- + li $r3, '\r
- + putch $r3
- + li $r3, '\n
- + putch $r3
- + li $r3, 'R
- + putch $r3
- + li $r3, '\r
- + putch $r3
- + li $r3, '\n
- + putch $r3
- + li $r3, 'E
- + putch $r3
- + li $r3, '\r
- + putch $r3
- + li $r3, '\n
- + putch $r3
- + li $r3, 'S
- + putch $r3
- + li $r3, '\r
- + putch $r3
- + li $r3, '\n
- + putch $r3
- + li $r3, 'U
- + putch $r3
- + li $r3, '\r
- + putch $r3
- + li $r3, '\n
- + putch $r3
- + li $r3, 'M
- + putch $r3
- + li $r3, '\r
- + putch $r3
- + li $r3, '\n
- + putch $r3
- + li $r3, 'E
- + putch $r3
- + li $r3, '\r
- + putch $r3
- + li $r3, '\n
- + putch $r3
- + /* ADD by river 2010.09.23 */
- +
- + /*tlbop FlushAll*/ ! invalidate TLB\n"
- +
- + /* ADD by river 2010.09.23 */
- + /* restore PSW */
- + //sethi $r2, hi20(PCU_PA_BASE + 0x420)
- + //ori $r2, $r2, lo12(PCU_PA_BASE + 0x420)
- + //lwi $r3, [$r2]
- + //mtsr $r3, $ir0
- + //move $p1, $r3
- + /* restore $mr0 */
- + sethi $r2, hi20(PCU_PA_BASE + 0x424)
- + ori $r2, $r2, lo12(PCU_PA_BASE + 0x424)
- + lwi $r3, [$r2]
- + mtsr $r3, $mr0
- + /* restore $mr1 */
- + sethi $r2, hi20(PCU_PA_BASE + 0x428)
- + ori $r2, $r2, lo12(PCU_PA_BASE + 0x428)
- + lwi $r3, [$r2]
- + mtsr $r3, $mr1
- +
- + /* restore $mr2 */
- + //sethi $r2, hi20(PCU_PA_BASE + 0x42c)
- + //ori $r2, $r2, lo12(PCU_PA_BASE + 0x42c)
- + //lwi $r3, [$r2]
- + //mtsr $r3, $mr2
- + /* restore $mr3 */
- + //sethi $r2, hi20(PCU_PA_BASE + 0x430)
- + //ori $r2, $r2, lo12(PCU_PA_BASE + 0x430)
- + //lwi $r3, [$r2]
- + //mtsr $r3, $mr3
- + /* restore $mr4 */
- + sethi $r2, hi20(PCU_PA_BASE + 0x434)
- + ori $r2, $r2, lo12(PCU_PA_BASE + 0x434)
- + lwi $r3, [$r2]
- + mtsr $r3, $mr4
- + /* restore $mr5 */
- + //sethi $r2, hi20(PCU_PA_BASE + 0x438)
- + //ori $r2, $r2, lo12(PCU_PA_BASE + 0x438)
- + //lwi $r3, [$r2]
- + //mtsr $r3, $mr5
- + /* restore $mr6 */
- + sethi $r2, hi20(PCU_PA_BASE + 0x43c)
- + ori $r2, $r2, lo12(PCU_PA_BASE + 0x43c)
- + lwi $r3, [$r2]
- + mtsr $r3, $mr6
- + /* restore $mr7 */
- + sethi $r2, hi20(PCU_PA_BASE + 0x440)
- + ori $r2, $r2, lo12(PCU_PA_BASE + 0x440)
- + lwi $r3, [$r2]
- + mtsr $r3, $mr7
- + /* restore $mr8 */
- + sethi $r2, hi20(PCU_PA_BASE + 0x444)
- + ori $r2, $r2, lo12(PCU_PA_BASE + 0x444)
- + lwi $r3, [$r2]
- + /* ADD by river 2010.12.02 for ICache Enable */
- + ori $r3, $r3, #0x1
- + /* End ADD by river 2010.12.02 for ICache Enable */
- + mtsr $r3, $mr8
- +
- + /* restore $ir3 */
- + sethi $r2, hi20(PCU_PA_BASE + 0x450)
- + ori $r2, $r2, lo12(PCU_PA_BASE + 0x450)
- + lwi $r3, [$r2]
- + mtsr $r3, $ir3
- +
- + move $p1, $r3
- + li $r3, '\r
- + putch $r3
- + li $r3, '\n
- + putch $r3
- + print_hex $p1
- + li $r3, '\r
- + putch $r3
- + li $r3, '\n
- + putch $r3
- +
- +
- + /* restore $ir14 */
- + sethi $r2, hi20(PCU_PA_BASE + 0x454)
- + ori $r2, $r2, lo12(PCU_PA_BASE + 0x454)
- + lwi $r3, [$r2]
- + mtsr $r3, $ir14
- +
- + /* restore $ir15 */
- + sethi $r2, hi20(PCU_PA_BASE + 0x458)
- + ori $r2, $r2, lo12(PCU_PA_BASE + 0x458)
- + lwi $r3, [$r2]
- + mtsr $r3, $ir15
- +
- + li $r3, '\r
- + putch $r3
- + li $r3, '\n
- + putch $r3
- + move $p1, $r3
- + print_hex $p1
- +
- + /* End ADD by river 2010.09.23 */
- +
- + /* in this buggy version(ram locate at 1G) TC01 we don't need to do remap.
- + * ebios set memory locate at 1G & size = 1G, for more detail info, please
- + * refer to ebios boot.S.
- + *
- + * sethi $r2, hi20(0x90c00000 + 0x88)
- + * ori $r2, $r2, lo12(0x90c00000 + 0x88)
- + * movi $r3, #0x1
- + * swi $r3, [$r2]
- + **/
- +
- + /* restore 8 bytes from pcu scratch pad resgister to 16mb */
- + li $r0, 0x10000
- + li $r2, (PCU_PA_BASE + 0x414)
- + lwi $r1, [$r2]
- + swi $r1, [$r0]
- + lwi $r1, [$r2 + 0x4]
- + swi $r1, [$r0 + 0x4]
- +
- + .p2align 5
- + resume_lock_start:
- + /* ADD by river 2010.12.02 for ag102_cpu_resume2 for jral.ton $r4, $r4 */
- + sethi $r2, hi20(PCU_PA_BASE + 0x404)
- + ori $r2, $r2, lo12(PCU_PA_BASE + 0x404)
- + lwi $r4, [$r2]
- + /* End ADD by river 2010.12.02 for ag102_cpu_resume2 */
- +
- + /* ADD by river 2010.12.02 for restore kernel ROM map */
- + sethi $r0, hi20(0x40080000)
- + ori $r0, $r0, lo12(0x40080000)
- + sethi $r1, hi20(AHB_ATFAHBC020S_0_PA_BASE + 0x10)
- + ori $r1, $r1, lo12(AHB_ATFAHBC020S_0_PA_BASE + 0x10)
- + swi $r0, [$r1]
- +
- + /* ADD by river 2010.12.02 for restore kernel RAM map */
- + sethi $r0, hi20(0x000A0000)
- + ori $r0, $r0, lo12(0x000A0000)
- + sethi $r1, hi20(AHB_ATFAHBC020S_0_PA_BASE + 0x18)
- + ori $r1, $r1, lo12(AHB_ATFAHBC020S_0_PA_BASE + 0x18)
- + swi $r0, [$r1]
- +
- + /******************* Gavin version ***************************/
- + //MOD by river 2010.10.13
- + /*sethi $r2, hi20(PCU_PA_BASE + 0x404)
- + ori $r2, $r2, lo12(PCU_PA_BASE + 0x404)
- + lwi $r4, [$r2]
- + mtsr $r4, $IPC
- + li $r1, 0xcb
- + mtsr $r1, $IPSW
- + iret*/
- + //End MOD by river 2010.10.13
- + //End Gavin version////////////////////////////////////////////////////////////
- +
- + /* End ADD by river 2010.09.23 */
- + //MOD by river 2010.10.13
- + //////// jral.ton version ////////////////////////////////////////////////////
- +
- + jral.ton $r4, $r4
- + .p2align
- + resume_lock_end:
- + //End MOD by river 2010.10.13
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/amic.c linux-3.4.110/arch/nds32/platforms/amic.c
- --- linux-3.4.110.orig/arch/nds32/platforms/amic.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/amic.c 2016-04-07 10:20:51.002083345 +0200
- @@ -0,0 +1,203 @@
- +#include <linux/irq.h>
- +#include <linux/interrupt.h>
- +#include <linux/ioport.h>
- +#include <linux/delay.h>
- +
- +#include <asm/io.h>
- +#include <asm/amic.h>
- +
- +#define DEBUG(enabled, tagged, ...) \
- + do { \
- + if (enabled) { \
- + if (tagged) \
- + printk("[ %30s() ] ", __func__); \
- + printk(__VA_ARGS__); \
- + } \
- + } while (0)
- +
- +static DEFINE_SPINLOCK(amic_irq_lock);
- +
- +static void amic_ack_irq(unsigned int irq)
- +{
- + unsigned int data;
- +
- + spin_lock(&amic_irq_lock);
- + writel(1 << irq, AMIC_BASE + INTSTA);
- + data = readl(AMIC_BASE + INTSTA);
- + spin_unlock(&amic_irq_lock);
- +}
- +
- +static void amic_mask_irq(unsigned int irq)
- +{
- + unsigned int data;
- +
- + spin_lock(&amic_irq_lock);
- + data = readl(AMIC_BASE + INTEN);
- + data &= ~(1 << irq);
- + writel(data, AMIC_BASE + INTEN);
- + data = readl(AMIC_BASE + INTEN);
- + spin_unlock(&amic_irq_lock);
- +}
- +
- +static int amic_set_type(unsigned int irq, unsigned int flow_type)
- +{
- + unsigned int data;
- +
- + spin_lock(&amic_irq_lock);
- + if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
- + data = readl(AMIC_BASE + INTTRG);
- + data |= 1 << irq;
- + writel(data, AMIC_BASE + INTTRG);
- + }
- +
- + if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
- + data = readl(AMIC_BASE + INTTRG);
- + data &= ~(1 << irq);
- + writel(data, AMIC_BASE + INTTRG);
- + }
- +
- + if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) {
- + data = readl(AMIC_BASE + INTLVL);
- + data |= 1 << irq;
- + writel(data, AMIC_BASE + INTLVL);
- + }
- +
- + if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_EDGE_RISING)) {
- + data = readl(AMIC_BASE + INTLVL);
- + data &= ~(1 << irq);
- + writel(data, AMIC_BASE + INTLVL);
- + }
- + spin_unlock(&amic_irq_lock);
- + return 0;
- +}
- +
- +static void amic_unmask_irq(unsigned int irq)
- +{
- + unsigned int data;
- +
- + spin_lock(&amic_irq_lock);
- + data = readl(AMIC_BASE + INTEN);
- + data |= 1 << irq;
- + writel(data, AMIC_BASE + INTEN);
- + data = readl(AMIC_BASE + INTEN);
- + spin_unlock(&amic_irq_lock);
- +}
- +
- +static int amic_set_affinity(unsigned int irq, const struct cpumask *dest)
- +{
- + int cnt = 0;
- + int cpu;
- + volatile unsigned int data;
- + volatile unsigned int dc, amic_irq;
- +
- + if (num_online_cpus() > 2)
- + return 0;
- +
- + spin_lock(&amic_irq_lock);
- + /* remap irq number for real controller */
- + /* this may be needed in future */
- + /* amic_irq = irq_remap(irq); */
- + amic_irq = irq;
- +
- + /* change owner */
- + data = readl(AMIC_BASE + CPUID0 + ((amic_irq >> 4) << 2));
- + for_each_online_cpu(cpu) {
- + if (cpumask_test_cpu(cpu, dest)) {
- + data &= ~(0x3 << ((amic_irq & ~0x10) * 2));
- + data |= cpu << ((amic_irq & ~0x10) * 2);
- + cnt++;
- + }
- + }
- + writel(data, AMIC_BASE + CPUID0 + ((amic_irq >> 4) << 2));
- +
- + dc = readl(AMIC_BASE + CPUDC);
- + if (cnt == 2) /* set bit */
- + writel((dc | (1 << amic_irq)), (AMIC_BASE + CPUDC));
- + else /* clear bit */
- + writel((dc & ~(1 << amic_irq)), (AMIC_BASE + CPUDC));
- +
- + spin_unlock(&amic_irq_lock);
- +
- + DEBUG(0, 1, "en=%08x,status=%08x\n", readl(AMIC_BASE + INTEN),
- + readl(AMIC_BASE + INTSTA));
- +
- + return 0;
- +}
- +
- +static struct irq_chip amic_chip = {
- + .name = "AMIC",
- + .ack = amic_ack_irq,
- + .mask = amic_mask_irq,
- + .unmask = amic_unmask_irq,
- + .set_affinity = amic_set_affinity,
- + .set_type = amic_set_type,
- +};
- +
- +void __init amic_init(void)
- +{
- + int i, edge;
- + unsigned int temp = smp_processor_id();
- + temp |= temp << 2;
- + temp |= temp << 4;
- + temp |= temp << 8;
- + temp |= temp << 16;
- +
- + writel(0x0, AMIC_BASE + INTEN);
- + writel(0x0, AMIC_BASE + CPUDC);
- + writel(temp, AMIC_BASE + CPUID0);
- + writel(temp, AMIC_BASE + CPUID1);
- + writel(0xffff, AMIC_BASE + IPISTA);
- + writel(0xffffffff, AMIC_BASE + INTSTA);
- + writel(0x11111111, AMIC_BASE + PRITY0);
- + writel(0x11111111, AMIC_BASE + PRITY1);
- + writel(0x11111111, AMIC_BASE + PRITY2);
- + writel(0x11111111, AMIC_BASE + PRITY3);
- + writel(DEFAULT_MODE, AMIC_BASE + INTTRG);
- + writel(~DEFAULT_LEVEL, AMIC_BASE + INTLVL);
- + printk("AMIC config %x %x\n", temp, readl(AMIC_BASE + CONFIG));
- +
- + for (i = IRQ_BASE, edge = 1; i < IRQ_BASE + IRQ_TOTAL; i++, edge <<= 1) {
- + set_irq_chip(i, &amic_chip);
- + if (DEFAULT_MODE & edge)
- + set_irq_handler(i, handle_edge_irq);
- + else
- + set_irq_handler(i, handle_level_irq);
- + }
- +
- +}
- +
- +unsigned int get_IntSrc(void)
- +{
- + unsigned int irqsta, irq = 31;
- +
- + spin_lock(&amic_irq_lock);
- + irqsta = readl(AMIC_BASE + IPISTA);
- + if (irqsta != 0)
- + irqsta = 0;
- + else
- + irqsta = readl(AMIC_BASE + INTSTA);
- + spin_unlock(&amic_irq_lock);
- +
- + if (irqsta == 0)
- + return 32;
- + if (irqsta & 0x0000ffff) {
- + irq -= 16;
- + irqsta <<= 16;
- + }
- + if (irqsta & 0x00ff0000) {
- + irq -= 8;
- + irqsta <<= 8;
- + }
- + if (irqsta & 0x0f000000) {
- + irq -= 4;
- + irqsta <<= 4;
- + }
- + if (irqsta & 0x30000000) {
- + irq -= 2;
- + irqsta <<= 2;
- + }
- + if (irqsta & 0x40000000) {
- + irq -= 1;
- + }
- + return irq;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/dmad.c linux-3.4.110/arch/nds32/platforms/dmad.c
- --- linux-3.4.110.orig/arch/nds32/platforms/dmad.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/dmad.c 2016-04-07 10:20:51.018083964 +0200
- @@ -0,0 +1,3601 @@
- +/*****************************************************************************
- + *
- + * Copyright Andes Technology Corporation 2007-2008
- + * All Rights Reserved.
- + *
- + * Revision History:
- + *
- + * Aug.21.2007 Created.
- + * Feb.23.2009 Porting to Linux 2.6.
- +*****************************************************************************/
- +
- +#include <linux/module.h>
- +#include <linux/init.h>
- +#include <linux/mm.h>
- +#include <linux/slab.h>
- +#include <linux/spinlock.h>
- +#include <linux/completion.h>
- +#include <linux/errno.h>
- +#include <linux/interrupt.h>
- +#include <linux/ioport.h>
- +#include <asm/sizes.h>
- +#include <asm/types.h>
- +#include <asm/io.h>
- +#include <asm/dmad.h>
- +#include <linux/irq.h>
- +
- +#if (defined(CONFIG_PLATFORM_AHBDMA) || defined(CONFIG_PLATFORM_APBDMA))
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- +#define DMAD_AHB_MAX_CHANNELS DMAC_MAX_CHANNELS
- +#else
- +#define DMAD_AHB_MAX_CHANNELS 0
- +#endif /* CONFIG_PLATFORM_AHBDMA */
- +
- +#ifdef CONFIG_PLATFORM_APBDMA
- +#define DMAD_APB_MAX_CHANNELS APBBR_DMA_MAX_CHANNELS
- +#else
- +#define DMAD_APB_MAX_CHANNELS 0
- +#endif /* CONFIG_PLATFORM_APBDMA */
- +
- +#define DMAD_DRB_POOL_SIZE 32 /* 128 */
- +
- +/* reg/io supplementals */
- +static inline void setbl(addr_t bit, addr_t reg)
- +{
- + outl(inl(reg) | (addr_t) ((addr_t) 1 << bit), reg);
- +}
- +
- +static inline void clrbl(addr_t bit, addr_t reg)
- +{
- + outl(inl(reg) & (~((addr_t) ((addr_t) 1 << bit))), reg);
- +}
- +
- +static inline addr_t getbl(addr_t bit, addr_t reg)
- +{
- + return inl(reg) & (addr_t) ((addr_t) 1 << bit);
- +}
- +
- +/******************************************************************************/
- +
- +enum DMAD_DRQ_FLAGS {
- + DMAD_DRQ_STATE_READY = 0x00000001, /* channel allocation status */
- + DMAD_DRQ_STATE_ABORT = 0x00000002, /* abort drb alloc block-wait */
- + DMAD_DRQ_DIR_A1_TO_A0 = 0x00000004, /* Transfer direction */
- +};
- +
- +#define DMAD_DRQ_DIR_MASK DMAD_DRQ_DIR_A1_TO_A0
- +
- +/* DMA request queue, one instance per channel */
- +typedef struct dmad_drq {
- + u32 state; /* enum DMAD_DRQ_STATE */
- +
- + addr_t channel_base; /* register base address */
- + addr_t enable_port; /* enable register */
- + addr_t src_port; /* source address register */
- + addr_t dst_port; /* dest address register */
- + addr_t cyc_port; /* size(cycle) register */
- +
- + u32 flags; /* enum DMAD_CHREQ_FLAGS */
- +
- + spinlock_t drb_pool_lock;
- + dmad_drb *drb_pool; /* drb pool */
- +
- + u32 fre_head; /* free list head */
- + u32 fre_tail; /* free list tail */
- +
- + u32 rdy_head; /* ready list head */
- + u32 rdy_tail; /* ready list tail */
- +
- + u32 sbt_head; /* submitted list head */
- + u32 sbt_tail; /* submitted list tail */
- +
- + u32 data_width; /* dma transfer data width */
- +
- + struct completion drb_alloc_sync;
- +
- + /* client supplied callback function, executed in interrupt context
- + * client private data to be passed to data argument of completion_cb().
- + */
- + void (*completion_cb) (int channel, u16 status, void *data);
- + void *completion_data;
- +
- + /* ring-mode fields are valid for DMAD_FLAGS_RING_MODE */
- + dma_addr_t ring_base; /* ring buffer base address */
- + dma_addr_t ring_size; /* size (of data width) */
- + addr_t ring_port; /* for setup/fetch hw_ptr */
- + dmad_drb *ring_drb;
- +
- + addr_t dev_addr; /* device data port */
- +
- + int periods; /* interrupts periods */
- + dma_addr_t period_size; /* of dma data with */
- + dma_addr_t period_bytes; /* Period size, in bytes */
- +
- + /* ring_size - period_size * periods */
- + dma_addr_t remnant_size;
- +
- + dma_addr_t sw_ptr; /* sw pointer */
- + int sw_p_idx; /* current ring_ptr */
- + dma_addr_t sw_p_off; /* offset to period base */
- +
- +} dmad_drq;
- +
- +/* To shrink code size and improve performance, common channel registers
- + * are preload in drq struct at channel allocation time. One of the key
- + * dependency is the enable bit of both DMAC and APBDMA channel command
- + * registers. Please make sure hw design them at bit 0 of the command register
- + * in future evolvement.
- + */
- +#if (DMAC_CSR_CH_EN_BIT != APBBR_DMA_CHEN_BIT)
- +#error "DMAC_CSR_CH_EN_BIT != APBBR_DMA_CHEN_BIT"
- +#endif
- +
- +#define DMAD_PORT_ENABLE_BIT APBBR_DMA_CHEN_BIT
- +
- +static inline void dmad_enable_channel(dmad_drq * drq)
- +{
- + setbl(DMAD_PORT_ENABLE_BIT, drq->enable_port);
- +}
- +
- +static inline void dmad_disable_channel(dmad_drq * drq)
- +{
- + clrbl(DMAD_PORT_ENABLE_BIT, drq->enable_port);
- +}
- +
- +static inline addr_t dmad_is_channel_enabled(dmad_drq * drq)
- +{
- + return (addr_t) getbl(DMAD_PORT_ENABLE_BIT, drq->enable_port);
- +}
- +
- +/* AHB DMAC channel re-route table structure */
- +typedef struct _DMAD_AHB_CH_ROUTE {
- + u32 dev_reqn; /* device req/gnt number */
- + addr_t clear_cr; /* routing control register address */
- + addr_t route_cr; /* routing control register address */
- +} DMAD_AHB_CH_ROUTE;
- +
- +#ifdef CONFIG_PLAT_AG102
- +#if 0
- +/* AHB DMAC channel re-route table. Indexed by AHB DMAC req/ack number. */
- +static DMAD_AHB_CH_ROUTE ahb_ch_route_table[] __attribute__ ((__unused__)) = {
- + /* all todo ... */
- +
- + {
- + 0x00, DMAC_REQN_IDERX, DMAC_REQN_IDERX}, {
- + 0x01, DMAC_REQN_IDETX, DMAC_REQN_IDETX}, {
- + 0x02, DMAC_REQN_I2SAC97RX, DMAC_REQN_I2SAC97RX}, {
- + 0x03, DMAC_REQN_I2SAC97TX, DMAC_REQN_I2SAC97TX}, {
- + 0x04, DMAC_REQN_UART2RX, DMAC_REQN_UART2RX}, {
- + 0x05, DMAC_REQN_UART2TX, DMAC_REQN_UART2TX}, {
- + 0x06, DMAC_REQN_UART1RX, DMAC_REQN_UART1RX}, {
- + 0x07, DMAC_REQN_UART1TX, DMAC_REQN_UART1TX}, {
- + 0x08, DMAC_REQN_SDC, DMAC_REQN_SDC}, {
- + 0x09, DMAC_REQN_CFC, DMAC_REQN_CFC}, {
- + 0x0a, DMAC_REQN_LPCREQ0, DMAC_REQN_LPCREQ0}, {
- + 0x0b, DMAC_REQN_LPCREQ1, DMAC_REQN_LPCREQ1}, {
- + 0x0c, DMAC_REQN_LPCREQ2, DMAC_REQN_LPCREQ2}, {
- + 0x0d, DMAC_REQN_LPCREQ3, DMAC_REQN_LPCREQ3}, {
- + 0x0e, 0, 0}, {
- +0x0f, DMAC_REQN_LPCREQ5, DMAC_REQN_LPCREQ5},};
- +#endif
- +#else /* CONFIG_PLAT_AG102 */
- +
- +/* AHB DMAC channel re-route table. Indexed by AHB DMAC req/ack number. */
- +static DMAD_AHB_CH_ROUTE ahb_ch_route_table[] = {
- + {0x00, 0, 0},
- + {0x01, PMU_CFC_REQACK_CFG, PMU_CFC_REQACK_CFG},
- + {0x02, PMU_SSP1_REQACK_CFG, PMU_SSP1_REQACK_CFG},
- + {0x03, PMU_UART1RX_REQACK_CFG, PMU_UART1TX_REQACK_CFG},
- + {0x04, PMU_UART1TX_REQACK_CFG, PMU_UART1RX_REQACK_CFG},
- + {0x05, PMU_UART2RX_REQACK_CFG, PMU_UART2TX_REQACK_CFG},
- + {0x06, PMU_UART2TX_REQACK_CFG, PMU_UART2RX_REQACK_CFG},
- + {0x07, PMU_SDC_REQACK_CFG, PMU_SDC_REQACK_CFG},
- + {0x08, PMU_I2SAC97RX_REQACK_CFG, PMU_I2SAC97TX_REQACK_CFG},
- + {0x09, 0, 0},
- + {0x0a, PMU_I2SAC97TX_REQACK_CFG, PMU_I2SAC97RX_REQACK_CFG},
- + {0x0b, PMU_USB_REQACK_CFG, PMU_USB_REQACK_CFG},
- + {0x0c, 0, 0},
- + {0x0d, 0, 0},
- + {0x0e, PMU_EXT0_REQACK_CFG, PMU_EXT0_REQACK_CFG},
- + {0x0f, PMU_EXT1_REQACK_CFG, PMU_EXT1_REQACK_CFG},
- +};
- +
- +#endif /* CONFIG_PLAT_AG102 */
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- +
- +/* system irq number (per channel, ahb) */
- +static const unsigned int ahb_irqs[DMAD_AHB_MAX_CHANNELS] = {
- + DMAC_FTDMAC020_0_IRQ0,
- + DMAC_FTDMAC020_0_IRQ1,
- + DMAC_FTDMAC020_0_IRQ2,
- + DMAC_FTDMAC020_0_IRQ3,
- + DMAC_FTDMAC020_0_IRQ4,
- + DMAC_FTDMAC020_0_IRQ5,
- + DMAC_FTDMAC020_0_IRQ6,
- + DMAC_FTDMAC020_0_IRQ7,
- +};
- +
- +#endif /* CONFIG_PLATFORM_AHBDMA */
- +
- +#ifdef CONFIG_PLATFORM_APBDMA
- +
- +/* APB Bridge DMA request number re-route table */
- +typedef struct _DMAD_APB_REQN_ROUTE {
- + u32 apb_reqn; /* APB device req/gnt number */
- + u32 ahb_reqn_tx; /* AHB DMAC req/ack number (tx) */
- + u32 ahb_reqn_rx; /* AHB DMAC req/ack number (rx) */
- + u32 bus_sel; /* APBBR_ADDRSEL_APB(0) or APBBR_ADDRSEL_AHB(1) */
- +} DMAD_APB_REQN_ROUTE;
- +
- +#ifdef CONFIG_PLAT_AG102
- +
- +/* APB Bridge DMA request number re-route table. Indexed by APB DMA req/gnt
- + * number. */
- +static DMAD_APB_REQN_ROUTE apb_reqn_route_table[] = {
- + {0x00, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- + {0x01, DMAC_REQN_CFC, DMAC_REQN_CFC, APBBR_ADDRSEL_APB},
- + {0x02, 0x00, 0x00, APBBR_ADDRSEL_APB},
- + {0x03, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- + {0x04, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- + //MOD by river 2010.10.20
- + {0x05, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- + //End MOD by river 2010.10.20
- + {0x06, DMAC_REQN_I2SAC97TX, DMAC_REQN_I2SAC97RX, APBBR_ADDRSEL_APB},
- + {0x07, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- + //MOD by river 2010.10.20
- + {0x08, DMAC_REQN_SDC, DMAC_REQN_SDC, APBBR_ADDRSEL_APB},
- + //End MOD by river 2010.10.20
- + {0x09, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- + {0x0a, DMAC_REQN_UART2TX, DMAC_REQN_UART2RX, APBBR_ADDRSEL_APB},
- + {0x0b, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- + {0x0c, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- + {0x0d, DMAC_REQN_I2SAC97TX, DMAC_REQN_I2SAC97RX, APBBR_ADDRSEL_APB},
- + {0x0e, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- + {0x0f, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- +};
- +
- +#else /* CONFIG_PLAT_AG102 */
- +
- +/* APB Bridge DMA request number re-route table. Indexed by APB DMA req/gnt
- + * number. */
- +static DMAD_APB_REQN_ROUTE apb_reqn_route_table[] = {
- + {0x00, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- + {0x01, DMAC_REQN_CFC, DMAC_REQN_CFC, APBBR_ADDRSEL_APB},
- + {0x02, DMAC_REQN_SSP, DMAC_REQN_SSP, APBBR_ADDRSEL_APB},
- + {0x03, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- + {0x04, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- + {0x05, DMAC_REQN_SDC, DMAC_REQN_SDC, APBBR_ADDRSEL_APB},
- + {0x06, DMAC_REQN_I2SAC97TX, DMAC_REQN_I2SAC97RX, APBBR_ADDRSEL_APB},
- +/* for amerald
- + { 0x07, 0x00, 0x00, APBBR_ADDRSEL_AHB },*/
- + {0x07, APBBR_REQN_SDC_AMERALD, APBBR_REQN_SDC_AMERALD,
- + APBBR_ADDRSEL_AHB},
- +/* for amerald ac97
- + { 0x08, 0x00, 0x00, APBBR_ADDRSEL_AHB }, */
- + {0x08, APBBR_REQN_I2SAC97TX_AMERALD, APBBR_REQN_I2SAC97TX_AMERALD,
- + APBBR_ADDRSEL_APB},
- + {0x09, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- + {0x0a, DMAC_REQN_UART2TX, DMAC_REQN_UART2RX, APBBR_ADDRSEL_APB},
- + {0x0b, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- + {0x0c, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- + {0x0d, DMAC_REQN_I2SAC97TX, DMAC_REQN_I2SAC97RX, APBBR_ADDRSEL_APB},
- + {0x0e, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- + {0x0f, 0x00, 0x00, APBBR_ADDRSEL_AHB},
- +};
- +
- +#endif /* CONFIG_PLAT_AG102 */
- +
- +/* system irq number (per channel, apb) */
- +static const unsigned int apb_irqs[DMAD_APB_MAX_CHANNELS] = {
- + APBBRG_FTAPBBRG020S_0_IRQ0,
- + APBBRG_FTAPBBRG020S_0_IRQ1,
- + APBBRG_FTAPBBRG020S_0_IRQ2,
- + APBBRG_FTAPBBRG020S_0_IRQ3,
- +};
- +
- +#endif
- +
- +/* Driver data structure, one instance per system */
- +typedef struct DMAD_DATA_STRUCT {
- + /* Driver data initialization flag */
- +
- + /* DMA queue pool access control object */
- + spinlock_t drq_pool_lock;
- +
- + /* DMA queue base address, to ease alloc/free flow */
- + dmad_drq *drq_pool;
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + /* DMA queue for AHB DMA channels */
- + dmad_drq *ahb_drq_pool;
- +#endif
- +
- +#ifdef CONFIG_PLATFORM_APBDMA
- + /* DMA queue for APB DMA channels */
- + dmad_drq *apb_drq_pool;
- +#endif
- +
- +} DMAD_DATA;
- +
- +/* Driver data structure instance, one instance per system */
- +static DMAD_DATA dmad __attribute__ ((aligned(4))) = {
- + .drq_pool_lock = __SPIN_LOCK_UNLOCKED(dmad.drq_pool_lock),
- +// .drq_pool_lock = SPIN_LOCK_UNLOCKED,
- + .drq_pool = 0,
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + .ahb_drq_pool = 0,
- +#endif
- +#ifdef CONFIG_PLATFORM_APBDMA
- + .apb_drq_pool = 0,
- +#endif
- +};
- +
- +/**
- + * dmad_next_drb - static function
- + * @drb_pool : [in] The raw DRB pool of a DMA channel
- + * @node : [in] The node number to lookup its next node
- + * @drb : [out] The drb next to the "node" node number
- + *
- + * Lookup next DRB of the specified node number. "drb" is null if reaches end
- + * of the list.
- + */
- +static inline void dmad_next_drb(dmad_drb * drb_pool, u32 node, dmad_drb ** drb)
- +{
- + if (likely(drb_pool[node].next != 0))
- + *drb = &drb_pool[drb_pool[node].next];
- + else
- + *drb = 0;
- +}
- +
- +/**
- + * dmad_prev_drb - static function
- + * @drb_pool : [in] The raw DRB pool of a DMA channel
- + * @node : [in] The node number to lookup its previous node
- + * @drb : [out] The drb previous to the "node" node number
- + *
- + * Lookup previous DRB of the specified node number. "drb" is null if reaches
- + * head-end of the list.
- + */
- +static inline void dmad_prev_drb(dmad_drb * drb_pool, u32 node, dmad_drb ** drb)
- +{
- + if (unlikely(drb_pool[node].prev != 0))
- + *drb = &drb_pool[drb_pool[node].prev];
- + else
- + *drb = 0;
- +}
- +
- +/**
- + * dmad_detach_node - static function
- + * @drb_pool : [in] The raw DRB pool of a DMA channel
- + * @head : [in/out] Reference to the head node number
- + * @tail : [in/out] Reference to the tail node number
- + * @node : [in] The node to be dettached from the queue
- + *
- + * Detached a DRB specified by the node number from the queue. The head and
- + * tail records will be updated accordingly.
- + */
- +static inline void dmad_detach_node(dmad_drb * drb_pool,
- + u32 * head, u32 * tail, u32 node)
- +{
- + if (likely(drb_pool[node].prev != 0)) {
- + /* prev->next = this->next (= 0, if this is a tail) */
- + drb_pool[drb_pool[node].prev].next = drb_pool[node].next;
- + } else {
- + /* this node is head, move head to next node
- + * (= 0, if this is the only one node) */
- + *head = drb_pool[node].next;
- + }
- +
- + if (unlikely(drb_pool[node].next != 0)) {
- + /* next->prev = this->prev (= 0, if this is a head) */
- + drb_pool[drb_pool[node].next].prev = drb_pool[node].prev;
- + } else {
- + /* this node is tail, move tail to previous node
- + * (= 0, if this is the only one node) */
- + *tail = drb_pool[node].prev;
- + }
- +
- + drb_pool[node].prev = drb_pool[node].next = 0;
- +}
- +
- +/**
- + * dmad_detach_head - static function
- + * @drb_pool : [in] The raw DRB pool of a DMA channel
- + * @head : [in/out] Reference to the head node number
- + * @tail : [in/out] Reference to the tail node number
- + * @drb : [out] The detached head node; null if the queue is empty
- + *
- + * Detached a DRB from the head of the queue. The head and tail records will
- + * be updated accordingly.
- + */
- +static inline void dmad_detach_head(dmad_drb * drb_pool,
- + u32 * head, u32 * tail, dmad_drb ** drb)
- +{
- + if (unlikely(*head == 0)) {
- + *drb = NULL;
- + return;
- + }
- +
- + *drb = &drb_pool[*head];
- +
- + if (likely((*drb)->next != 0)) {
- + /* next->prev = this->prev (= 0, if this is a head) */
- + drb_pool[(*drb)->next].prev = 0;
- +
- + /* prev->next = this->next (do nothing, if this is a head) */
- +
- + /* head = this->next */
- + *head = (*drb)->next;
- + } else {
- + /* head = tail = 0 */
- + *head = 0;
- + *tail = 0;
- + }
- +
- + /* this->prev = this->next = 0 (do nothing, if save code size) */
- + (*drb)->prev = (*drb)->next = 0;
- +}
- +
- +/**
- + * dmad_get_head - static function
- + * @drb_pool : [in] The raw DRB pool of a DMA channel
- + * @head : [in/out] Reference to the head node number
- + * @tail : [in/out] Reference to the tail node number
- + * @drb : [out] The head node; null if the queue is empty
- + *
- + * Get a DRB from the head of the queue. The head and tail records remain
- + * unchanged.
- + */
- +static inline void dmad_get_head(dmad_drb * drb_pool, const u32 * head,
- + const u32 * tail, dmad_drb ** drb)
- +{
- + if (unlikely(*head == 0)) {
- + *drb = NULL;
- + return;
- + }
- +
- + *drb = &drb_pool[*head];
- +}
- +
- +/**
- + * dmad_detach_tail - static function
- + * @drb_pool : [in] The raw DRB pool of a DMA channel
- + * @head : [in/out] Reference to the head node number
- + * @tail : [in/out] Reference to the tail node number
- + * @drb : [out] The tail node; null if the queue is empty
- + *
- + * Detached a DRB from the head of the queue. The head and tail records will
- + * be updated accordingly.
- + */
- +static inline void dmad_detach_tail(dmad_drb * drb_pool,
- + u32 * head, u32 * tail, dmad_drb ** drb)
- +{
- + if (unlikely(*tail == 0)) {
- + *drb = NULL;
- + return;
- + }
- +
- + *drb = &drb_pool[*tail];
- +
- + if (likely((*drb)->prev != 0)) {
- + /* prev->next = this->next (= 0, if this is a tail) */
- + drb_pool[(*drb)->prev].next = 0;
- +
- + /* next->prev = this->prev (do nothing, if this is a tail) */
- +
- + /* tail = this->prev */
- + *tail = (*drb)->prev;
- + } else {
- + /* head = tail = 0 */
- + *head = 0;
- + *tail = 0;
- + }
- +
- + /* this->next = this->prev = 0 (do nothing, if save code size) */
- + (*drb)->prev = (*drb)->next = 0;
- +}
- +
- +/**
- + * dmad_get_tail - static function
- + * @drb_pool : [in] The raw DRB pool of a DMA channel
- + * @head : [in/out] Reference to the head node number
- + * @tail : [in/out] Reference to the tail node number
- + * @drb : [out] The tail node; null if the queue is empty
- + *
- + * Get a DRB from the tail of the queue. The head and tail records remain
- + * unchanged.
- + */
- +static inline void dmad_get_tail(dmad_drb * drb_pool,
- + u32 * head, u32 * tail, dmad_drb ** drb)
- +{
- + if (unlikely(*tail == 0)) {
- + *drb = NULL;
- + return;
- + }
- +
- + *drb = &drb_pool[*tail];
- +}
- +
- +/**
- + * dmad_attach_head - static function
- + * @drb_pool : [in] The raw DRB pool of a DMA channel
- + * @head : [in/out] Reference to the head node number
- + * @tail : [in/out] Reference to the tail node number
- + * @node : [in] The node to be attached
- + *
- + * Attach a DRB node to the head of the queue. The head and tail records will
- + * be updated accordingly.
- + */
- +static inline void dmad_attach_head(dmad_drb * drb_pool,
- + u32 * head, u32 * tail, u32 node)
- +{
- + if (likely(*head != 0)) {
- + /* head->prev = this */
- + drb_pool[*head].prev = node;
- +
- + /* this->next = head */
- + drb_pool[node].next = *head;
- + /* this->prev = 0 */
- + drb_pool[node].prev = 0;
- +
- + /* head = node */
- + *head = node;
- + } else {
- + /* head = tail = node */
- + *head = *tail = node;
- + drb_pool[node].prev = drb_pool[node].next = 0;
- + }
- +}
- +
- +/**
- + * dmad_attach_head - static function
- + * @drb_pool : [in] The raw DRB pool of a DMA channel
- + * @head : [in/out] Reference to the head node number
- + * @tail : [in/out] Reference to the tail node number
- + * @node : [in] The node to be attached
- + *
- + * Attach a DRB node to the tail of the queue. The head and tail records will
- + * be updated accordingly.
- + */
- +static inline void dmad_attach_tail(dmad_drb * drb_pool,
- + u32 * head, u32 * tail, u32 node)
- +{
- + if (likely(*tail != 0)) {
- + /* tail->next = this */
- + drb_pool[*tail].next = node;
- +
- + /* this->prev = tail */
- + drb_pool[node].prev = *tail;
- + /* this->next = 0 */
- + drb_pool[node].next = 0;
- +
- + /* tail = node */
- + *tail = node;
- + } else {
- + /* head = tail = node */
- + *head = *tail = node;
- + drb_pool[node].prev = drb_pool[node].next = 0;
- + }
- +}
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- +
- +/**
- + * dmad_ahb_isr - AHB DMA interrupt service routine
- + *
- + * @irq : [in] The irq number
- + * @dev_id : [in] The identifier to identify the asserted channel
- + *
- + * This is the ISR that services all AHB DMA channels.
- + */
- +static irqreturn_t dmad_ahb_isr(int irq, void *dev_id)
- +{
- + dmad_drq *drq;
- + dmad_drb *drb, *drb_iter;
- + u32 channel = ((u32) dev_id) - 1;
- + u8 tc_int = 0;
- + u8 err_int = 0;
- + u8 abt_int = 0;
- + u8 cpl_events = 1;
- +
- + dmad_dbg("%s() >> channel(%d)\n", __func__, channel);
- +
- + if (channel >= DMAD_AHB_MAX_CHANNELS) {
- + dmad_err("%s() invlaid channel number: %d!\n",
- + __func__, channel);
- + return IRQ_HANDLED;
- + }
- +
- + /* Fetch channel's DRQ struct (DMA Request Queue) */
- + drq = (dmad_drq *) & dmad.ahb_drq_pool[channel];
- +
- + /* Check DMA status register to get channel number */
- + if (likely(getbl(channel, DMAC_INT_TC))) {
- +
- + /* Mark as TC int */
- + tc_int = 1;
- +
- + /* DMAC INT TC status clear */
- + setbl(channel, DMAC_INT_TC_CLR);
- +
- + } else if (getbl(channel + DMAC_INT_ERR_SHIFT, DMAC_INT_ERRABT)) {
- +
- + /* Mark as ERR int */
- + err_int = 1;
- +
- + /* DMAC INT ERR status clear */
- + setbl(channel + DMAC_INT_ERR_CLR_SHIFT, DMAC_INT_ERRABT_CLR);
- +
- + } else if (getbl(channel + DMAC_INT_ABT_SHIFT, DMAC_INT_ERRABT)) {
- +
- + /* Mark as ABT int */
- + abt_int = 1;
- +
- + /* DMAC INT ABT status clear */
- + setbl(channel + DMAC_INT_ABT_CLR_SHIFT, DMAC_INT_ERRABT_CLR);
- +
- + } else {
- +
- + dmad_err("%s() possible false-fired ahb dma int,"
- + "channel %d status-reg: tc(0x%08x) arrabt(0x%08x)\n",
- + __func__, channel,
- + inl(DMAC_INT_TC), inl(DMAC_INT_ERRABT_CLR));
- +
- + /* Stop DMA channel (make sure the channel will be stopped) */
- + clrbl(DMAC_CSR_CH_EN_BIT, drq->channel_base + DMAC_CSR_OFFSET);
- +
- + return IRQ_HANDLED;
- + }
- +
- + /* DMAC
- + * Stop DMA channel temporarily */
- + dmad_disable_channel(drq);
- +
- + spin_lock(&drq->drb_pool_lock);
- +
- + /* Lookup/detach latest submitted DRB (DMA Request Block) from
- + * the DRQ (DMA Request Queue), so ISR could kick off next DRB */
- + dmad_detach_head(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail, &drb);
- + if (drb == NULL) {
- + spin_unlock(&drq->drb_pool_lock);
- + /* submitted list could be empty if client cancel all requests
- + * of the channel. */
- + return IRQ_HANDLED;
- + }
- +
- + /* release blocking of drb-allocation, if any ... */
- + if (unlikely((drq->fre_head == 0) &&
- + (drq->flags & DMAD_FLAGS_SLEEP_BLOCK))) {
- + complete_all(&drq->drb_alloc_sync);
- + }
- +
- + /* Process DRBs according to interrupt reason */
- + if (tc_int) {
- +
- + dmad_dbg("dma finish\n");
- +
- + dmad_dbg("finish drb(%d 0x%08x) addr0(0x%08x) "
- + "addr1(0x%08x) size(0x%08x)\n",
- + drb->node, (u32) drb, drb->src_addr,
- + drb->dst_addr, drb->req_cycle);
- +
- + if (drb->req_cycle == 0)
- + cpl_events = 0;
- +
- + // Mark DRB state as completed
- + drb->state = DMAD_DRB_STATE_COMPLETED;
- + if (cpl_events && drb->sync)
- + complete_all(drb->sync);
- +
- + dmad_attach_tail(drq->drb_pool, &drq->fre_head,
- + &drq->fre_tail, drb->node);
- +
- + // Check whether there are pending requests in the DRQ
- + if (drq->sbt_head != 0) {
- +
- + // Lookup next DRB (DMA Request Block)
- + drb_iter = &drq->drb_pool[drq->sbt_head];
- +
- + dmad_dbg("exec drb(%d 0x%08x) addr0(0x%08x) "
- + "addr1(0x%08x) size(0x%08x)\n",
- + drb_iter->node, (u32) drb_iter,
- + drb_iter->src_addr, drb_iter->dst_addr,
- + drb_iter->req_cycle);
- +
- + // Kick-off DMA for next DRB
- + // - Source and destination address
- + if (drq->flags & DMAD_DRQ_DIR_A1_TO_A0) {
- + outl(drb_iter->addr1, drq->src_port);
- + outl(drb_iter->addr0, drq->dst_port);
- + } else {
- + outl(drb_iter->addr0, drq->src_port);
- + outl(drb_iter->addr1, drq->dst_port);
- + }
- +
- + /* - Transfer size (in units of source width) */
- + outl(drb_iter->req_cycle, drq->cyc_port);
- +
- + /* Kick off next request */
- + dmad_enable_channel(drq);
- +
- + drb_iter->state = DMAD_DRB_STATE_EXECUTED;
- +
- + } else {
- + /* No pending requests, keep the DMA channel stopped */
- + }
- +
- + } else {
- +
- + dmad_err("%s() ahb dma channel %d error!\n", __func__, channel);
- +
- + /* Zero out src, dst, and size */
- + outl(0, drq->src_port);
- + outl(0, drq->dst_port);
- + outl(0, drq->cyc_port);
- +
- + /* Remove all pending requests in the queue */
- + drb_iter = drb;
- + while (drb_iter) {
- +
- + dmad_err("abort drb(%d 0x%08x) addr0(0x%08x) "
- + "addr1(0x%08x) size(0x%08x)\n",
- + drb_iter->node, (u32) drb_iter,
- + drb_iter->src_addr, drb_iter->dst_addr,
- + drb_iter->req_cycle);
- +
- + if (drb_iter->req_cycle == 0)
- + cpl_events = 0;
- +
- + /* Mark DRB state as abort */
- + drb_iter->state = DMAD_DRB_STATE_ABORT;
- +
- + if (cpl_events && drb_iter->sync)
- + complete_all(drb_iter->sync);
- +
- + dmad_attach_tail(drq->drb_pool, &drq->fre_head,
- + &drq->fre_tail, drb_iter->node);
- +
- + /* Detach next submitted DRB (DMA Request Block)
- + * from the DRQ (DMA Request Queue) */
- + dmad_detach_head(drq->drb_pool, &drq->sbt_head,
- + &drq->sbt_tail, &drb_iter);
- + }
- + }
- +
- + spin_unlock(&drq->drb_pool_lock);
- +
- + /* dispatch interrupt-context level callbacks */
- + if (cpl_events && drq->completion_cb) {
- + /* signal DMA driver that new node is available */
- + drq->completion_cb(channel, tc_int, drq->completion_data);
- + }
- +
- + dmad_dbg("%s() <<\n", __func__);
- +
- + return IRQ_HANDLED;
- +}
- +
- +/**
- + * dmad_ahb_config_dir - prepare command reg according to tx direction
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @channel_cmds : [out] Reference to array of command words to be prepared with
- + * @return : none
- + *
- + * Prepare command registers according to transfer direction ...
- + * channel_cmd[0] DMAC_CSR
- + * channel_cmd[1] DMAC_CFG
- + *
- + * This function only serves as local helper. No protection wrappers.
- + */
- +static void dmad_ahb_config_dir(dmad_chreq * ch_req, addr_t * channel_cmds)
- +{
- + dmad_drq *drq = (dmad_drq *) ch_req->drq;
- + dmad_ahb_chreq *ahb_req = (dmad_ahb_chreq *) (&ch_req->ahb_req);
- +/* for amerald */
- + u32 reqn0, reqn1;
- + dmad_dbg("%s() channel_cmds(0x%08x, 0x%08x)\n",
- + __func__, channel_cmds[0], channel_cmds[1]);
- +/* for amerald */
- + if ((inl(PMU_BASE) & AMERALD_MASK) == AMERALD_PRODUCT_ID) {
- + reqn0 = ahb_req->addr0_reqn;
- + reqn1 = ahb_req->addr1_reqn;
- + } else {
- + reqn0 = ch_req->channel;
- + reqn1 = ch_req->channel;
- + }
- + channel_cmds[0] &= ~(addr_t)
- + (DMAC_CSR_SRC_WIDTH_MASK | DMAC_CSR_SRCAD_CTL_MASK |
- + DMAC_CSR_DST_WIDTH_MASK | DMAC_CSR_DSTAD_CTL_MASK |
- + DMAC_CSR_MODE_MASK);
- + channel_cmds[1] &= ~(addr_t)
- + (DMAC_CFG_INT_SRC_RS_MASK | DMAC_CFG_INT_SRC_HE_MASK |
- + DMAC_CFG_INT_DST_RS_MASK | DMAC_CFG_INT_DST_HE_MASK);
- +
- + /* 0 - addr0 to addr1; 1 - addr1 to addr0 */
- + if (ahb_req->tx_dir == 0) {
- +
- + dmad_dbg("%s() addr0 --> addr1\n", __func__);
- +
- + /* - Channel CSR
- + * DST_SEL : 0 (Master 0)
- + * SRC_SEL : 0 (Master 0)
- + * DSTAD_CTL : ahb_req->dst_ctrl
- + * SRCAD_CTL : ahb_req->src_ctrl
- + * MODE : 0 (normal)
- + * DST_WIDTH : ahb_req->dst_width
- + * SRC_WIDTH : ahb_req->src_width
- + * SRC_SIZE : 0 (burst size = 1 byte)
- + */
- + channel_cmds[0] |=
- + (((ahb_req->addr0_width << DMAC_CSR_SRC_WIDTH_SHIFT) &
- + DMAC_CSR_SRC_WIDTH_MASK) |
- + ((ahb_req->addr0_ctrl << DMAC_CSR_SRCAD_CTL_SHIFT) &
- + DMAC_CSR_SRCAD_CTL_MASK) |
- + ((ahb_req->addr1_width << DMAC_CSR_DST_WIDTH_SHIFT) &
- + DMAC_CSR_DST_WIDTH_MASK) |
- + ((ahb_req->addr1_ctrl << DMAC_CSR_DSTAD_CTL_SHIFT) &
- + DMAC_CSR_DSTAD_CTL_MASK));
- +
- + /* - Channel CFG
- + * SRC_RS : channel number (not reqn)
- + * SRC_HE : 0 if memory, 1 if device
- + * DST_RS : channel number (not reqn)
- + * DST_HE : 0 if memory, 1 if device
- + */
- + if (likely(ahb_req->hw_handshake != 0)) {
- + /* Channel CSR - Enable HW-handshake mode */
- + channel_cmds[0] |= DMAC_CSR_MODE_MASK;
- +
- + /* Channel CFG - Device REQN and HW-handshake mode */
- +#ifdef CONFIG_PLAT_AG102
- + /* AG102 fixes this bug */
- + if (ahb_req->addr0_reqn != DMAC_REQN_NONE) {
- + channel_cmds[1] |= (DMAC_CFG_INT_SRC_HE_MASK |
- + ((ahb_req->addr0_reqn <<
- + DMAC_CFG_INT_SRC_RS_SHIFT)
- + &
- + DMAC_CFG_INT_SRC_RS_MASK));
- + }
- +
- + if (ahb_req->addr1_reqn != DMAC_REQN_NONE) {
- + channel_cmds[1] |= (DMAC_CFG_INT_DST_HE_MASK |
- + ((ahb_req->addr1_reqn <<
- + DMAC_CFG_INT_DST_RS_SHIFT)
- + &
- + DMAC_CFG_INT_DST_RS_MASK));
- + }
- +#else
- + /* AG101/XC5 bug */
- +/* for amerald */
- + if (ahb_req->addr0_reqn != DMAC_REQN_NONE) {
- + channel_cmds[1] |= (DMAC_CFG_INT_SRC_HE_MASK |
- + ((reqn0 <<
- + DMAC_CFG_INT_SRC_RS_SHIFT)
- + &
- + DMAC_CFG_INT_SRC_RS_MASK));
- + }
- +
- + if (ahb_req->addr1_reqn != DMAC_REQN_NONE) {
- + channel_cmds[1] |= (DMAC_CFG_INT_DST_HE_MASK |
- + ((reqn1 <<
- + DMAC_CFG_INT_DST_RS_SHIFT)
- + &
- + DMAC_CFG_INT_DST_RS_MASK));
- + }
- +#endif
- + }
- +
- + /* update source data width for faster cycle/byte size conversion */
- + drq->data_width = ahb_req->addr0_width;
- +
- + /* remember channel transfer direction */
- + drq->flags &= ~(addr_t) DMAD_DRQ_DIR_A1_TO_A0;
- +
- + } else {
- +
- + dmad_dbg("%s() addr0 <-- addr1\n", __func__);
- +
- + /* - Channel CSR
- + * DST_SEL : 0 (Master 0)
- + * SRC_SEL : 0 (Master 0)
- + * DSTAD_CTL : ahb_req->dst_ctrl
- + * SRCAD_CTL : ahb_req->src_ctrl
- + * MODE : 0 (normal)
- + * DST_WIDTH : ahb_req->dst_width
- + * SRC_WIDTH : ahb_req->src_width
- + * SRC_SIZE : 0 (burst size = 1 byte)
- + */
- + channel_cmds[0] |=
- + (((ahb_req->addr1_width << DMAC_CSR_SRC_WIDTH_SHIFT) &
- + DMAC_CSR_SRC_WIDTH_MASK) |
- + ((ahb_req->addr1_ctrl << DMAC_CSR_SRCAD_CTL_SHIFT) &
- + DMAC_CSR_SRCAD_CTL_MASK) |
- + ((ahb_req->addr0_width << DMAC_CSR_DST_WIDTH_SHIFT) &
- + DMAC_CSR_DST_WIDTH_MASK) |
- + ((ahb_req->addr0_ctrl << DMAC_CSR_DSTAD_CTL_SHIFT) &
- + DMAC_CSR_DSTAD_CTL_MASK));
- +
- + /* - Channel CFG
- + * SRC_RS : channel number (not reqn)
- + * SRC_HE : 0 if memory, 1 if device
- + * DST_RS : channel number (not reqn)
- + * DST_HE : 0 if memory, 1 if device
- + */
- + if (likely(ahb_req->hw_handshake != 0)) {
- + /* Channel CSR - Enable HW-handshake mode */
- + channel_cmds[0] |= DMAC_CSR_MODE_MASK;
- +
- + /* Channel CFG - Device REQN and HW-handshake mode */
- +#ifdef CONFIG_PLAT_AG102
- + /* AG102 fixes this bug */
- + if (ahb_req->addr1_reqn != DMAC_REQN_NONE) {
- + channel_cmds[1] |= (DMAC_CFG_INT_SRC_HE_MASK |
- + ((ahb_req->addr1_reqn <<
- + DMAC_CFG_INT_SRC_RS_SHIFT)
- + &
- + DMAC_CFG_INT_SRC_RS_MASK));
- + }
- +
- + if (ahb_req->addr0_reqn != DMAC_REQN_NONE) {
- + channel_cmds[1] |= (DMAC_CFG_INT_DST_HE_MASK |
- + ((ahb_req->addr0_reqn <<
- + DMAC_CFG_INT_DST_RS_SHIFT)
- + &
- + DMAC_CFG_INT_DST_RS_MASK));
- + }
- +#else
- + /* AG101/XC5 bug */
- +/* for amerald */
- + if (ahb_req->addr1_reqn != DMAC_REQN_NONE) {
- + channel_cmds[1] |= (DMAC_CFG_INT_SRC_HE_MASK |
- + ((reqn1 <<
- + DMAC_CFG_INT_SRC_RS_SHIFT)
- + &
- + DMAC_CFG_INT_SRC_RS_MASK));
- + }
- +
- + if (ahb_req->addr0_reqn != DMAC_REQN_NONE) {
- + channel_cmds[1] |= (DMAC_CFG_INT_DST_HE_MASK |
- + ((reqn0 <<
- + DMAC_CFG_INT_DST_RS_SHIFT)
- + &
- + DMAC_CFG_INT_DST_RS_MASK));
- + }
- +#endif
- + }
- +
- + /* source data width */
- + drq->data_width = ahb_req->addr1_width;
- +
- + /* remember channel transfer direction */
- + drq->flags |= (addr_t) DMAD_DRQ_DIR_A1_TO_A0;
- + }
- +
- + dmad_dbg("%s() channel_cmds(0x%08x, 0x%08x)\n",
- + __func__, channel_cmds[0], channel_cmds[1]);
- +}
- +
- +/**
- + * dmad_ahb_init - initialize a ahb dma channel
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @return : 0 if success, non-zero if any error
- + *
- + * Register AHB DMA ISR and performs hw initialization for the given DMA
- + * channel.
- + */
- +static int dmad_ahb_init(dmad_chreq * ch_req)
- +{
- + int err = 0;
- + dmad_drq *drq = (dmad_drq *) ch_req->drq;
- + dmad_ahb_chreq *ahb_req = (dmad_ahb_chreq *) (&ch_req->ahb_req);
- + u32 channel = (u32) ch_req->channel;
- + addr_t channel_base = drq->channel_base;
- + addr_t channel_cmds[2]; // [0] DMAC_CSR; [1] DMAC_CFG
- + unsigned long lock_flags;
- +
- + dmad_dbg("%s()\n", __func__);
- +
- + /* register interrupt handler */
- + err = request_irq(ahb_irqs[channel], dmad_ahb_isr, 0,
- + "AHB_DMA", (void *)(channel + 1));
- + if (unlikely(err != 0)) {
- + dmad_err("unable to request IRQ %d for AHB DMA "
- + "(error %d)\n", ahb_irqs[channel], err);
- + free_irq(ahb_irqs[channel], (void *)(channel + 1));
- + return err;
- + }
- +
- + spin_lock_irqsave(&dmad.drq_pool_lock, lock_flags);
- +
- + /**********************************************************
- + * Following code require _safe_exit return path
- + */
- +
- +#ifdef CONFIG_PLAT_AG102
- + /* PCU
- + *
- + * Add by Dennis 2011.03.09
- + * set 0 to dma selection register to using AHB
- + * DMA.
- + */
- + if (ahb_req->dst_reqn == ahb_req->src_reqn) {
- + dmad_err
- + ("[dmad] invalid source reqn(%d) or destination reqn(%d)\n",
- + ahb_req->src_reqn, ahb_req->dst_reqn);
- + err = -EBADR;
- + goto _safe_exit;
- + }
- + outl(0, PCU_DMA_SEL);
- +#else /* CONFIG_PLAT_AG102 */
- +
- + /* PMU
- + *
- + * Route APB device DMA to an AHB DMAC channel and specify the channel
- + * number. (connection status could be read back from PMU_AHBDMA_REQACK
- + * register)
- + *
- + * Note: Only one device is routed per AHB DMA channel, the other target
- + * should be either (1) the same device (same reqn), or (2) the AHB
- + * device (reqn = 0).
- + */
- +
- + if (ahb_req->dst_reqn != DMAC_REQN_NONE) {
- + // DMA transfer to device
- + if ((ahb_req->dst_reqn > DMAC_REQN_MAX) ||
- + (ahb_ch_route_table[ahb_req->dst_reqn].route_cr == 0)) {
- + dmad_err("Invalid destination reqn(%d) "
- + "or route_cr(0x%08x)\n", ahb_req->dst_reqn,
- + (u32) ahb_ch_route_table[ahb_req->dst_reqn].
- + route_cr);
- + err = -EBADR;
- + goto _safe_exit;
- + }
- +
- + outl(0, ahb_ch_route_table[ahb_req->dst_reqn].clear_cr);
- + outl(PMU_DMACUSED_MASK | ((channel << PMU_CHANNEL_SHIFT) &
- + PMU_CHANNEL_MASK),
- + ahb_ch_route_table[ahb_req->dst_reqn].route_cr);
- +
- + } else if (ahb_req->src_reqn != DMAC_REQN_NONE) {
- +
- + // DMA transfer from device
- + if ((ahb_req->src_reqn > DMAC_REQN_MAX) ||
- + (ahb_ch_route_table[ahb_req->src_reqn].route_cr == 0)) {
- + dmad_err("Invalid source reqn(%d) or "
- + "route_cr(0x%08x)\n", ahb_req->src_reqn,
- + (u32) ahb_ch_route_table[ahb_req->src_reqn].
- + route_cr);
- + err = -EBADR;
- + goto _safe_exit;
- + }
- +
- + outl(0, ahb_ch_route_table[ahb_req->src_reqn].clear_cr);
- + outl(PMU_DMACUSED_MASK | ((channel << PMU_CHANNEL_SHIFT) &
- + PMU_CHANNEL_MASK),
- + ahb_ch_route_table[ahb_req->src_reqn].route_cr);
- + }
- +#endif /* CONFIG_PLAT_AG102 */
- +
- + /* DMAC (Controller Setting) */
- +
- + /* - INT TC/ERR/ABT status clear */
- + setbl(channel, DMAC_INT_TC_CLR);
- + setbl(channel + DMAC_INT_ERR_CLR_SHIFT, DMAC_INT_ERRABT_CLR);
- + setbl(channel + DMAC_INT_ABT_CLR_SHIFT, DMAC_INT_ERRABT_CLR);
- +
- + // - CSR (enable DMAC, set M0 & M1 default to little endian)
- + outl(DMAC_DMACEN_MASK |
- + ((DMAC_ENDIAN_LITTLE << DMAC_M0ENDIAN_BIT) & DMAC_M0ENDIAN_MASK) |
- + ((DMAC_ENDIAN_LITTLE << DMAC_M1ENDIAN_BIT) & DMAC_M1ENDIAN_MASK),
- + DMAC_CSR);
- +
- + /* DMAC (Channel-Specific Setting) */
- + /* - SYNC */
- + if (ahb_req->sync)
- + setbl(channel, DMAC_SYNC);
- + else
- + clrbl(channel, DMAC_SYNC);
- +
- + /* - Channel CSR
- + * CH_EN : 0 (disable)
- + * DST_SEL : 0 (Master 0)
- + * SRC_SEL : 0 (Master 0)
- + * DSTAD_CTL : ahb_req->dst_ctrl
- + * SRCAD_CTL : ahb_req->src_ctrl
- + * MODE : 0 (normal)
- + * DST_WIDTH : ahb_req->dst_width
- + * SRC_WIDTH : ahb_req->src_width
- + * ABT : 0 (not abort)
- + * SRC_SIZE : 0 (burst size = 1 byte)
- + * PROT1 : 0 (user mode)
- + * PROT2 : 0 (bot bufferable)
- + * PROT3 : 0 (not cacheable)
- + * CHPRI : ahb_req->priority
- + * DMA_FF_TH : 0 (FIA320 only, threshold = 1)
- + * TC_MSK : 0 (TC counter status enable)
- + */
- + channel_cmds[0] = (ahb_req->priority << DMAC_CSR_CHPRI_SHIFT) &
- + DMAC_CSR_CHPRI_MASK;
- + channel_cmds[0] |= (ahb_req->burst_size << DMAC_CSR_SRC_SIZE_SHIFT) &
- + DMAC_CSR_SRC_SIZE_MASK;
- +
- + // - Channel CFG
- + // INT_TC_MSK : 0 (enable TC int)
- + // INT_ERR_MSK : 0 (enable ERR int)
- + // INT_ABT_MSK : 0 (enable ABT int)
- + // SRC_RS : 0
- + // SRC_HE : 0
- + // BUSY : r/o
- + // DST_RS : 0
- + // DST_HE : 0
- + // LLP_CNT : r/o
- + channel_cmds[1] = 0;
- +
- + if (0 ==
- + (ch_req->flags & (DMAD_FLAGS_RING_MODE | DMAD_FLAGS_BIDIRECTION)))
- + ahb_req->tx_dir = 0;
- +
- + dmad_ahb_config_dir(ch_req, channel_cmds);
- +
- + outl(channel_cmds[0], channel_base + DMAC_CSR_OFFSET);
- + outl(channel_cmds[1], channel_base + DMAC_CFG_OFFSET);
- +
- + /* SRCADR and DESADR */
- + outl(0, (addr_t) drq->src_port);
- + outl(0, (addr_t) drq->dst_port);
- +
- + /* CYC (transfer size) */
- + outl(0, (addr_t) drq->cyc_port);
- +
- + /* LLP */
- + outl(0, channel_base + DMAC_LLP_OFFSET);
- +
- + /* TOT_SIZE - not now */
- +
- +_safe_exit:
- +
- + spin_unlock_irqrestore(&dmad.drq_pool_lock, lock_flags);
- +
- + return err;
- +}
- +
- +#endif /* CONFIG_PLATFORM_AHBDMA */
- +
- +#ifdef CONFIG_PLATFORM_APBDMA
- +
- +/**
- + * dmad_apb_isr - APB DMA interrupt service routine
- + *
- + * @irq : [in] The irq number
- + * @dev_id : [in] The identifier to identify the asserted channel
- + *
- + * This is the ISR that services all APB DMA channels.
- + */
- +static irqreturn_t dmad_apb_isr(int irq, void *dev_id)
- +{
- + dmad_drq *drq;
- + dmad_drb *drb, *drb_iter;
- + u32 channel = ((u32) dev_id) - 1;
- + u32 status;
- + u8 finish_int = 0;
- + u8 err_int = 0;
- + u8 cpl_events = 1;
- +
- + dmad_dbg("%s() >> channel(%d)\n", __func__, channel);
- +
- + if (channel >= DMAD_APB_MAX_CHANNELS) {
- + dmad_err("%s() invlaid channel number: %d!\n",
- + __func__, channel);
- + return IRQ_HANDLED;
- + }
- +
- + /* Lookup channel's DRQ (DMA Request Queue) */
- + drq = (dmad_drq *) & dmad.apb_drq_pool[channel];
- +
- + /* - Check DMA status register to get channel number */
- + status = inl((addr_t) drq->channel_base + APBBR_DMA_CMD_OFFSET);
- +
- + if (likely(status & APBBR_DMA_FINTST_MASK)) {
- +
- + /*dmad_dbg("apb dma int status: finish (0x%08x)\n", status); */
- + finish_int = 1;
- +
- + /* APB DMA finish int status clear */
- + clrbl(APBBR_DMA_FINTST_BIT,
- + (addr_t) drq->channel_base + APBBR_DMA_CMD_OFFSET);
- +
- + } else if (status & APBBR_DMA_ERRINTST_MASK) {
- +
- + /* Perform DMA error checking if no valid channel was found
- + * who assert the finish signal. */
- + dmad_err("apb dma int status: err (0x%08x)\n", status);
- +
- + /* Mark as error int */
- + err_int = 1;
- +
- + /* APB DMA error int status clear */
- + clrbl(APBBR_DMA_ERRINTST_BIT,
- + (addr_t) drq->channel_base + APBBR_DMA_CMD_OFFSET);
- +
- + } else {
- +
- + dmad_err("%s() possible false-fired apb dma int,"
- + " channel %d status-reg: 0x%08x\n",
- + __func__, channel, status);
- +
- + /* Stop DMA channel (make sure the channel will be stopped) */
- + clrbl(APBBR_DMA_CHEN_BIT,
- + (addr_t) drq->channel_base + APBBR_DMA_CMD_OFFSET);
- +
- + return IRQ_HANDLED;
- + }
- +
- + /* Stop DMA channel (make sure the channel will be stopped) */
- + dmad_disable_channel(drq);
- +
- + spin_lock(&drq->drb_pool_lock);
- +
- + /* Lookup/detach latest submitted DRB (DMA Request Block) from */
- + /* the DRQ (DMA Request Queue), so ISR could kick off next DRB */
- + dmad_detach_head(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail, &drb);
- +
- + if (unlikely(drb == NULL)) {
- + spin_unlock(&drq->drb_pool_lock);
- + return IRQ_HANDLED;
- + }
- +
- + /* release blocking of drb-allocation, if any ... */
- + if (unlikely((drq->fre_head == 0) &&
- + (drq->flags & DMAD_FLAGS_SLEEP_BLOCK))) {
- + complete_all(&drq->drb_alloc_sync);
- + }
- +
- + /* Process DRBs according to the cause of this interrupt */
- + if (likely(finish_int)) {
- +
- + if (drb->req_cycle == 0)
- + cpl_events = 0;
- +
- + /* Mark DRB state as completed */
- + drb->state = DMAD_DRB_STATE_COMPLETED;
- + if (cpl_events && drb->sync)
- + complete_all(drb->sync);
- +
- + dmad_attach_tail(drq->drb_pool, &drq->fre_head,
- + &drq->fre_tail, drb->node);
- +
- + /* Check whether there are pending requests in the DRQ */
- + if (drq->sbt_head != 0) {
- +
- + /* Lookup next DRB (DMA Request Block) */
- + drb_iter = &drq->drb_pool[drq->sbt_head];
- +
- + dmad_dbg("exec drb(%d 0x%08x) addr0(0x%08x) "
- + "addr1(0x%08x) size(0x%08x)\n",
- + drb_iter->node, (u32) drb_iter,
- + drb_iter->src_addr, drb_iter->dst_addr,
- + drb_iter->req_cycle);
- +
- + /* Kick-off DMA for next DRB */
- + /* - Source and destination address */
- + if (drq->flags & DMAD_DRQ_DIR_A1_TO_A0) {
- + outl(drb_iter->addr1, drq->src_port);
- + outl(drb_iter->addr0, drq->dst_port);
- + } else {
- + outl(drb_iter->addr0, drq->src_port);
- + outl(drb_iter->addr1, drq->dst_port);
- + }
- +
- + /* - Transfer size (in units of source width) */
- + outl(drb_iter->req_cycle, drq->cyc_port);
- +
- + /* Kick off next request */
- + dmad_enable_channel(drq);
- +
- + drb_iter->state = DMAD_DRB_STATE_EXECUTED;
- +
- + } else {
- + /* No pending requests, keep the DMA channel stopped */
- + }
- +
- + } else if (err_int) {
- +
- + dmad_err("%s() apb dma channel %d error!\n", __func__, channel);
- +
- + /* Zero out src, dst, and size */
- + outl(0, drq->src_port);
- + outl(0, drq->dst_port);
- + outl(0, drq->cyc_port);
- +
- + /* Remove all pending requests in the queue */
- + drb_iter = drb;
- + while (drb_iter) {
- +
- + dmad_err("abort drb(%d 0x%08x) addr0(0x%08x) "
- + "addr1(0x%08x) size(0x%08x)\n",
- + drb_iter->node, (u32) drb_iter,
- + drb_iter->src_addr, drb_iter->dst_addr,
- + drb_iter->req_cycle);
- +
- + if (drb_iter->req_cycle == 0)
- + cpl_events = 0;
- +
- + /* Mark DRB state as abort */
- + drb_iter->state = DMAD_DRB_STATE_ABORT;
- +
- + if (cpl_events && drb_iter->sync)
- + complete_all(drb_iter->sync);
- +
- + dmad_attach_tail(drq->drb_pool, &drq->fre_head,
- + &drq->fre_tail, drb_iter->node);
- +
- + dmad_detach_head(drq->drb_pool, &drq->sbt_head,
- + &drq->sbt_tail, &drb_iter);
- + }
- + }
- +
- + spin_unlock(&drq->drb_pool_lock);
- +
- + /* dispatch interrupt-context level callbacks */
- + if (cpl_events && drq->completion_cb) {
- + /* signal DMA driver that new node is available */
- + drq->completion_cb(channel, status, drq->completion_data);
- + }
- +
- + dmad_dbg("%s() <<\n", __func__);
- +
- + return IRQ_HANDLED;
- +}
- +
- +/**
- + * dmad_apb_config_dir - prepare command reg according to tx direction
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @channel_cmds : [out] Reference to array of command words to be prepared with
- + * @return : none
- + *
- + * Prepare command registers according to transfer direction ...
- + * channel_cmd[0] APBBR_DMA_CMD
- + *
- + * This function only serves as local helper. No protection wrappers.
- + */
- +static void dmad_apb_config_dir(dmad_chreq * ch_req, addr_t * channel_cmds)
- +{
- + dmad_drq *drq = (dmad_drq *) ch_req->drq;
- + dmad_apb_chreq *apb_req = (dmad_apb_chreq *) (&ch_req->apb_req);
- +
- + dmad_dbg("%s() channel_cmd(0x%08x)\n", __func__, channel_cmds[0]);
- +
- + *channel_cmds &= ~(addr_t)
- + (APBBR_DMA_SRCADDRINC_MASK | APBBR_DMA_DSTADDRINC_MASK |
- + APBBR_DMA_DSTADDRSEL_MASK | APBBR_DMA_DREQSEL_MASK |
- + APBBR_DMA_SRCADDRSEL_MASK | APBBR_DMA_SREQSEL_MASK);
- +
- + /* 0 - addr0 to addr1; 1 - addr1 to addr0 */
- + if (apb_req->tx_dir == 0) {
- +
- + dmad_dbg("%s() addr0 --> addr1\n", __func__);
- +
- + /* APB Bridge DMA (Channel Setting)
- + * - CMD
- + * SRCADR : apb_req->src_ctrl
- + * DESADR : apb_req->dst_ctrl
- + */
- + *channel_cmds |=
- + (((apb_req->addr0_ctrl << APBBR_DMA_SRCADDRINC_SHIFT) &
- + APBBR_DMA_SRCADDRINC_MASK) |
- + ((apb_req->addr1_ctrl << APBBR_DMA_DSTADDRINC_SHIFT) &
- + APBBR_DMA_DSTADDRINC_MASK));
- +
- + /* - CMD
- + * DESADRSEL : AHB/APB, driver auto-conf
- + * DREQSEL
- + */
- + *channel_cmds |=
- + ((addr_t) (APBBR_DMA_DSTADDRSEL_MASK &
- + (apb_reqn_route_table[apb_req->addr1_reqn].
- + bus_sel << APBBR_DMA_DSTADDRSEL_BIT)) |
- + (((addr_t) apb_req->
- + addr1_reqn << APBBR_DMA_DREQSEL_SHIFT) &
- + APBBR_DMA_DREQSEL_MASK));
- +
- + /* - CMD
- + * SRCADRSEL : AHB/APB, driver auto-conf
- + * SREQSEL
- + */
- + *channel_cmds |=
- + ((addr_t) (APBBR_DMA_SRCADDRSEL_MASK &
- + (apb_reqn_route_table[apb_req->addr0_reqn].
- + bus_sel << APBBR_DMA_SRCADDRSEL_BIT)) |
- + (((addr_t) apb_req->
- + addr0_reqn << APBBR_DMA_SREQSEL_SHIFT) &
- + APBBR_DMA_SREQSEL_MASK));
- +
- + drq->flags &= ~(addr_t) DMAD_DRQ_DIR_A1_TO_A0;
- +
- + } else {
- +
- + dmad_dbg("%s() addr0 <-- addr1\n", __func__);
- +
- + /* APB Bridge DMA (Channel Setting)
- + * - CMD
- + * SRCADR : apb_req->src_ctrl
- + * DESADR : apb_req->dst_ctrl
- + */
- + *channel_cmds |=
- + (((apb_req->addr1_ctrl << APBBR_DMA_SRCADDRINC_SHIFT) &
- + APBBR_DMA_SRCADDRINC_MASK) |
- + ((apb_req->addr0_ctrl << APBBR_DMA_DSTADDRINC_SHIFT) &
- + APBBR_DMA_DSTADDRINC_MASK));
- +
- + /* - CMD
- + * DESADRSEL : AHB/APB, driver auto-conf
- + * DREQSEL
- + */
- + *channel_cmds |= ((addr_t) (APBBR_DMA_DSTADDRSEL_MASK &
- + (apb_reqn_route_table
- + [apb_req->addr0_reqn].
- + bus_sel <<
- + APBBR_DMA_DSTADDRSEL_BIT)) |
- + (((addr_t) apb_req->
- + addr0_reqn << APBBR_DMA_DREQSEL_SHIFT) &
- + APBBR_DMA_DREQSEL_MASK));
- +
- + /* - CMD
- + * SRCADRSEL : AHB/APB, driver auto-conf
- + * SREQSEL
- + */
- + *channel_cmds |= ((addr_t) (APBBR_DMA_SRCADDRSEL_MASK &
- + (apb_reqn_route_table
- + [apb_req->addr1_reqn].
- + bus_sel <<
- + APBBR_DMA_SRCADDRSEL_BIT)) |
- + (((addr_t) apb_req->
- + addr1_reqn << APBBR_DMA_SREQSEL_SHIFT) &
- + APBBR_DMA_SREQSEL_MASK));
- +
- + drq->flags |= (addr_t) DMAD_DRQ_DIR_A1_TO_A0;
- + }
- +
- + dmad_dbg("%s() channel_cmd(0x%08x)\n", __func__, channel_cmds[0]);
- +}
- +
- +/**
- + * dmad_apb_init - initialize a apb dma channel
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @return : 0 if success, non-zero if any error
- + *
- + * Register APB DMA ISR and performs hw initialization for the given DMA
- + * channel.
- + */
- +static int dmad_apb_init(dmad_chreq * ch_req)
- +{
- + int err = 0;
- + dmad_drq *drq = (dmad_drq *) ch_req->drq;
- + dmad_apb_chreq *apb_req = (dmad_apb_chreq *) (&ch_req->apb_req);
- + u32 channel = (u32) ch_req->channel;
- + addr_t channel_cmd = 0;
- + unsigned long lock_flags;
- +
- + dmad_dbg("%s()\n", __func__);
- +
- + /* register interrupt handler */
- + err = request_irq(apb_irqs[channel], dmad_apb_isr, 0,
- + "APB_DMA", (void *)(channel + 1));
- + if (unlikely(err != 0)) {
- + dmad_err("unable to request IRQ %d for APB DMA (error %d)\n",
- + apb_irqs[channel], err);
- + free_irq(apb_irqs[channel], (void *)(channel + 1));
- + return err;
- + }
- +
- + spin_lock_irqsave(&dmad.drq_pool_lock, lock_flags);
- +
- + /**********************************************************
- + * Following code require _safe_exit return path
- + */
- +
- +#ifdef CONFIG_PLAT_AG102
- +
- + /* PCU
- + *
- + */
- + //ADD by river 2010.10.20
- + if (unlikely((apb_req->src_reqn > APBBR_REQN_MAX) ||
- + (apb_req->dst_reqn > APBBR_REQN_MAX))) {
- + dmad_err("Invalid source reqn(%d) or destination reqn(%d)\n",
- + apb_req->src_reqn, apb_req->dst_reqn);
- + err = -EBADR;
- + goto _safe_exit;
- + }
- +
- + if (apb_req->src_reqn != APBBR_REQN_NONE) {
- + u32 ahb_reqn;
- +
- + if (apb_req->tx_dir == DMAD_DIR_A0_TO_A1)
- + ahb_reqn =
- + apb_reqn_route_table[apb_req->src_reqn].ahb_reqn_tx;
- + else
- + ahb_reqn =
- + apb_reqn_route_table[apb_req->src_reqn].ahb_reqn_rx;
- +
- + }
- +
- + if (apb_req->dst_reqn != APBBR_REQN_NONE) {
- + u32 ahb_reqn;
- +
- + if (apb_req->tx_dir == DMAD_DIR_A0_TO_A1)
- + ahb_reqn =
- + apb_reqn_route_table[apb_req->dst_reqn].ahb_reqn_tx;
- + else
- + ahb_reqn =
- + apb_reqn_route_table[apb_req->dst_reqn].ahb_reqn_rx;
- +
- + }
- + //End ADD by river 2010.10.20
- +
- +#else /* CONFIG_PLAT_AG102 */
- +
- + /* PMU
- + * - Undo APB device DMA to AHB DMAC channel routing. (connection status
- + * is obtained from reading back the PMU_AHBDMA_REQACK register)
- + */
- + if (unlikely((apb_req->src_reqn > APBBR_REQN_MAX) ||
- + (apb_req->dst_reqn > APBBR_REQN_MAX))) {
- + dmad_err("Invalid source reqn(%d) or destination reqn(%d)\n",
- + apb_req->src_reqn, apb_req->dst_reqn);
- + err = -EBADR;
- + goto _safe_exit;
- + }
- +
- + if (apb_req->src_reqn != APBBR_REQN_NONE) {
- + u32 ahb_reqn;
- +
- + if (apb_req->tx_dir == DMAD_DIR_A0_TO_A1)
- + ahb_reqn =
- + apb_reqn_route_table[apb_req->src_reqn].ahb_reqn_tx;
- + else
- + ahb_reqn =
- + apb_reqn_route_table[apb_req->src_reqn].ahb_reqn_rx;
- +
- + outl(0, ahb_ch_route_table[ahb_reqn].clear_cr);
- + outl(0, ahb_ch_route_table[ahb_reqn].route_cr);
- + outl(0, ahb_ch_route_table[ahb_reqn].clear_cr);
- + outl(0, ahb_ch_route_table[ahb_reqn].route_cr);
- + }
- +
- + if (apb_req->dst_reqn != APBBR_REQN_NONE) {
- + u32 ahb_reqn;
- +
- + if (apb_req->tx_dir == DMAD_DIR_A0_TO_A1)
- + ahb_reqn =
- + apb_reqn_route_table[apb_req->dst_reqn].ahb_reqn_tx;
- + else
- + ahb_reqn =
- + apb_reqn_route_table[apb_req->dst_reqn].ahb_reqn_rx;
- +
- + outl(0, ahb_ch_route_table[ahb_reqn].clear_cr);
- + outl(0, ahb_ch_route_table[ahb_reqn].route_cr);
- + outl(0, ahb_ch_route_table[ahb_reqn].clear_cr);
- + outl(0, ahb_ch_route_table[ahb_reqn].route_cr);
- + }
- +#endif /* CONFIG_PLAT_AG102 */
- +
- + /* APB Bridge DMA (Channel Setting)
- + * - CMD
- + * ENBDIS : 0 (disable for now)
- + * FININTSTS : 0 (clear finishing interrupt status)
- + * FININTENB : 1 (enable finishing interrupt)
- + * BURMOD : apb_req->burst_mode
- + * ERRINTSTS : 0 (clear error interrupt status)
- + * ERRINTENB : 1 (enable error interrupt)
- + * SRCADRSEL : AHB/APB, driver auto-conf
- + * DESADRSEL : AHB/APB, driver auto-conf
- + * SRCADR : apb_req->src_ctrl
- + * DESADR : apb_req->dst_ctrl
- + * REQSEL : apb_req->src_reqn
- + * DATAWIDTH : apb_req->data_width
- + */
- +
- + /* - CMD
- + * ENBDIS
- + * FININTSTS
- + * FININTENB
- + * BURMOD
- + * ERRINTSTS
- + * ERRINTENB
- + * DATAWIDTH
- + */
- + channel_cmd =
- + ((addr_t) APBBR_DMA_FINTEN_MASK | APBBR_DMA_ERRINTEN_MASK |
- + ((apb_req->
- + burst_mode << APBBR_DMA_BURST_BIT) & APBBR_DMA_BURST_MASK) |
- + ((apb_req->
- + data_width << APBBR_DMA_DATAWIDTH_SHIFT) &
- + APBBR_DMA_DATAWIDTH_MASK));
- +
- + /* - CMD
- + * SRCADRSEL
- + * DESADRSEL
- + * SRCADR
- + * DESADR
- + * REQSEL
- + */
- + if (0 ==
- + (ch_req->flags & (DMAD_FLAGS_RING_MODE | DMAD_FLAGS_BIDIRECTION)))
- + apb_req->tx_dir = 0;
- + dmad_apb_config_dir(ch_req, &channel_cmd);
- +
- + /* - CMD outport */
- + outl(channel_cmd, (addr_t) drq->channel_base + APBBR_DMA_CMD_OFFSET);
- +
- + /* SRCADR and DESADR */
- + outl(0, (addr_t) drq->src_port);
- + outl(0, (addr_t) drq->dst_port);
- +
- + /* CYC (transfer size) */
- + outl(0, (addr_t) drq->cyc_port);
- +
- + /* keep channel data width for faster cycle/byte size conversion */
- + drq->data_width = apb_req->data_width;
- +
- +_safe_exit:
- +
- + spin_unlock_irqrestore(&dmad.drq_pool_lock, lock_flags);
- +
- + return err;
- +}
- +
- +#endif /* CONFIG_PLATFORM_APBDMA */
- +
- +/**
- + * dmad_channel_init - initialize given dma channel
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @return : 0 if success, non-zero if any error
- + *
- + * This function serves as the abstraction layer of dmad_ahb_init()
- + * and dmad_apb_init() functions.
- + */
- +static int dmad_channel_init(dmad_chreq * ch_req)
- +{
- + int err = 0;
- +
- + dmad_dbg("%s()\n", __func__);
- +
- + if (unlikely(ch_req == NULL))
- + return -EFAULT;
- +
- + if (unlikely(ch_req->drq == NULL))
- + return -EBADR;
- +
- + /* Initialize DMA controller */
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + if (ch_req->controller == DMAD_DMAC_AHB_CORE)
- + err = dmad_ahb_init(ch_req);
- +#endif
- +#ifdef CONFIG_PLATFORM_APBDMA
- + if (ch_req->controller == DMAD_DMAC_APB_CORE)
- + err = dmad_apb_init(ch_req);
- +#endif
- +
- + return err;
- +}
- +
- +static inline void dmad_reset_channel(dmad_drq * drq)
- +{
- + /* disable dma controller */
- + dmad_disable_channel(drq);
- +
- + /* Source and destination address */
- + outl(0, drq->src_port);
- + outl(0, drq->dst_port);
- +
- + /* Transfer size (in units of source width) */
- + outl(0, drq->cyc_port);
- +}
- +
- +/**
- + * dmad_channel_reset - reset given dma channel
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @return : 0 if success, non-zero if any error
- + *
- + * This function serves as the abstraction layer of dmad_ahb_reset()
- + * and dmad_apb_reset() functions.
- + */
- +static int dmad_channel_reset(dmad_chreq * ch_req)
- +{
- + u32 channel = (u32) ch_req->channel;
- + unsigned long lock_flags;
- + int err = 0;
- +
- + dmad_dbg("%s()\n", __func__);
- +
- + if (unlikely(ch_req == NULL))
- + return -EFAULT;
- +
- + if (unlikely(ch_req->drq == NULL))
- + return -EBADR;
- +
- + spin_lock_irqsave(&((dmad_drq *) ch_req->drq)->drb_pool_lock,
- + lock_flags);
- +
- + /* stop DMA channel */
- + dmad_reset_channel((dmad_drq *) ch_req->drq);
- +
- + spin_unlock_irqrestore(&((dmad_drq *) ch_req->drq)->drb_pool_lock,
- + lock_flags);
- +
- + /* unregister interrupt handler */
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + if (ch_req->controller == DMAD_DMAC_AHB_CORE)
- + free_irq(ahb_irqs[channel], (void *)(channel + 1));
- +#endif
- +#ifdef CONFIG_PLATFORM_APBDMA
- + if (ch_req->controller == DMAD_DMAC_APB_CORE)
- + free_irq(apb_irqs[channel], (void *)(channel + 1));
- +#endif
- +
- + return err;
- +}
- +
- +/**
- + * dmad_channel_alloc - allocates and initialize a dma channel
- + * @ch_req : [in/out] Reference to the DMA request descriptor structure
- + * @return : 0 if success, non-zero if any error
- + *
- + * This function allocates a DMA channel according to client's request
- + * parameters. ISR and HW state will also be initialized accordingly.
- + */
- +int dmad_channel_alloc(dmad_chreq * ch_req)
- +{
- + dmad_drq *drq_iter = NULL;
- + dmad_drb *drb_iter;
- + int err = 0;
- + u32 i = 0;
- +
- + dmad_dbg("%s()\n", __func__);
- +
- + if (ch_req == NULL) {
- + printk(KERN_ERR "%s() invalid argument!\n", __func__);
- + return -EFAULT;
- + }
- +
- + spin_lock(&dmad.drq_pool_lock);
- +
- + /* locate an available DMA channel */
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + if (ch_req->controller == DMAD_DMAC_AHB_CORE) {
- +
- + drq_iter = dmad.ahb_drq_pool;
- +
- + if ((ch_req->ahb_req.src_reqn != DMAC_REQN_NONE) ||
- + (ch_req->ahb_req.dst_reqn != DMAC_REQN_NONE)) {
- + /* [2007-12-03] It looks current board have problem to
- + * do dma traffic for APB devices on DMAC channel 0/1.
- + * Redirect all APB devices to start from channel 2.
- + */
- +
- + /* [todo] include USB controller ? */
- + drq_iter = &dmad.ahb_drq_pool[2];
- + for (i = 2; i < DMAD_AHB_MAX_CHANNELS; ++i, ++drq_iter) {
- + if (!(drq_iter->state & DMAD_DRQ_STATE_READY))
- + break;
- + }
- + } else {
- + /* channel for other devices is free to allocate */
- + for (i = 0; i < DMAD_AHB_MAX_CHANNELS; ++i, ++drq_iter) {
- + if (!(drq_iter->state & DMAD_DRQ_STATE_READY))
- + break;
- + }
- + }
- +
- + if (unlikely(i == DMAD_AHB_MAX_CHANNELS)) {
- + spin_unlock(&dmad.drq_pool_lock);
- + dmad_err("out of available channels (AHB DMAC)!\n");
- + return -ENOSPC;
- + }
- +
- + dmad_dbg("allocated channel: %d (AHB DMAC)\n", i);
- +
- + }
- +#endif
- +#ifdef CONFIG_PLATFORM_APBDMA
- + if (ch_req->controller == DMAD_DMAC_APB_CORE) {
- +
- + drq_iter = dmad.apb_drq_pool;
- +
- + for (i = 0; i < DMAD_APB_MAX_CHANNELS; ++i, ++drq_iter) {
- + if ((drq_iter->state & DMAD_DRQ_STATE_READY) == 0)
- + break;
- + }
- +
- + if (unlikely(i == DMAD_APB_MAX_CHANNELS)) {
- + spin_unlock(&dmad.drq_pool_lock);
- + dmad_err("out of available channels (APB DMAC)!\n");
- + return -ENOSPC;
- + }
- +
- + dmad_dbg("allocated channel: %d (APB DMAC)\n", i);
- + }
- +#endif
- + if (drq_iter == NULL) {
- + spin_unlock(&dmad.drq_pool_lock);
- + printk(KERN_ERR "%s() invalid argument!\n", __func__);
- + return -EFAULT;
- + }
- +
- + spin_unlock(&dmad.drq_pool_lock);
- + memset(drq_iter, 0, sizeof(dmad_drq));
- +
- + /* Initialize DMA channel's DRB pool as list of free DRBs */
- + drq_iter->drb_pool =
- + kmalloc(DMAD_DRB_POOL_SIZE * sizeof(dmad_drb), GFP_ATOMIC);
- +
- + if (drq_iter->drb_pool == NULL) {
- + printk(KERN_ERR "%s() failed to allocate drb pool!\n",
- + __func__);
- + return -ENOMEM;
- + }
- +
- + /* Allocate the DMA channel */
- + drq_iter->state = DMAD_DRQ_STATE_READY;
- + drq_iter->flags = ch_req->flags;
- +
- + /* Initialize synchronization object for DMA queue access control */
- + spin_lock_init(&drq_iter->drb_pool_lock);
- +
- + /* Initialize synchronization object for free drb notification */
- + init_completion(&drq_iter->drb_alloc_sync);
- +
- + /* Record the channel number in client's struct */
- + ch_req->channel = i;
- +
- + /* Record the channel's queue handle in client's struct */
- + ch_req->drq = drq_iter;
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + if (ch_req->controller == DMAD_DMAC_AHB_CORE) {
- + drq_iter->channel_base = (addr_t) DMAC_BASE_CH(i);
- + drq_iter->enable_port =
- + (addr_t) drq_iter->channel_base + DMAC_CSR_OFFSET;
- + drq_iter->src_port =
- + (addr_t) drq_iter->channel_base + DMAC_SRC_ADDR_OFFSET;
- + drq_iter->dst_port =
- + (addr_t) drq_iter->channel_base + DMAC_DST_ADDR_OFFSET;
- + drq_iter->cyc_port =
- + (addr_t) drq_iter->channel_base + DMAC_SIZE_OFFSET;
- + }
- +#endif
- +#ifdef CONFIG_PLATFORM_APBDMA
- + if (ch_req->controller == DMAD_DMAC_APB_CORE) {
- + drq_iter->channel_base = (addr_t) APBBR_DMA_BASE_CH(i);
- + drq_iter->enable_port =
- + (addr_t) drq_iter->channel_base + APBBR_DMA_CMD_OFFSET;
- + drq_iter->src_port =
- + (addr_t) drq_iter->channel_base + APBBR_DMA_SAD_OFFSET;
- + drq_iter->dst_port =
- + (addr_t) drq_iter->channel_base + APBBR_DMA_DAD_OFFSET;
- + drq_iter->cyc_port =
- + (addr_t) drq_iter->channel_base + APBBR_DMA_CYC_OFFSET;
- + }
- +#endif
- + /* drb-0 is an invalid node - for node validation */
- + drb_iter = &drq_iter->drb_pool[0];
- + drb_iter->prev = 0;
- + drb_iter->next = 0;
- + drb_iter->node = 0;
- + ++drb_iter;
- +
- + /* init other drbs - link in order */
- + for (i = 1; i < DMAD_DRB_POOL_SIZE; ++i, ++drb_iter) {
- + drb_iter->prev = i - 1;
- + drb_iter->next = i + 1;
- + drb_iter->node = i;
- + }
- + drq_iter->drb_pool[DMAD_DRB_POOL_SIZE - 1].next = 0;
- +
- + /* Initialize channel's DRB free-list, ready-list, and submitted-list */
- + drq_iter->fre_head = 1;
- + drq_iter->fre_tail = DMAD_DRB_POOL_SIZE - 1;
- + drq_iter->rdy_head = drq_iter->rdy_tail = 0;
- + drq_iter->sbt_head = drq_iter->sbt_tail = 0;
- +
- + /* initialize ring buffer mode resources */
- + if (ch_req->flags & DMAD_FLAGS_RING_MODE) {
- +
- + int remnant = (int)ch_req->ring_size -
- + (int)ch_req->periods * (int)ch_req->period_size;
- + if (remnant == 0) {
- + drq_iter->periods = ch_req->periods;
- + } else if (remnant > 0) {
- + drq_iter->periods = ch_req->periods; // + 1;
- + } else {
- + dmad_err("%s() Error - buffer_size < "
- + "periods * period_size!\n", __func__);
- + err = -EFAULT;
- + goto _err_exit;
- + }
- +
- + drq_iter->ring_size = ch_req->ring_size;
- + drq_iter->period_size = ch_req->period_size;
- + drq_iter->remnant_size = (dma_addr_t) remnant;
- +
- + drq_iter->ring_base = (dma_addr_t) ch_req->ring_base;
- + drq_iter->dev_addr = (dma_addr_t) ch_req->dev_addr;
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + if (ch_req->controller == DMAD_DMAC_AHB_CORE) {
- + if ((ch_req->ahb_req.ring_ctrl == DMAC_CSR_AD_DEC) ||
- + (ch_req->ahb_req.dev_ctrl == DMAC_CSR_AD_DEC)) {
- + dmad_err("%s() Error - decremental"
- + " addressing DMA is not supported in"
- + " ring mode currently!\n", __func__);
- + err = -EFAULT;
- + goto _err_exit;
- + }
- +
- + if (ch_req->ahb_req.ring_ctrl == DMAC_CSR_AD_FIX) {
- + dmad_err("%s() Error - ring address control is "
- + "fixed in ring DMA mode!\n", __func__);
- + err = -EFAULT;
- + goto _err_exit;
- + }
- +
- + drq_iter->period_bytes =
- + DMAC_CYCLE_TO_BYTES(ch_req->period_size,
- + ch_req->ahb_req.ring_width);
- +
- + /* 0 - addr0 to addr1; 1 - addr1 to addr0 */
- + if (ch_req->ahb_req.tx_dir == 0)
- + drq_iter->ring_port =
- + (addr_t) drq_iter->src_port;
- + else
- + drq_iter->ring_port =
- + (addr_t) drq_iter->dst_port;
- +
- + }
- +#endif
- +#ifdef CONFIG_PLATFORM_APBDMA
- + if (ch_req->controller == DMAD_DMAC_APB_CORE) {
- +
- + if ((ch_req->apb_req.ring_ctrl >= APBBR_ADDRINC_D1) ||
- + (ch_req->apb_req.dev_ctrl >= APBBR_ADDRINC_D1)) {
- + dmad_err("%s() Error - decremental"
- + " addressing DMA is not supported in"
- + " ring mode currently!\n", __func__);
- + err = -EFAULT;
- + goto _err_exit;
- + }
- +
- + if (ch_req->apb_req.ring_ctrl == APBBR_ADDRINC_FIXED) {
- + dmad_err("%s() Error - ring address control is "
- + "fixed in ring DMA mode!\n", __func__);
- + err = -EFAULT;
- + goto _err_exit;
- + }
- +
- + drq_iter->period_bytes =
- + APBBR_DMA_CYCLE_TO_BYTES(ch_req->period_size,
- + ch_req->apb_req.
- + data_width);
- +
- + /* 0 - addr0 to addr1; 1 - addr1 to addr0 */
- + if (ch_req->apb_req.tx_dir == 0)
- + drq_iter->ring_port =
- + (addr_t) drq_iter->src_port;
- + else
- + drq_iter->ring_port =
- + (addr_t) drq_iter->dst_port;
- + }
- +#endif
- + dmad_dbg("%s() ring: base(0x%08x) port(0x%08x) periods(0x%08x)"
- + " period_size(0x%08x) period_bytes(0x%08x)"
- + " remnant_size(0x%08x)\n",
- + __func__, drq_iter->ring_base, drq_iter->ring_port,
- + drq_iter->periods, drq_iter->period_size,
- + drq_iter->period_bytes, drq_iter->remnant_size);
- + }
- +
- + drq_iter->completion_cb = ch_req->completion_cb;
- + drq_iter->completion_data = ch_req->completion_data;
- +
- + /* Initialize the channel && register isr */
- + err = dmad_channel_init(ch_req);
- +
- +_err_exit:
- +
- + if (err != 0) {
- + spin_lock(&dmad.drq_pool_lock);
- +
- + kfree(drq_iter->drb_pool);
- + memset(drq_iter, 0, sizeof(dmad_drq));
- +
- + ch_req->channel = -1;
- + ch_req->drq = (void *)0;
- +
- + spin_unlock(&dmad.drq_pool_lock);
- +
- + dmad_err("Failed to initialize APB DMA! "
- + "Channel allocation aborted!\n");
- + }
- +
- + return err;
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_channel_alloc);
- +
- +/**
- + * dmad_channel_free - release a dma channel
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @return : 0 if success, non-zero if any error
- + *
- + * This function releases a DMA channel. The channel is available for future
- + * allocation after the invokation.
- + */
- +int dmad_channel_free(dmad_chreq * ch_req)
- +{
- + dmad_drq *drq;
- +
- + dmad_dbg("%s()\n", __func__);
- +
- + if (unlikely(ch_req == NULL)) {
- + dmad_err("null ch_req!\n");
- + return -EFAULT;
- + }
- +
- + drq = (dmad_drq *) ch_req->drq;
- +
- + if (unlikely(drq == NULL)) {
- + dmad_err("null ch_req->drq!\n");
- + return -EBADR;
- + }
- + if (unlikely((ch_req->channel < 0) ||
- + ((drq->state & DMAD_DRQ_STATE_READY) == 0))) {
- + dmad_err("try to free a free channel!\n");
- + return -EBADR;
- + }
- +
- + /* Stop/abort channel I/O
- + * (forced to shutdown and should be protected against isr)
- + */
- + dmad_drain_requests(ch_req, 1);
- + dmad_channel_reset(ch_req);
- +
- + dmad_dbg("freed channel: %d\n", ch_req->channel);
- +
- + spin_lock(&dmad.drq_pool_lock);
- +
- + kfree(drq->drb_pool);
- + memset(drq, 0, sizeof(dmad_drq));
- +
- + ch_req->drq = 0;
- + ch_req->channel = (u32) - 1;
- +
- + spin_unlock(&dmad.drq_pool_lock);
- +
- + return 0;
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_channel_free);
- +
- +/**
- + * dmad_channel_enable - enable/disable a dma channel
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @enable : [in] 1 to enable the channel, 0 to disable
- + * @return : 0 if success, non-zero if any error
- + *
- + * Enable or disable the given DMA channel.
- + */
- +int dmad_channel_enable(const dmad_chreq * ch_req, u8 enable)
- +{
- + dmad_drq *drq;
- + unsigned long lock_flags;
- +
- + dmad_dbg("%s()\n", __func__);
- +
- + if (unlikely(ch_req == NULL))
- + return -EFAULT;
- +
- + drq = (dmad_drq *) ch_req->drq;
- +
- + if (unlikely(drq == NULL))
- + return -EBADR;
- +
- + spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
- +
- + /* Enable/disable DMA channel */
- + if (enable)
- + dmad_enable_channel(drq);
- + else
- + dmad_disable_channel(drq);
- +
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- +
- + return 0;
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_channel_enable);
- +
- +/**
- + * dmad_config_channel_dir - config dma channel transfer direction
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @dir : [in] DMAD_DRQ_DIR_A0_TO_A1 or DMAD_DRQ_DIR_A1_TO_A0
- + * @return : 0 if success, non-zero if any error
- + *
- + * Reconfigure the channel transfer direction. This function works only if
- + * the channel was allocated with the DMAD_FLAGS_BIDIRECTION flags. Note
- + * that bi-direction mode and ring mode are mutual-exclusive from user's
- + * perspective.
- + */
- +int dmad_config_channel_dir(dmad_chreq * ch_req, u8 dir)
- +{
- + dmad_drq *drq;
- + addr_t channel_cmds[2];
- + unsigned long lock_flags;
- + u8 cur_dir;
- +
- + if (unlikely(ch_req == NULL))
- + return -EFAULT;
- +
- + drq = (dmad_drq *) ch_req->drq;
- +
- + if (unlikely(drq == NULL))
- + return -EBADR;
- +
- + if (unlikely(!(ch_req->flags & DMAD_FLAGS_BIDIRECTION))) {
- + dmad_err("%s() Channel is not configured as"
- + " bidirectional!\n", __func__);
- + return -EFAULT;
- + }
- +
- + cur_dir = drq->flags & DMAD_DRQ_DIR_MASK;
- + if (dir == cur_dir) {
- + dmad_dbg("%s() cur_dir(%d) == dir(%d) skip reprogramming hw.\n",
- + __func__, cur_dir, dir);
- + return 0;
- + }
- +
- + spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
- +
- + if (unlikely((drq->sbt_head != 0) /*||dmad_is_channel_enabled(drq) */ )) {
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- + dmad_err("%s() Cannot change direction while the "
- + "channel has pending requests!\n", __func__);
- + return -EFAULT;
- + }
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + if (ch_req->controller == DMAD_DMAC_AHB_CORE) {
- +
- + channel_cmds[0] =
- + inl((addr_t) drq->channel_base + DMAC_CSR_OFFSET);
- + channel_cmds[1] =
- + inl((addr_t) drq->channel_base + DMAC_CFG_OFFSET);
- +
- + ch_req->ahb_req.tx_dir = dir;
- + dmad_ahb_config_dir(ch_req, channel_cmds);
- +
- + outl(channel_cmds[1],
- + (addr_t) drq->channel_base + DMAC_CFG_OFFSET);
- + outl(channel_cmds[0],
- + (addr_t) drq->channel_base + DMAC_CSR_OFFSET);
- +
- + }
- +#endif
- +#ifdef CONFIG_PLATFORM_APBDMA
- + if (ch_req->controller == DMAD_DMAC_APB_CORE) {
- +
- + channel_cmds[0] =
- + inl((addr_t) drq->channel_base + APBBR_DMA_CMD_OFFSET);
- +
- + ch_req->apb_req.tx_dir = dir;
- + dmad_apb_config_dir(ch_req, channel_cmds);
- +
- + outl(channel_cmds[0],
- + (addr_t) drq->channel_base + APBBR_DMA_CMD_OFFSET);
- + }
- +#endif
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- +
- + return 0;
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_config_channel_dir);
- +
- +/**
- + * dmad_max_size_per_drb - return maximum transfer size per drb
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @return : The maximum transfer size per drb, in bytes.
- + *
- + * Calculate the maximum transfer size per drb according to the setting of
- + * data width during channel initialization.
- + *
- + * Return size is aligned to 4-byte boundary; this ensures the alignment
- + * requirement of dma starting address if the function was used in a loop to
- + * separate a large size dma transfer.
- + */
- +u32 dmad_max_size_per_drb(dmad_chreq * ch_req)
- +{
- + addr_t size = 0;
- + addr_t data_width = (addr_t) ((dmad_drq *) ch_req->drq)->data_width;
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + if (ch_req->controller == DMAD_DMAC_AHB_CORE) {
- + size = DMAC_CYCLE_TO_BYTES(DMAC_TOT_SIZE_MASK & ((addr_t) ~ 3),
- + data_width);
- + }
- +#endif
- +#ifdef CONFIG_PLATFORM_APBDMA
- + if (ch_req->controller == DMAD_DMAC_APB_CORE) {
- + size =
- + APBBR_DMA_CYCLE_TO_BYTES(APBBR_DMA_CYC_MASK &
- + ((addr_t) ~ 3), data_width);
- + }
- +#endif
- + dmad_dbg("%s() - 0x%08x bytes\n", __func__, size);
- +
- + return size;
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_max_size_per_drb);
- +
- +/**
- + * dmad_bytes_to_cycles - calculate drb transfer size, in cycles
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @byte_size : [in] The DMA transfer size to be converted, in bytes
- + * @return : The drb transfer size, in cycles.
- + *
- + * Calculate the drb transfer cycle according to the setting of channel data
- + * width and burst setting.
- + *
- + * AHB DMA : unit is number of "data width".
- + * APB DMA : unit is number of "data width * burst size"
- + *
- + * APB Note: According to specification, decrement addressing seems to regard
- + * the burst size setting. For code efficiency,
- + * dmad_make_req_cycles() does not take care of this case and might
- + * produce wrong result.
- + */
- +u32 dmad_bytes_to_cycles(dmad_chreq * ch_req, u32 byte_size)
- +{
- + addr_t cycle = 0;
- + addr_t data_width = (addr_t) ((dmad_drq *) ch_req->drq)->data_width;
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + if (ch_req->controller == DMAD_DMAC_AHB_CORE) {
- + cycle = DMAC_BYTES_TO_CYCLE(byte_size, data_width);
- + }
- +#endif
- +#ifdef CONFIG_PLATFORM_APBDMA
- + if (ch_req->controller == DMAD_DMAC_APB_CORE) {
- + cycle = APBBR_DMA_BYTES_TO_CYCLE(byte_size, data_width);
- + if (ch_req->apb_req.burst_mode)
- + cycle = cycle >> 2;
- + }
- +#endif
- +
- + dmad_dbg("%s() - 0x%08x bytes --> 0x%08x cycles\n",
- + __func__, byte_size, cycle);
- +
- + return cycle;
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_bytes_to_cycles);
- +
- +/**
- + * dmad_alloc_drb_internal - allocate a dma-request-block of a dma channel
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @drb : [out] Reference to a drb pointer to receive the allocated drb
- + * @return : 0 if success, non-zero if any error
- + *
- + * Allocates a DRB (DMA request block) of the given DMA channel. DRB is a
- + * single dma request which will be pushed into the submission queue of the
- + * given DMA channel. This is a lightweight internal version of
- + * dmad_alloc_drb() majorly for use in ring mode. Critical access to the
- + * drb pool should be protected before entering this function.
- + */
- +static inline int dmad_alloc_drb_internal(dmad_drq * drq, dmad_drb ** drb)
- +{
- + /* Initialize drb ptr in case of fail allocation */
- + *drb = NULL;
- +
- + if (unlikely(drq->fre_head == 0)) {
- + return -EAGAIN;
- + }
- +
- + dmad_detach_head(drq->drb_pool, &drq->fre_head, &drq->fre_tail, drb);
- +
- + dmad_attach_tail(drq->drb_pool,
- + &drq->rdy_head, &drq->rdy_tail, (*drb)->node);
- +
- + (*drb)->state = DMAD_DRB_STATE_READY;
- + (*drb)->sync = 0;
- +
- + dmad_dbg("%s() drb(%d 0x%08x)\n", __func__, (*drb)->node, (u32) (*drb));
- +
- + return 0;
- +}
- +
- +/**
- + * dmad_alloc_drb - allocate a dma-request-block of a dma channel
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @drb : [out] Reference to a drb pointer to receive the allocated drb
- + * @return : 0 if success, non-zero if any error
- + *
- + * Allocates a DRB (DMA request block) of the given DMA channel. DRB is a
- + * single dma request which will be pushed into the submission queue of the
- + * given DMA channel.
- + */
- +int dmad_alloc_drb(dmad_chreq * ch_req, dmad_drb ** drb)
- +{
- + dmad_drq *drq;
- + unsigned long lock_flags;
- +
- + dmad_dbg("%s()\n", __func__);
- +
- + if (unlikely(ch_req == NULL)) {
- + dmad_err("null ch_req!\n");
- + return -EFAULT;
- + }
- +
- + drq = (dmad_drq *) ch_req->drq;
- +
- + if (likely(drq == NULL)) {
- + dmad_err("null ch_req->drq!\n");
- + return -EBADR;
- + }
- +
- + spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
- +
- + /* Initialize drb ptr in case of fail allocation */
- + *drb = NULL;
- +
- + if (unlikely(drq->fre_head == 0)) {
- +
- + drq->state &= (u32) ~ DMAD_DRQ_STATE_ABORT;
- +
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- +
- +_wait_for_free_drbs:
- +
- + /* Wait for free urbs */
- + if (drq->flags & DMAD_FLAGS_SLEEP_BLOCK) {
- +
- + int timeout =
- + wait_for_completion_interruptible_timeout(&drq->
- + drb_alloc_sync,
- + msecs_to_jiffies
- + (6000));
- +
- + /* reset sync object */
- + INIT_COMPLETION(drq->drb_alloc_sync);
- +
- + if (timeout < 0) {
- + dmad_err("%s() wait for"
- + " completion error! (%d)\n",
- + __func__, timeout);
- + return timeout;
- + }
- +
- + } else if (drq->flags & DMAD_FLAGS_SPIN_BLOCK) {
- +
- + u32 timeout = 0x00ffffff;
- +
- + while ((drq->fre_head == 0) && (--timeout != 0)) {
- + }
- + if (timeout == 0) {
- + dmad_err("%s() polling wait for "
- + "completion timeout!\n", __func__);
- + return -EAGAIN;
- + }
- +
- + } else {
- + return -EAGAIN;
- + }
- +
- + spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
- +
- + /* check whether all the requests of the channel has been
- + * abandoned or not */
- + if (unlikely(drq->state & DMAD_DRQ_STATE_ABORT)) {
- + dmad_dbg("%s() drb-allocation aborted due"
- + " to cancel-request ...\n", __func__);
- + drq->state &= (u32) ~ DMAD_DRQ_STATE_ABORT;
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- + return -ECANCELED;
- + }
- +
- + /* check again to avoid non-atomic operation between above
- + * two calls */
- + if (unlikely(drq->fre_head == 0)) {
- + dmad_dbg("%s() lost free drbs ... "
- + "continue waiting ...\n", __func__);
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- + goto _wait_for_free_drbs;
- + }
- + }
- +
- + dmad_detach_head(drq->drb_pool, &drq->fre_head, &drq->fre_tail, drb);
- +
- + dmad_attach_tail(drq->drb_pool,
- + &drq->rdy_head, &drq->rdy_tail, (*drb)->node);
- +
- + (*drb)->state = DMAD_DRB_STATE_READY;
- + (*drb)->sync = 0;
- +
- + dmad_dbg("%s() drb(%d 0x%08x)\n", __func__, (*drb)->node, (u32) (*drb));
- +
- + drq->state &= (u32) ~ DMAD_DRQ_STATE_ABORT;
- +
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- +
- + return 0;
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_alloc_drb);
- +
- +/**
- + * dmad_free_drb - free a dma-request-block of a dma channel
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @drb : [in] Reference to a drb to be freed
- + * @return : 0 if success, non-zero if any error
- + *
- + * Frees a DRB (DMA request block) of the given DMA channel. DRB is a
- + * single dma request which will be pushed into the submission queue of the
- + * given DMA channel.
- + */
- +int dmad_free_drb(dmad_chreq * ch_req, dmad_drb * drb)
- +{
- + dmad_drq *drq;
- + unsigned long lock_flags;
- +
- + dmad_dbg("%s()\n", __func__);
- +
- + if (unlikely(ch_req == NULL)) {
- + dmad_err("null ch_req!\n");
- + return -EFAULT;
- + }
- +
- + drq = (dmad_drq *) ch_req->drq;
- +
- + if (unlikely(drq == NULL)) {
- + dmad_err("null ch_req->drq!\n");
- + return -EBADR;
- + }
- +
- + spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
- +
- + /****************************************************
- + * Following code requires _safe_exit return path
- + */
- +
- + if (unlikely((drq->rdy_head == 0) || (drb->node == 0) ||
- + (drb->state != DMAD_DRB_STATE_READY) ||
- + (drb->node >= DMAD_DRB_POOL_SIZE))) {
- + dmad_err("Ready-queue is empty or invalid node!\n");
- +
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- + return -EBADR;
- + }
- +
- + dmad_detach_node(drq->drb_pool,
- + &drq->rdy_head, &drq->rdy_tail, drb->node);
- + dmad_attach_tail(drq->drb_pool,
- + &drq->fre_head, &drq->fre_tail, drb->node);
- +
- + drb->state = DMAD_DRB_STATE_FREE;
- + drb->sync = 0;
- +
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- +
- + return 0;
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_free_drb);
- +
- +/**
- + * dmad_submit_request_internal - submit a dma-request-block to the dma channel
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @drb : [in] Reference to a drb to be submitted
- + * @keep_fired : [in] non-zero to kickoff dma even the channel has stopped due
- + * to finishing its previous request
- + * @return : 0 if success, non-zero if any error
- + *
- + * Submit a DRB (DMA request block) of the given DMA channel to submission
- + * queue. DRB is a single dma request which will be pushed into the
- + * submission queue of the given DMA channel. This is a lightweight internal
- + * version of dmad_alloc_drb() majorly for use in ring mode. Critical access to
- + * the drb pool should be protected before entering this function.
- + */
- +static inline int dmad_submit_request_internal(dmad_drq * drq, dmad_drb * drb)
- +{
- + if (drb->state == DMAD_DRB_STATE_READY) {
- + /* Detach user node from ready list */
- + dmad_detach_node(drq->drb_pool,
- + &drq->rdy_head, &drq->rdy_tail, drb->node);
- +
- + dmad_attach_tail(drq->drb_pool,
- + &drq->sbt_head, &drq->sbt_tail, drb->node);
- +
- + drb->state = DMAD_DRB_STATE_SUBMITTED;
- +
- + dmad_dbg("%s() submit drb(%d 0x%08x) addr0(0x%08x) "
- + "addr1(0x%08x) size(0x%08x) state(%d)\n", __func__,
- + drb->node, (u32) drb, drb->src_addr, drb->dst_addr,
- + drb->req_cycle, drb->state);
- + } else {
- + dmad_dbg("%s() skip drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x)"
- + " size(0x%08x) state(%d)\n", __func__,
- + drb->node, (u32) drb, drb->src_addr, drb->dst_addr,
- + drb->req_cycle, drb->state);
- + }
- +
- + return 0;
- +}
- +
- +/**
- + * dmad_submit_request - submit a dma-request-block to the dma channel
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @drb : [in] Reference to a drb to be submitted
- + * @keep_fired : [in] non-zero to kickoff dma even the channel has stopped due
- + * to finishing its previous request
- + * @return : 0 if success, non-zero if any error
- + *
- + * Submit a DRB (DMA request block) of the given DMA channel to submission
- + * queue. DRB is a single dma request which will be pushed into the
- + * submission queue of the given DMA channel.
- + */
- +int dmad_submit_request(dmad_chreq * ch_req, dmad_drb * drb, u8 keep_fired)
- +{
- + dmad_drq *drq;
- + unsigned long lock_flags;
- +
- + dmad_dbg("%s()\n", __func__);
- +
- + if (unlikely(ch_req == NULL)) {
- + dmad_err("null ch_req!\n");
- + return -EFAULT;
- + }
- +
- + drq = (dmad_drq *) ch_req->drq;
- +
- + if (unlikely(drq == NULL)) {
- + dmad_err("null ch_req->drq!\n");
- + return -EBADR;
- + }
- +
- + spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
- +
- + /******************************************************
- + * Following code require _safe_exit return path
- + */
- +
- + if (unlikely((drq->rdy_head == 0) || (drb->node == 0) ||
- + (drb->node >= DMAD_DRB_POOL_SIZE))) {
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- + return -EBADR;
- + }
- +
- + /* Detach user node from ready list */
- + dmad_detach_node(drq->drb_pool, &drq->rdy_head, &drq->rdy_tail,
- + drb->node);
- +
- + /* Queue DRB to the end of the submitted list */
- + dmad_dbg("submit drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x) "
- + "size(0x%08x) sync(0x%08x) fire(%d)\n",
- + drb->node, (u32) drb, drb->src_addr, drb->dst_addr,
- + drb->req_cycle, (u32) drb->sync, keep_fired);
- +
- + /* Check if submission is performed to an empty queue */
- + if (unlikely(keep_fired && (drq->sbt_head == 0))) {
- + /* DMA is not running, so kick off transmission */
- + dmad_dbg("kickoff dma engine.\n");
- +
- + dmad_attach_tail(drq->drb_pool,
- + &drq->sbt_head, &drq->sbt_tail, drb->node);
- +
- + /* Source and destination address */
- + if (drq->flags & DMAD_DRQ_DIR_A1_TO_A0) {
- + outl(drb->addr1, (addr_t) drq->src_port);
- + outl(drb->addr0, (addr_t) drq->dst_port);
- + } else {
- + outl(drb->addr0, (addr_t) drq->src_port);
- + outl(drb->addr1, (addr_t) drq->dst_port);
- + }
- +
- + /* Transfer size (in units of source width) */
- + outl(drb->req_cycle, (addr_t) drq->cyc_port);
- +
- + /* Enable DMA channel (Kick off transmission when client
- + * enable it's transfer state) */
- + dmad_enable_channel(drq);
- +
- + drb->state = DMAD_DRB_STATE_EXECUTED;
- +
- + } else {
- + /* DMA is already running, so only queue DRB to the end of the
- + * list */
- + dmad_attach_tail(drq->drb_pool,
- + &drq->sbt_head, &drq->sbt_tail, drb->node);
- + drb->state = DMAD_DRB_STATE_SUBMITTED;
- + }
- +
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- +
- + return 0;
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_submit_request);
- +
- +/**
- + * dmad_withdraw_request - cancel a submitted dma-request-block
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @drb : [in] Reference to a drb to be submitted
- + * @keep_fired : [in] non-zero to kickoff dma even the channel has stopped due
- + * to finishing its previous request
- + * @return : 0 if success, non-zero if any error
- + *
- + * Cancel a submitted DRB (DMA request block) of the given DMA channel in its
- + * submission queue. DRB is a single dma request which will be pushed into the
- + * submission queue of the given DMA channel. Cancellation fails if the DRB has
- + * already been kicked off.
- + */
- +int dmad_withdraw_request(dmad_chreq * ch_req, dmad_drb * drb)
- +{
- + dmad_drq *drq = 0;
- + unsigned long lock_flags;
- +
- + dmad_dbg("%s()\n", __func__);
- +
- + if (unlikely(ch_req == NULL)) {
- + dmad_err("null ch_req!\n");
- + return -EFAULT;
- + }
- +
- + drq = (dmad_drq *) ch_req->drq;
- +
- + if (unlikely(drq == NULL)) {
- + dmad_err("null ch_req->drq!\n");
- + return -EBADR;
- + }
- +
- + if (unlikely(drq->sbt_head == 0))
- + return -EBADR;
- +
- + if (unlikely((drb->node == 0) || (drb->node >= DMAD_DRB_POOL_SIZE)))
- + return -EBADR;
- +
- + spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
- +
- + if (unlikely((drq->sbt_head == 0) || (drb->node == 0) ||
- + (drb->state != DMAD_DRB_STATE_SUBMITTED) ||
- + (drb->node >= DMAD_DRB_POOL_SIZE))) {
- + dmad_err("Submitted-queue is empty or invalid node!\n");
- +
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- + return -EBADR;
- + }
- +
- + dmad_dbg("cancel drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x) "
- + "size(0x%08x) state(%d)\n",
- + drb->node, (u32) drb, drb->src_addr, drb->dst_addr,
- + drb->req_cycle, drb->state);
- +
- + if (unlikely(drb->state == DMAD_DRB_STATE_EXECUTED)) {
- + dmad_dbg("Already running drb cannot be stopped currently!\n");
- +
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- + return 0;/*-EBADR; */
- + }
- +
- + dmad_detach_node(drq->drb_pool,
- + &drq->rdy_head, &drq->rdy_tail, drb->node);
- + dmad_attach_tail(drq->drb_pool,
- + &drq->fre_head, &drq->fre_tail, drb->node);
- +
- + drb->state = DMAD_DRB_STATE_FREE;
- +
- + if (drb->sync)
- + complete_all(drb->sync);
- + drb->sync = 0;
- +
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- +
- + return 0;
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_withdraw_request);
- +
- +/**
- + * dmad_kickoff_requests_internal - kickoff hw DMA transmission
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @return : 0 if success, non-zero if any error
- + *
- + * Kickoff hw DMA transmission of the given DMA channel. This function is
- + * valid for both ring & non-ring mode. This is a lightweight internal version
- + * of dmad_kickoff_requests() majorly for use in ring mode. Critical access to
- + * the drb pool should be protected before entering this function.
- + */
- +static inline int dmad_kickoff_requests_internal(dmad_drq * drq)
- +{
- + dmad_drb *drb;
- +
- + dmad_get_head(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail, &drb);
- +
- + if (!drb) {
- + dmad_err("%s() null drb!\n", __func__);
- + return -EBADR;
- + }
- +
- + dmad_dbg("%s() drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x) "
- + "size(0x%08x) state(%d)\n", __func__,
- + drb->node, (u32) drb, drb->src_addr, drb->dst_addr,
- + drb->req_cycle, drb->state);
- +
- + if (drb->state == DMAD_DRB_STATE_SUBMITTED) {
- + /* Transfer size (in units of source width) */
- + outl(drb->req_cycle, (addr_t) drq->cyc_port);
- +
- + /* Source and destination address */
- + if (drq->flags & DMAD_DRQ_DIR_A1_TO_A0) {
- + outl(drb->addr1, (addr_t) drq->src_port);
- + outl(drb->addr0, (addr_t) drq->dst_port);
- + } else {
- + outl(drb->addr0, (addr_t) drq->src_port);
- + outl(drb->addr1, (addr_t) drq->dst_port);
- + }
- +
- + drb->state = DMAD_DRB_STATE_EXECUTED;
- + }
- +
- + /* Enable DMA channel */
- + if (!dmad_is_channel_enabled(drq)) {
- + dmad_enable_channel(drq);
- + }
- +
- + return 0;
- +}
- +
- +/**
- + * dmad_kickoff_requests - kickoff hw DMA transmission of the given DMA channel
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @return : 0 if success, non-zero if any error
- + *
- + * Kickoff hw DMA transmission of the given DMA channel. This function is
- + * valid for both ring & non-ring mode.
- + */
- +int dmad_kickoff_requests(dmad_chreq * ch_req)
- +{
- + dmad_drq *drq = 0;
- + dmad_drb *drb = 0;
- + unsigned long lock_flags;
- + dma_addr_t req_cycle;
- +
- + dmad_dbg("%s()\n", __func__);
- +
- + if (unlikely(ch_req == NULL)) {
- + dmad_err("null ch_req!\n");
- + return -EFAULT;
- + }
- +
- + drq = (dmad_drq *) ch_req->drq;
- +
- + if (unlikely(drq == NULL)) {
- + dmad_err("null ch_req->drq!\n");
- + return -EBADR;
- + }
- +
- + spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
- +
- + dmad_get_head(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail, &drb);
- +
- + dmad_dbg("drq(0x%08x) channel_base(0x%08x)\n",
- + (u32) drq, drq->channel_base);
- + dmad_dbg("kick off drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x) "
- + "size(0x%08x) state(%d) a1_to_a0(%d)\n",
- + (u32) drb->node, (u32) drb, drb->addr0, drb->addr1,
- + drb->req_cycle, drb->state,
- + drq->flags & DMAD_DRQ_DIR_A1_TO_A0);
- +
- + /* do nothing if no drbs are in the submission queue */
- + if (unlikely((drb == 0) || (drb->state != DMAD_DRB_STATE_SUBMITTED))) {
- + dmad_dbg("%s() invalid drb(%d 0x%08x) or drb-state(%d)!\n",
- + __func__,
- + drb->node, (u32) drb, drb ? drb->state : 0xffffffff);
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- + return 0;
- + }
- +
- + req_cycle = drb->req_cycle;
- +
- + if (unlikely(req_cycle == 0)) {
- + dmad_dbg("%s() zero transfer size!\n", __func__);
- + goto _safe_exit;
- + }
- +
- + /* Transfer size (in units of source width) */
- + outl(req_cycle, (addr_t) drq->cyc_port);
- +
- + /* Source and destination address */
- + if (drq->flags & DMAD_DRQ_DIR_A1_TO_A0) {
- + outl(drb->addr1, (addr_t) drq->src_port);
- + outl(drb->addr0, (addr_t) drq->dst_port);
- + } else {
- + outl(drb->addr0, (addr_t) drq->src_port);
- + outl(drb->addr1, (addr_t) drq->dst_port);
- + }
- +
- + drb->state = DMAD_DRB_STATE_EXECUTED;
- +
- + /* Enable DMA channel */
- + dmad_enable_channel(drq);
- +
- +_safe_exit:
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- +
- + return 0;
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_kickoff_requests);
- +
- +/**
- + * dmad_probe_hw_ptr_src - probe DMA source hw-address of the given channel
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @return : physical address of current HW source pointer
- + *
- + * Probe DMA source hw-address of the given channel.
- + */
- +dma_addr_t dmad_probe_hw_ptr_src(dmad_chreq * ch_req)
- +{
- + return (dma_addr_t) inl(((dmad_drq *) ch_req->drq)->src_port);
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_probe_hw_ptr_src);
- +
- +/**
- + * dmad_probe_hw_ptr_dst - probe DMA destination hw-address of the given channel
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @return : physical address of current HW destination pointer
- + *
- + * Probe DMA destination hw-address of the given channel.
- + */
- +dma_addr_t dmad_probe_hw_ptr_dst(dmad_chreq * ch_req)
- +{
- + return (dma_addr_t) inl(((dmad_drq *) ch_req->drq)->dst_port);
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_probe_hw_ptr_dst);
- +
- +/**
- + * dmad_update_ring - update DMA ring buffer base && size of the given channel
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @size : [in] The new ring buffer size, in unit of data width (cycles)
- + * @return : 0 if success, non-zero if any error
- + *
- + * Update DMA ring buffer size of the given channel. This function is valid
- + * only if the channel is initialized as ring buffer mode.
- + */
- +int dmad_update_ring(dmad_chreq * ch_req)
- +{
- + unsigned long lock_flags;
- + dmad_drq *drq = (dmad_drq *) ch_req->drq;
- + int remnant;
- +
- + if (unlikely(dmad_is_channel_enabled(drq))) {
- + dmad_err("%s() Error - dma channel should be "
- + "disabled before updating ring size!\n", __func__);
- + return -EFAULT;
- + }
- +
- + spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
- +
- + /* todo: range checking */
- +
- + remnant = (int)ch_req->ring_size -
- + (int)ch_req->periods * (int)ch_req->period_size;
- + if (remnant == 0) {
- + drq->periods = ch_req->periods;
- + } else if (remnant > 0) {
- + drq->periods = ch_req->periods; // + 1;
- + } else {
- + dmad_err("%s() Error - buffer_size < "
- + "periods * period_size!\n", __func__);
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- + return -EFAULT;
- + }
- +
- + drq->ring_base = ch_req->ring_base;
- + drq->ring_size = ch_req->ring_size;
- + drq->period_size = ch_req->period_size;
- + drq->remnant_size = (dma_addr_t) remnant;
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + if (ch_req->controller == DMAD_DMAC_AHB_CORE) {
- + drq->period_bytes =
- + DMAC_CYCLE_TO_BYTES(drq->period_size, drq->data_width);
- + }
- +#endif
- +#ifdef CONFIG_PLATFORM_APBDMA
- + if (ch_req->controller == DMAD_DMAC_APB_CORE) {
- + drq->period_bytes =
- + APBBR_DMA_CYCLE_TO_BYTES(drq->period_size, drq->data_width);
- + }
- +#endif
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- +
- + dmad_dbg("%s() ring: base(0x%08x) port(0x%08x) periods(0x%08x) "
- + "period_size(0x%08x) period_bytes(0x%08x) "
- + "remnant_size(0x%08x)\n",
- + __func__, drq->ring_base, drq->ring_port,
- + drq->periods, drq->period_size, drq->period_bytes,
- + drq->remnant_size);
- +
- + return 0;
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_update_ring);
- +
- +/**
- + * dmad_update_ring_sw_ptr - update DMA ring buffer sw-pointer
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @sw_ptr : [in] The new sw-pointer for the hw-pointer to chase of
- + * @keep_fired : [in] non-zero to kickoff dma even the channel has stopped due
- + * to finishing its previous request
- + * @return : 0 if success, non-zero if any error
- + *
- + * Update DMA ring buffer sw-pointer of the given channel on the fly. This
- + * function is valid only if the channel is initialized as ring buffer mode.
- + * Uint of sw_ptr is in number of dma data width.
- + */
- +int dmad_update_ring_sw_ptr(dmad_chreq * ch_req,
- + dma_addr_t sw_ptr, u8 keep_fired)
- +{
- + dmad_drq *drq;
- + unsigned long lock_flags;
- + dma_addr_t hw_off = 0, ring_ptr;
- + dma_addr_t sw_p_off, ring_p_off, period_size, period_bytes;
- + dma_addr_t remnant_size;
- + int sw_p_idx, ring_p_idx, period, periods;
- + dmad_drb *drb = NULL;
- +
- + /*if (ch_req == NULL) { */
- + /* dmad_dbg("%s() null ch_req!\n", __func__); */
- + /* return -EFAULT; */
- + /*} */
- +
- + drq = (dmad_drq *) ch_req->drq;
- +
- + /*if (drq == NULL) { */
- + /* dmad_dbg("%s() null ch_req->drq!\n", __func__); */
- + /* return -EBADR; */
- + /*} */
- +
- + if (unlikely(sw_ptr > drq->ring_size)) {
- + dmad_err("%s() Invalid ring buffer sw-pointer "
- + "range (0x%08x)! ring_size(0x%08x)\n",
- + __func__, sw_ptr, drq->ring_size);
- + return -EBADR;
- + }
- +
- + spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
- +
- + periods = drq->periods;
- + period_size = drq->period_size;
- + period_bytes = drq->period_bytes;
- + remnant_size = drq->remnant_size;
- +
- + ring_ptr = drq->sw_ptr;
- + ring_p_idx = drq->sw_p_idx;
- + ring_p_off = drq->sw_p_off;
- +
- + sw_p_idx = (int)(sw_ptr / period_size);
- + sw_p_off = sw_ptr % period_size;
- +
- + if (remnant_size && (sw_p_idx == periods)) {
- + --sw_p_idx;
- + sw_p_off += period_size;
- + }
- +
- + dmad_dbg("%s() ring_ptr(0x%08x) ring_p_idx(0x%08x) "
- + "ring_p_off(0x%08x)\n",
- + __func__, ring_ptr, ring_p_idx, ring_p_off);
- + dmad_dbg("%s() sw_ptr(0x%08x) sw_p_idx(0x%08x) sw_p_off(0x%08x)\n",
- + __func__, sw_ptr, sw_p_idx, sw_p_off);
- +
- + if (drq->ring_drb &&
- + (drq->ring_drb->state & (DMAD_DRB_STATE_READY |
- + DMAD_DRB_STATE_SUBMITTED |
- + DMAD_DRB_STATE_EXECUTED))) {
- + drb = drq->ring_drb;
- + } else {
- + /* alloc new drb if there is none yet at ring_ptr */
- + if (0 != dmad_alloc_drb_internal(drq, &drb)) {
- + dmad_err("%s() drb allocation failed!\n", __func__);
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- + return -ENOSPC;
- + }
- + drb->addr0 = ((dma_addr_t) ring_p_idx * period_bytes) +
- + drq->ring_base;
- + drb->addr1 = drq->dev_addr;
- + drb->req_cycle = 0; // redundent, though, no harm to performance
- +
- + dmad_dbg("init_drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x) "
- + "size(0x%08x) state(%d)\n",
- + (u32) drb->node, (u32) drb, drb->src_addr,
- + drb->dst_addr, drb->req_cycle, drb->state);
- +
- + drq->ring_drb = drb;
- + }
- +
- + /* Following code-path has been optimized. The design flow is expanded
- + * below for reference.
- + *
- + * if (sw_ptr >= ring_ptr)
- + * if (sw_p_idx == ring_p_idx)
- + * ring_drb::req_cycle <- sw_p_off
- + * if (ring_drb::state == executed)
- + * hw_cycle <- sw_p_idx
- + * fi
- + * else
- + * ring_drb::req_cycle <- period_size
- + * if (ring_drb::state == executed)
- + * hw_cycle <- period_size
- + * fi
- + * for (i = ring_p_idx+1 ~ sw_p_idx-1)
- + * new_drb::ring_addr <- i * period_bytes + ring_base
- + * new_drb::req_cycle <- period_size
- + * rof
- + * sw_drb::ring_addr <- sw_p_idx * period_bytes + ring_base
- + * sw_drb::req_cycle <- sw_p_off
- + * else
- + * // sw_ptr < ring_ptr
- + * ring_drb::req_cycle <- period_size
- + * if (ring_drb::state == executed)
- + * hw_cycle <- period_size
- + * fi
- + * for (i = ring_p_idx+1 ~ idx_max)
- + * new_drb::ring_addr <- i * period_bytes + ring_base
- + * new_drb::req_cycle <- period_size
- + * rof
- + * for (i = 0 ~ sw_p_idx-1)
- + * new_drb::ring_addr <- i * period_bytes + ring_base
- + * new_drb::req_cycle <- period_size
- + * rof
- + * sw_drb::ring_addr <- sw_p_idx * period_bytes + ring_base
- + * sw_drb::req_cycle <- sw_p_off
- + * fi
- + */
- + if ((sw_ptr >= ring_ptr) && (sw_p_idx == ring_p_idx) && (sw_p_off != 0)) {
- +
- + dmad_dbg("update ring drb\n");
- +
- + /* update drb size at ring_ptr */
- + drb->req_cycle = sw_p_off;
- +
- + dmad_dbg("ring_drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x) "
- + "size(0x%08x) state(%d)\n",
- + (u32) drb->node, (u32) drb, drb->addr0, drb->addr1,
- + drb->req_cycle, drb->state);
- +
- + /* update hw dma size of this drb if it has been sent to the
- + * controller */
- + if (drb->state == DMAD_DRB_STATE_EXECUTED) {
- + dmad_disable_channel(drq);
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + if (ch_req->controller == DMAD_DMAC_AHB_CORE)
- + hw_off = DMAC_BYTES_TO_CYCLE((addr_t)
- + inl((addr_t) drq->
- + ring_port) -
- + (addr_t) drb->
- + addr0,
- + drq->data_width);
- +#endif
- +#ifdef CONFIG_PLATFORM_APBDMA
- + if (ch_req->controller == DMAD_DMAC_APB_CORE)
- + hw_off = APBBR_DMA_BYTES_TO_CYCLE((addr_t)
- + inl((addr_t)
- + drq->
- + ring_port)
- + -
- + (addr_t) drb->
- + addr0,
- + drq->
- + data_width);
- +#endif
- + dmad_dbg("hw_off(0x%08x) sw_p_off(0x%08x)\n",
- + (u32) hw_off, (u32) sw_p_off);
- +
- + if (sw_p_off < hw_off)
- + dmad_err("%s() underrun! sw_p_off(0x%08x) <"
- + " hw_off(0x%08x)\n", __func__,
- + (u32) sw_p_off, (u32) hw_off);
- + else
- + outl(sw_p_off - hw_off, drq->cyc_port);
- +
- + dmad_enable_channel(drq);
- +
- + } else {
- + dmad_submit_request_internal(drq, drb);
- + }
- +
- + } else {
- +
- + dmad_dbg("fulfill ring drb - sw_ptr(0x%08x) ring_ptr(0x%08x)\n",
- + (u32) sw_ptr, (u32) ring_ptr);
- +
- + /* fulfill last drb at ring_ptr */
- + if (ring_p_idx == (periods - 1))
- + drb->req_cycle = period_size + remnant_size;
- + else
- + drb->req_cycle = period_size;
- +
- + dmad_dbg("ring_drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x) "
- + "size(0x%08x) state(%d)\n",
- + (u32) drb->node, (u32) drb, drb->addr0, drb->addr1,
- + drb->req_cycle, drb->state);
- +
- + if (drb->state == DMAD_DRB_STATE_EXECUTED) {
- + dmad_disable_channel(drq);
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + if (ch_req->controller == DMAD_DMAC_AHB_CORE)
- + hw_off = DMAC_BYTES_TO_CYCLE((addr_t)
- + inl((addr_t) drq->
- + ring_port) -
- + (addr_t) drb->
- + addr0,
- + drq->data_width);
- +#endif
- +#ifdef CONFIG_PLATFORM_APBDMA
- + if (ch_req->controller == DMAD_DMAC_APB_CORE)
- + hw_off = APBBR_DMA_BYTES_TO_CYCLE((addr_t)
- + inl((addr_t)
- + drq->
- + ring_port)
- + -
- + (addr_t) drb->
- + addr0,
- + drq->
- + data_width);
- +#endif
- + dmad_dbg("hw_off(0x%08x) period_size(0x%08x)\n",
- + (u32) hw_off, (u32) period_size);
- +
- + if (ring_p_idx == (periods - 1)) {
- + if (period_size < hw_off)
- + dmad_err("%s() illegal! "
- + "period_size(0x%08x) + "
- + "remnant_size(0x%08x) < "
- + "hw_off(0x%08x)\n", __func__,
- + (u32) period_size,
- + (u32) remnant_size,
- + (u32) hw_off);
- + else
- + outl(period_size + remnant_size -
- + hw_off, drq->cyc_port);
- + } else {
- + if (period_size < hw_off)
- + dmad_err("%s() illegal! "
- + "period_size(0x%08x) < "
- + "hw_off(0x%08x)\n", __func__,
- + (u32) period_size,
- + (u32) hw_off);
- + else
- + outl(period_size - hw_off,
- + drq->cyc_port);
- + }
- +
- + dmad_enable_channel(drq);
- +
- + } else {
- + dmad_submit_request_internal(drq, drb);
- + }
- +
- + ++ring_p_idx;
- +
- + /* adjust sw_ptr period index ahead by one ring cycle */
- + //if (sw_ptr < ring_ptr) {
- + if (sw_p_idx < ring_p_idx) {
- + sw_p_idx += periods;
- + }
- +
- + /* allocate in-between (ring_ptr+1 to sw_ptr-1)
- + * full-cycle drbs */
- + for (period = ring_p_idx; period < sw_p_idx; ++period) {
- + if (0 != dmad_alloc_drb_internal(drq, &drb)) {
- + dmad_err("%s() drb allocation failed!\n",
- + __func__);
- + spin_unlock_irqrestore(&drq->drb_pool_lock,
- + lock_flags);
- + return -ENOSPC;
- + }
- +
- + drb->addr0 = (dma_addr_t) (period % periods) *
- + period_bytes + drq->ring_base;
- + drb->addr1 = drq->dev_addr;
- +
- + if (period == (periods - 1)) {
- + drb->req_cycle = period_size + remnant_size;
- + } else {
- + drb->req_cycle = period_size;
- + }
- +
- + dmad_dbg("inbtw_drb(%d 0x%08x) addr0(0x%08x) "
- + "addr1(0x%08x) size(0x%08x) state(%d)\n",
- + (u32) drb->node, (u32) drb, drb->addr0,
- + drb->addr1, drb->req_cycle, drb->state);
- +
- + dmad_submit_request_internal(drq, drb);
- + }
- +
- + /* allocate drb right at sw_ptr */
- + if (0 != dmad_alloc_drb_internal(drq, &drb)) {
- + dmad_err("%s() drb allocation failed!\n", __func__);
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- + return -ENOSPC;
- + }
- + drb->addr0 = (dma_addr_t) (sw_p_idx % periods) *
- + period_bytes + drq->ring_base;
- + drb->addr1 = drq->dev_addr;
- + drb->req_cycle = sw_p_off;
- +
- + dmad_dbg("swptr_drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x) "
- + "size(0x%08x) state(%d)\n",
- + (u32) drb->node, (u32) drb, drb->addr0, drb->addr1,
- + drb->req_cycle, drb->state);
- +
- + drq->ring_drb = drb;
- +
- + if (sw_p_off > 0)
- + dmad_submit_request_internal(drq, drb);
- + }
- +
- + drq->sw_ptr = sw_ptr % drq->ring_size;
- + drq->sw_p_idx = sw_p_idx % periods;
- + drq->sw_p_off = sw_p_off;
- +
- + if (likely(keep_fired)) {
- + dmad_kickoff_requests_internal(drq);
- + }
- +
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- +
- + return 0;
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_update_ring_sw_ptr);
- +
- +/**
- + * dmad_probe_ring_hw_ptr - probe DMA ring buffer position of the given channel
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @return : Ring buffer position of current HW ring buffer pointer
- + *
- + * Probe DMA ring buffer position of the given channel. The position is
- + * relative to the ring buffer base. This function is valid only if the
- + * channel is initialized as ring buffer mode.
- + */
- +dma_addr_t dmad_probe_ring_hw_ptr(dmad_chreq * ch_req)
- +{
- + dmad_drq *drq = (dmad_drq *) ch_req->drq;
- + dma_addr_t cycles =
- + (dma_addr_t) inl(drq->ring_port) - (dma_addr_t) drq->ring_base;
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + if (ch_req->controller == DMAD_DMAC_AHB_CORE)
- + cycles = DMAC_BYTES_TO_CYCLE(cycles, drq->data_width);
- +#endif
- +#ifdef CONFIG_PLATFORM_APBDMA
- + if (ch_req->controller == DMAD_DMAC_APB_CORE)
- + cycles = APBBR_DMA_BYTES_TO_CYCLE(cycles, drq->data_width);
- +#endif
- + return cycles;
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_probe_ring_hw_ptr);
- +
- +/**
- + * dmad_channel_drain - cancel DMA transmission of the given DMA channel
- + * @controller : [in] One of the enum value of DMAD_DMAC_CORE
- + * @drq : [in] Reference to the DMA queue structure (dmad_drq)
- + * @shutdown : [in] Non-zero to force a immediate channel shutdown
- + * @return : 0 if success, non-zero if any error
- + *
- + * Stop the DMA transmission and cancel all submitted requests of the given
- + * DMA channel. This function drains a single channel and is the internal
- + * implementation of the interface routine dmad_drain_requests() and the
- + * module_exit function.
- + */
- +static int dmad_channel_drain(u32 controller, dmad_drq * drq, u8 shutdown)
- +{
- + dmad_drb *drb = 0;
- + unsigned long lock_flags;
- +
- + if (unlikely(drq == NULL)) {
- + dmad_err("null ch_req->drq!\n");
- + return -EBADR;
- + }
- +
- + spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
- +
- + /* Stop DMA channel if forced to shutdown immediately */
- + if (shutdown) {
- + /* disable dma controller */
- + dmad_reset_channel(drq);
- +
- + /* todo: more settings to stop DMA controller ?? */
- +
- + /*if (drb->state == DMAD_DRB_STATE_EXECUTED) { */
- + /*} */
- + }
- +
- + /* Detach DRBs in submit queue */
- + dmad_detach_head(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail, &drb);
- +
- + while (drb) {
- + dmad_dbg("cancel sbt drb(%d 0x%08x) addr0(0x%08x) "
- + "addr1(0x%08x) size(0x%08x) state(%d)\n",
- + drb->node, (u32) drb, drb->src_addr, drb->dst_addr,
- + drb->req_cycle, (u32) drb->state);
- +
- + /* Mark DRB state as abort */
- + drb->state = DMAD_DRB_STATE_ABORT;
- +
- + if (drb->sync)
- + complete_all(drb->sync);
- +
- + dmad_attach_tail(drq->drb_pool, &drq->fre_head, &drq->fre_tail,
- + drb->node);
- +
- + dmad_detach_head(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail,
- + &drb);
- + }
- +
- + /* Detach DRBs in ready queue */
- + dmad_detach_head(drq->drb_pool, &drq->rdy_head, &drq->rdy_tail, &drb);
- +
- + while (drb) {
- + dmad_dbg("cancel rdy drb(%d 0x%08x) addr0(0x%08x) "
- + "addr1(0x%08x) size(0x%08x) state(%d)\n",
- + drb->node, (u32) drb, drb->src_addr, drb->dst_addr,
- + drb->req_cycle, (u32) drb->state);
- +
- + /* Mark DRB state as abort */
- + drb->state = DMAD_DRB_STATE_ABORT;
- +
- + dmad_attach_tail(drq->drb_pool, &drq->fre_head, &drq->fre_tail,
- + drb->node);
- +
- + /* Detach next submitted DRB (DMA Request Block) from the
- + * DRQ (DMA Request Queue) */
- + dmad_detach_head(drq->drb_pool, &drq->rdy_head, &drq->rdy_tail,
- + &drb);
- + }
- +
- + drq->state |= DMAD_DRQ_STATE_ABORT;
- +
- + drq->ring_drb = NULL;
- + drq->sw_ptr = 0;
- + drq->sw_p_idx = 0;
- + drq->sw_p_off = 0;
- +
- + spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
- +
- + if ( /*(drq->fre_head == 0) && */ (drq->flags & DMAD_FLAGS_SLEEP_BLOCK)) {
- + complete_all(&drq->drb_alloc_sync);
- + }
- +
- + return 0;
- +}
- +
- +/**
- + * dmad_cancel_requests - cancel DMA transmission of the given DMA channel
- + * @ch_req : [in] Reference to the DMA request descriptor structure
- + * @shutdown : [in] Non-zero to force a immediate channel shutdown
- + * @return : 0 if success, non-zero if any error
- + *
- + * Stop the DMA transmission and cancel all submitted requests of the given
- + * DMA channel.
- + */
- +int dmad_drain_requests(dmad_chreq * ch_req, u8 shutdown)
- +{
- + dmad_dbg("%s()\n", __func__);
- +
- + if (ch_req == NULL) {
- + dmad_err("null ch_req!\n");
- + return -EFAULT;
- + }
- +
- + return dmad_channel_drain(ch_req->controller, ch_req->drq, shutdown);
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_drain_requests);
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- +
- +/**
- + * dmad_probe_irq_source - probe DMA channel who asserts the shared sw-irq line
- + * @return : The channel number which asserts the shared sw-irq line
- + *
- + * Probe DMA channel who asserts the shared sw-irq line.
- + */
- +int dmad_probe_irq_source_ahb(void)
- +{
- + int channel; /* interrupt channel number */
- +
- + /* todo: spin_lock */
- +
- + /* - Check DMA status register to get channel number */
- + for (channel = 0; channel < DMAD_AHB_MAX_CHANNELS; ++channel) {
- + if (getbl(channel, DMAC_INT_TC))
- + return channel;
- + }
- +
- + /* Perform DMA error checking if no valid channel was found who
- + * assert the finish signal. */
- + for (channel = 0; channel < DMAD_AHB_MAX_CHANNELS; ++channel) {
- + if (getbl(channel, DMAC_INT_ERRABT))
- + return channel;
- + if (getbl(channel << DMAC_INT_ABT_SHIFT, DMAC_INT_ERRABT))
- + return channel;
- + }
- +
- + /* todo: spin_unlock */
- +
- + return -EFAULT;
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_probe_irq_source_ahb);
- +
- +#endif /* CONFIG_PLATFORM_AHBDMA */
- +
- +#ifdef CONFIG_PLATFORM_APBDMA
- +
- +int dmad_probe_irq_source_apb(void)
- +{
- + int channel; /* interrupt channel number */
- +
- + /* todo: spin_lock */
- +
- + /* Check DMA status register to get channel number */
- + for (channel = 0; channel < DMAD_APB_MAX_CHANNELS; ++channel) {
- + if (getbl(APBBR_DMA_FINTST_BIT, APBBR_DMA_BASE_CH(channel) +
- + APBBR_DMA_CMD_OFFSET))
- + return channel;
- + }
- +
- + /* Perform DMA error checking if no valid channel was found who
- + * assert the finish signal. */
- + for (channel = 0; channel < DMAD_APB_MAX_CHANNELS; ++channel) {
- + if (getbl(APBBR_DMA_ERRINTST_BIT, APBBR_DMA_BASE_CH(channel) +
- + APBBR_DMA_CMD_OFFSET))
- + return channel;
- + }
- +
- + /* todo: spin_unlock */
- +
- + return -EFAULT;
- +}
- +
- +EXPORT_SYMBOL_GPL(dmad_probe_irq_source_apb);
- +
- +#endif /* CONFIG_PLATFORM_APBDMA */
- +
- +/**
- + * dmad_module_init - dma module-init function
- + * @return : 0 if success, non-zero if any error
- + */
- +int __init dmad_module_init(void)
- +{
- + int err = 0;
- + dmad_dbg("%s() >>\n", __func__);
- +
- + /* clear device struct since the module may be load/unload many times */
- + memset(&dmad, 0, sizeof(dmad));
- +
- + dmad.drq_pool =
- + kmalloc((DMAD_AHB_MAX_CHANNELS +
- + DMAD_APB_MAX_CHANNELS) * sizeof(dmad_drq), GFP_KERNEL);
- + if (dmad.drq_pool == NULL) {
- + dmad_err("%s() failed to allocate drb pool!\n", __func__);
- + return -ENOMEM;
- + }
- +
- + memset(dmad.drq_pool, 0,
- + (DMAD_AHB_MAX_CHANNELS + DMAD_APB_MAX_CHANNELS) *
- + sizeof(dmad_drq));
- +
- + spin_lock_init(&dmad.drq_pool_lock);
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + dmad.ahb_drq_pool = dmad.drq_pool;
- + if (unlikely(!request_region(DMAC_BASE, SZ_1K, "AHB DMAC"))) {
- + dmad_err("Cannot reserve AHB DMAC I/O region\n");
- + err = -EBUSY;
- + }
- +#endif
- +
- +#ifdef CONFIG_PLATFORM_APBDMA
- + dmad.apb_drq_pool = &dmad.drq_pool[DMAD_AHB_MAX_CHANNELS];
- + if (unlikely(!request_region(APBBR_BASE, SZ_1K, "APB DMAC"))) {
- + dmad_err("Cannot reserve APB DMAC I/O region\n");
- + err = -EBUSY;
- + }
- +#endif
- +
- + dmad_dbg("DMA module init result: (%d)\n", err);
- + dmad_dbg(" AHB channels: %d; APB channels %d; "
- + "DRBs per channel: %d\n",
- + DMAC_MAX_CHANNELS, APBBR_DMA_MAX_CHANNELS, DMAD_DRB_POOL_SIZE);
- +
- + dmad_dbg("%s() return code (%d) <<\n", __func__, err);
- + return err;
- +}
- +
- +/**
- + * dmad_module_init - dma module clean up function
- + */
- +void __exit dmad_module_exit(void)
- +{
- + dmad_drq *drq;
- + u32 channel;
- +
- + dmad_dbg("%s() >>\n", __func__);
- +
- + spin_lock(&dmad.drq_pool_lock);
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + /* cancel existing requests and unregister interrupt handler */
- + for (channel = 0; channel < DMAD_AHB_MAX_CHANNELS; ++channel) {
- +
- + /* shutdown dma requests */
- + drq = (dmad_drq *) & dmad.ahb_drq_pool[channel];
- +
- + if ((drq->state & DMAD_DRQ_STATE_READY) != 0)
- + dmad_channel_drain(DMAD_DMAC_AHB_CORE, drq, 1);
- +
- + /* free registered irq handlers */
- + free_irq(ahb_irqs[channel], (void *)(channel + 1));
- + }
- +#endif
- +
- +#ifdef CONFIG_PLATFORM_APBDMA
- + /* cancel existing requests and unregister interrupt handler */
- + for (channel = 0; channel < DMAD_APB_MAX_CHANNELS; ++channel) {
- +
- + /* shutdown dma requests */
- + drq = (dmad_drq *) & dmad.apb_drq_pool[channel];
- +
- + if ((drq->state & DMAD_DRQ_STATE_READY) != 0)
- + dmad_channel_drain(DMAD_DMAC_APB_CORE, drq, 1);
- +
- + /* free registered irq handlers */
- + free_irq(apb_irqs[channel], (void *)(channel + 1));
- + }
- +#endif
- + spin_unlock(&dmad.drq_pool_lock);
- +
- + if (dmad.drq_pool)
- + kfree(dmad.drq_pool);
- + memset(&dmad, 0, sizeof(dmad));
- +
- + /* release I/O space */
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + release_region(DMAC_BASE, SZ_1K);
- +#endif /*CONFIG_PLATFORM_AHBDMA */
- +
- +#ifdef CONFIG_PLATFORM_APBDMA
- + release_region(APBBR_BASE, SZ_1K);
- +#endif /* CONFIG_PLATFORM_APBDMA */
- +
- + dmad_dbg("DMA module unloaded!\n");
- +}
- +
- +#ifndef MODULE
- +arch_initcall(dmad_module_init);
- +#else
- +module_init(dmad_module_init);
- +module_exit(dmad_module_exit);
- +#endif
- +
- +#endif /* CONFIG_PLATFORM_AHBDMA || CONFIG_PLATFORM_APBDMA */
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/dmad_intc.c linux-3.4.110/arch/nds32/platforms/dmad_intc.c
- --- linux-3.4.110.orig/arch/nds32/platforms/dmad_intc.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/dmad_intc.c 2016-04-07 10:20:51.018083964 +0200
- @@ -0,0 +1,124 @@
- +/*
- + * linux/arch/armnommu/mach-faraday/platform-a320/apb_intc.c
- + *
- + * Faraday AHB DMA Interrupt Process Driver Implementation
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + *
- + * ChangeLog
- + *
- + * Peter Liao 09/28/2005 Created
- + */
- +
- +#include <linux/irq.h>
- +#include <linux/interrupt.h>
- +#include <linux/ioport.h>
- +#include <asm/io.h>
- +
- +#include <asm/intc.h>
- +#include <asm/spec.h>
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- +extern int dmad_probe_irq_source_ahb(void);
- +
- +void AHBDMA_irq_rounter(unsigned int irq, struct irq_desc *desc)
- +{
- + int ahb_irq;
- + struct irq_desc *ahb_desc;
- + struct irq_data data;
- + data.irq = irq;
- +
- + raw_spin_lock(&desc->lock);
- + desc->irq_data.chip->irq_mask(&data);
- + desc->irq_data.chip->irq_ack(&data);
- +
- + ahb_irq = dmad_probe_irq_source_ahb();
- + if (ahb_irq >= 0) {
- + ahb_irq += DMAC_FTDMAC020_IRQ0;
- + ahb_desc = irq_desc + ahb_irq;
- +
- + raw_spin_unlock(&desc->lock);
- + ahb_desc->handle_irq(ahb_irq, ahb_desc);
- + raw_spin_lock(&desc->lock);
- + }
- +
- + desc->irq_data.chip->irq_unmask(&data);
- + raw_spin_unlock(&desc->lock);
- +}
- +
- +int __init intc_ftdmac020_init_irq(void)
- +{
- + int i;
- +
- + /* Register all IRQ */
- + for (i = DMAC_FTDMAC020_IRQ0;
- + i < DMAC_FTDMAC020_IRQ0 + DMAC_FTDMAC020_IRQ_COUNT; i++) {
- + // level trigger
- + irq_set_chip(i, &dummy_irq_chip);
- + irq_set_handler(i, handle_simple_irq);
- + }
- + irq_set_chained_handler(PLATFORM_AHBDMA_IRQ, AHBDMA_irq_rounter);
- +
- + return 0;
- +}
- +
- +arch_initcall(intc_ftdmac020_init_irq);
- +#endif /* CONFIG_PLATFORM_AHBDMA */
- +
- +#ifdef CONFIG_PLATFORM_APBDMA
- +extern int dmad_probe_irq_source_apb(void);
- +
- +void APBDMA_irq_rounter(unsigned int irq, struct irq_desc *desc)
- +{
- + int apb_irq;
- + struct irq_desc *apb_desc;
- + struct irq_data data;
- + data.irq = irq;
- +
- + raw_spin_lock(&desc->lock);
- +
- + //mask_ack_irq(desc, irq);
- + desc->irq_data.chip->irq_mask(&data);
- + desc->irq_data.chip->irq_ack(&data);
- +
- + apb_irq = dmad_probe_irq_source_apb();
- + //printk(KERN_INFO "irq (%d) ch(%d)\n", irq, apb_irq);
- +
- + if (apb_irq >= 0) {
- + apb_irq += APBBRG_FTAPBBRG020S_0_IRQ0;
- + apb_desc = irq_desc + apb_irq;
- +
- + raw_spin_unlock(&desc->lock);
- + apb_desc->handle_irq(irq, apb_desc);
- + raw_spin_lock(&desc->lock);
- + }
- +
- + desc->irq_data.chip->irq_unmask(&data);
- + raw_spin_unlock(&desc->lock);
- +}
- +
- +int __init intc_ftapbbrg020s_init_irq(void)
- +{
- + int i;
- +
- + /* Register all IRQ */
- + for (i = APBBRG_FTAPBBRG020S_0_IRQ0;
- + i < APBBRG_FTAPBBRG020S_0_IRQ0 + APBBRG_FTAPBBRG020S_IRQ_COUNT;
- + i++) {
- + // level trigger
- + irq_set_chip(i, &dummy_irq_chip);
- + irq_set_handler(i, handle_simple_irq);
- + }
- +
- + irq_set_chained_handler(PLATFORM_APBDMA_IRQ, APBDMA_irq_rounter);
- +
- + return 0;
- +}
- +
- +arch_initcall(intc_ftapbbrg020s_init_irq);
- +#endif /* CONFIG_PLATFORM_APBDMA */
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ftpci.c linux-3.4.110/arch/nds32/platforms/ftpci.c
- --- linux-3.4.110.orig/arch/nds32/platforms/ftpci.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/ftpci.c 2016-04-07 10:20:51.018083964 +0200
- @@ -0,0 +1,497 @@
- +/*
- + * linux/arch/nds32/platforms/ftpci.c
- + *
- + * Faraday FTPCI100 PCI Bridge Controller Device Driver Implementation
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + *
- + * ChangeLog
- + *
- + * Peter Liao 09/28/2005 Created.
- + */
- +
- +#include <linux/sched.h>
- +#include <linux/kernel.h>
- +#include <linux/pci.h>
- +#include <linux/ptrace.h>
- +#include <linux/slab.h>
- +#include <linux/ioport.h>
- +#include <linux/interrupt.h>
- +#include <linux/spinlock.h>
- +#include <linux/init.h>
- +#include <asm/hardware.h>
- +#include <asm/irq.h>
- +#include <asm/system.h>
- +#include <asm/mach/pci.h>
- +#include <asm/io.h>
- +#include <asm/sizes.h>
- +#include <asm/ftpci.h>
- +#include <asm/spec.h>
- +#include <asm/mach-types.h>
- +
- +#define IPMODULE PCIC
- +#define IPNAME FTPCI100
- +
- +#define DEBUGFPCI
- +#undef DEBUGFPCI
- +
- +#ifdef DEBUGFPCI
- +#define DBGFPCI(x...) printk(x)
- +#else
- +#define DBGFPCI(x...)
- +#endif
- +#define FPCI_VA_BASE IP_VA_BASE(0)
- +#define FTPCI_PCI_BRIDGE_VENID PCI_BRIDGE_VENID
- +#define FPCI_IO_VA_BASE PCIIO_VA_BASE
- +#define FPCI_IO_PA_BASE PCIIO_PA_BASE
- +#define FPCI_IO_VA_END PCIIO_VA_LIMIT
- +#define FPCI_MEM_VA_BASE PCIMEM_VA_BASE
- +#define FPCI_MEM_PA_BASE PCIMEM_PA_BASE
- +#define FPCI_MEM_VA_END PCIMEM_VA_LIMIT
- +#define FPCI_MEM_PA_END (PCIMEM_PA_BASE + SZ_256M)
- +
- +// --------------------------------------------------------------------
- +// AHB Control Register
- +// --------------------------------------------------------------------
- +#define FTPCI_IOSIZE_REG 0x0
- +#define FTPCI_PROT_REG 0x4
- +#define FTPCI_CTRL_REG 0x8
- +#define FTPCI_ERREN_REG 0xc
- +#define FTPCI_SOFTRST_REG 0x10
- +#define FTPCI_EN64_REG 0x14
- +#define FTPCI_ADDRH32_REG 0x18
- +#define FTPCI_CFG_ADR_REG 0x28
- +#define FTPCI_CFG_DATA_REG 0x2c
- +
- +// --------------------------------------------------------------------
- +// FTPCI_IOSIZE_REG's constant definitions
- +// --------------------------------------------------------------------
- +#define FTPCI_BASE_IO_SIZE_1M 0x0
- +#define FTPCI_BASE_IO_SIZE_2M 0x1
- +#define FTPCI_BASE_IO_SIZE_4M 0x2
- +#define FTPCI_BASE_IO_SIZE_8M 0x3
- +#define FTPCI_BASE_IO_SIZE_16M 0x4
- +#define FTPCI_BASE_IO_SIZE_32M 0x5
- +#define FTPCI_BASE_IO_SIZE_64M 0x6
- +#define FTPCI_BASE_IO_SIZE_128M 0x7
- +#define FTPCI_BASE_IO_SIZE_256M 0x8
- +#define FTPCI_BASE_IO_SIZE_512M 0x9
- +#define FTPCI_BASE_IO_SIZE_1G 0xa
- +#define FTPCI_BASE_IO_SIZE_2G 0xb
- +
- +// --------------------------------------------------------------------
- +// PCI Configuration Register
- +// --------------------------------------------------------------------
- +#define PCI_INT_MASK 0x4c
- +#define PCI_MEM_BASE_SIZE1 0x50
- +#define PCI_MEM_BASE_SIZE2 0x54
- +#define PCI_MEM_BASE_SIZE3 0x58
- +
- +// --------------------------------------------------------------------
- +// PCI_INT_MASK's bit definitions
- +// --------------------------------------------------------------------
- +#define PCI_INTA_ENABLE (1U<<22)
- +#define PCI_INTB_ENABLE (1U<<23)
- +#define PCI_INTC_ENABLE (1U<<24)
- +#define PCI_INTD_ENABLE (1U<<25)
- +
- +// --------------------------------------------------------------------
- +// PCI_MEM_BASE_SIZE1's constant definitions
- +// --------------------------------------------------------------------
- +#define FTPCI_BASE_ADR_SIZE_1MB (PHYS_OFFSET | (0x0<<16))
- +#define FTPCI_BASE_ADR_SIZE_2MB (PHYS_OFFSET | (0x1<<16))
- +#define FTPCI_BASE_ADR_SIZE_4MB (PHYS_OFFSET | (0x2<<16))
- +#define FTPCI_BASE_ADR_SIZE_8MB (PHYS_OFFSET | (0x3<<16))
- +#define FTPCI_BASE_ADR_SIZE_16MB (PHYS_OFFSET | (0x4<<16))
- +#define FTPCI_BASE_ADR_SIZE_32MB (PHYS_OFFSET | (0x5<<16))
- +#define FTPCI_BASE_ADR_SIZE_64MB (PHYS_OFFSET | (0x6<<16))
- +#define FTPCI_BASE_ADR_SIZE_128MB (PHYS_OFFSET | (0x7<<16))
- +#define FTPCI_BASE_ADR_SIZE_256MB (PHYS_OFFSET | (0x8<<16))
- +#define FTPCI_BASE_ADR_SIZE_512MB (PHYS_OFFSET | (0x9<<16))
- +#define FTPCI_BASE_ADR_SIZE_1GB (PHYS_OFFSET | (0xa<<16))
- +#define FTPCI_BASE_ADR_SIZE_2GB (PHYS_OFFSET | (0xb<<16))
- +
- +#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3) )
- +
- +struct pci_dev *pci_bridge = NULL;
- +static unsigned int pci_config_addr;
- +static unsigned int pci_config_data;
- +int ftpci_probed = 0;
- +
- +static struct resource pcic_resource = {
- + .name = "Faradat PCIC",
- + .start = IP_VA_BASE(0),
- + .end = IP_VA_LIMIT(0),
- +};
- +
- +// Luke Lee 03/21/2005 mod begin
- +static int ftpci_read_config_byte(struct pci_bus *bus, unsigned int devfn,
- + int where, u8 * val)
- +{
- + u32 v;
- + unsigned int shift;
- +
- + outl(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
- + v = inl(pci_config_data);
- + shift = (where & 0x3) * 8;
- + *val = (v >> shift) & 0xff;
- + return PCIBIOS_SUCCESSFUL;
- +}
- +
- +static int ftpci_read_config_word(struct pci_bus *bus, unsigned int devfn,
- + int where, u16 * val)
- +{
- + u32 v;
- + unsigned int shift;
- +
- + outl(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
- + v = inl(pci_config_data);
- + shift = (where & 0x3) * 8;
- + *val = (v >> shift) & 0xffff;
- + return PCIBIOS_SUCCESSFUL;
- +}
- +
- +static int ftpci_read_config_dword(struct pci_bus *bus, unsigned int devfn,
- + int where, u32 * val)
- +{
- + u32 v;
- +
- + outl(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
- + v = inl(pci_config_data);
- + *val = v;
- + return PCIBIOS_SUCCESSFUL;
- +}
- +
- +static int ftpci_write_config_byte(struct pci_bus *bus, unsigned int devfn,
- + int where, u8 val)
- +{
- + u32 org_val;
- + unsigned int shift;
- +
- + shift = (where & 0x3) * 8;
- + outl(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
- + org_val = inl(pci_config_data);
- + org_val = (org_val & ~(0xff << shift)) | ((u32) val << shift);
- + outl(org_val, pci_config_data);
- + return PCIBIOS_SUCCESSFUL;
- +}
- +
- +static int ftpci_write_config_word(struct pci_bus *bus, unsigned int devfn,
- + int where, u16 val)
- +{
- + u32 org_val;
- + unsigned int shift;
- +
- + shift = (where & 0x3) * 8;
- + outl(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
- + org_val = inl(pci_config_data);
- + org_val = (org_val & ~(0xffff << shift)) | ((u32) val << shift);
- + outl(org_val, pci_config_data);
- + return PCIBIOS_SUCCESSFUL;
- +}
- +
- +static int ftpci_write_config_dword(struct pci_bus *bus, unsigned int devfn,
- + int where, u32 val)
- +{
- + outl(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
- + outl(val, pci_config_data);
- + return PCIBIOS_SUCCESSFUL;
- +}
- +
- +// Luke Lee 03/21/2005 mod end
- +
- +// Luke Lee 03/21/2005 ins begin
- +static int ftpci_read_config(struct pci_bus *bus, unsigned int devfn, int where,
- + int size, u32 * val)
- +{
- + int r;
- + switch (size) {
- + case 1:
- + r = ftpci_read_config_byte(bus, devfn, where, (u8 *) val); // Luke Lee TOFIX 03/22/2005 : convert to (u8*) -- beware of endian !
- + break;
- + case 2:
- + r = ftpci_read_config_word(bus, devfn, where, (u16 *) val); // Luke Lee TOFIX 03/22/2005 : convert to (u16*) -- beware of endian !
- + break;
- +
- + default:
- + r = ftpci_read_config_dword(bus, devfn, where, val);
- + break;
- + }
- +
- + return r;
- +}
- +
- +static int ftpci_write_config(struct pci_bus *bus, unsigned int devfn,
- + int where, int size, u32 val)
- +{
- + int r;
- + switch (size) {
- + case 1:
- + r = ftpci_write_config_byte(bus, devfn, where, val);
- + break;
- + case 2:
- + r = ftpci_write_config_word(bus, devfn, where, val);
- + break;
- +
- + case 4:
- + r = ftpci_write_config_dword(bus, devfn, where, val);
- + break;
- + default:
- + printk("Invalid size for ftpci_write()\n");
- + r = PCIBIOS_FUNC_NOT_SUPPORTED; // Luke Lee 03/23/2005 ins 1
- + }
- +
- + return r;
- +}
- +
- +// Luke Lee 03/21/2005 ins end
- +
- +static struct pci_ops ftpci_ops = {
- + // Luke Lee 03/21/2005 mod begin
- + .read = ftpci_read_config,
- + .write = ftpci_write_config,
- + // Luke Lee 03/21/2005 mod end
- +};
- +
- +/* using virtual address for pci_resource_start() function*/
- +static struct resource pci_io = {
- + .name = "Faraday PCI I/O Space",
- + .start = FPCI_IO_VA_BASE,
- + .end = FPCI_IO_VA_END,
- + .flags = IORESOURCE_IO,
- +};
- +
- +/* using physical address for memory resource*/
- +static struct resource pci_mem = {
- + .name = "Faraday PCI non-prefetchable Memory Space",
- + .start = FPCI_MEM_PA_BASE,
- + .end = FPCI_MEM_PA_END,
- + .flags = IORESOURCE_MEM,
- +};
- +
- +// Luke Lee 03/23/2005 unrem 1 rem 1
- +int __init ftpci_setup_resource(struct resource **resource)
- +{
- + DBGFPCI("PCI I/O space from %08lX to %08lX\n", pci_io.start,
- + pci_io.end);
- + DBGFPCI("PCI Memory space from %08lX to %08lX\n", pci_mem.start,
- + pci_mem.end);
- + if (request_resource(&ioport_resource, &pci_io)) {
- + printk(KERN_ERR "PCI: unable to allocate io region\n");
- + return -EBUSY; // Luke Lee 03/23/2005 unrem 1
- + }
- + if (request_resource(&iomem_resource, &pci_mem)) {
- + printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
- + "memory region\n");
- + return -EBUSY; // Luke Lee 03/23/2005 unrem 1
- + }
- +
- + /*
- + * bus->resource[0] is the IO resource for this bus
- + * bus->resource[1] is the mem resource for this bus
- + * bus->resource[2] is the prefetch mem resource for this bus
- + */
- +
- + resource[0] = &pci_io;
- + resource[1] = &pci_mem;
- + resource[2] = NULL;
- +
- + return 1; // Luke Lee 03/23/2005 unrem 1
- +}
- +
- +int ftpci_get_irq(void)
- +{
- + unsigned int status;
- + ftpci_read_config_dword(pci_bridge->bus, pci_bridge->devfn, 0x4c, &status); // Luke Lee 03/22/2005 mod 1
- + DBGFPCI("ftpci_get_irq,status=0x%x\n", status);
- + status = (status >> 28);
- + if (status & 0x1)
- + return 0;
- + if (status & 0x2)
- + return 1;
- + if (status & 0x4)
- + return 2;
- + if (status & 0x8)
- + return 3;
- + return -1;
- +}
- +
- +void ftpci_clear_irq(unsigned int irq)
- +{
- + //int i;
- + unsigned int status;
- + ftpci_read_config_dword(pci_bridge->bus, pci_bridge->devfn, 0x4c, &status); // Luke Lee 03/22/2005 mod 1
- + if (irq == 0)
- + status = (status & 0xfffffff) | ((0x1) << 28);
- + else if (irq == 1)
- + status = (status & 0xfffffff) | ((0x2) << 28);
- + else if (irq == 2)
- + status = (status & 0xfffffff) | ((0x4) << 28);
- + else if (irq == 3)
- + status = (status & 0xfffffff) | ((0x8) << 28);
- + ftpci_write_config_dword(pci_bridge->bus, pci_bridge->devfn, 0x4c, status); // Luke Lee 03/22/2005 mod 1
- +}
- +
- +void ftpci_unmask_irq(unsigned int irq)
- +{
- + u32 val;
- + ftpci_read_config_dword(pci_bridge->bus, pci_bridge->devfn,
- + PCI_INT_MASK, &val);
- + val |= (PCI_INTA_ENABLE << irq);
- + ftpci_write_config_dword(pci_bridge->bus, pci_bridge->devfn,
- + PCI_INT_MASK, val);
- +}
- +
- +void ftpci_mask_irq(unsigned int irq)
- +{
- + u32 val;
- + ftpci_read_config_dword(pci_bridge->bus, pci_bridge->devfn,
- + PCI_INT_MASK, &val);
- + val &= ~(PCI_INTA_ENABLE << irq);
- + ftpci_write_config_dword(pci_bridge->bus, pci_bridge->devfn,
- + PCI_INT_MASK, val);
- +}
- +
- +static int ftpci_probe(unsigned int addr_p)
- +{
- + unsigned int *addr = (unsigned int *)addr_p;
- + *(volatile unsigned int *)addr = 0x80000000;
- + if (*(volatile unsigned int *)addr == 0x80000000) {
- + DBGFPCI("Faraday FPCI bridge probed ok\n");
- + ftpci_probed = 1;
- + } else {
- + ftpci_probed = 0;
- + }
- + *(volatile unsigned int *)addr = 0x0;
- + return ftpci_probed;
- +}
- +
- +void __init ftpci_preinit(void /**sysdata*/ ) // Luke Lee 03/22/2005 mod 1
- +{
- + DBGFPCI("ftpci_preinit()\n\r");
- +
- +#ifdef CONFIG_PLAT_AG101
- + /* Walk around for A321 but remove after leopard pci */
- + *(volatile unsigned long *)(FPCI_VA_BASE + 0x8) = 0x10;
- +#endif
- +
- + pci_config_addr = FPCI_VA_BASE + FTPCI_CFG_ADR_REG;
- + pci_config_data = FPCI_VA_BASE + FTPCI_CFG_DATA_REG;
- + DBGFPCI("Config addr is %08X, data port is %08X\n",
- + (int)pci_config_addr, (int)pci_config_data);
- +
- + if (!ftpci_probe(pci_config_addr))
- + return;
- +}
- +
- +void ftpci_postinit(void /**sysdata*/ )
- +{
- + u32 val;
- + DBGFPCI("ftpci_postinit()\n\r");
- + pci_bridge = pci_get_device(PCI_BRIDGE_VENID, PCI_BRIDGE_DEVID, NULL);
- + if (pci_bridge == NULL)
- + return;
- + // Enable the Interrupt Mask (INTA/INTB/INTC/INTD)
- + ftpci_read_config_dword(pci_bridge->bus, pci_bridge->devfn, PCI_INT_MASK, &val); // Luke Lee 03/22/2005 mod 1
- + val |=
- + (PCI_INTA_ENABLE | PCI_INTB_ENABLE | PCI_INTC_ENABLE |
- + PCI_INTD_ENABLE);
- + ftpci_write_config_dword(pci_bridge->bus, pci_bridge->devfn, PCI_INT_MASK, val); // Luke Lee 03/22/2005 mod 1
- +
- + // Write DMA Start Address/Size Data to the Bridge configuration space
- + ftpci_write_config_dword(pci_bridge->bus, pci_bridge->devfn, PCI_MEM_BASE_SIZE1, FTPCI_BASE_ADR_SIZE_1GB); // Luke Lee 03/22/2005 mod 1
- + DBGFPCI("%s: Post init ok\n", __func__);
- +}
- +
- +/*
- + * This routine handles multiple bridges.
- + */
- +static u8 __init fpci_swizzle(struct pci_dev *dev, u8 * pinp)
- +{
- + // If there are one more bridges on our platfrom, we need to implement this function.
- + DBGFPCI("a320_swizzle(%X,%X)\n\r", (unsigned)dev, (unsigned)pinp);
- + return 0;
- +}
- +
- +static int __init fpci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
- +{
- + DBGFPCI("a320_map_irq,slot=%d pin=%d\n", PCI_SLOT(dev->devfn), pin);
- + switch ((PCI_SLOT(dev->devfn) + pin - 8 - 1) % 4) {
- + case 0:
- + return IP_IRQ0(0);
- + case 1:
- + return IP_IRQ1(0);
- + case 2:
- + return IP_IRQ2(0);
- + case 3:
- + return IP_IRQ3(0);
- + default:
- + printk(KERN_ERR "Not Support Slot %d\n", slot);
- + break;
- + }
- + return -1;
- +}
- +
- +int __init ftpci_setup(int nr, struct pci_sys_data *sys)
- +{
- + int ret = 0;
- + if (nr == 0) {
- + ret = ftpci_setup_resource(sys->resource);
- +// sys->mem_offset = FPCI_MEM_VA_BASE - FPCI_MEM_PA_BASE;
- + sys->mem_offset = 0;
- + sys->io_offset = FPCI_IO_VA_BASE - FPCI_IO_PA_BASE;
- + }
- + return ret;
- +}
- +
- +static struct pci_bus *__devinit ftpci_scan_bus(int nr,
- + struct pci_sys_data *sys)
- +{
- + return pci_scan_bus(sys->busnr, &ftpci_ops, sys);
- +}
- +
- +static struct hw_pci a320_pci __initdata = {
- + .swizzle = fpci_swizzle,
- + .map_irq = fpci_map_irq,
- + .setup = ftpci_setup,
- + .nr_controllers = 1,
- + .scan = ftpci_scan_bus,
- + .preinit = ftpci_preinit, /* The first called init function */
- + .postinit = ftpci_postinit, /* It is called after hw init and scanned PCI bus */
- +};
- +
- +static int __init fpci_init(void)
- +{
- +#ifdef MODULE
- + printk(KERN_INFO "Faraday PCI driver Init");
- +#endif
- + printk(KERN_DEBUG "Init A321 PCI bridge controller\n");
- + /* Register I/O address range of this PCI Bridge Controller */
- + DBGFPCI("Name:%s, Base=%lX, End=%lX\n", pcic_resource.name,
- + pcic_resource.start, pcic_resource.end);
- + request_resource(&ioport_resource, &pcic_resource);
- + pci_common_init(&a320_pci);
- + return 0;
- +}
- +
- +subsys_initcall(fpci_init);
- +
- +EXPORT_SYMBOL(ftpci_probed);
- +EXPORT_SYMBOL(ftpci_clear_irq);
- +EXPORT_SYMBOL(ftpci_get_irq);
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/intc.c linux-3.4.110/arch/nds32/platforms/intc.c
- --- linux-3.4.110.orig/arch/nds32/platforms/intc.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/intc.c 2016-04-07 10:20:51.018083964 +0200
- @@ -0,0 +1,257 @@
- +/*
- + * linux/arch/nds32/platforms/intc.c
- + *
- + * Faraday FTINTC010 Master Interrupt Controller Device Driver Implementation
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + * Note
- + *
- + * This program implements only the master INTC of the platform. Slave INTCs must
- + * be initialized by themselves.
- + *
- + * ChangeLog
- + *
- + * Luke Lee 09/14/2005 Created.
- + */
- +
- +#include <linux/irq.h>
- +#include <linux/interrupt.h>
- +#include <linux/ioport.h>
- +#include <asm/io.h>
- +
- +#include <asm/intc.h>
- +#include <asm/spec.h>
- +#include <asm/ftpci.h>
- +
- +#define IPMODULE INTC
- +#define IPNAME FTINTC010
- +
- +/*
- + * Edge trigger IRQ chip methods
- + */
- +#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
- +spinlock_t irq_chip_lock;
- +#endif
- +
- +static void intc_ftintc010_ack_irq(struct irq_data *data)
- +{
- + unsigned int tmp;
- +
- + // ack and disable
- +#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
- + spin_lock_irq(&irq_chip_lock);
- +#endif
- + *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_CLEAR_REG) = 1 << data->irq;
- + tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_CLEAR_REG);
- + tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MODE_REG);
- +
- + if (!(tmp & (1UL << data->irq))) { /* level trigger */
- +
- + *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MASK_REG) &=
- + ~(1 << data->irq);
- + tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MASK_REG);
- + }
- +#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
- + spin_unlock_irq(&irq_chip_lock);
- +#endif
- +}
- +
- +static void intc_ftintc010_mask_irq(struct irq_data *data)
- +{
- + unsigned int tmp;
- +
- + // disable
- +#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
- + spin_lock_irq(&irq_chip_lock);
- +#endif
- + *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MASK_REG) &=
- + ~(1 << data->irq);
- + tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MASK_REG);
- +#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
- + spin_unlock_irq(&irq_chip_lock);
- +#endif
- +}
- +
- +static void intc_ftintc010_mask_ack_irq(struct irq_data *data)
- +{
- + unsigned int tmp;
- +
- + // disable
- +#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
- + spin_lock_irq(&irq_chip_lock);
- +#endif
- + *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MASK_REG) &=
- + ~(1 << data->irq);
- + tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MASK_REG);
- +
- + *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_CLEAR_REG) = 1 << data->irq;
- + tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_CLEAR_REG);
- +
- +#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
- + spin_unlock_irq(&irq_chip_lock);
- +#endif
- +}
- +
- +static void intc_ftintc010_unmask_irq(struct irq_data *data)
- +{
- + unsigned int tmp;
- +
- + // enable
- +#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
- + spin_lock_irq(&irq_chip_lock);
- +#endif
- + *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MASK_REG) |= 1 << data->irq;
- + tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MASK_REG);
- +#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
- + spin_unlock_irq(&irq_chip_lock);
- +#endif
- +}
- +
- +static int intc_ftintc010_set_type(struct irq_data *data,
- + unsigned int flow_type)
- +{
- +#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
- + spin_lock_irq(&irq_chip_lock);
- +#endif
- + /*
- + * IRQ Trigger Mode Register 1: edge
- + * IRQ Trigger Level Register 1: active high
- + */
- +
- + int tmp;
- +
- + if (flow_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW)) {
- +
- + *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_LEVEL_REG) &=
- + ~(1UL << data->irq);
- + tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_LEVEL_REG);
- + }
- +
- + if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH)) {
- +
- + *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_LEVEL_REG) |=
- + (1UL << data->irq);
- + tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_LEVEL_REG);
- + }
- +
- + if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
- +
- + *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MODE_REG) |=
- + (1UL << data->irq);
- + tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MODE_REG);
- + (irq_desc + data->irq)->handle_irq = handle_edge_irq;
- + }
- +
- + if (flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) {
- +
- + *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MODE_REG) &=
- + ~(1UL << data->irq);
- + tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MODE_REG);
- + (irq_desc + data->irq)->handle_irq = handle_level_irq;
- + }
- +#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
- + spin_unlock_irq(&irq_chip_lock);
- +#endif
- + return 0;
- +}
- +
- +static struct irq_chip intc_ftintc010_chip = {
- +
- + .irq_ack = intc_ftintc010_ack_irq,
- + .irq_mask = intc_ftintc010_mask_irq,
- + .irq_mask_ack = intc_ftintc010_mask_ack_irq,
- + .irq_unmask = intc_ftintc010_unmask_irq,
- + .irq_set_type = intc_ftintc010_set_type,
- +};
- +
- +static struct resource intc_resource = {
- +
- + .name = "Main interrupt controller",
- + .start = IP_VA_BASE(0),
- + .end = IP_VA_BASE(0) + IP_VA_SIZE(0),
- +};
- +
- +/*
- + * Initialization of master interrupt controller, after this INTC is
- + * enabled, the rest of Linux initialization codes can then be completed.
- + * For example, timer interrupts and UART interrupts must be enabled during
- + * the boot process.
- + */
- +void __init intc_ftintc010_init_irq(void)
- +{
- + int i, edge;
- +
- +#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
- + spin_lock_init(&irq_chip_lock);
- +#endif
- + /* Initialize the INTC */
- + outl(0x00000000, IP_VA_BASE(0) + IRQ_MASK_REG);
- + outl(0x00000000, IP_VA_BASE(0) + FIQ_MASK_REG);
- + outl(0xffffffff, IP_VA_BASE(0) + IRQ_CLEAR_REG);
- + outl(0xffffffff, IP_VA_BASE(0) + FIQ_CLEAR_REG);
- + outl(PLATFORM_IRQ_TRIGGER_MODE, IP_VA_BASE(0) + IRQ_MODE_REG);
- + /* FTINTC010: bit 0=active high or rising edge, 1=active low or falling edge. */
- + outl(PLATFORM_IRQ_TRIGGER_LEVEL, IP_VA_BASE(0) + IRQ_LEVEL_REG);
- +
- + /* Register all IRQ */
- + for (i = PLATFORM_IRQ_BASE, edge = 1;
- + i < PLATFORM_IRQ_BASE + PLATFORM_IRQ_TOTALCOUNT; i++, edge <<= 1) {
- +
- + irq_set_chip(i, &intc_ftintc010_chip);
- +
- + if (PLATFORM_IRQ_TRIGGER_MODE & edge) /* edge trigger */
- + irq_set_handler(i, handle_edge_irq);
- +
- + else /* level trigger */
- + irq_set_handler(i, handle_level_irq);
- + }
- +
- + /* Register I/O address range of this INTC */
- + request_resource(&ioport_resource, &intc_resource);
- +
- +}
- +
- +unsigned int get_IntSrc(void)
- +{
- + unsigned int irq_status, irq = 31;
- +
- + irq_status = inl(IP_VA_BASE(0) + IRQ_STATUS_REG);
- + if (irq_status == 0)
- + return 32;
- + if (irq_status & 0x0000ffff) {
- + irq -= 16;
- + irq_status <<= 16;
- + }
- + if (irq_status & 0x00ff0000) {
- + irq -= 8;
- + irq_status <<= 8;
- + }
- + if (irq_status & 0x0f000000) {
- + irq -= 4;
- + irq_status <<= 4;
- + }
- + if (irq_status & 0x30000000) {
- + irq -= 2;
- + irq_status <<= 2;
- + }
- + if (irq_status & 0x40000000) {
- + irq -= 1;
- + }
- + return irq;
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/Kconfig linux-3.4.110/arch/nds32/platforms/Kconfig
- --- linux-3.4.110.orig/arch/nds32/platforms/Kconfig 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/Kconfig 2016-04-07 10:20:51.018083964 +0200
- @@ -0,0 +1,122 @@
- +choice
- + prompt "platform type"
- + default PLAT_AG101P
- +
- +config PLAT_VEP
- + bool "vep platform"
- + select CPU_CUSTOM
- + select PLATFORM_INTC
- +
- +config PLAT_AG101
- + bool "ag101 platform"
- + select CPU_N1213
- + select CPU_N1213_43U1HA0
- + select PLATFORM_INTC
- +
- +config PLAT_AG102
- + bool "ag102 platform"
- + select CPU_N1233F
- + select PLATFORM_AMIC
- +
- +config PLAT_AG101P
- + bool "ag101p platform"
- + select CPU_CUSTOM
- + select PLATFORM_INTC if !IVIC
- + select PLATFORM_NOINTC if IVIC
- +
- +config PLAT_QEMU
- + bool "qemu platform"
- + select CPU_CUSTOM
- + select PLATFORM_INTC
- +endchoice
- +
- +config PLATFORM_NOINTC
- + def_bool n
- + depends on PLAT_AG101P
- +
- +config PLATFORM_INTC
- + def_bool n
- + depends on !PLAT_AG102
- +
- +config PLATFORM_AMIC
- + def_bool n
- + depends on PLAT_AG102
- +
- +config ARCH_WANT_OPTIONAL_GPIOLIB
- + bool "Arch Want Optional GPIOLIB"
- + default y
- +
- +if PLAT_VEP
- +source "arch/nds32/platforms/vep/Kconfig"
- +endif
- +
- +if PLAT_AG101
- +source "arch/nds32/platforms/ag101/Kconfig"
- +endif
- +
- +if PLAT_AG102
- +source "arch/nds32/platforms/ag102/Kconfig"
- +endif
- +
- +if PLAT_AG101P
- +source "arch/nds32/platforms/ag101p/Kconfig"
- +endif
- +
- +if PLAT_QEMU
- +source "arch/nds32/platforms/qemu/Kconfig"
- +endif
- +
- +menu "Common Platform Options"
- +
- +config PLATFORM_AHBDMA
- + tristate "AHB DMA Support"
- + help
- + AHB DMA service API support for other device drivers
- +
- +config PLATFORM_APBDMA
- + tristate "APB DMA Support"
- + help
- + AHB DMA service API support for other device drivers
- +
- +config SYS_CLK
- + int "AHB System Clock"
- + default 67737600
- + help
- + Manual setting of AHB clock, must match the jumper setting on
- + the board, or the system time won't be correctly calculated.
- + Notice that even when AUTO_SYS_CLK is ON, this value is still
- + required for adjusting minor time offsets. However, the influence
- + should be within micro-second to nano-second scale.
- +
- +config UART_CLK
- + int "UART Clock"
- + default 18432000
- + help
- + Change the UART clock in case of non-3.6864MHz OSC is used as main
- + clock source, or an external UART clock source is fed from GPIO23.
- + To support external UART clock from GPIO23, set PMU
- + "Multi-Function Port Setting Register" bit #8 (UartClkSel) to 1.
- + This control register can be found at physical address 0x98100028
- + If this options is changed, please also append "38400" to your
- + kernel command line, e.g.:
- + console=uart,shift,2,io,0xF9820000,38400
- + Note: For A320, the default UART clock is obtained by = 5 * OSC =
- + 5 * 3.6864MHz = 18.432MHz.
- +
- +menu "Memory configuration"
- +
- +config SDRAM_SIZE
- + hex "SDRAM Size (hex)"
- + default 4000000
- + ---help---
- + RAM size
- +
- +config MEMORY_START
- + hex "Physical memory start address"
- + default "0x00000000"
- + ---help---
- + Physical memory start address, you may modify it if it is porting to
- + a new SoC with different start address.
- +endmenu
- +
- +endmenu
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/Makefile linux-3.4.110/arch/nds32/platforms/Makefile
- --- linux-3.4.110.orig/arch/nds32/platforms/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/Makefile 2016-04-07 10:20:51.018083964 +0200
- @@ -0,0 +1,25 @@
- +obj-y := timer.o
- +
- +ifdef CONFIG_FUNCTION_TRACER
- +CFLAGS_REMOVE_timer.o = -pg
- +endif
- +
- +obj-$(CONFIG_PLATFORM_NOINTC) += nointc.o
- +obj-$(CONFIG_PLATFORM_INTC) += intc.o
- +obj-$(CONFIG_PLATFORM_AMIC) += amic.o
- +
- +ifeq ("$(CONFIG_PLATFORM_AHBDMA)", "y")
- + obj-y += dmad_intc.o dmad.o
- +else
- + ifeq ("$(CONFIG_PLATFORM_APBDMA)", "y")
- + obj-y += dmad_intc.o dmad.o
- + endif
- +endif
- +
- +obj-$(CONFIG_PCI) += ftpci.o pci_intc.o
- +
- +obj-$(CONFIG_PLAT_VEP) += vep/
- +obj-$(CONFIG_PLAT_AG101) += ag101/
- +obj-$(CONFIG_PLAT_AG102) += ag102/
- +obj-$(CONFIG_PLAT_AG101P) += ag101p/
- +obj-$(CONFIG_PLAT_QEMU) += qemu/
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/nointc.c linux-3.4.110/arch/nds32/platforms/nointc.c
- --- linux-3.4.110.orig/arch/nds32/platforms/nointc.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/nointc.c 2016-04-07 10:20:51.018083964 +0200
- @@ -0,0 +1,134 @@
- +/*
- + * linux/arch/nds32/platforms/intc.c
- + *
- + * Faraday FTINTC010 Master Interrupt Controller Device Driver Implementation
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + */
- +
- +#include <linux/irq.h>
- +
- +static void nointc_ack_irq(struct irq_data *data)
- +{
- + SET_INT_PEND2(1 << data->irq);
- +#if 0
- + asm volatile ("mtsr %0, $INT_PEND2\n\t"
- + "dsb\n\t"::"r" (1 << data->irq));
- +#endif
- +#if 0
- + asm volatile ("mfsr $r6, $INT_MASK2\n\t"
- + "and $r6, $r6,%0\n\t"
- + "mtsr $r6, $INT_MASK2\n\t"
- + "dsb\n\t"::"r" (~(1 << data->irq)):"$r6");
- +#endif
- +}
- +
- +static void nointc_mask_irq(struct irq_data *data)
- +{
- + unsigned long int_mask2 = GET_INT_MASK2();
- + SET_INT_MASK2(int_mask2 & (~(1 << data->irq)));
- +#if 0
- + asm volatile ("mfsr $r6, $INT_MASK2\n\t"
- + "and $r6, $r6,%0\n\t"
- + "mtsr $r6, $INT_MASK2\n\t"
- + "dsb\n\t"::"r" (~(1 << data->irq)):"$r6");
- +#endif
- +}
- +
- +static void nointc_mask_ack_irq(struct irq_data *data)
- +{
- + unsigned long int_mask2 = GET_INT_MASK2();
- + SET_INT_MASK2(int_mask2 & (~(1 << data->irq)));
- + SET_INT_PEND2(1 << data->irq);
- +#if 0
- + asm volatile ("not $r7, %0\n\t"
- + "mfsr $r6, $INT_MASK2\n\t"
- + "and $r6, $r6, $r7\n\t"
- + "mtsr $r6, $INT_MASK2\n\t"
- + "mtsr %0, $INT_PEND2\n\t"
- + "dsb\n\t"::"r" (1 << data->irq):"$r6", "$r7");
- +#endif
- +
- +}
- +
- +static void nointc_unmask_irq(struct irq_data *data)
- +{
- + unsigned long int_mask2 = GET_INT_MASK2();
- + SET_INT_MASK2(int_mask2 | (1 << data->irq));
- +#if 0
- + asm volatile ("mfsr $r6, $INT_MASK2\n\t"
- + "or $r6, $r6,%0\n\t"
- + "mtsr $r6, $INT_MASK2\n\t"
- + "dsb\n\t"::"r" (1 << data->irq):"$r6");
- +#endif
- +}
- +
- +static int nointc_set_type(struct irq_data *data, unsigned int flow_type)
- +{
- + printk(KERN_WARNING "interrupt type is not configurable\n");
- + return 0;
- +}
- +
- +static struct irq_chip nointc_chip = {
- +
- + .irq_ack = nointc_ack_irq,
- + .irq_mask = nointc_mask_irq,
- + .irq_mask_ack = nointc_mask_ack_irq,
- + .irq_unmask = nointc_unmask_irq,
- + .irq_set_type = nointc_set_type,
- +};
- +
- +static unsigned int __initdata nivic_map[6] = { 6, 2, 10, 16, 24, 32 };
- +
- +void __init nointc_init_irq(void)
- +{
- + int i;
- + unsigned long int_trigger_type, int_vec_base, nivic;
- +
- + int_vec_base = GET_IVB();
- +
- +#if 0
- + asm volatile ("mfsr %0, $IVB\n":"=r" (int_vec_base));
- +#endif
- +
- + if (((int_vec_base & IVB_mskIVIC_VER) >> IVB_offIVIC_VER) == 0) {
- + panic("Unable to use NOINTC option to boot on this cpu\n");
- + }
- +
- + nivic = (int_vec_base & IVB_mskNIVIC) >> IVB_offNIVIC;
- + if (nivic >= (sizeof nivic_map / sizeof nivic_map[0])) {
- + panic
- + ("The number of input for IVIC Controller is not supported on this cpu\n");
- + }
- + nivic = nivic_map[nivic];
- +
- + int_trigger_type = GET_INT_TRIGGER();
- +#if 0
- + asm volatile ("mfsr %0, $INT_TRIGGER\n":"=r" (int_trigger_type));
- +#endif
- +
- + for (i = 0; i < nivic; i++) {
- + irq_set_chip(i, &nointc_chip);
- + if (int_trigger_type & (1 << i))
- + /* edge-triggered */
- + irq_set_handler(i, handle_edge_irq);
- + else
- + /* level-triggered */
- + irq_set_handler(i, handle_level_irq);
- + }
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/pci_intc.c linux-3.4.110/arch/nds32/platforms/pci_intc.c
- --- linux-3.4.110.orig/arch/nds32/platforms/pci_intc.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/pci_intc.c 2016-04-07 10:20:51.018083964 +0200
- @@ -0,0 +1,93 @@
- +/*
- + * linux/arch/nds32/platforms/pci_intc.c
- + *
- + * Faraday PCI Bridge Interrupt Process Driver Implementation
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + * Copyright (C) 2008 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + *
- + * ChangeLog
- + *
- + * Luke Lee 09/15/2005 Created.
- + * Luke Lee 09/27/2005 Fixed for parent chip registration and notification.
- + * Peter Liao 09/28/2005 Port for PCI IP
- + */
- +
- +#include <linux/irq.h>
- +#include <linux/interrupt.h>
- +#include <linux/ioport.h>
- +#include <asm/io.h>
- +
- +#include <asm/spec.h>
- +#include <asm/ftpci.h>
- +
- +#define IPMODULE PCIC
- +#define IPNAME FPCI010
- +
- +/*
- + * Level trigger IRQ chip methods
- + */
- +
- +static void intc_ftpci100_level_ack_irq(unsigned int irq)
- +{
- + ftpci_clear_irq(irq - PLATFORM_PCI_IRQ_BASE);
- +}
- +
- +static void intc_ftpci100_level_mask_irq(unsigned int irq)
- +{
- + ftpci_mask_irq(irq - PLATFORM_PCI_IRQ_BASE);
- +}
- +
- +static void intc_ftpci100_level_unmask_irq(unsigned int irq)
- +{
- + ftpci_unmask_irq(irq - PLATFORM_PCI_IRQ_BASE);
- +}
- +
- +static struct irq_chip intc_ftpci100_level_chip = {
- + .ack = intc_ftpci100_level_ack_irq,
- + .mask = intc_ftpci100_level_mask_irq,
- + .unmask = intc_ftpci100_level_unmask_irq,
- +};
- +
- +void pci_irq_rounter(unsigned int irq, struct irq_desc *desc)
- +{
- + int pci_irq;
- + struct irq_desc *pci_desc;
- +
- + desc->chip->mask(irq);
- + desc->chip->ack(irq);
- +
- + pci_irq = ftpci_get_irq();
- + if (pci_irq >= 0) {
- + pci_irq += PCIC_FTPCI100_IRQ0;
- + pci_desc = irq_desc + pci_irq;
- + pci_desc->handle_irq(pci_irq, pci_desc);
- + }
- +
- + desc->chip->unmask(irq);
- +}
- +
- +int __init intc_ftpci100_init_irq(void)
- +{
- + int i;
- +
- + /* Register all IRQ */
- + for (i = PCIC_FTPCI100_IRQ0;
- + i < PCIC_FTPCI100_IRQ0 + PCIC_FTPCI100_IRQ_COUNT; i++) {
- + // level trigger
- + set_irq_chip(i, &intc_ftpci100_level_chip);
- + set_irq_handler(i, handle_level_irq);
- + }
- +#ifndef CONFIG_PLAT_AG101
- + set_irq_chained_handler(PLATFORM_PCI_IRQ, pci_irq_rounter);
- +#endif
- +
- + return 0;
- +}
- +
- +subsys_initcall(intc_ftpci100_init_irq);
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/qemu/devices.c linux-3.4.110/arch/nds32/platforms/qemu/devices.c
- --- linux-3.4.110.orig/arch/nds32/platforms/qemu/devices.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/qemu/devices.c 2016-04-07 10:20:51.018083964 +0200
- @@ -0,0 +1,124 @@
- +#include <linux/serial_8250.h>
- +#include <asm/mach-types.h>
- +#include <asm/sizes.h>
- +#include <asm/mach/arch.h>
- +#include <asm/mach/map.h>
- +#include <asm/spec.h>
- +#include <asm/intc.h>
- +#include <asm/timer.h>
- +
- +const struct map_desc platform_io_desc[] __initdata = {
- + {UART0_VA_BASE, UART0_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {UART1_VA_BASE, UART1_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {INTC_FTINTC010_0_VA_BASE, INTC_FTINTC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {TIMER_FTTMR010_0_VA_BASE, TIMER_FTTMR010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {SSP_FTSSP010_0_VA_BASE, SSP_FTSSP010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {PMU_FTPMU010_0_VA_BASE, PMU_FTPMU010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {MAC_FTMAC100_0_VA_BASE, MAC_FTMAC100_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {SDC_FTSDC010_0_VA_BASE, SDC_FTSDC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {RTC_FTRTC010_0_VA_BASE, RTC_FTRTC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {WDT_FTWDT010_0_VA_BASE, WDT_FTWDT010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {GPIO_FTGPIO010_0_VA_BASE, GPIO_FTGPIO010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {CFC_FTCFC010_0_VA_BASE, CFC_FTCFC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {LCD_FTLCDC100_0_VA_BASE, LCD_FTLCDC100_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {I2C_FTI2C010_0_VA_BASE, I2C_FTI2C010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {DMAC_FTDMAC020_0_VA_BASE, DMAC_FTDMAC020_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {APBBRG_FTAPBBRG020S_0_VA_BASE, APBBRG_FTAPBBRG020S_0_PA_BASE,
- + PAGE_SIZE, MT_DEVICE_NCB},
- + {PCIIO_0_VA_BASE, PCIIO_0_PA_BASE, 0x000FF000, MT_DEVICE_NCB},
- + {PCIC_FTPCI100_0_VA_BASE, PCIC_FTPCI100_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {LED_VA_BASE, LED_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {SDMC_FTSDMC021_VA_BASE, SDMC_FTSDMC021_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {L2CC_VA_BASE, L2CC_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB}
- +};
- +
- +static void __init platform_map_io(void)
- +{
- + iotable_init((struct map_desc *)platform_io_desc,
- + ARRAY_SIZE(platform_io_desc));
- +}
- +
- +static struct uart_port uart0 = {
- + .membase = (void __iomem *)UART0_VA_BASE,
- + .irq = UART0_IRQ,
- + .uartclk = CONFIG_UART_CLK,
- + .regshift = 2,
- + .iotype = UPIO_MEM,
- + .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
- + .line = 0,
- + .mapbase = UART0_PA_BASE,
- +};
- +
- +static struct uart_port uart1 = {
- + .membase = (void __iomem *)UART1_VA_BASE,
- + .irq = UART1_IRQ,
- + .uartclk = CONFIG_UART_CLK,
- + .regshift = 2,
- + .iotype = UPIO_MEM,
- + .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
- + .line = 1,
- + .mapbase = UART1_PA_BASE,
- +};
- +
- +static void __init soc_init(void)
- +{
- + early_serial_setup(&uart0);
- + early_serial_setup(&uart1);
- +}
- +
- +static struct resource smc91x_resources[] = {
- + [0] = {
- + .name = "smc91x",
- + .start = 0x92100000,
- + .end = 0x92110000,
- + .flags = IORESOURCE_MEM,
- + },
- + [1] = {
- + .start = 25,
- + .end = 25,
- + .flags = IORESOURCE_IRQ,
- + },
- +};
- +
- +static struct platform_device smc91x_device = {
- + .name = "smc91x",
- + .id = 0,
- + .num_resources = ARRAY_SIZE(smc91x_resources),
- + .resource = smc91x_resources,
- +};
- +
- +static __init int smc_init(void)
- +{
- + int ret;
- + ret = platform_device_register(&smc91x_device);
- + if (ret == 0)
- + printk("smc is installed now.\n");
- + else
- + printk("smc failed.\n");
- + return 0;
- +}
- +
- +module_init(smc_init);
- +
- +MACHINE_START(FARADAY, PLATFORM_NAME)
- + .param_offset = BOOT_PARAMETER_PA_BASE,
- + .map_io = platform_map_io,
- + .init_irq = platform_init_irq,
- + .timer = &platform_timer, /* defined in timer.c */
- + .init_machine = soc_init,
- +MACHINE_END
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/qemu/Kconfig linux-3.4.110/arch/nds32/platforms/qemu/Kconfig
- --- linux-3.4.110.orig/arch/nds32/platforms/qemu/Kconfig 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/qemu/Kconfig 2016-04-07 10:20:51.018083964 +0200
- @@ -0,0 +1,3 @@
- +menu "QEMU Platform Options"
- +
- +endmenu
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/qemu/Makefile linux-3.4.110/arch/nds32/platforms/qemu/Makefile
- --- linux-3.4.110.orig/arch/nds32/platforms/qemu/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/qemu/Makefile 2016-04-07 10:20:51.018083964 +0200
- @@ -0,0 +1 @@
- +obj-y = devices.o
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/timer.c linux-3.4.110/arch/nds32/platforms/timer.c
- --- linux-3.4.110.orig/arch/nds32/platforms/timer.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/timer.c 2016-04-07 10:20:51.018083964 +0200
- @@ -0,0 +1,250 @@
- +/*
- + * linux/arch/nds32/platforms/timer.c
- + *
- + * Faraday FTTMR010 Timer Device Driver Implementation
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + * Copyright (C) 2009 Andes Technology Corporation
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + */
- +
- +#include <linux/irq.h>
- +#include <linux/clocksource.h>
- +#include <linux/clockchips.h>
- +
- +#include <linux/interrupt.h>
- +#include <linux/ioport.h>
- +#include <linux/cpufreq.h>
- +
- +#include <asm/mach/time.h>
- +#include <asm/timer.h>
- +#include <asm/spec.h>
- +
- +#define REG32_TMR(x) *(volatile unsigned long *)(TIMER_FTTMR010_VA_BASE + (x))
- +#define APB_CLK_IN (AHB_CLK_IN / 2)
- +
- +static struct resource timer_resource = {
- + .name = "Timer 1~3",
- + .start = TIMER_FTTMR010_VA_BASE,
- + .end = TIMER_FTTMR010_VA_LIMIT,
- +};
- +
- +static inline cycle_t clocksource_read_cycles(struct clocksource *cs)
- +{
- + return (cycle_t) REG32_TMR(TIMER3_COUNT);
- +}
- +
- +static void clksrc_fttmr010_resume(struct clocksource *cs)
- +{
- + REG32_TMR(TIMER_INTRMASK) |= TM3MATCH1 | TM3MATCH2 | TM3OVERFLOW;
- + REG32_TMR(TIMER_TMCR) |= TM3UPDOWN | TM3ENABLE;
- +}
- +
- +static struct clocksource clksrc_fttmr010 = {
- + .name = "fttmr010_tm1",
- + .rating = 300,
- + .read = clocksource_read_cycles,
- + .mask = CLOCKSOURCE_MASK(32),
- + .shift = 21,
- + .flags = CLOCK_SOURCE_IS_CONTINUOUS,
- + .resume = clksrc_fttmr010_resume,
- +};
- +
- +static void __init fttmr010_clocksource_init(void)
- +{
- + clksrc_fttmr010.mult =
- + clocksource_hz2mult(APB_CLK_IN, clksrc_fttmr010.shift);
- +
- + REG32_TMR(TIMER3_LOAD) = 0;
- + REG32_TMR(TIMER_INTRMASK) |= TM3MATCH1 | TM3MATCH2 | TM3OVERFLOW;
- + REG32_TMR(TIMER_TMCR) |= TM3UPDOWN | TM3ENABLE;
- + if (clocksource_register(&clksrc_fttmr010))
- + printk(KERN_ERR "Error: failed to register %s\n",
- + clksrc_fttmr010.name);
- +}
- +
- +static int fttmr010_set_next_event(unsigned long cycles,
- + struct clock_event_device *evt)
- +{
- + REG32_TMR(TIMER1_LOAD) = cycles;
- + return 0;
- +}
- +
- +static void fttmr010_set_mode(enum clock_event_mode mode,
- + struct clock_event_device *evt)
- +{
- + switch (mode) {
- + case CLOCK_EVT_MODE_ONESHOT:
- + REG32_TMR(TIMER1_LOAD) = 0xffffffff;
- + REG32_TMR(TIMER_TMCR) |= TM1ENABLE;
- + break;
- +
- + case CLOCK_EVT_MODE_PERIODIC:
- + REG32_TMR(TIMER1_COUNT) = APB_CLK_IN / HZ - 1;
- + REG32_TMR(TIMER1_LOAD) = APB_CLK_IN / HZ - 1;
- + REG32_TMR(TIMER_TMCR) |= TM1ENABLE;
- + break;
- + case CLOCK_EVT_MODE_UNUSED:
- + break;
- + case CLOCK_EVT_MODE_SHUTDOWN:
- + REG32_TMR(TIMER_TMCR) &= ~TM1ENABLE;
- + break;
- + case CLOCK_EVT_MODE_RESUME:
- + REG32_TMR(TIMER_INTRMASK) |= TM1MATCH1 | TM1MATCH2;
- + REG32_TMR(TIMER_TMCR) |= TM1ENABLE | TM1OFENABLE;
- + break;
- + }
- +}
- +
- +static struct clock_event_device clockevent_fttmr010 = {
- + .name = "fttmr010_tm1",
- + .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
- + .shift = 32,
- + .cpumask = cpu_all_mask,
- + .set_next_event = fttmr010_set_next_event,
- + .set_mode = fttmr010_set_mode,
- +};
- +
- +static irqreturn_t timer1_interrupt(int irq, void *dev_id)
- +{
- + struct clock_event_device *evt = dev_id;
- +
- + REG32_TMR(TIMER_INTRSTATE) = TM1MATCH1 | TM1MATCH2 | TM1OVERFLOW;
- +
- + evt->event_handler(evt);
- +
- + return IRQ_HANDLED;
- +}
- +
- +static struct irqaction timer1_irq = {
- + .name = "Timer Tick",
- + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
- + .handler = timer1_interrupt,
- + .dev_id = &clockevent_fttmr010
- +};
- +
- +static void __init fttmr010_clockevent_init(void)
- +{
- + clockevent_fttmr010.mult =
- + div_sc(APB_CLK_IN, NSEC_PER_SEC, clockevent_fttmr010.shift);
- + clockevent_fttmr010.max_delta_ns =
- + clockevent_delta2ns(0xffffffff, &clockevent_fttmr010);
- + clockevent_fttmr010.min_delta_ns =
- + clockevent_delta2ns(3, &clockevent_fttmr010);
- +
- + clockevents_register_device(&clockevent_fttmr010);
- + setup_irq(TIMER_FTTMR010_IRQ0, &timer1_irq);
- +}
- +
- +static void fttmr010_resume(void)
- +{
- +}
- +
- +#ifdef CONFIG_CPU_FREQ
- +void ag102_calc_ahb_clk(void);
- +static int fttmr010_cpufreq_notifier(struct notifier_block *nb,
- + unsigned long val, void *data)
- +{
- + if (val == CPUFREQ_POSTCHANGE) {
- +
- + unsigned long flags;
- +#ifdef CONFIG_PLAT_AG102
- + ag102_calc_ahb_clk();
- +#endif
- + local_irq_save(flags);
- +
- + clocksource_unregister(&clksrc_fttmr010);
- +
- + clksrc_fttmr010.mult =
- + clocksource_hz2mult(APB_CLK_IN, clksrc_fttmr010.shift);
- +#ifdef CONFIG_PLAT_AG101
- + clksrc_fttmr010.mult_orig =
- + clocksource_hz2mult(APB_CLK_IN, clksrc_fttmr010.shift);
- +#endif
- +
- + if (clocksource_register(&clksrc_fttmr010))
- + printk(KERN_ERR "Error: failed to re-register %s\n",
- + clksrc_fttmr010.name);
- + else
- + printk("Re-register clock source %s\n",
- + clksrc_fttmr010.name);
- +
- + local_irq_restore(flags);
- +
- + clockevent_fttmr010.mult =
- + div_sc(APB_CLK_IN, NSEC_PER_SEC, clockevent_fttmr010.shift);
- +
- +#ifdef CONFIG_PLAT_AG102
- + printk("Add timer clock modifier...\n");
- + fttmr010_set_mode(CLOCK_EVT_MODE_PERIODIC, 0);
- +#endif
- + }
- +
- + return 0;
- +}
- +
- +static struct notifier_block fttmr010_cpufreq_notifier_block = {
- + .notifier_call = fttmr010_cpufreq_notifier
- +};
- +
- +static int __init fttmr010_init_cpufreq(void)
- +{
- + if (cpufreq_register_notifier(&fttmr010_cpufreq_notifier_block,
- + CPUFREQ_TRANSITION_NOTIFIER))
- + printk("fttmr010: Failed to setup cpufreq notifier\n");
- +
- + return 0;
- +}
- +
- +core_initcall(fttmr010_init_cpufreq);
- +#endif
- +
- +static int clksrc_init;
- +static void __init fttmr010_init(void)
- +{
- + request_resource(&ioport_resource, &timer_resource);
- +
- + printk
- + ("FTTMR010 timer 1 installed on IRQ %d, with clock %d at %d HZ.\r\n",
- + TIMER_FTTMR010_IRQ0, APB_CLK_IN, HZ);
- +
- + REG32_TMR(TIMER_TMCR) &=
- + ~(TM1ENABLE | TM1CLOCK | TM1OFENABLE | TM1UPDOWN);
- + REG32_TMR(TIMER_INTRMASK) |= TM1MATCH1 | TM1MATCH2;
- + REG32_TMR(TIMER_TMCR) |= TM1OFENABLE;
- +
- + fttmr010_clocksource_init();
- + fttmr010_clockevent_init();
- + clksrc_init = 1;
- +}
- +
- +struct sys_timer platform_timer = {
- + .init = fttmr010_init,
- + .resume = fttmr010_resume,
- +};
- +
- +unsigned long long sched_clock(void)
- +{
- + if (clksrc_init)
- + return
- + clocksource_cyc2ns(clocksource_read_cycles
- + (&clksrc_fttmr010), clksrc_fttmr010.mult,
- + clksrc_fttmr010.shift);
- + else
- + return (unsigned long long)(jiffies - INITIAL_JIFFIES)
- + * (NSEC_PER_SEC / HZ);
- +}
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/vep/devices.c linux-3.4.110/arch/nds32/platforms/vep/devices.c
- --- linux-3.4.110.orig/arch/nds32/platforms/vep/devices.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/vep/devices.c 2016-04-07 10:20:51.018083964 +0200
- @@ -0,0 +1,83 @@
- +#include <linux/serial_8250.h>
- +#include <asm/mach-types.h>
- +#include <asm/sizes.h>
- +#include <asm/mach/arch.h>
- +#include <asm/mach/map.h>
- +#include <asm/spec.h>
- +#include <asm/intc.h>
- +#include <asm/timer.h>
- +
- +const struct map_desc platform_io_desc[] __initdata = {
- + {UART0_VA_BASE, UART0_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {UART1_VA_BASE, UART1_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {INTC_FTINTC010_0_VA_BASE, INTC_FTINTC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {TIMER_FTTMR010_0_VA_BASE, TIMER_FTTMR010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {SSP_FTSSP010_0_VA_BASE, SSP_FTSSP010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {PMU_FTPMU010_0_VA_BASE, PMU_FTPMU010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {MAC_FTMAC100_0_VA_BASE, MAC_FTMAC100_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {SDC_FTSDC010_0_VA_BASE, SDC_FTSDC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {RTC_FTRTC010_0_VA_BASE, RTC_FTRTC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {WDT_FTWDT010_0_VA_BASE, WDT_FTWDT010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {GPIO_FTGPIO010_0_VA_BASE, GPIO_FTGPIO010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {CFC_FTCFC010_0_VA_BASE, CFC_FTCFC010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {LCD_FTLCDC100_0_VA_BASE, LCD_FTLCDC100_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {I2C_FTI2C010_0_VA_BASE, I2C_FTI2C010_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {DMAC_FTDMAC020_0_VA_BASE, DMAC_FTDMAC020_0_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {APBBRG_FTAPBBRG020S_0_VA_BASE, APBBRG_FTAPBBRG020S_0_PA_BASE,
- + PAGE_SIZE, MT_DEVICE_NCB},
- + {LED_VA_BASE, LED_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
- + {SDMC_FTSDMC021_VA_BASE, SDMC_FTSDMC021_PA_BASE, PAGE_SIZE,
- + MT_DEVICE_NCB},
- + {L2CC_VA_BASE, L2CC_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB}
- +};
- +
- +static void __init platform_map_io(void)
- +{
- + iotable_init((struct map_desc *)platform_io_desc,
- + ARRAY_SIZE(platform_io_desc));
- +}
- +
- +static struct uart_port uart0 = {
- + .membase = (void __iomem *)UART0_VA_BASE,
- + .irq = UART0_IRQ,
- + .uartclk = CONFIG_UART_CLK,
- + .regshift = 2,
- + .iotype = UPIO_MEM,
- + .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
- + .line = 0,
- + .mapbase = UART0_PA_BASE,
- +};
- +
- +static struct uart_port uart1 = {
- + .membase = (void __iomem *)UART1_VA_BASE,
- + .irq = UART1_IRQ,
- + .uartclk = CONFIG_UART_CLK,
- + .regshift = 2,
- + .iotype = UPIO_MEM,
- + .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
- + .line = 1,
- + .mapbase = UART1_PA_BASE,
- +};
- +
- +static void __init soc_init(void)
- +{
- + early_serial_setup(&uart0);
- + early_serial_setup(&uart1);
- +}
- +
- +MACHINE_START(FARADAY, PLATFORM_NAME)
- + .param_offset = BOOT_PARAMETER_PA_BASE,.map_io = platform_map_io,.init_irq = platform_init_irq,.timer = &platform_timer, /* defined in timer.c */
- + .init_machine = soc_init, MACHINE_END
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/vep/Kconfig linux-3.4.110/arch/nds32/platforms/vep/Kconfig
- --- linux-3.4.110.orig/arch/nds32/platforms/vep/Kconfig 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/vep/Kconfig 2016-04-07 10:20:51.018083964 +0200
- @@ -0,0 +1,7 @@
- +menu "VEP Platform Options"
- +
- +config CACHE_L2
- + bool "Support L2 cache"
- + default n
- +
- +endmenu
- diff -Nur linux-3.4.110.orig/arch/nds32/platforms/vep/Makefile linux-3.4.110/arch/nds32/platforms/vep/Makefile
- --- linux-3.4.110.orig/arch/nds32/platforms/vep/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/arch/nds32/platforms/vep/Makefile 2016-04-07 10:20:51.018083964 +0200
- @@ -0,0 +1 @@
- +obj-y = devices.o
- diff -Nur linux-3.4.110.orig/build_linux.sh linux-3.4.110/build_linux.sh
- --- linux-3.4.110.orig/build_linux.sh 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/build_linux.sh 2016-04-07 10:20:51.018083964 +0200
- @@ -0,0 +1,202 @@
- +#!/bin/sh
- +
- +export ARCH=nds32
- +
- +print_help()
- +{
- + echo "Usage: <platform> [platform_defconfig] [--bootm] [--ramdisk=<ramdisk absolute path>]"
- + echo "Stop Building."
- + exit
- +}
- +
- +BUILDBOOTM=0
- +BUILDBOOTPIMAGE=0
- +BUILDHEADERS=0
- +
- +case "$1" in
- + qemu)
- + TARGET=qemu_defconfig
- + IMAGE=qemu
- + export CROSS_COMPILE=nds32le-linux-
- + echo "Building $IMAGE kernel."
- + ;;
- + vep-be)
- + TARGET=vep-be_defconfig
- + IMAGE=vep-be
- + export CROSS_COMPILE=nds32be-linux-
- + echo "Building $IMAGE kernel."
- + ;;
- + vep-le)
- + TARGET=vep-le_defconfig
- + IMAGE=vep-le
- + export CROSS_COMPILE=nds32le-linux-
- + echo "Building $IMAGE kernel."
- + ;;
- + xc5)
- + TARGET=xc5_defconfig
- + IMAGE=xc5
- + export CROSS_COMPILE=nds32le-linux-
- + echo "Building $IMAGE kernel."
- + ;;
- + xc5_8k)
- + TARGET=xc5_8k_defconfig
- + IMAGE=xc5_8k
- + export CROSS_COMPILE=nds32le-linux-
- + echo "Building $IMAGE kernel."
- + ;;
- + ag101a0)
- + TARGET=ag101a0_defconfig
- + IMAGE=ag101a0
- + export CROSS_COMPILE=nds32le-linux-
- + echo "Building $IMAGE kernel."
- + ;;
- + ag101b0)
- + TARGET=ag101b0_defconfig
- + IMAGE=ag101b0
- + export CROSS_COMPILE=nds32le-linux-
- + echo "Building $IMAGE kernel."
- + ;;
- + ag102)
- + TARGET=ag102_defconfig
- + IMAGE=ag102
- + export CROSS_COMPILE=nds32le-linux-
- + echo "Building $IMAGE kernel."
- + ;;
- + u200)
- + TARGET=u200_defconfig
- + IMAGE=u200
- + export CROSS_COMPILE=nds32le-linux-
- + echo "Building $IMAGE kernel."
- + ;;
- + xc5-qa)
- + TARGET=xc5-qa_defconfig
- + IMAGE=xc5-qa
- + export CROSS_COMPILE=nds32le-linux-
- + echo "Building $IMAGE kernel."
- + ;;
- + ag101-qa)
- + TARGET=ag101-qa_defconfig
- + IMAGE=ag101-qa
- + export CROSS_COMPILE=nds32le-linux-
- + echo "Building $IMAGE kernel."
- + ;;
- + *)
- + if [ $# = 1 ]; then
- + echo "No defconfig is given."
- + print_help
- + fi
- + if [ ! -e $2 ]; then
- + echo "Given defconfig is not exist."
- + print_help
- + elif [ ! -f $2 ]; then
- + echo "Given defconfig is not a file."
- + print_help
- + elif [ ! -s $2 ]; then
- + echo "Given defconfig is size 0."
- + print_help
- + elif [ ! -r $2 ]; then
- + echo "Given defconfig has no read attribute."
- + print_help
- + fi
- + TARGET=none
- + IMAGE=$1
- + export CROSS_COMPILE=nds32le-linux-
- + echo "Building $IMAGE kernel."
- +esac
- +
- +ZIMAGE="$IMAGE"_zImage
- +VMLINUZ="$IMAGE"_vmlinuz
- +VMLINUX="$IMAGE"_vmlinux
- +BOOTPIMAGE="$IMAGE"_bootpImage
- +BOOTP="$IMAGE"_bootp
- +BOOTM="$IMAGE"_bootm
- +
- +for ARG in $@; do
- + if [ $ARG = $1 ]; then
- + continue
- + fi
- +
- + if [ $ARG = $2 ]; then
- + if [ $TARGET = "none" ]; then
- + continue
- + fi
- + fi
- +
- + case "$ARG" in
- +
- + --bootm)
- + BUILDBOOTM=1
- + ;;
- +
- + --ramdisk=*)
- + BUILDBOOTPIMAGE=1
- + RAMDISK=${ARG#*=}
- + if [ ! -e $RAMDISK ]; then
- + echo "Given ramdisk is not exist."
- + print_help
- + elif [ ! -f $RAMDISK ]; then
- + echo "Given ramdisk is not a file."
- + print_help
- + elif [ ! -s $RAMDISK ]; then
- + echo "Given ramdisk is size 0."
- + print_help
- + elif [ ! -r $RAMDISK ]; then
- + echo "Given ramdisk has no read attribute."
- + print_help
- + fi
- + ;;
- +# --headers)
- +# BUILDHEADERS=1
- +# git apply ../linux-2.6-patch/headers.patch
- +# echo "Exporting kernel headers."
- +# ;;
- + *)
- + print_help
- + esac
- +done
- +
- +if [ "$OSTYPE" = "cygwin" ]; then
- + HOST_LOADLIBES=-lintl\ -lcurses
- +fi
- +export HOST_LOADLIBES
- +
- +which ${CROSS_COMPILE}gcc &> /dev/null || export CROSS_COMPILE=nds32-elf-
- +
- +make mrproper | tee $IMAGE.log
- +if [ $TARGET != "none" ]; then
- + make $TARGET| tee -a $IMAGE.log
- +else
- + cp $2 .config
- +fi
- +
- +if [ $BUILDHEADERS = 1 ]; then
- + make dep | tee -a $IMAGE.log
- + make headers_install | tee -a $IMAGE.log
- +else
- + make | tee -a $IMAGE.log
- +
- + cp arch/nds32/boot/zImage ./$ZIMAGE | tee -a $IMAGE.log
- + cp arch/nds32/boot/compressed/vmlinux ./$VMLINUZ | tee -a $IMAGE.log
- + cp ./vmlinux ./$VMLINUX | tee -a $IMAGE.log
- +
- + if [ $BUILDBOOTPIMAGE = 1 ]; then
- + make bootpImage INITRD=$RAMDISK | tee -a $IMAGE.log
- + cp arch/nds32/boot/bootpImage ./$BOOTPIMAGE | tee -a $IMAGE.log
- + cp arch/nds32/boot/bootp/bootp ./$BOOTP | tee -a $IMAGE.log
- + fi
- +
- + if [ $BUILDBOOTM = 1 ]; then
- + if [ -e "../u-boot/tools/mkimage" ]; then
- + ../u-boot/tools/mkimage \
- + -A nds32 \
- + -O linux \
- + -T kernel \
- + -C none \
- + -a 0x500000 \
- + -e 0x500040 \
- + -d ./arch/nds32/boot/zImage $BOOTM | tee -a $IMAGE.log
- + else
- + echo "Error: ../u-boot/tools/mkimage not found" | tee -a $IMAGE.log
- + fi
- + fi
- +fi
- diff -Nur linux-3.4.110.orig/drivers/block/ftcfc010.c linux-3.4.110/drivers/block/ftcfc010.c
- --- linux-3.4.110.orig/drivers/block/ftcfc010.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/block/ftcfc010.c 2016-04-07 10:20:51.022084119 +0200
- @@ -0,0 +1,1299 @@
- +/* drivers/block/CPESD/ftsdc010.c
- + *******************************************************************************
- + * Faraday FTSDC010 Device Driver
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + *
- + * All Rights Reserved
- + *
- + * Porting to Linux 2.6 on 20050815
- + * Author: Chris Lee, I-Jui Sung, Peter Liao (support APB DMA)
- + * Version: 0.2
- + * History:
- + * 0.1 new creation
- + * 0.2 Porting to meet the style of linux dma
- + * 0.3 modify dma usage to virtual irq of dma interrupt
- + * 0.4 (20050701) Improve r/w performance
- + * 0.5 Porting to Linux 2.6 and replace busy_loop checking with timer's timeout
- + * Todo:
- + *******************************************************************************
- + */
- +
- +#define DEBUG_OFF 0
- +
- +#define DEBUG( enable, tagged, ...) \
- +do{ \
- + if( enable){ \
- + if( tagged) \
- + printk( "[ %30s() ] ", __func__); \
- + printk( __VA_ARGS__); \
- + } \
- +} while( 0)
- +
- +#include <linux/interrupt.h>
- +#include <linux/kernel.h>
- +#include <linux/module.h>
- +#include <linux/sched.h>
- +#include <linux/delay.h>
- +#include <linux/init.h>
- +#include <linux/ioport.h>
- +#include <linux/hdreg.h> /* HDIO_GETGEO */
- +#include <linux/fs.h>
- +#include <linux/blkdev.h>
- +#include <linux/buffer_head.h> /* invalidate_bdev */
- +#include <linux/bio.h>
- +#include <linux/pci.h>
- +#include <asm/io.h>
- +#include <asm/uaccess.h>
- +#include <asm/spec.h>
- +#include <asm/dmad.h>
- +
- +#define IPMODULE CFC
- +#define IPNAME FTCFC010
- +
- +#include "ftcfc010.h"
- +
- +static int hardsect_size = 512;
- +module_param( hardsect_size, int, 0);
- +
- +static int cf_major = 0; /* must be declared before including blk.h */
- +#define DEVICE_NAME "Faraday CFC" /* name for messaging */
- +
- +#define FTCFC_VA_BASE IP_VA_BASE( 0)
- +#define FTCFC_PA_BASE IP_PA_BASE( 0)
- +#define FTCFC_IRQ CFC_FTCFC010_IRQ1
- +
- +#undef CF_DEBUG
- +#define CF_DEBUG 0
- +struct block_device_operations cf_fops;
- +
- +typedef struct cf_dev {
- +
- + int size; /* device size in sectors */
- + int usage; /* # of users currently */
- + int media_change; /* Flag: media changed? */
- + struct gendisk *gd; /* The gendisk structure */
- + spinlock_t lock; /* For mutual exclusion */
- + struct request_queue *queue; /* The device request queue */
- + int card_state;
- + u32 lba_sec_offset;
- + dmad_chreq ch_req;
- +
- +} cf_dev_t;
- +
- +static cf_dev_t *cf_devices;
- +static cf_card_t cf_card_info;
- +
- +static dma_addr_t dma_buf;
- +struct completion cf_dma_cmpl;
- +
- +static uint first_run;
- +static uint cf_err_code;
- +
- +static int g_cf_sectors;
- +
- +static void SetTransferSize( u32 Addr, u32 Type, u32 OP_Type, u32 Inc_Addr, u32 Transize)
- +{
- + u32 ctrl_reg, buf_ctrl_reg;
- + DEBUG( CF_DEBUG, 1, "Enter\n");
- +
- + /* set read/write command */
- + while( cfc->HostStatus & BUF_ACTIVE_BIT)
- + ;
- +
- + /* Set Transfer size mode to default */
- + cfc->TransSzMode2En = 0;
- +
- + /* set 8/16 bits mode */
- + ctrl_reg = cfc->ControlReg;
- +
- + if( Transize == SIZE_1_BYTE)
- + ctrl_reg = ( ctrl_reg & ~MODE_BIT) | BYTE_MODE;
- + else
- + ctrl_reg = ( ctrl_reg & ~MODE_BIT) | WORD_MODE;
- +
- + DEBUG( CF_DEBUG, 1, "ctrl 1: 0x%08lx\n", ( unsigned long)ctrl_reg);
- + cfc->ControlReg = ctrl_reg;
- +
- + /* Write command to buffer */
- + buf_ctrl_reg = cfc->BuffCtrlReg;
- + buf_ctrl_reg = ( buf_ctrl_reg & ~ADR_BIT & ~TYPE_BIT & ~RW_BIT & ~INCADR_BIT & ~TRANS_SIZE_CONTROL_BIT)
- + | Addr | Type | OP_Type | Inc_Addr | ( Transize << TRANS_SIZE_LOC);
- +
- + cfc->BuffCtrlReg = buf_ctrl_reg;
- + DEBUG( CF_DEBUG, 1, "buf_ctrl 1: 0x%08lx\n", ( unsigned long)buf_ctrl_reg);
- + DEBUG( CF_DEBUG, 1, "Exit\n");
- +}
- +
- +static void SetTransferSizeEx( u32 Addr, u32 Type, u32 OP_Type, u32 Inc_Addr, u32 Transize)
- +{
- + u32 ctrl_reg, buf_ctrl_reg;
- +
- + DEBUG( CF_DEBUG, 1, "Enter, SetTransferSizeEx: %d\n", Transize);
- +
- + /* set read/write command */
- + while( cfc->HostStatus & BUF_ACTIVE_BIT)
- + ;
- +
- + /* Set Transfer size mode to default */
- + cfc->TransSzMode2En = 1;
- +
- + /* set 8/16 bits mode */
- + ctrl_reg = cfc->ControlReg;
- +
- + if( Transize == SIZE_1_BYTE)
- + ctrl_reg = ( ctrl_reg & ~MODE_BIT) | BYTE_MODE;
- + else
- + ctrl_reg = ( ctrl_reg & ~MODE_BIT) | WORD_MODE;
- +
- + cfc->ControlReg = ctrl_reg;
- +
- + /* Set Transfer size mode2 reg in FTCFC */
- + cfc->TransSzMode2Cnt = Transize - 1;
- +
- + /* Write command to buffer */
- + buf_ctrl_reg = cfc->BuffCtrlReg;
- + buf_ctrl_reg = ( buf_ctrl_reg & ~ADR_BIT & ~TYPE_BIT & ~RW_BIT & ~INCADR_BIT & ~TRANS_SIZE_CONTROL_BIT)
- + | Addr | Type | OP_Type | Inc_Addr;
- +
- + cfc->BuffCtrlReg = buf_ctrl_reg;
- +
- + DEBUG( CF_DEBUG, 1, "Exit\n");
- +}
- +
- +static void WriteCFCardByte( u32 Addr, u8 Value, u32 Type)
- +{
- + while( !( cfc->HostStatus & RDY_nIREQ_BIT))
- + ;
- +
- + SetTransferSize( Addr, Type, WRITE_OP, NOINCADR, SIZE_1_BYTE);
- +
- + cfc->BufferData = Value;
- +
- + while( !( cfc->HostStatus & INTA_BIT))
- + ;
- +
- + /* clear command complete status */
- + cfc->HostStatus = INTA_BIT;
- +}
- +
- +static u8 ReadCFCardByte( u32 Addr, u32 Type)
- +{
- + u8 ret_data;
- +
- + DEBUG( CF_DEBUG, 1, "Enter\n");
- +
- + /* wait until ready */
- + while( !( cfc->HostStatus & RDY_nIREQ_BIT))
- + ;
- +
- + SetTransferSize( Addr, Type, READ_OP, NOINCADR, SIZE_1_BYTE);
- +
- + while( !( cfc->HostStatus & INTA_BIT))
- + ;
- +
- + ret_data = cfc->BufferData & 0xff;
- + DEBUG( CF_DEBUG, 1, "data: 0x%02x\n", ret_data);
- +
- + while( !( cfc->HostStatus & INTA_BIT))
- + ;
- +
- + /* clear command complete status */
- + cfc->HostStatus = INTA_BIT;
- +
- + DEBUG( CF_DEBUG, 1, "Exit\n");
- + return ret_data;
- +}
- +
- +/* set Head-cylinder-sector on CF */
- +static u32 Translate_Config_HCS( u32 LBA, u32 Sec_count)
- +{
- + u8 DriveHead = ( u8)( 0xE0 | ( LBA >> 24)); /* 0xE0 set in LBA mode (bit 7&5 must set to 1) */
- + u8 CylHigh = ( u8)( ( LBA >> 16) & 0xFF);
- + u8 CylLow = ( u8)( ( LBA >> 8) & 0xFF);
- + u8 SecNum = ( u8)( LBA & 0xFF);
- +
- + DEBUG( CF_DEBUG, 1, "LBA:%d, %d %d %d %d, count: %d\n",
- + LBA, DriveHead, CylHigh, CylLow, SecNum, Sec_count);
- +
- + /* Set CF-ATA reg for start sector */
- + WriteCFCardByte( BLKMEM_DRIVE_REG, DriveHead, COMMON_MEM);
- + WriteCFCardByte( BLKMEM_CYLINDER_HIGH_REG, CylHigh, COMMON_MEM);
- + WriteCFCardByte( BLKMEM_CYLINDER_LOW_REG, CylLow, COMMON_MEM);
- + WriteCFCardByte( BLKMEM_SECTOR_NUMBER_REG, SecNum, COMMON_MEM);
- + WriteCFCardByte( BLKMEM_SECTOR_COUNT_REG, Sec_count, COMMON_MEM);
- +
- + return 1;
- +}
- +
- +/*
- + * SetCFCardConfiguration(): ATTRIBUTE MEMORY
- + * Set CF storgae card configuration option register
- + * Conf1 Conf0 Disk Card Mode
- + * ---------------------------------------------------------------
- + * 0 0 Memory Mapped
- + * 0 1 I/O Mapped, any 16 byte system decoded
- + * 1 0 I/O Mapped, 1F0h - 1F7h / 3F6h - 3F7h
- + * 1 1 I/O Mapped, 170h - 177h / 376h - 377h
- + */
- +static void SetCFCardMode( u8 Mode)
- +{
- + u8 Reg;
- +
- + DEBUG( CF_DEBUG, 1, "Enter\n");
- +
- + Reg = ReadCFCardByte( CONFIG_OPTION_REG, ATTRIBUTE_MEM); /* CONFIG_OPTION_REG = 0x200 */
- + Reg &= ( LEVLREQ_BIT | SRESET_BIT); /* clear bit0-5 */
- +
- + WriteCFCardByte( CONFIG_OPTION_REG, Reg | Mode, ATTRIBUTE_MEM);
- +
- + DEBUG( CF_DEBUG, 1, "Exit\n");
- +}
- +
- +/* return 0: fail, 1: success */
- +static u32 CF_SendCommand( u16 Cmd)
- +{
- + u16 Reg;
- + DEBUG( CF_DEBUG, 1, "Enter\n");
- +
- + do{
- + WriteCFCardByte( BLKMEM_COMMAND_REG, Cmd, COMMON_MEM);
- +
- + /*
- + * Check status register of Task file register is valid for access
- + * No other bits in status register are valid when BUSY bit is
- + * set to a 1
- + */
- + while( ( ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM) & BUSY_BIT))
- + ;
- +
- + Reg = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
- +
- + if( Reg & ERR_BIT){
- +
- + DEBUG( CF_DEBUG, 1, "Exit ( fail)\n");
- + return 0;
- + }
- +
- + } while( !( Reg & RDY_BIT));
- +
- + DEBUG( CF_DEBUG, 1, "Exit\n");
- + return 1;
- +}
- +
- +static void CardReset( void)
- +{
- + u32 ctrl_reg = cfc->ControlReg;
- + u8 data;
- +
- + DEBUG( CF_DEBUG, 1, "Enter\n");
- + cfc->ControlReg = ctrl_reg | RESET_BIT | SIGNAL_ON | PWR_ON; /* set reset bit, float control, power on */
- +
- + /* Software must manually clear this bit */
- + mdelay( 100);
- +
- + /* clear reset bit */
- + cfc->ControlReg = ( ctrl_reg &~ RESET_BIT) | SIGNAL_ON | PWR_ON | DATA_CMP_INT_MASK | IO_INT_MASK;
- +
- + do {
- + data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
- +
- + } while( data & BUSY_BIT); /* please be careful that is locked here */
- +
- + data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
- +
- + /* Check if Drive Ready & Drive Seek Complete */
- + if( data == ( RDY_BIT | DSC_BIT))
- + DEBUG( CF_DEBUG, 1, "Reset CF OK, data: 0x%02x\n", ( unsigned char)data);
- + else
- + DEBUG( CF_DEBUG, 1, "Reset CF fail, data: 0x%02x\n", ( unsigned char)data);
- +
- + DEBUG( CF_DEBUG, 1, "Exit\n");
- +}
- +
- +static u32 CFCardInit( void)
- +{
- + u8 buff[CF_SECTOR_SIZE];
- + u32 i;
- + u32 BSA, BSM, BSIO, BSMOW, BSIORW, apb_ns;
- +
- + DEBUG( CF_DEBUG, 1, "Enter\n");
- +
- + if( !( cfc->HostStatus & CARD_DETECT_BIT)){
- +
- + DEBUG( CF_DEBUG, 1, "No CF Card In Socket\n");
- + return -1;
- + }
- +
- + CardReset();
- +
- + /* set timer */
- +
- + apb_ns = 1000000000 / ( AHB_CLK_IN / 2 ); /* the time of APB clock */
- + BSA = ( 50 + ( apb_ns - ( 50 % apb_ns))) / apb_ns; /* Based on the item tc( R) of BSA */
- + BSMOW = 3;
- + BSIORW = 3;
- + BSM = ( 30 + ( apb_ns - ( 30 % apb_ns))) / apb_ns; /* Base on the item tw( WE) of BSM */
- + BSIO = ( 35 + ( apb_ns - ( 35 % apb_ns))) / apb_ns; /* Base on the item tsuA( IORD,IOWR) of BSIO */
- +
- + cfc->TimeCfgReg = ( ( BSMOW & 0x03) << 12)
- + | ( ( BSIORW & 0x03) << 14)
- + | ( ( BSA & 0x0f) << 0)
- + | ( ( BSM & 0x0f) << 4)
- + | ( ( BSIO & 0x0f) << 8);
- +
- + SetCFCardMode( CF_MEM_MAP_MODE); /* set memory mode read write access */
- +
- + cfc->MultiSector = 0x1; /* enable multi sector read/write */
- +
- + /* select drive */
- + WriteCFCardByte( BLKMEM_DRIVE_REG, 0, COMMON_MEM);
- +
- + /* identify drive device */
- + if( !CF_SendCommand( ATA_IDENTIFY_DRIVE)){
- +
- + DEBUG( CF_DEBUG, 1, "Send Identify Drive command fail\n");
- + return -1;
- + }
- +
- + SetTransferSize( BLKMEM_DATA_REG, COMMON_MEM, READ_OP, NOINCADR, SIZE_512_BYTE);
- +
- + for( i = 0; i < CF_SECTOR_SIZE / 4; i++){
- +
- + while( !( cfc->HostStatus & BUF_DATA_RDY_BIT))
- + ;
- +
- + *( ( u32*)&buff[ i*4]) = cfc->BufferData;
- + }
- +
- + /* clear command complete status */
- + cfc->HostStatus = INTA_BIT;
- +
- + g_cf_sectors = ( ( u32)buff[ 15] << 24) | ( ( u32)buff[ 14] << 16) | ( ( u32)buff[ 17] << 8) | ( ( u32)buff[ 16]);
- + DEBUG( CF_DEBUG, 1, "Card identify - capicity: %d sectors, size: %d kbytes \n", g_cf_sectors, g_cf_sectors >> 1);
- + DEBUG( CF_DEBUG, 1, "Exit\n");
- +
- + return 0;
- +}
- +
- +static int cfc_read_block( cf_card_t *info, uint size, uint *buf)
- +{
- + /*
- + * Please refer SanDisk SD Manual v1.9 Section 5.1.9.2 ( page 5-76) to set the timeout setting
- + */
- + unsigned long timeout = jiffies + CFC_TIMEOUT_BASE *( ( size + 2048 + 511) >> 9);
- + uint count;
- + u8 data;
- + dmad_chreq *ch_req = (dmad_chreq *)info->private;
- + dmad_drb *drb = 0;
- + u32 drb_size = 0;
- + dma_addr_t addr_iter;
- +
- + if( info->DMAEnable){
- +
- + DEBUG( CF_DEBUG, 1, "DMA Read - size: %d, buf: 0x%08lx, dma_buf: 0x%08lx\n",
- + size, ( unsigned long)buf, ( unsigned long)dma_buf);
- +
- + init_completion(&cf_dma_cmpl);
- +
- + if (dma_buf)
- + consistent_sync(__va(dma_buf), size, DMA_FROM_DEVICE);
- + else
- + consistent_sync(buf, size, DMA_FROM_DEVICE);
- +
- + //prepare parameter for add dma entry
- + dmad_config_channel_dir(ch_req, DMAD_DIR_A0_TO_A1);
- +
- + drb_size = dmad_max_size_per_drb(ch_req);
- +
- + if (dma_buf)
- + addr_iter = dma_buf; // given dest phy addr
- + else
- + addr_iter = __pa(buf);
- +
- + cfc->ControlReg |= ENDMA_BIT;
- +
- + while (size > 0) {
- +
- + if (unlikely(0 != dmad_alloc_drb(ch_req, &drb) || (drb == 0))) {
- + printk(KERN_ERR "%s() Failed to allocate dma request block!\n", __func__);
- + return FALSE;
- + }
- +
- + drb->addr0 = FTCFC_PA_BASE + 0x10;
- + drb->addr1 = addr_iter;
- +
- + if (size <= drb_size) {
- + drb->req_cycle = dmad_bytes_to_cycles(ch_req, size);
- + drb->sync = &cf_dma_cmpl;
- + size = 0;
- + } else {
- + drb->req_cycle = dmad_bytes_to_cycles(ch_req, drb_size);
- + drb->sync = 0;
- + size -= drb_size;
- + addr_iter += drb_size;
- + }
- + //printk(KERN_INFO "%s() size_remain 0x%08x.\n", __func__, size);
- +
- + if (unlikely(0 != dmad_submit_request(ch_req, drb, 1))) {
- + printk(KERN_ERR "%s() Failed to submit dma request block!\n", __func__);
- + return FALSE;
- + }
- + }
- +
- + if (wait_for_completion_timeout(&cf_dma_cmpl, timeout - jiffies) == 0)
- + printk("%s: read timeout\n", __func__);
- +
- + DEBUG( CF_DEBUG, 1, "ControlReg: 0x%08x, HostStatus: 0x%08x, BufCtrl: 0x%08x\n",
- + cfc->ControlReg, cfc->HostStatus, cfc->BuffCtrlReg);
- +
- + while( !( cfc->HostStatus & INTA_BIT))
- + ;
- +
- + cfc->HostStatus = INTA_BIT;
- +
- + /* Stop DMA */
- + cfc->ControlReg &= ~ENDMA_BIT;
- + cfc->ControlReg &= ~MODE_BIT;
- +
- + do {
- + data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
- +
- + } while( data & BUSY_BIT);
- + }
- + else {
- + while( size > 0){
- +
- + /* read data from FIFO */
- + if( size >= ( CFC_READ_FIFO_LEN << 2))
- + count = CFC_READ_FIFO_LEN;
- + else
- + count = size >> 2;
- +
- + /* read data from FIFO */
- + DEBUG( CF_DEBUG, 0, "\n");
- + size -= ( count << 2);
- + }
- + }
- +
- + data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
- +
- + while( 1){
- +
- + if( data & ERR_BIT){
- +
- + DEBUG( CF_DEBUG, 1, "ERROR: ( CFReadSector) CF Read sector error.\n");
- + return FALSE;
- + }
- + else if( data & DWF_BIT){
- +
- + DEBUG( CF_DEBUG, 1, "ERROR: ( CFReadSector) CF write fault error.\n");
- + return FALSE;
- + }
- + else if( data & ( RDY_BIT | DSC_BIT)){
- +
- + break;
- + }
- + data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
- + }
- +
- + return TRUE;
- +}
- +
- +static int cfc_write_block( cf_card_t *info, uint size, uint *buf)
- +{
- + unsigned long timeout = jiffies + CFC_TIMEOUT_BASE * 3 *( ( size + 511) >> 9);
- + uint count;
- + u8 data;
- + dmad_chreq *ch_req = (dmad_chreq *)info->private;
- + dmad_drb *drb = 0;
- + u32 drb_size = 0;
- + dma_addr_t addr_iter;
- +
- + if( info->DMAEnable){
- +
- + DEBUG( CF_DEBUG, 1, "size: %d, buf: %p) - DMA Write\n", size, buf);
- +
- + init_completion(&cf_dma_cmpl);
- +
- + if (dma_buf)
- + consistent_sync(__va(dma_buf), size, DMA_TO_DEVICE);
- + else
- + consistent_sync(buf, size, DMA_TO_DEVICE);
- +
- + //prepare parameter for add dma entry
- + dmad_config_channel_dir(ch_req, DMAD_DIR_A1_TO_A0);
- +
- + drb_size = dmad_max_size_per_drb(ch_req);
- +
- + if (dma_buf)
- + addr_iter = dma_buf; // given dest phy addr
- + else
- + addr_iter = __pa(buf);
- +
- + cfc->ControlReg |= ENDMA_BIT;
- +
- + while (size > 0) {
- +
- + if (unlikely(0 != dmad_alloc_drb(ch_req, &drb) || (drb == 0))) {
- + printk(KERN_ERR "%s() Failed to allocate dma request block!\n", __func__);
- + return FALSE;
- + }
- +
- + drb->addr0 = FTCFC_PA_BASE + 0x10;
- + drb->addr1 = addr_iter;
- +
- + if (size <= drb_size) {
- + drb->req_cycle = dmad_bytes_to_cycles(ch_req, size);
- + drb->sync = &cf_dma_cmpl;
- + size = 0;
- + } else {
- + drb->req_cycle = dmad_bytes_to_cycles(ch_req, drb_size);
- + drb->sync = 0;
- + size -= drb_size;
- + addr_iter += drb_size;
- + }
- + //printk(KERN_INFO "%s() size_remain 0x%08x.\n", __func__, size);
- +
- + if (unlikely(0 != dmad_submit_request(ch_req, drb, 1))) {
- + printk(KERN_ERR "%s() Failed to submit dma request block!\n", __func__);
- + return FALSE;
- + }
- + }
- +
- + if (wait_for_completion_timeout(&cf_dma_cmpl, timeout - jiffies) == 0)
- + printk("write timeout\n");
- +
- + while( !( cfc->HostStatus & INTA_BIT))
- + ;
- +
- + cfc->HostStatus = INTA_BIT;
- + /* Stop DMA */
- + cfc->ControlReg &= ~ENDMA_BIT;
- + cfc->ControlReg &= ~MODE_BIT;
- +
- + do{
- + data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
- +
- + } while( data & BUSY_BIT);
- + }
- + else {
- + while( size > 0){
- +
- + /* write data from FIFO */
- + if( size >= ( CFC_WRITE_FIFO_LEN << 2))
- + count = CFC_WRITE_FIFO_LEN;
- + else
- + count = ( size >> 2);
- +
- + size -= ( count << 2);
- + }
- + }
- +
- + data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
- +
- + while( 1){
- +
- + if( data & ERR_BIT){
- +
- + DEBUG( CF_DEBUG, 1, "ERROR: ( CFReadSector) CF Read sector error.\n");
- + return FALSE;
- + }
- + else if( data & DWF_BIT){
- +
- + DEBUG( CF_DEBUG, 1, "ERROR: ( CFReadSector) CF write fault error.\n");
- + return FALSE;
- + }
- + else if( data & ( RDY_BIT | DSC_BIT))
- + break;
- +
- + data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
- + }
- + return TRUE;
- +}
- +
- +static int cf_card_insert( cf_card_t *info)
- +{
- + DEBUG( CF_DEBUG, 1, "Enter\n");
- + CardReset();
- + DEBUG( CF_DEBUG, 1, "Exit\n");
- +
- + return TRUE;
- +}
- +
- +/* Free IRQ and DMA resources */
- +static void cf_free( cf_dev_t *dev)
- +{
- + release_region( FTCFC_VA_BASE, 0x48); /* return ioport */
- + free_irq( FTCFC_IRQ, dev); /* return Hotswapping irq */
- +
- + if (cf_card_info.DMAEnable) {
- +#if (CF_DEBUG)
- + if (dev->ch_req.controller == DMAD_DMAC_APB_CORE)
- + printk("%s: free APB dma channel (%d)\n", __func__, dev->ch_req.channel);
- + else
- + printk("%s: free AHB dma channel (%d)\n", __func__, dev->ch_req.channel);
- +#endif
- + dmad_channel_free(&dev->ch_req);
- + cf_card_info.DMAEnable = FALSE;
- + }
- +}
- +
- +static int cf_card_remove( cf_card_t *info)
- +{
- + cf_err_code = ERR_NO_ERROR;
- +
- + info->ActiveState = FALSE;
- + info->WriteProtect = FALSE;
- + info->RCA = 0;
- +
- + /* reset host interface controller */
- + cfc->ControlReg |= RESET_BIT;
- +
- + mdelay( 100);
- + cfc->ControlReg &= ~RESET_BIT; /* must manually clear reset bit */
- + return TRUE;
- +}
- +
- +irqreturn_t cf_hotswap_interrupt_handler( int irq, void *dev_id)
- +{
- + cf_dev_t *dev = dev_id;
- +
- + DEBUG( CF_DEBUG, 1, "irq: %d\n", irq);
- +
- + /*
- + * When the card is inserted or removed, we must delay a short time to make sure
- + * the SDC_STATUS_REG_CARD_INSERT bit of status register is stable
- + */
- +
- + if( cfc->HostStatus & INT_CD_BIT ){
- +
- + mdelay( 100); /* wait 0.1 sec for card stable */
- +
- + DEBUG( CF_DEBUG, 1, "Card %s\n", cfc->HostStatus & CARD_DETECT_BIT ? "Insert" : "Remove");
- + if( cfc->HostStatus & CARD_DETECT_BIT ){
- +
- + dev->card_state = CF_CARD_INSERT;
- + cf_card_insert( &cf_card_info);
- + }
- + else {
- + dev->card_state = CF_CARD_REMOVE;
- + cf_card_remove( &cf_card_info);
- + }
- +
- + cfc->HostStatus = INT_CD_BIT;
- + }
- + else{
- + DEBUG( CF_DEBUG, 1, "cfc->HostStatus & INT_CD_BIT == 0\n");
- + }
- +
- + DEBUG( CF_DEBUG, 1, "Exit: card state = %d\n", dev->card_state);
- + return IRQ_HANDLED;
- +}
- +
- +int cf_read_multiple_block( cf_card_t *info, uint addr, uint count, uint size, uint timeout, unchar *buf)
- +{
- + u8 data;
- +
- + DEBUG( CF_DEBUG, 1, "read block addr: 0x%x(%d) sectors: %d\n", addr, addr, count);
- +
- + cf_err_code = ERR_NO_ERROR;
- + Translate_Config_HCS( addr, count);
- + CF_SendCommand( ATA_READ_SECTOR);
- +
- + do{
- + data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
- +
- + } while( data & BUSY_BIT);
- +
- + SetTransferSizeEx( BLKMEM_DATA_REG, COMMON_MEM, READ_OP, NOINCADR, CF_SECTOR_SIZE * count);
- +
- + if( first_run == 0){
- +
- + udelay( 100000);
- +
- + first_run = 1;
- + }
- +
- + if( !cfc_read_block( info, CF_SECTOR_SIZE * count, ( uint *)buf))
- + return FALSE;
- +
- + if( cf_err_code != ERR_NO_ERROR){
- +
- + DEBUG( CF_DEBUG, 1, "error = 0x%x\n", cf_err_code);
- + DEBUG( CF_DEBUG, 1, "r addr %d count %d\n", addr, count);
- +
- + return FALSE;
- + }
- +
- + return TRUE;
- +}
- +
- +int cf_write_multiple_block( cf_card_t *info, uint addr, uint count, uint size, uint timeout, unchar *buf)
- +{
- + u8 data;
- +
- + DEBUG( CF_DEBUG, 1, "write block addr: 0x%08lx, sectors: %x, sector: %x\n", ( unsigned long)addr, count, 512);
- +
- + cf_err_code = ERR_NO_ERROR;
- + Translate_Config_HCS( addr, count);
- + CF_SendCommand( ATA_WRITE_SECTOR);
- + do {
- + data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
- + } while( data & BUSY_BIT);
- +
- + SetTransferSizeEx( BLKMEM_DATA_REG, COMMON_MEM, WRITE_OP, NOINCADR, CF_SECTOR_SIZE * count);
- +
- + if( !cfc_write_block( info, CF_SECTOR_SIZE*count, ( uint *) buf))
- + return FALSE;
- +
- + if( cf_err_code != ERR_NO_ERROR){
- +
- + DEBUG( CF_DEBUG, 1, "error: 0x%08lx\n", ( unsigned long)cf_err_code);
- + DEBUG( CF_DEBUG, 1, "w addr: %d, count: %d\n", addr, count);
- + return FALSE;
- + }
- +
- + return TRUE;
- +}
- +
- +
- +/***************************************************************************
- + * SD Card Read/Write/Erase Function
- + ***************************************************************************/
- +int cf_read_sector( cf_card_t *info, uint addr, uint count, unchar *buf)
- +{
- + DEBUG( CF_DEBUG, 1, "Enter\n");
- +
- + if( !cf_read_multiple_block( info, addr + cf_devices->lba_sec_offset, count,
- + info->CSD.ReadBlockLength, info->ReadAccessTimoutCycle, buf)){
- +
- + DEBUG( CF_DEBUG, 1, "read failed\n");
- + return FALSE;
- + }
- +
- + DEBUG( CF_DEBUG, 1, "read ok\n");
- +
- + if( cf_devices->lba_sec_offset == 0){
- +
- + if( !cf_read_multiple_block( info, 0, 1, info->CSD.ReadBlockLength, info->ReadAccessTimoutCycle, buf))
- + return FALSE;
- +
- + /* lba ( ??) sector offset */
- + cf_devices->lba_sec_offset = ( *( buf + 0x1C6))
- + | ( *( buf + 0x1C7)) << 8
- + | ( *( buf + 0x1C8)) << 16
- + | ( *( buf + 0x1C9)) << 24;
- +
- + /* device total sector number */
- + g_cf_sectors = ( *( buf + 0x1CA))
- + | ( *( buf + 0x1CB)) << 8
- + | ( *( buf + 0x1CC)) << 16
- + | ( *( buf + 0x1CD)) << 24;
- +
- + /* only for testing , it only to let format command ok */
- + if( ( buf[ 0x1be] != 0x0) && ( buf[ 0x1be] != 0x80)) /* partition identify */
- + cf_devices->lba_sec_offset = 0; /* sector 0 is PBR */
- + else
- + cf_devices->lba_sec_offset = ( buf[ 0x1c6])
- + | ( buf[ 0x1c7] << 8)
- + | ( buf[ 0x1c8] << 16)
- + | ( buf[ 0x1c9] << 24);
- +
- + DEBUG( CF_DEBUG, 1, "lba_sec_offet is %d\n", cf_devices->lba_sec_offset);
- + DEBUG( CF_DEBUG, 1, "the device( partition) total sector number is %d\n", g_cf_sectors);
- + }
- +
- + DEBUG( CF_DEBUG, 1, "Exit\n");
- + return TRUE;
- +}
- +
- +int cf_write_sector( cf_card_t *info, uint addr, uint count, unchar *buf)
- +{
- + if( !cf_write_multiple_block( info, addr+cf_devices->lba_sec_offset, count,
- + info->CSD.ReadBlockLength, info->ReadAccessTimoutCycle, buf)){
- +
- + DEBUG( CF_DEBUG, 1, "write failed\n");
- +
- + return FALSE;
- + }
- +
- + DEBUG( CF_DEBUG, 1, "write ok\n");
- +
- + return TRUE;
- +}
- +
- +/*
- + * Perform an actual transfer:
- + * Returns: # of sectors transferred. 0 = error
- + */
- +int cf_transfer( cf_dev_t *device, const struct request *req)
- +{
- + int status = 0;
- + int count = 0;
- +
- + struct bio *bio = req->bio;
- + struct bio_vec *bvec;
- + struct req_iterator iter;
- +
- + DEBUG( CF_DEBUG, 1, "req sector: %d, phys_seg: %d, buf: 0x%08lx\n",
- + (int)req->__sector, req->nr_phys_segments,
- + (unsigned long)bio_data(bio));
- +
- + spin_unlock_irq( &device->lock);
- +
- + rq_for_each_segment( bvec, req, iter){
- +
- + unsigned char *buf = page_address( bvec->bv_page) + bvec->bv_offset;
- + int sectors = bio_cur_bytes( bio) >> 9;
- +
- + DEBUG( CF_DEBUG, 1, "bvec[%2d]: sector: %d, count: %d, curr: %d, buf: 0x%08lx\n",
- + iter.i, ( int)bio->bi_sector, count, ( int)sectors, ( unsigned long)buf);
- +
- + cf_card_info.private = (void *)&device->ch_req;
- +
- + if( rq_data_dir( req) == 0) /* Read */
- + status = cf_read_sector( &cf_card_info, bio->bi_sector, sectors, buf);
- + else
- + status = cf_write_sector( &cf_card_info, bio->bi_sector, sectors, buf);
- +
- + DEBUG( CF_DEBUG, 1, "status: %d\n", status);
- +
- + if (status <= 0) {
- + spin_lock_irq( &device->lock);
- + return count;
- + }
- +
- + count += sectors;
- + bio->bi_sector += sectors;
- + }
- +
- + spin_lock_irq( &device->lock);
- +
- + if( status <= 0)
- + return 0;
- + else
- + return count;
- +}
- +
- +static int cf_card_setup(cf_dev_t *dev)
- +{
- + int i;
- +
- + DEBUG( CF_DEBUG, 1, "Enter\n");
- + first_run = 0;
- + cf_err_code = ERR_NO_ERROR;
- +
- + cf_card_info.ActiveState = FALSE;
- + cf_card_info.WriteProtect = FALSE;
- + cf_card_info.IOAddr = FTCFC_VA_BASE;
- + cf_card_info.DMAEnable = TRUE;
- + cf_card_info.DMAChannel = dev->ch_req.channel;
- + cf_card_info.SysFrequency = AHB_CLK_IN / 2;
- + cf_card_info.RCA = 0;
- +
- + DEBUG( CF_DEBUG, 1, "DMA Enable is %d, Sys frequency = %d\n", cf_card_info.DMAEnable, cf_card_info.SysFrequency);
- +
- + if( !cf_card_insert( &cf_card_info))
- + return FALSE;
- +
- + /* Marketing MB is not 1048576 */
- + DEBUG( CF_DEBUG, 1, "FTCFC010: CF Card Capacity = %d KBytes\n", g_cf_sectors >> 1);
- +
- + for( i = 0; i < CF_DEVS; i++)
- + cf_devices[i].size = g_cf_sectors; /* unit is block, not bytes */
- +
- + DEBUG( CF_DEBUG, 1, "Exit\n");
- +
- + return TRUE;
- +}
- +
- +int cf_ioctl( struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg)
- +{
- + int size;
- + struct hd_geometry geo;
- + cf_dev_t *device = bdev->bd_disk->private_data;
- +
- + DEBUG( CF_DEBUG, 1, "ioctl 0x%x 0x%lx\n", cmd, arg);
- +
- + switch ( cmd){
- +
- + case BLKGETSIZE:
- + /*
- + * Return the device size, expressed in sectors
- + * FIXME: distinguish between kernel sector size and media sector size
- + */
- + size = device->size;
- + __copy_to_user ( ( long *) arg, &size, sizeof ( long));
- + return 0;
- +
- + case HDIO_GETGEO:
- + /*
- + * get geometry: we have to fake one... trim the size to a
- + * multiple of 64 ( 32k): tell we have 16 sectors, 4 heads,
- + * whatever cylinders. Tell also that data starts at sector. 4.
- + */
- + geo.cylinders = ( device->size / 4) / 8; /* ?? only for test */
- + geo.heads = 4;
- + geo.sectors = 8;
- + geo.start = 0;
- + __copy_to_user ( ( void *) arg, &geo, sizeof ( geo));
- + return 0;
- +
- + default:
- + /* For ioctls we don't understand, let the block layer handle them */
- + return -ENOTTY;
- + }
- +
- + return -ENOTTY; /* unknown command */
- +}
- +
- +static void cf_request( struct request_queue *q)
- +{
- + cf_dev_t *dev;
- + int ret = 0;
- + struct request *req;
- + static int act = 0;
- +
- + if( act)
- + return;
- +
- + act = 1;
- +
- + while( ( req = blk_fetch_request( q)) != NULL){
- +
- + dev = req->rq_disk->private_data;
- +
- + if( !dev || dev->card_state == CF_CARD_REMOVE){
- +
- + DEBUG( CF_DEBUG, 1, "CF: locating device error\n");
- + __blk_end_request_cur( req, -EIO);
- +
- + act = 0;
- + return;
- + }
- +
- + ret = cf_transfer( dev, req);
- + __blk_end_request( req, 0, ret << 9);
- + }
- +
- + act = 0;
- +}
- +
- +static int cf_dma_ch_alloc(cf_dev_t *dev)
- +{
- + dmad_chreq *ch_req = &dev->ch_req;
- +
- + memset(ch_req, 0, sizeof(dmad_chreq));
- +
- +#ifdef CONFIG_PLATFORM_APBDMA
- +
- + ch_req->apb_req.addr0_ctrl = APBBR_ADDRINC_FIXED; /* (in) APBBR_ADDRINC_xxx */
- + ch_req->apb_req.addr0_reqn = APBBR_REQN_CFC; /* (in) APBBR_REQN_xxx (also used to help determine bus selection) */
- + ch_req->apb_req.addr1_ctrl = APBBR_ADDRINC_I4X; /* (in) APBBR_ADDRINC_xxx */
- + ch_req->apb_req.addr1_reqn = APBBR_REQN_NONE; /* (in) APBBR_REQN_xxx (also used to help determine bus selection) */
- + ch_req->apb_req.burst_mode = 0; /* (in) Burst mode (0: no burst 1-, 1: burst 4- data cycles per dma cycle) */
- + ch_req->apb_req.data_width = APBBR_DATAWIDTH_4; /* (in) APBBR_DATAWIDTH_4(word), APBBR_DATAWIDTH_2(half-word), APBBR_DATAWIDTH_1(byte) */
- + ch_req->apb_req.tx_dir = DMAD_DIR_A0_TO_A1; /* (in) DMAD_DIR_A0_TO_A1, DMAD_DIR_A1_TO_A0 */
- +
- + ch_req->controller = DMAD_DMAC_APB_CORE; /* (in) DMAD_DMAC_AHB_CORE, DMAD_DMAC_APB_CORE */
- + ch_req->flags = DMAD_FLAGS_SLEEP_BLOCK | DMAD_FLAGS_BIDIRECTION;
- +
- + if (dmad_channel_alloc(ch_req) != 0) {
- + memset(ch_req, 0, sizeof(dmad_chreq));
- + printk(KERN_INFO "%s: APB dma channel allocation failed\n", __func__);
- + goto _try_ahb;
- + }
- +
- +#if (CF_DEBUG)
- + printk("%s: APB dma channel allocated (ch: %d)\n", __func__, ch_req->channel);
- +#endif
- +
- + return 0;
- +
- +_try_ahb:
- +
- +#endif /* CONFIG_PLATFORM_APBDMA */
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- +
- + ch_req->ahb_req.sync = 1; /* (in) non-zero if src and dst have different clock domain */
- + ch_req->ahb_req.priority = DMAC_CSR_CHPRI_1; /* (in) DMAC_CSR_CHPRI_0 (lowest) ~ DMAC_CSR_CHPRI_3 (highest) */
- + ch_req->ahb_req.hw_handshake = 1; /* (in) non-zero to enable hardware handshake mode */
- + ch_req->ahb_req.burst_size = DMAC_CSR_SIZE_4; /* (in) DMAC_CSR_SIZE_1 ~ DMAC_CSR_SIZE_256 */
- + ch_req->ahb_req.addr0_width = DMAC_CSR_WIDTH_32; /* (in) DMAC_CSR_WIDTH_8, DMAC_CSR_WIDTH_16, or DMAC_CSR_WIDTH_32 */
- + ch_req->ahb_req.addr0_ctrl = DMAC_CSR_AD_FIX; /* (in) DMAC_CSR_AD_INC, DMAC_CSR_AD_DEC, or DMAC_CSR_AD_FIX */
- + ch_req->ahb_req.addr0_reqn = DMAC_REQN_CFC; /* (in) DMAC_REQN_xxx (also used to help determine channel number) */
- + ch_req->ahb_req.addr1_width = DMAC_CSR_WIDTH_32; /* (in) DMAC_CSR_WIDTH_8, DMAC_CSR_WIDTH_16, or DMAC_CSR_WIDTH_32 */
- + ch_req->ahb_req.addr1_ctrl = DMAC_CSR_AD_INC; /* (in) DMAC_CSR_AD_INC, DMAC_CSR_AD_DEC, or DMAC_CSR_AD_FIX */
- + ch_req->ahb_req.addr1_reqn = DMAC_REQN_NONE; /* (in) DMAC_REQN_xxx (also used to help determine channel number) */
- + ch_req->ahb_req.tx_dir = DMAD_DIR_A0_TO_A1; /* (in) DMAD_DIR_A0_TO_A1, DMAD_DIR_A1_TO_A0 */
- +
- + ch_req->controller = DMAD_DMAC_AHB_CORE; /* (in) DMAD_DMAC_AHB_CORE, DMAD_DMAC_APB_CORE */
- + ch_req->flags = DMAD_FLAGS_SLEEP_BLOCK | DMAD_FLAGS_BIDIRECTION;
- +
- + if (dmad_channel_alloc(ch_req) != 0) {
- + memset(ch_req, 0, sizeof(dmad_chreq));
- + printk(KERN_INFO "%s: AHB dma channel allocation failed\n", __func__);
- + goto _err_exit;
- + }
- +
- +#if (CF_DEBUG)
- + printk("%s: AHB dma channel allocated (ch: %d)\n", __func__, ch_req->channel);
- +#endif
- +
- + return 0;
- +
- +_err_exit:
- +
- +#endif /* CONFIG_PLATFORM_AHBDMA */
- +
- + return -ENODEV;
- +}
- +
- +/*
- + * Note no locks taken out here. In a worst case scenario, we could drop
- + * a chunk of system memory. But that should never happen, since validation
- + * happens at open or mount time, when locks are held.
- + */
- +static int cf_revalidate( struct gendisk *gd)
- +{
- + cf_dev_t *dev = gd->private_data;
- +
- + DEBUG( CF_DEBUG, 1, "Enter\n");
- + dev->card_state = cfc->HostStatus & CARD_DETECT_BIT ? CF_CARD_INSERT : CF_CARD_REMOVE;
- +
- + DEBUG( CF_DEBUG, 1, "card state: %s\n",
- + dev->card_state == CF_CARD_INSERT ? "INSERT" :
- + dev->card_state == CF_CARD_WORK ? "WORK" : "REMOVE");
- +
- + if( !dev->usage){
- +
- + if( cf_card_setup(dev) != TRUE){
- +
- + DEBUG( CF_DEBUG, 1, "cf_card_setup failed\n");
- + dev->card_state = CF_CARD_REMOVE;
- +
- + return -1;
- + }
- + else {
- + DEBUG( CF_DEBUG, 1, "CFC Driver with DMA Mode\n");
- +
- + if (cf_card_info.DMAEnable) {
- + /* acquire dma channel */
- + if (cf_dma_ch_alloc(dev) != 0) {
- + cf_card_info.DMAEnable = FALSE;
- + cf_free( dev);
- + DEBUG( CF_DEBUG, 1, "Request DMA resource failed\n");
- + return -1;
- + }
- + DEBUG( CF_DEBUG, 1, "Request DMA resource success\n");
- + }
- +
- + /* SDC interrupt, currently only for HotSwap */
- + DEBUG( CF_DEBUG, 1, "Request CFC IRQ: %d\n", FTCFC_IRQ);
- +
- + if( request_irq( FTCFC_IRQ, cf_hotswap_interrupt_handler, IRQF_DISABLED, "CF controller", dev) != 0){
- +
- + DEBUG( CF_DEBUG, 1, "Unable to allocate CFC IRQ: 0x%x\n", FTCFC_IRQ);
- + cf_free( dev);
- + return -1;
- + }
- +
- + /* require io port address for sd controller */
- + if( request_region( FTCFC_VA_BASE, 0x48, "CF Controller") == NULL){
- +
- + DEBUG( CF_DEBUG, 1, "request io port of sd controller fail\n");
- + cf_free( dev);
- + return -1;
- + }
- +
- + dev->card_state = CF_CARD_WORK;
- + }
- + }
- +
- + DEBUG( CF_DEBUG, 1, "Exit\n");
- +
- + return 0;
- +}
- +
- +/* TODO: forbids open for write when WRITE_PROTECT = 1 */
- +static int cf_open( struct block_device *bdev, fmode_t mode)
- +{
- + cf_dev_t *dev= bdev->bd_disk->private_data; /* device information */
- +
- + DEBUG( CF_DEBUG, 1, "Enter\n");
- +
- + if( ( cfc->HostStatus & CARD_DETECT_BIT) != CARD_DETECT_BIT){
- +
- + DEBUG( CF_DEBUG, 1, "Error: ( ENOMEDIUM)\n");
- + return -ENOMEDIUM;
- + }
- +
- + if( CFCardInit()){
- +
- + DEBUG( CF_DEBUG, 1, "root initialize failed\n");
- + return FALSE;
- + }
- +
- + if( !dev->usage){
- +
- + dev->media_change = 1;
- + DEBUG( CF_DEBUG, 1, "forced check_disk_change check\n");
- + check_disk_change( bdev);
- + }
- + else{
- + dev->media_change = 0;
- + }
- +
- + DEBUG( CF_DEBUG, 1, "set_capacity() to %d blocks ( %d KBytes)\n", dev->size, dev->size >> 1);
- + set_capacity( dev->gd, dev->size);
- + dev->usage++;
- + cf_devices->lba_sec_offset = 0;
- + DEBUG( CF_DEBUG, 1, "dev: 0x%08lx, cf_devices: 0x%08lx\n", ( unsigned long)dev, ( unsigned long)cf_devices);
- +
- + DEBUG( CF_DEBUG, 1, "Exit\n");
- +
- + return 0; /* success */
- +}
- +
- +static int cf_release( struct gendisk *gd, fmode_t mode)
- +{
- + cf_dev_t *dev = gd->private_data;
- +
- + DEBUG( CF_DEBUG, 1, "Enter\n");
- +
- + dev->usage--;
- +
- + if( !dev->usage)
- + cf_free( dev);
- +
- + DEBUG( CF_DEBUG, 1, "Exit\n");
- +
- + return 0;
- +}
- +
- +static void setup_device( struct cf_dev *dev, int which)
- +{
- + memset ( dev, 0, sizeof ( struct cf_dev));
- + dev->size = 0;
- + spin_lock_init( &dev->lock);
- +
- + dev->queue = blk_init_queue( cf_request, &dev->lock);
- +
- + if( !dev->queue)
- + goto out_vfree;
- +
- + blk_queue_logical_block_size( dev->queue, hardsect_size);
- + dev->queue->queuedata = dev;
- +
- + dev->card_state = CF_CARD_REMOVE;
- +
- + /* And the gendisk structure. */
- + dev->gd = alloc_disk( CF_MINORS);
- + if( ! dev->gd){
- +
- + DEBUG( CF_DEBUG, 1, "alloc_disk failure\n");
- + goto out_vfree;
- + }
- +
- + dev->gd->flags = GENHD_FL_REMOVABLE | GENHD_FL_SUPPRESS_PARTITION_INFO;
- + dev->gd->major = cf_major;
- + dev->gd->first_minor = which * CF_MINORS;
- + dev->gd->minors = CF_MINORS;
- + dev->gd->fops = &cf_fops;
- + dev->gd->queue = dev->queue;
- + dev->gd->private_data = dev;
- +
- + snprintf ( dev->gd->disk_name, 32, "cpecf%c", which + 'a');
- + set_capacity( dev->gd, 0);
- + add_disk( dev->gd);
- +
- + return;
- +
- +out_vfree:
- +
- + return;
- +}
- +
- +static int cf_media_changed( struct gendisk *gd)
- +{
- + struct cf_dev *dev = gd->private_data;
- +
- + DEBUG( CF_DEBUG, 1, "cf_media_changed = %d\n", dev->media_change);
- +
- + return dev->media_change;
- +}
- +
- +struct block_device_operations cf_fops = {
- +
- + .owner = THIS_MODULE,
- + .open = cf_open,
- + .release = cf_release,
- + .ioctl = cf_ioctl,
- + .revalidate_disk = cf_revalidate,
- + .media_changed = cf_media_changed,
- +};
- +
- +static int __init cf_module_init( void)
- +{
- + int result= -ENOMEM, i;
- +
- + DEBUG( 1, 0, "Faraday CF controller Driver (DMA mode)\n");
- +
- + cf_major = register_blkdev( cf_major, DEVICE_NAME);
- +
- + if( cf_major <= 0){
- +
- + DEBUG( CF_DEBUG, 1, ":unable to get major number\n");
- + return -EBUSY;
- + }
- +
- + DEBUG( 1, 0, "CF: make node with 'mknod /dev/cpecf b %d 0'\n", cf_major);
- +
- + cf_devices = kzalloc( CF_DEVS * sizeof( cf_dev_t), GFP_KERNEL);
- +
- + if( !cf_devices)
- + goto fail_malloc;
- +
- + for( i = 0; i < CF_DEVS; i++)
- + setup_device( cf_devices + i, i);
- +
- + return 0;
- +
- +fail_malloc:
- +
- + if( cf_devices)
- + kfree( cf_devices);
- +
- + unregister_blkdev( cf_major, DEVICE_NAME);
- +
- + return result;
- +}
- +
- +static void cf_module_cleanup( void)
- +{
- + int i;
- +
- + if( cf_devices){
- +
- + for( i = 0; i < CF_DEVS; i++){
- +
- + del_gendisk( cf_devices[i].gd);
- + put_disk( cf_devices[i].gd);
- +
- + if( cf_devices[i].queue)
- + blk_cleanup_queue( cf_devices[i].queue);
- + }
- +
- + kfree( cf_devices);
- + }
- +
- + unregister_blkdev( cf_major, DEVICE_NAME);
- +}
- +
- +module_init( cf_module_init);
- +module_exit( cf_module_cleanup);
- +
- +MODULE_AUTHOR( "Faraday Corp.");
- +MODULE_LICENSE( "GPL");
- diff -Nur linux-3.4.110.orig/drivers/block/ftcfc010.h linux-3.4.110/drivers/block/ftcfc010.h
- --- linux-3.4.110.orig/drivers/block/ftcfc010.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/block/ftcfc010.h 2016-04-07 10:20:51.022084119 +0200
- @@ -0,0 +1,438 @@
- +/* drivers/block/CPECF/ftcfc.h
- + *
- + * Faraday FTCFC010 Device Driver
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + *
- + * All Rights Reserved
- + */
- +
- +#ifndef _FTCFC_H_
- +#define _FTCFC_H_
- +
- +#define CF_DEBUG 1
- +
- +#ifndef TRUE
- +#define TRUE 1
- +#endif
- +
- +#ifndef FALSE
- +#define FALSE 0
- +#endif
- +
- +#define CF_DEVS 1 /* number of disks */
- +#define CF_MINORS 16 /* minors per disk */
- +#define CF_SECTOR_SIZE 512 /* sector size */
- +
- +/* SD Card State */
- +#define CF_CARD_REMOVE 0
- +#define CF_CARD_INSERT 1
- +#define CF_CARD_WORK 2
- +
- +/* data window register */
- +#define CFC_READ_FIFO_LEN 4
- +#define CFC_WRITE_FIFO_LEN 4
- +
- +/* card type, sd or mmc */
- +#define MEMORY_CARD_TYPE_SD 0
- +#define MEMORY_CARD_TYPE_MMC 1
- +
- +/*****************************************************************************
- + * SYSTEM ERROR_CODE
- + ****************************************************************************/
- +#define ERR_NO_ERROR 0x00000000
- +
- +/* command error */
- +#define ERR_DATA_CRC_ERROR 0x00000100
- +#define ERR_RSP_CRC_ERROR 0x00000200
- +#define ERR_DATA_TIMEOUT_ERROR 0x00000400
- +#define ERR_RSP_TIMEOUT_ERROR 0x00000800
- +
- +#define ERR_WAIT_OVERRUN_TIMEOUT 0x00001000
- +#define ERR_WAIT_UNDERRUN_TIMEOUT 0x00002000
- +#define ERR_WAIT_DATA_CRC_TIMEOUT 0x00004000
- +#define ERR_WAIT_TRANSFER_END_TIMEOUT 0x00008000
- +
- +#define ERR_SEND_COMMAND_TIMEOUT 0x00010000
- +
- +/* using APB DMA error */
- +#define ERR_APBDMA_RSP_ERROR 0x02000000
- +
- +/*
- + * Please refer SanDisk SD Manual v1.9 Section 5.1.9.2 (page 5-76) to set the timeout setting
- + */
- +#if CF_DEBUG
- +#define CFC_TIMEOUT_BASE (HZ/2) /* Unit is 500 ms */
- +#else
- +#define CFC_TIMEOUT_BASE (HZ/3) /* Unit is 333 ms */
- +#endif
- +
- +typedef struct _cf_cid_t
- +{
- + uint ManufacturerID;
- + uint ApplicationID;
- + unchar ProductName[7];
- + uint ProductRevisionHigh;
- + uint ProductRevisionLow;
- + uint ProductSerialNumber;
- + uint ManufactureMonth;
- + uint ManufactureYear;
- +} cf_cid_t;
- +
- +typedef struct _cf_ccf_t
- +{
- + uint CSDStructure;
- + uint MMCSpecVersion;
- + uint TAAC_u;
- + uint NSAC_u;
- + uint TransferSpeed;
- + uint CardCmdClass;
- + uint ReadBlockLength;
- + uint ReadBlockPartial;
- + uint WriteBlockMisalign;
- + uint ReadBlockMisalign;
- + uint DSRImplemant;
- + uint BlockNumber;
- + uint MemorySize;
- + uint VDDReadMin_u;
- + uint VDDReadMax_u;
- + uint VDDWriteMin_u;
- + uint VDDWriteMax_u;
- + uint EraseBlkEnable;
- + uint EraseSectorSize;
- + uint WriteProtectGroupSize;
- + uint WriteProtectGroupEnable;
- + uint WriteSpeedFactor;
- + uint WriteBlockLength;
- + unchar WriteBlockPartial;
- + unchar CopyFlag;
- + unchar PermanentWriteProtect;
- + unchar TemporaryWriteProtect;
- + unchar FileFormat;
- +} cf_ccf_t;
- +
- +/*****************************************************************************
- + * SD SCR register
- + ****************************************************************************/
- +typedef struct _cf_scr_t
- +{
- + uint Reserved:16;
- + uint SD_BUS_WIDTH:4;
- + uint SD_SECURITY:3;
- + uint DATA_STAT_AFTER_ERASE:1;
- + uint SD_SPEC:4;
- + uint SCR_STRUCTURE:4;
- +
- + uint ManufacturerReserved;
- +} cf_scr_t;
- +
- +/*****************************************************************************
- + * sd card structure
- + ****************************************************************************/
- +typedef struct _cf_card_t
- +{
- + /* host interface configuration */
- + uint IOAddr; /* host controller register base address */
- + uint DMAEnable;
- + uint DMAChannel;
- +
- + uint CardType;
- +
- + uint CIDWord[4];
- + cf_cid_t CID;
- +
- + uint CSDWord[4];
- + cf_ccf_t CSD;
- +
- + ushort RCA;
- + cf_scr_t SCR;
- +
- + /* access time out */
- + uint ReadAccessTimoutCycle;
- + uint WriteAccessTimoutCycle;
- +
- + /* system configurations */
- + uint SysFrequency;
- +
- + /* card status */
- + int ActiveState;
- + int WriteProtect;
- +
- + void *private;
- +} cf_card_t;
- +
- +typedef struct _CF_Dev
- +{
- + u32 dev_size; /* used same as sect_num */
- + u32 sect_num; /* sector num */
- + u8 blksize_bit; /* It's not used */
- + u32 blksize; /* size of block in file system, 1024 */
- +
- + u32 phy_blksize; /* Physical size of block on the CF. It's not used */
- + u32 phy_sectorsize; /* the size of erasable sector. It's not used */
- + u32 wp_grp_size; /* the size of write protected group. It's not used */
- +
- + spinlock_t lock; /* synchronization */
- + struct semaphore sema; /* synchronization */
- + u32 usage;
- +
- + u8 busy;
- +
- + wait_queue_head_t select_wait; /* Kernel thread blocked on it. It's not used */
- + u8 cmd; /* What command being executed. */
- + u32 result; /* set by tasklet */
- + u8 *buff;
- +
- + u32 lba_sec_offset;
- +
- + /*APB_DMA */
- +
- + u8 DMATransDir; /* 0: IDLE, 1:READ, 2:WRITE */
- +} CF_Dev;
- +
- +#define CFC_R_IDLE 0x00
- +#define CFC_R_START_TRANSFER 0x01
- +#define CFC_R_SET_CFCARD_REG 0x02
- +#define CFC_R_SET_CFCARD_READ_CMD 0x03
- +#define CFC_R_CHK_CFCARD_READY 0x04
- +#define CFC_R_SET_DMA_REG 0x05
- +#define CFC_R_DMA_START 0x06
- +#define CFC_R_DMA_INT 0x07
- +#define CFC_R_DMA_FINISH 0x08
- +#define CFC_R_PIO_START 0x09
- +#define CFC_R_PIO_FINISH 0x0A
- +#define CFC_R_CHECK_CFCARD_BUSY 0x0B
- +#define CFC_R_CHECK_CFCARD_READY 0x0C
- +
- +#define CFC_W_IDLE 0x00
- +#define CFC_W_START_TRANSFER 0x10
- +#define CFC_W_SET_CFCARD_REG 0x20
- +#define CFC_W_SET_CFCARD_READ_CMD 0x30
- +#define CFC_W_CHK_CFCARD_READY 0x40
- +#define CFC_W_SET_DMA_REG 0x50
- +#define CFC_W_DMA_START 0x60
- +#define CFC_W_DMA_INT 0x70
- +#define CFC_W_DMA_FINISH 0x80
- +#define CFC_W_PIO_START 0x90
- +#define CFC_W_PIO_FINISH 0xA0
- +#define CFC_W_CHECK_CFCARD_BUSY 0xB0
- +#define CFC_W_CHECK_CFCARD_READY 0xC0
- +
- +#define DMA_IDLE 0x00
- +#define DMA_READ 0x01
- +#define DMA_WRITE 0x02
- +
- +typedef struct CFCTYPE
- +{
- + u32 HostStatus; /* 0x00 */
- + u32 ControlReg; /* 0x04 */
- + u32 TimeCfgReg; /* 0x08 */
- + u32 BuffCtrlReg; /* 0x0C */
- + u32 BufferData; /* 0x10 */
- + u32 MultiSector; /* 0x14 */
- +
- + /* Enchanced Feature */
- + u32 TransSzMode2En; /* 0x18 */
- + u32 TransSzMode2Cnt; /* 0x1C */
- + u32 Reserved[4]; /* 0x20~0x2F is reserved */
- + u32 Revision; /* 0x30 */
- + u32 Feature; /* 0x34 (define buffer size) */
- +
- +} CFCTYPE;
- +
- +#define cfc ((volatile struct CFCTYPE *) (FTCFC_VA_BASE))
- +
- +typedef struct _tag_CFCardInfo
- +{
- + u32 SectTotal;
- + u8 ConfigOptionReg;
- + u8 ConfigAndStatusReg;
- + u8 PinReplaceReg;
- + u8 SocketCopyReg;
- +
- +} CF_CARD_INFO;
- +
- +#define CFC_C_Complete 0x00000400
- +#define CFC_B_Ready 0x00000200
- +#define CFC_8bit 0x00000040
- +#define CFC_16bit 0x00000000
- +#define CFC_Reset 0x00000020
- +#define CFC_T_2048 0x000C0000
- +#define CFC_T_1024 0x000B0000
- +#define CFC_T_512 0x000A0000
- +#define CFC_T_256 0x00090000
- +#define CFC_T_128 0x00080000
- +#define CFC_T_64 0x00070000
- +#define CFC_T_32 0x00060000
- +#define CFC_T_16 0x00050000
- +#define CFC_T_8 0x00040000
- +#define CFC_T_4 0x00030000
- +#define CFC_T_2 0x00020000
- +#define CFC_T_1 0x00010000
- +#define CFC_Read 0x00000000
- +#define CFC_Write 0x00008000
- +#define CFC_Increment 0x00004000
- +#define CFC_Attribute 0x00000000
- +#define CFC_Memory 0x00002000
- +#define CFC_IO 0x00003000
- +
- +/* CF status register bit mapping */
- +#define RDY_nIREQ_BIT 0x0001
- +#define CARD_DETECT_BIT 0x0002
- +#define VOL33_SENSE_BIT 0x0004
- +#define VOL40_SENSE_BIT 0x0008
- +#define STATUS_CHANGE_BIT 0x0010
- +#define SPKR_BIT 0x0020
- +#define BUF_ACTIVE_BIT 0x0100
- +#define BUF_DATA_RDY_BIT 0x0200
- +#define INTA_BIT 0x0400
- +#define BUF_SIZE_BITS 0xF000
- +#define INT_CD_BIT 0x10000
- +#define INT_IO_BIT 0x20000
- +
- +/* CF control register bit mapping */
- +#define POWER_CONTROL_BIT 0x000F
- +#define FLOW_CONTROL_BIT 0x0010
- +#define RESET_BIT 0x0020
- +#define MODE_BIT 0x0040
- +#define DMA_BIT 0x0100
- +
- +#define PWR_ON 1
- +#define PWR_OFF 0
- +
- +#define SIGNAL_ON 0x0010
- +#define SIGNAL_OFF 0x0000
- +
- +#define BYTE_MODE 0x0040
- +#define WORD_MODE 0x0000
- +
- +#define ENDMA_BIT 0x0100
- +#define DISDMA_BIT 0x0000
- +
- +#define CARD_DETECT_INT_MASK 0x0200
- +#define DATA_CMP_INT_MASK 0x0400
- +#define IO_INT_MASK 0x0800
- +
- +/* active buffer control register bit mapping */
- +#define ADR_BIT 0x007FF
- +#define TYPE_BIT 0x03000
- +#define INCADR_BIT 0x04000
- +#define RW_BIT 0x08000
- +#define TRANS_SIZE_CONTROL_BIT 0xF0000
- +
- +#define INCADR 0x04000
- +#define NOINCADR 0x00000
- +#define TRANS_SIZE_LOC 16
- +
- +#define SIZE_1_BYTE 0x01
- +#define SIZE_2_BYTE 0x02
- +#define SIZE_4_BYTE 0x03
- +#define SIZE_8_BYTE 0x04
- +#define SIZE_16_BYTE 0x05
- +#define SIZE_32_BYTE 0x06
- +#define SIZE_64_BYTE 0x07
- +#define SIZE_128_BYTE 0x08
- +#define SIZE_256_BYTE 0x09
- +#define SIZE_512_BYTE 0x0a
- +#define SIZE_1024_BYTE 0x0b
- +#define SIZE_2048_BYTE 0x0c
- +
- +#define READ_OP 0x00000
- +#define WRITE_OP 0x08000
- +
- +/* type description */
- +#define ATTRIBUTE_MEM 0x00000
- +#define COMMON_MEM 0x02000
- +
- +/*
- + * CF card
- + * memory map register
- + * IO block register
- + */
- +#define BLKMEM_DATA_REG 0x000
- +#define BLKMEM_ERROR_REG ( BLKMEM_DATA_REG + 0x01)
- +#define BLKMEM_FEATURE_REG ( BLKMEM_DATA_REG + 0x01)
- +#define BLKMEM_SECTOR_COUNT_REG ( BLKMEM_DATA_REG + 0x02)
- +#define BLKMEM_SECTOR_NUMBER_REG ( BLKMEM_DATA_REG + 0x03)
- +#define BLKMEM_CYLINDER_LOW_REG ( BLKMEM_DATA_REG + 0x04)
- +#define BLKMEM_CYLINDER_HIGH_REG ( BLKMEM_DATA_REG + 0x05)
- +#define BLKMEM_DRIVE_REG ( BLKMEM_DATA_REG + 0x06)
- +#define BLKMEM_STATUS_REG ( BLKMEM_DATA_REG + 0x07)
- +#define BLKMEM_COMMAND_REG ( BLKMEM_DATA_REG + 0x07)
- +
- +#define BLKMEM_EVEN_DATA_REG ( BLKMEM_DATA_REG + 0x08)
- +#define BLKMEM_ODD_DATA_REG ( BLKMEM_DATA_REG + 0x09)
- +#define BLKMEM_DUP_ERROR_REG ( BLKMEM_DATA_REG + 0x0d)
- +#define BLKMEM_DUP_FEATURE_REG ( BLKMEM_DATA_REG + 0x0d)
- +#define BLKMEM_DEV_CONTROL_REG ( BLKMEM_DATA_REG + 0x0e)
- +#define BLKMEM_DRIVE_ADDR_REG ( BLKMEM_DATA_REG + 0x0f)
- +#define BLKMEM_WINDOW_REG ( BLKMEM_DATA_REG + 0x400)
- +#define BLKMEM_MAX_WINDOW_REG ( BLKMEM_DATA_REG + 0x7ff)
- +
- +/* status register */
- +#define BUSY_BIT 0x80
- +#define RDY_BIT 0x40
- +#define DWF_BIT 0x20
- +#define DSC_BIT 0x10
- +#define DRQ_BIT 0x08
- +#define CORR_BIT 0x04
- +#define ERR_BIT 0x01
- +
- +/* CF ATA command */
- +#define ATA_CHECK_POWER_MODE 0xe5
- +#define ATA_EXECUTE_DRIVE_DIAG 0x90
- +#define ATA_ERASE_SECTOR 0xc0
- +#define ATA_FORMAT_TRACK 0x50
- +#define ATA_IDENTIFY_DRIVE 0xec
- +#define ATA_IDLE 0xe3
- +#define ATA_IDLE_IMMEDIATE 0xe1
- +#define ATA_INIT_DRIVE_PARA 0x91
- +#define ATA_READ_BUFFER 0xe4
- +#define ATA_READ_LONG_SECTOR 0x22
- +#define ATA_READ_MULTIPLE 0xc4
- +#define ATA_READ_SECTOR 0x21
- +#define ATA_READ_VERIFY_SECTOR 0x40
- +#define ATA_RECALIBRATE 0x10
- +#define ATA_REQUEST_SENSE 0x03
- +#define ATA_SECURITY_DISABLE_PASSWORD 0xf6
- +#define ATA_SECURITY_EREASE_PREPARE 0xf3
- +#define ATA_SECURITY_ERASE_UNIT 0xf4
- +#define ATA_SECURITY_FREEZE_LOCK 0xf5
- +#define ATA_SECURITY_SET_PASSWORD 0xf1
- +#define ATA_SECURITY_UNLOCK 0xf2
- +#define ATA_SEEK 0x70
- +#define ATA_SET_FEATURE 0xef
- +#define ATA_SET_MULTIPLE_MODE 0xc6
- +#define ATA_SET_SLEEP_MODE 0xe6
- +#define ATA_STANDBY 0xe2
- +#define ATA_STANDBY_IMMEDIATE 0xe0
- +#define ATA_TRANSFER_SECTOR 0x87
- +#define ATA_WEAR_LEVEL 0xf5
- +#define ATA_WRITE_BUFFER 0xe8
- +#define ATA_WRITE_LONG_SECTOR 0x32
- +#define ATA_WRITE_MULTIPLE 0xc5
- +#define ATA_WRITE_MULTIPLE_WO_ERASE 0xcd
- +#define ATA_WRITE_SECTOR 0x30
- +#define ATA_WRITE_SECTOR_WO_ERASE 0x38
- +#define ATA_WRITE_VERIFY 0x3c
- +
- +#define CF_MEM_MAP_MODE 0x0
- +/* attribute memory space register description */
- +#define ATTRIBUTE_MEM_BASE 0
- +#define ATTRIBUTE_MEM_CONFIG_BASE 0x200
- +#define CONFIG_OPTION_REG ( ATTRIBUTE_MEM_CONFIG_BASE + 0x00)
- +#define CARD_CONFIG_STATUS_REG ( ATTRIBUTE_MEM_CONFIG_BASE + 0x02)
- +#define PIN_REPLACE_REG ( ATTRIBUTE_MEM_CONFIG_BASE + 0x04)
- +#define SOCKET_COPY_REG ( ATTRIBUTE_MEM_CONFIG_BASE + 0x06)
- +
- +/* configuration option register */
- +#define CONF0_BIT 0x01
- +#define CONF1_BIT 0x02
- +#define CONF2_BIT 0x04
- +#define CONF3_BIT 0x08
- +#define CONF4_BIT 0x10
- +#define CONF5_BIT 0x20
- +#define LEVLREQ_BIT 0x40
- +#define SRESET_BIT 0x80
- +
- +#endif
- diff -Nur linux-3.4.110.orig/drivers/block/ftsdc010.c linux-3.4.110/drivers/block/ftsdc010.c
- --- linux-3.4.110.orig/drivers/block/ftsdc010.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/block/ftsdc010.c 2016-04-07 10:20:51.022084119 +0200
- @@ -0,0 +1,2206 @@
- +/* drivers/block/CPESD/ftsdc010.c
- + *******************************************************************************
- + * Faraday FTSDC010 Device Driver
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + *
- + * All Rights Reserved
- + *
- + * Porting to Linux 2.6 on 20050815
- + * Author: Chris Lee, I-Jui Sung, Peter Liao (support APB DMA)
- + * Version: 0.2
- + * History:
- + * 0.1 new creation
- + * 0.2 Porting to meet the style of linux dma
- + * 0.3 modify dma usage to virtual irq of dma interrupt
- + * 0.4 (20050701) Improve r/w performance
- + * 0.5 Porting to Linux 2.6 and replace busy_loop checking with timer's timeout
- + * Todo:
- + *******************************************************************************
- + */
- +
- +#include <linux/kernel.h>
- +#include <linux/module.h>
- +#include <linux/sched.h>
- +#include <linux/delay.h>
- +#include <linux/init.h>
- +#include <linux/ioport.h>
- +#include <linux/hdreg.h> /* HDIO_GETGEO */
- +#include <linux/fs.h>
- +#include <linux/blkdev.h>
- +#include <linux/buffer_head.h> /* invalidate_bdev */
- +#include <linux/bio.h>
- +#include <linux/pci.h>
- +#include <linux/mutex.h>
- +#include <asm/io.h>
- +#include <asm/uaccess.h>
- +#include <asm/spec.h>
- +#include <asm/dmad.h>
- +
- +#define IPMODULE SDC
- +#define IPNAME FTSDC010
- +
- +/* Define CONFIG_FTSDC010_USE_TIMER_DELAY if you want to use software timer instead of busy loop checking */
- +#define CONFIG_FTSDC010_USE_TIMER_DELAY
- +#undef CONFIG_FTSDC010_USE_TIMER_DELAY
- +#include "ftsdc010.h"
- +#include <linux/interrupt.h>
- +MODULE_AUTHOR("Faraday Corp.");
- +MODULE_LICENSE("Faraday License");
- +
- +/* options */
- +#define FORCE_PCI_CONSISTENCY 1 /* define it to 1 if met consistency problems */
- +#define KERNEL_SECTOR_SIZE 512 /* Use this when we refer to kernel related sector size */
- +
- +static int hardsect_size = 512;
- +module_param(hardsect_size, int, 0);
- +/*------------------------------------------------------------------------------
- + * Predefine for block device
- + */
- +#define MAJOR_NR sd_major /* force definitions on in blk.h */
- +static int sd_major=0;//SD_MAJOR; /* must be declared before including blk.h */
- +#define SD_SHIFT 4 /* max 16 partitions */
- +#define DEVICE_NAME "Faraday SDC" /* name for messaging */
- +#define DEVICE_REQUEST sd_request
- +#define DEVICE_NR(device) (MINOR(device) >> SD_SHIFT)
- +//#define DEVICE_INTR sd_intrptr /* pointer to the bottom half */
- +#define DEVICE_NO_RANDOM /* no entropy to contribute */
- +#define DEVICE_OFF(d) /* do-nothing */
- +
- +/*#include <linux/blk.h>
- +#include <linux/blkpg.h>*/ /* blk_ioctl() */
- +
- +/*------------------------------------------------------------------------------
- + * Macro definition
- + */
- +#define FTSDC_VA_BASE IP_VA_BASE(0)
- +#define FTSDC_PA_BASE IP_PA_BASE(0)
- +#define FTSDC_IRQ IP_IRQ(0)
- +#define SDC_W_REG(offset, value) outl(value, IP_VA_BASE(0) + offset)
- +#define SDC_R_REG(offset) inl(IP_VA_BASE(0) + offset)
- +
- +
- +/*------------------------------------------------------------------------------
- + * Global variable
- + */
- +
- +/* The following items are obtained through kmalloc() in sd_module_init() */
- +
- +struct block_device_operations sd_fops;
- +/* our device structure */
- +struct sd_dev {
- + int size; /* device size in sectors */
- + int usage; /* # of users currently */
- + int media_change; /* Flag: media changed? */
- + struct gendisk *gd; /* The gendisk structure */
- + spinlock_t lock; /* For mutual exclusion */
- + struct request_queue *queue; /* The device request queue */
- + int card_state;
- + dmad_chreq ch_req;
- + bool dma_enable;
- +};
- +static struct sd_dev *sd_devices = NULL;
- +
- +static sd_card_t sd_card_info;
- +static int sector_offset,Do_onetime;
- +
- +dma_addr_t dma_buf = 0; /* ?? non-zero for for manually debug ?? */
- +struct completion sd_dma_cmpl;
- +
- +static int sync_mode=0;
- +
- +static uint first_run = 0;
- +uint sd_err_code;
- +
- +#define FILE_FORMAT_HARD_DISK_LIKE 0
- +#define FILE_FORMAT_FLOPPY_LIKE 1
- +#define FILE_FORMAT_UNIVERSAL 2
- +#define FILE_FORMAT_UNKNOW 3
- +#define FILE_FORMAT_RESERVED 4
- +
- +#define K 1000
- +
- +uint TAAC_TimeUnitTable[] = { // unit is ns
- + 1, 10, 100, 1 * K, 10 * K, 100 * K, 1 * K * K, 10 * K * K
- +};
- +
- +uint TRANS_SPEED_RateUintTable[] = {
- + 100 * K, 1 * K * K, 10 * K * K, 100 * K * K
- +};
- +
- +uint TRANS_SPEED_TimeValueTable_u[] = { // unit=1/10
- + 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80
- +};
- +
- +uint VDD_CURR_MIN_Table_u[] = { // unit=1/10
- + 5, 10, 50, 100, 250, 350, 600, 1000
- +};
- +
- +uint VDD_CURR_MAX_Table_u[] = {
- + 1, 5, 10, 25, 35, 45, 80, 200
- +};
- +
- +uint TAAC_TimeValueTable_u[] = { // unit=1/10
- + 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80
- +};
- +
- +
- +unsigned int SDC_READ_FIFO_LEN;
- +unsigned int SDC_WRITE_FIFO_LEN;
- +
- +/*------------------------------------------------------------------------------
- + * Local declaration of function
- + */
- +static int sd_revalidate(struct gendisk *gd);
- +static int sd_media_changed(struct gendisk *gd);
- +static int sd_card_setup(struct sd_dev *dev);
- +int sd_check_err(uint status);
- +int sd_get_scr(sd_card_t *info, uint *scr);
- +int sd_set_transfer_state(sd_card_t *info);
- +uint sd_block_size_convert(uint size);
- +int sd_read_sector(sd_card_t *info, uint addr, uint count, unchar *buf);
- +void sd_reset_host_controller(void);
- +/*------------------------------------------------------------------------------
- + * Local function
- + */
- +
- +/*
- + * SD host controller operation
- + */
- +int sdc_send_cmd(uint cmd, uint arg, uint *rsp)
- +{
- +#ifndef CONFIG_FTSDC010_USE_TIMER_DELAY
- + int count = 0;
- +#else
- + unsigned long timeout = jiffies + SDC_GET_STATUS_RETRY_TIMEOUT_COUNT;
- +#endif
- + int i;
- + uint status;
- + P_DEBUG("SD Cmd is %d\n",cmd);
- +
- + /* clear command relative bits of status register */
- + SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_RSP_CRC_FAIL | SDC_STATUS_REG_RSP_TIMEOUT | SDC_STATUS_REG_RSP_CRC_OK| SDC_STATUS_REG_CMD_SEND);
- + /* write argument to arugument register if necessary */
- + SDC_W_REG(SDC_ARGU_REG, arg);
- + /* send command */
- + SDC_W_REG(SDC_CMD_REG, cmd | SDC_CMD_REG_CMD_EN);
- +
- + /* wait for the CMD_SEND bit of status register is set */
- +#ifndef CONFIG_FTSDC010_USE_TIMER_DELAY
- + while (count++ < SDC_GET_STATUS_RETRY_COUNT) {
- +#else
- + while (time_before(jiffies, timeout)) {
- +#endif
- + status = SDC_R_REG(SDC_STATUS_REG);
- + if (!(cmd & SDC_CMD_REG_NEED_RSP)) {
- + /* if this command does not need response, wait command sent flag */
- + if (status & SDC_STATUS_REG_CMD_SEND) {
- + /* clear command sent bit */
- + SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_CMD_SEND);
- + sd_err_code = ERR_NO_ERROR;
- + return TRUE;
- + }
- + } else {
- + /* if this command needs response */
- + if (status & SDC_STATUS_REG_RSP_TIMEOUT) {
- + /* clear response timeout bit */
- + SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_RSP_TIMEOUT);
- + sd_err_code = ERR_RSP_TIMEOUT_ERROR;
- + printk("%s() ERR_RSP_TIMEOUT_ERROR\n", __func__);
- + return FALSE;
- + } else if (status & SDC_STATUS_REG_RSP_CRC_FAIL) {
- + /* clear response fail bit */
- + SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_RSP_CRC_FAIL);
- + sd_err_code = ERR_RSP_CRC_ERROR;
- + printk("%s() ERR_RSP_CRC_ERROR\n", __func__);
- + return FALSE;
- + } else if (status & SDC_STATUS_REG_RSP_CRC_OK) {
- + /* clear response OK bit */
- + SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_RSP_CRC_OK);
- + /* if it is long response */
- + if (cmd & SDC_CMD_REG_LONG_RSP)
- + for (i = 0; i < 4; i++, rsp++)
- + *rsp = SDC_R_REG(SDC_RESPONSE0_REG + (i * 4));
- + else
- + *rsp = SDC_R_REG(SDC_RESPONSE0_REG);
- + sd_err_code = ERR_NO_ERROR;
- + return TRUE;
- + }
- + }
- + }
- + sd_err_code = ERR_SEND_COMMAND_TIMEOUT;
- + P_DEBUG("%s() ERR_SEND_COMMAND_TIMEOUT\n", __func__);
- + return FALSE;
- +}
- +
- +int sdc_check_tx_ready(void)
- +{
- + uint status;
- +#ifndef CONFIG_FTSDC010_USE_TIMER_DELAY
- + int count = 0;
- + while (count++ < SDC_GET_STATUS_RETRY_COUNT) {
- +#else
- + unsigned long timeout = jiffies + SDC_GET_STATUS_RETRY_TIMEOUT_COUNT;
- + while (time_before(jiffies, timeout)) {
- +#endif
- + status = SDC_R_REG(SDC_STATUS_REG);
- + if (status & SDC_STATUS_REG_FIFO_UNDERRUN) {
- + /* clear FIFO underrun bit */
- + SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_FIFO_UNDERRUN);
- + return TRUE;
- + } else if (status & SDC_STATUS_REG_DATA_TIMEOUT) {
- + /* clear data timeout bit */
- + printk("Wait Write FIFO TimeOut\n");
- + SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_DATA_TIMEOUT);
- + sd_err_code = ERR_DATA_TIMEOUT_ERROR;
- + return FALSE;
- + }
- + }
- + sd_err_code = ERR_WAIT_UNDERRUN_TIMEOUT;
- + P_DEBUG("%s() ERR_WAIT_UNDERRUN_TIMEOUT\n", __func__);
- + return FALSE;
- +}
- +
- +int sdc_check_rx_ready(void)
- +{
- + uint status;
- +#ifndef CONFIG_FTSDC010_USE_TIMER_DELAY
- + int count = 0;
- + while (count++ < SDC_GET_STATUS_RETRY_COUNT) {
- +#else
- + unsigned long timeout = jiffies + SDC_GET_STATUS_RETRY_TIMEOUT_COUNT;
- + while (time_before(jiffies, timeout)) {
- +#endif
- + status = SDC_R_REG(SDC_STATUS_REG);
- + if (status & SDC_STATUS_REG_FIFO_OVERRUN) {
- + /* clear FIFO overrun bit */
- + SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_FIFO_OVERRUN);
- + return TRUE;
- + } else if (status & SDC_STATUS_REG_DATA_TIMEOUT) {
- + /* clear data timeout bit */
- + printk("Wait Read FIFO TimeOut\n");
- + SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_DATA_TIMEOUT);
- + sd_err_code = ERR_DATA_TIMEOUT_ERROR;
- + return FALSE;
- + }
- + }
- + sd_err_code = ERR_WAIT_OVERRUN_TIMEOUT;
- + P_DEBUG("%s() ERR_WAIT_OVERRUN_TIMEOUT\n", __func__);
- + return FALSE;
- +}
- +
- +int sdc_check_data_crc(void)
- +{
- + uint status=0;
- +#ifndef CONFIG_FTSDC010_USE_TIMER_DELAY
- + int count = 0;
- + while (count++ < SDC_GET_STATUS_RETRY_COUNT) {
- +#else
- + unsigned long timeout = jiffies + SDC_GET_STATUS_RETRY_TIMEOUT_COUNT;
- + while (time_before(jiffies, timeout)) {
- +#endif
- + status = SDC_R_REG(SDC_STATUS_REG);
- + if (status & SDC_STATUS_REG_DATA_CRC_OK) {
- + P_DEBUGG("%s : receive data ok, status=0x%x\n", __func__, status);
- + /* clear data CRC OK bit */
- + SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_DATA_CRC_OK);
- + return TRUE;
- + } else if (status & SDC_STATUS_REG_DATA_CRC_FAIL) {
- + /* clear data CRC fail bit */
- + SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_DATA_CRC_FAIL);
- + sd_err_code = ERR_DATA_CRC_ERROR;
- + printk("%s() ERR_DATA_CRC_ERROR\n", __func__);
- + return FALSE;
- + } else if (status & SDC_STATUS_REG_DATA_TIMEOUT) {
- + /* clear data timeout bit */
- + SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_DATA_TIMEOUT);
- + sd_err_code = ERR_DATA_TIMEOUT_ERROR;
- + printk("%s() ERR_DATA_TIMEOUT_ERROR\n", __func__);
- + return FALSE;
- + }
- + }
- + P_DEBUG("%s() ERR_WAIT_DATA_CRC_TIMEOUT, status=0x%x\n", __func__, status);
- + sd_err_code = ERR_WAIT_DATA_CRC_TIMEOUT;
- + return FALSE;
- +}
- +
- +static inline int sdc_check_data_end(void)
- +{
- + uint status;
- +#ifndef CONFIG_FTSDC010_USE_TIMER_DELAY
- + int count = 0;
- + while (count++ < SDC_GET_STATUS_RETRY_COUNT) {
- +#else
- + unsigned long timeout = jiffies + SDC_GET_STATUS_RETRY_TIMEOUT_COUNT;
- + while (time_before(jiffies, timeout)) {
- +#endif
- + status = SDC_R_REG(SDC_STATUS_REG);
- + if (status & SDC_STATUS_REG_DATA_END) {
- + SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_DATA_END);
- + return TRUE;
- + } else if (status & SDC_STATUS_REG_DATA_TIMEOUT) {
- + /* clear data timeout bit */
- + SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_DATA_TIMEOUT);
- + sd_err_code = ERR_DATA_TIMEOUT_ERROR;
- + printk("%s() ERR_DATA_TIMEOUT_ERROR\n", __func__);
- + return FALSE;
- + }
- + }
- + sd_err_code = ERR_WAIT_TRANSFER_END_TIMEOUT;
- + P_DEBUG("%s() ERR_WAIT_TRANSFER_END_TIMEOUT\n", __func__);
- + return FALSE;
- +}
- +
- +int sdc_set_bus_width_cmd(sd_card_t *info, uint width)
- +{
- + uint status;
- +
- + /* send CMD55 to indicate to the card that the next command is an application specific command */
- + if (!sdc_send_cmd(SD_APP_CMD | SDC_CMD_REG_NEED_RSP, (((uint)info->RCA) << 16), &status))
- + return FALSE;
- + if (!sd_check_err(status))
- + return FALSE;
- + /* send ACMD6 to set bus width */
- + if (!sdc_send_cmd(SD_SET_BUS_WIDTH_CMD | SDC_CMD_REG_APP_CMD | SDC_CMD_REG_NEED_RSP, width, &status))
- + return FALSE;
- + if (!sd_check_err(status))
- + return FALSE;
- +
- + return TRUE;
- +}
- +
- +int sdc_set_bus_width(sd_card_t *info)
- +{
- + uint width;
- +
- + /* if it is not SD card, it does not support wide bus */
- + if (info->CardType != MEMORY_CARD_TYPE_SD)
- + return TRUE;
- + /* get SCR register */
- + if (!sd_get_scr(info, (uint *) &info->SCR))
- + return FALSE;
- + /* if host controller does not support wide bus, return */
- + if ((SDC_R_REG(SDC_BUS_WIDTH_REG) & SDC_WIDE_BUS_SUPPORT) != SDC_WIDE_BUS_SUPPORT)
- + return TRUE;
- + if (!sd_set_transfer_state(info))
- + return FALSE;
- + if (info->SCR.SD_BUS_WIDTH & SD_SCR_4_BIT_BIT)
- + width = SD_BUS_WIDTH_4_BIT;
- + else
- + width = SD_BUS_WIDTH_1_BIT;
- + if (!sdc_set_bus_width_cmd(info, width))
- + return FALSE;
- + if (width == SD_BUS_WIDTH_1_BIT)
- + SDC_W_REG(SDC_BUS_WIDTH_REG, SDC_BUS_WIDTH_REG_SINGLE_BUS);
- + else
- + SDC_W_REG(SDC_BUS_WIDTH_REG, SDC_BUS_WIDTH_REG_WIDE_BUS);
- +
- + return TRUE;
- +}
- +
- +static inline int sdc_pre_erase_cmd(uint nr_blocks)
- +{
- + uint status;
- + sd_card_t *info=&sd_card_info;
- + /* send CMD55 to indicate to the card that the next command is an application specific command */
- + if (!sdc_send_cmd(SD_APP_CMD | SDC_CMD_REG_NEED_RSP, (((uint)info->RCA) << 16), &status))
- + return FALSE;
- + if (!sd_check_err(status))
- + return FALSE;
- + /* send ACMD6 to set bus width */
- + if (!sdc_send_cmd(23 | SDC_CMD_REG_APP_CMD | SDC_CMD_REG_NEED_RSP, nr_blocks, &status))
- + return FALSE;
- + if (!sd_check_err(status))
- + return FALSE;
- +
- + return TRUE;
- +}
- +
- +
- +uint sdc_set_bus_clock(sd_card_t *info, uint clock)
- +{
- + uint div = 0, reg;
- +
- + while (clock < (info->SysFrequency / (2 * (div + 1))))
- + div++;
- + /* write clock divided */
- + reg = SDC_R_REG(SDC_CLOCK_CTRL_REG);
- + reg &= (~SDC_CLOCK_REG_CLK_DIV | 0x80); //ijsung: preserv SD or MMC
- + reg += div & SDC_CLOCK_REG_CLK_DIV;
- + SDC_W_REG(SDC_CLOCK_CTRL_REG, reg);
- + P_DEBUG("%s: SD clock=%d, info->SysFrequency=%d, div=%d\n",__func__,clock, info->SysFrequency, div);
- + return info->SysFrequency / (2 * (div + 1));
- +}
- +
- +static inline int sdc_set_block_size(uint size)
- +{
- + uint status;
- + static uint last_size=0;
- + if (size == last_size)
- + return TRUE;
- + else
- + last_size=size;
- +
- + if (!sdc_send_cmd(SD_SET_BLOCKLEN_CMD | SDC_CMD_REG_NEED_RSP, size, &status))
- + return FALSE;
- + if (!sd_check_err(status))
- + return FALSE;
- + return TRUE;
- +}
- +
- +void sdc_set_card_type(int type)
- +{
- + uint reg;
- +
- + reg = SDC_R_REG(SDC_CLOCK_CTRL_REG);
- + reg &= ~SDC_CLOCK_REG_CARD_TYPE;
- +
- + if (type == MEMORY_CARD_TYPE_SD) {
- + reg |= SDC_CARD_TYPE_SD;
- + }
- + else {
- + reg |= SDC_CARD_TYPE_MMC;
- + }
- +
- + SDC_W_REG(SDC_CLOCK_CTRL_REG, reg);
- +}
- +
- +int sdc_read_block(sd_card_t *info, uint size, uint *buf)
- +{
- + /*
- + * Please refer SanDisk SD Manual v1.9 Section 5.1.9.2 (page 5-76) to set the timeout setting
- + */
- + unsigned long timeout = jiffies + SDC_TIMEOUT_BASE*((size+511)>>9);
- + uint count, i;
- + dmad_chreq *ch_req = (dmad_chreq *)info->private;
- + dmad_drb *drb = 0;
- + u32 drb_size = 0;
- + dma_addr_t addr_iter;
- +
- + //if (info->DMAEnable) {
- + if ((info->DMAEnable) && ((size & 0xf) == 0)) {
- + P_DEBUG("%s:size=%d, buf=%p) - DMA Read\n", __func__, size,buf );
- + P_DEBUG("dma_buf = %d\n", dma_buf);
- +
- + init_completion(&sd_dma_cmpl);
- +
- + if (dma_buf)
- + consistent_sync(__va(dma_buf), size, DMA_FROM_DEVICE);
- + else
- + consistent_sync(buf, size, DMA_FROM_DEVICE);
- +
- + //prepare parameter for add dma entry
- + dmad_config_channel_dir(ch_req, DMAD_DIR_A0_TO_A1);
- +
- + drb_size = dmad_max_size_per_drb(ch_req);
- +
- + if (dma_buf)
- + addr_iter = dma_buf; // given dest phy addr
- + else
- + addr_iter = __pa(buf);
- +
- + while (size > 0) {
- +
- + if (unlikely(0 != dmad_alloc_drb(ch_req, &drb) || (drb == 0))) {
- + printk(KERN_ERR "%s() Failed to allocate dma request block!\n", __func__);
- + return FALSE;
- + }
- +
- + drb->addr0 = FTSDC_PA_BASE + SDC_DATA_WINDOW_REG;
- + drb->addr1 = addr_iter;
- +
- + if (size <= drb_size) {
- + drb->req_cycle = dmad_bytes_to_cycles(ch_req, size);
- + drb->sync = &sd_dma_cmpl;
- + size = 0;
- + } else {
- + drb->req_cycle = dmad_bytes_to_cycles(ch_req, drb_size);
- + drb->sync = 0;
- + size -= drb_size;
- + addr_iter += drb_size;
- + }
- + //printk(KERN_INFO "%s() size_remain 0x%08x.\n", __func__, size);
- +
- + if (unlikely(0 != dmad_submit_request(ch_req, drb, 1))) {
- + printk(KERN_ERR "%s() Failed to submit dma request block!\n", __func__);
- + return FALSE;
- + }
- + }
- +
- + if (wait_for_completion_timeout(&sd_dma_cmpl, timeout - jiffies) == 0)
- + printk("%s: read timeout\n", __func__);
- + } else {
- + while (size > 0) {
- + if (!sdc_check_rx_ready()) {
- + printk("error...........\n");
- + return FALSE;
- + }
- + /* read data from FIFO */
- + if (size >= (SDC_READ_FIFO_LEN << 2))
- + count = SDC_READ_FIFO_LEN;
- + else
- + count = size >> 2;
- + /* read data from FIFO */
- + P_DEBUG("\n");
- + for (i = 1; i <= count; i++, buf++)
- + {
- + *buf = SDC_R_REG(SDC_DATA_WINDOW_REG);
- + P_DEBUG("%.8x ",*buf);
- + }
- + size -= (count << 2);
- + }
- + }
- + return sdc_check_data_crc();
- +}
- +
- +int sdc_write_block(sd_card_t *info, uint size, uint *buf)
- +{
- + unsigned long timeout = jiffies + SDC_TIMEOUT_BASE*3*((size+511)>>9);
- + uint count, i;
- + dmad_chreq *ch_req = (dmad_chreq *)info->private;
- + dmad_drb *drb = 0;
- + u32 drb_size = 0;
- + dma_addr_t addr_iter;
- +
- + //if (info->DMAEnable) {
- + if ((info->DMAEnable) && ((size & 0xf) == 0)) {
- + P_DEBUG("%s:size=%d, buf=%p) - DMA Write\n", __func__, size,buf );
- +
- + init_completion(&sd_dma_cmpl);
- +
- + if (dma_buf)
- + consistent_sync(__va(dma_buf), size, DMA_TO_DEVICE);
- + else
- + consistent_sync(buf, size, DMA_TO_DEVICE);
- +
- + //prepare parameter for add dma entry
- + dmad_config_channel_dir(ch_req, DMAD_DIR_A1_TO_A0);
- +
- + drb_size = dmad_max_size_per_drb(ch_req);
- +
- + if (dma_buf)
- + addr_iter = dma_buf; // given dest phy addr
- + else
- + addr_iter = __pa(buf);
- +
- + while (size > 0) {
- +
- + if (unlikely(0 != dmad_alloc_drb(ch_req, &drb) || (drb == 0))) {
- + printk(KERN_ERR "%s() Failed to allocate dma request block!\n", __func__);
- + return FALSE;
- + }
- +
- + drb->addr0 = FTSDC_PA_BASE + SDC_DATA_WINDOW_REG;
- + drb->addr1 = addr_iter;
- +
- + if (size <= drb_size) {
- + drb->req_cycle = dmad_bytes_to_cycles(ch_req, size);
- + drb->sync = &sd_dma_cmpl;
- + size = 0;
- + } else {
- + drb->req_cycle = dmad_bytes_to_cycles(ch_req, drb_size);
- + drb->sync = 0;
- + size -= drb_size;
- + addr_iter += drb_size;
- + }
- + //printk(KERN_INFO "%s() size_remain 0x%08x.\n", __func__, size);
- +
- + if (unlikely(0 != dmad_submit_request(ch_req, drb, 1))) {
- + printk(KERN_ERR "%s() Failed to submit dma request block!\n", __func__);
- + return FALSE;
- + }
- + }
- +
- + if (wait_for_completion_timeout(&sd_dma_cmpl, timeout - jiffies) == 0)
- + printk("write timeout\n");
- + } else {
- + while (size > 0) {
- + if (!sdc_check_tx_ready())
- + return FALSE;
- + /* write data from FIFO */
- + if (size >= (SDC_WRITE_FIFO_LEN << 2))
- + count = SDC_WRITE_FIFO_LEN;
- + else
- + count = (size >> 2) ;
- + /* write data from FIFO */
- + for (i = 0; i < count; i++, buf++)
- + SDC_W_REG(SDC_DATA_WINDOW_REG, *buf);
- + size -= (count << 2);
- + }
- + }
- + return sdc_check_data_crc();
- +}
- +
- +void sdc_config_transfer(sd_card_t *SDCard, uint len, uint size, uint rw, uint timeout)
- +{
- + u32 con;
- + /* write timeout */
- + SDC_W_REG(SDC_DATA_TIMER_REG, timeout * 2);
- + /* set data length */
- + SDC_W_REG(SDC_DATA_LEN_REG, len);
- +
- + /* set data block */
- + if (SDCard->DMAEnable) {
- + con = sd_block_size_convert(size) | SDC_DATA_CTRL_REG_DMA_EN | rw | SDC_DATA_CTRL_REG_DATA_EN;
- + con |= SDC_DMA_TYPE_4;
- + P_DEBUG("%s() transfer DMA mode\n", __func__);
- + SDC_W_REG(SDC_DATA_CTRL_REG, con);
- + } else {
- + P_DEBUG("%s() transfer nonDMA mode\n", __func__);
- + SDC_W_REG(SDC_DATA_CTRL_REG, sd_block_size_convert(size) | rw | SDC_DATA_CTRL_REG_DATA_EN);
- + }
- +}
- +
- +/* Note: This funciton may be called by interrupt handler */
- +void sdc_reset(void)
- +{
- + uint ret;
- + unsigned long delay = jiffies + (HZ/10)*3; //Delay 300ms
- +
- + /* reset host interface */
- + SDC_W_REG(SDC_CMD_REG, SDC_CMD_REG_SDC_RST);
- +
- + /* loop, until the reset bit is clear */
- + do {
- + ret = SDC_R_REG(SDC_CMD_REG);
- + } while ((ret & SDC_CMD_REG_SDC_RST) != 0);
- + #if 0
- + udelay(1000);
- + #else
- + while(time_before(jiffies, delay));
- + #endif
- +}
- +
- +/*
- + * SD card operation
- + */
- +void sd_endian_change(uint *dt, int len)
- +{
- + uint ul;
- +
- + for(; len > 0; len--, dt++) {
- + ul = *dt;
- + ((unchar *)dt)[0] = ((unchar *)&ul)[3];
- + ((unchar *)dt)[1] = ((unchar *)&ul)[2];
- + ((unchar *)dt)[2] = ((unchar *)&ul)[1];
- + ((unchar *)dt)[3] = ((unchar *)&ul)[0];
- + }
- +}
- +
- +int sd_get_ocr(sd_card_t *info, uint hocr, uint *cocr)
- +{
- + uint status;
- + int count = 0;
- +
- + do {
- + if (info->CardType == MEMORY_CARD_TYPE_SD) {
- + /* send CMD55 to indicate to the card that the next command is an application specific command */
- + if (!sdc_send_cmd(SD_APP_CMD | SDC_CMD_REG_NEED_RSP, ((uint) info->RCA) << 16, &status))
- + return FALSE;
- + if (!sd_check_err(status))
- + return FALSE;
- + /* send ACMD41 to get OCR register */
- + if (!sdc_send_cmd(SD_APP_OP_COND | SDC_CMD_REG_APP_CMD | SDC_CMD_REG_NEED_RSP, (uint) hocr, (uint *) cocr))
- + return FALSE;
- + } else {
- + /* send CMD1 to get OCR register */
- + if (!sdc_send_cmd(SD_MMC_OP_COND | SDC_CMD_REG_NEED_RSP, (uint) hocr, (uint *) cocr))
- + return FALSE;
- + }
- + if (count++ > SD_CARD_GET_OCR_RETRY_COUNT) {
- + sd_err_code = ERR_SD_CARD_IS_BUSY;
- + printk("%s : ERR_SD_CARD_IS_BUSY\n", __func__);
- + return FALSE;
- + }
- + udelay(1000); /* According to spec, at most 1 msec or 74 clock cycles */
- + } while ((*cocr & SD_OCR_BUSY_BIT) != SD_OCR_BUSY_BIT);
- +
- + return TRUE;
- +}
- +
- +int sd_get_scr(sd_card_t *info, uint *scr)
- +{
- + uint status;
- +
- + if (!sd_set_transfer_state(info))
- + return FALSE;
- + if (!sdc_set_block_size(8))
- + return FALSE;
- + sdc_config_transfer(info, 8, 8, SDC_DATA_CTRL_REG_DATA_READ, 0xFFFFFFFF);
- + /* send CMD55 to indicate to the card that the next command is an application specific command */
- + if (!sdc_send_cmd(SD_APP_CMD | SDC_CMD_REG_NEED_RSP, ((uint) info->RCA) << 16, &status))
- + return FALSE;
- + if (!sd_check_err(status))
- + return FALSE;
- + /* send ACMD51 to get SCR */
- + if (!sdc_send_cmd(SD_SEND_SCR_CMD | SDC_CMD_REG_APP_CMD | SDC_CMD_REG_NEED_RSP, 0, &status))
- + return FALSE;
- + if (!sd_check_err(status))
- + return FALSE;
- + if (!sdc_read_block(info, 8, (uint *) scr))
- + return FALSE;
- + if (!sdc_check_data_end())
- + return FALSE;
- + sd_endian_change(scr, 2);
- +
- + return TRUE;
- +}
- +
- +int sd_check_err(uint status)
- +{
- + if (status & SD_STATUS_ERROR_BITS) {
- + sd_err_code = ERR_SD_CARD_STATUS_ERROR;
- + printk("%s() ERR_SD_CARD_STATUS_ERROR %X\n", __func__, status);
- + return FALSE;
- + }
- + sd_err_code = ERR_NO_ERROR;
- + return TRUE;
- +}
- +
- +int sd_get_card_state(sd_card_t *info, uint *ret)
- +{
- + uint status;
- +
- + /* send CMD13 to get card status */
- + if (!sdc_send_cmd(SD_SEND_STATUS_CMD | SDC_CMD_REG_NEED_RSP, ((uint) info->RCA) << 16, &status))
- + return FALSE;
- + if (!sd_check_err(status))
- + return FALSE;
- + *ret = (status & SD_STATUS_CURRENT_STATE) >> SD_STATUS_CURRENT_STATE_LOC;
- + return TRUE;
- +}
- +
- +int sd_operation_complete(sd_card_t *info, uint finish)
- +{
- + uint state;
- + int count = 0;
- + while (count++ < SD_CARD_WAIT_OPERATION_COMPLETE_RETRY_COUNT) {
- + if (!sd_get_card_state(info, &state))
- + return FALSE;
- + if (state == finish)
- + return TRUE;
- + }
- + P_DEBUG("%s() error\n", __func__);
- + return FALSE;
- +}
- +
- +int sd_stop_transmission(void)
- +{
- + uint status;
- +
- + /* send CMD12 to stop transmission */
- + if (!sdc_send_cmd(SD_STOP_TRANSMISSION_CMD | SDC_CMD_REG_NEED_RSP, 0, &status))
- + return FALSE;
- +
- + if (!sd_check_err(status))
- + return FALSE;
- +
- + return TRUE;
- +}
- +
- +int sd_set_card_standby(sd_card_t *info)
- +{
- + uint state;
- + int count = 0;
- + while (count++ < SD_CARD_STATE_CHANGE_RETRY_COUNT) {
- + if (!sd_get_card_state(info, &state))
- + return FALSE;
- +
- + switch (state) {
- + case SD_IDLE_STATE:
- + case SD_READY_STATE:
- + case SD_IDENT_STATE:
- + printk("%s() error\n", __func__);
- + return FALSE;
- + case SD_DIS_STATE:
- + return sd_operation_complete(info, SD_STBY_STATE);
- + case SD_TRAN_STATE:
- + if (!sdc_send_cmd(SD_SELECT_CARD_CMD, 0, NULL))
- + return FALSE;
- + break;
- + case SD_DATA_STATE:
- + if (sd_operation_complete(info, SD_TRAN_STATE))
- + return TRUE;
- + if (sd_err_code != ERR_NO_ERROR)
- + return FALSE;
- + if (!sd_stop_transmission())
- + return FALSE;
- + break;
- + case SD_RCV_STATE:
- + if (sd_operation_complete(info, SD_TRAN_STATE))
- + return TRUE;
- + if (sd_err_code != ERR_NO_ERROR)
- + return FALSE;
- + if (!sd_stop_transmission())
- + return FALSE;
- + break;
- + case SD_PRG_STATE:
- + if (!sd_operation_complete(info, SD_TRAN_STATE))
- + return FALSE;
- + break;
- + case SD_STBY_STATE:
- + return TRUE;
- + }
- + }
- + P_DEBUG("%s() error\n", __func__);
- + return FALSE;
- +}
- +
- +uint two_power(uint n)
- +{
- + uint pow = 1;
- +
- + for (; n > 0; n--)
- + pow <<= 1;
- + return pow;
- +}
- +
- +int sd_csd_parse(sd_csd_t *csd, uint *csd_word)
- +{
- + sd_csd_bit_t *csd_bit;
- + uint mult, blocks, len;
- +
- + if ((csd_word[0] & 0x00000001) != 1) {
- + sd_err_code = ERR_CSD_REGISTER_ERROR;
- + printk("%s() ERR_CSD_REGISTER_ERROR\n", __func__);
- + return FALSE;
- + }
- +
- + csd_bit = (sd_csd_bit_t *) csd_word;
- + csd->CSDStructure = csd_bit->CSD_STRUCTURE;
- + csd->MMCSpecVersion = csd_bit->MMC_SPEC_VERS;
- + csd->TAAC_u = TAAC_TimeValueTable_u[csd_bit->TAAC_TimeValue] * TAAC_TimeUnitTable[csd_bit->TAAC_TimeUnit] / 10;
- + csd->NSAC_u = csd_bit->NSAC * 100;
- + csd->TransferSpeed = TRANS_SPEED_RateUintTable[csd_bit->TRAN_SPEED_RateUnit] * TRANS_SPEED_TimeValueTable_u[csd_bit->TRAN_SPEED_TimeValue] / 10;
- + csd->CardCmdClass = csd_bit->CCC;
- + csd->ReadBlockLength = two_power(csd_bit->READ_BL_LEN);
- + csd->ReadBlockPartial = csd_bit->READ_BL_PARTIAL;
- + csd->WriteBlockMisalign = csd_bit->WRITE_BLK_MISALIGN;
- + csd->ReadBlockMisalign = csd_bit->READ_BLK_MISALIGN;
- + csd->DSRImplemant = csd_bit->DSR_IMP;
- + mult = 1 << (csd_bit->C_SIZE_MULT + 2);
- + blocks = ((csd_bit->C_SIZE_1 | (csd_bit->C_SIZE_2 << 2)) + 1) * mult;
- + len = 1 << (csd_bit->READ_BL_LEN);
- + csd->BlockNumber = blocks;
- + csd->MemorySize = blocks * len;
- + csd->VDDReadMin_u = VDD_CURR_MIN_Table_u[csd_bit->VDD_R_CURR_MIN];
- + csd->VDDReadMax_u = VDD_CURR_MAX_Table_u[csd_bit->VDD_R_CURR_MAX];
- + csd->VDDWriteMin_u = VDD_CURR_MIN_Table_u[csd_bit->VDD_W_CURR_MIN];
- + csd->VDDWriteMax_u = VDD_CURR_MAX_Table_u[csd_bit->VDD_W_CURR_MAX];
- + csd->EraseBlkEnable = csd_bit->ERASE_BLK_ENABLE;
- + csd->EraseSectorSize = csd_bit->ERASE_SECTOR_SIZE + 1;
- + csd->WriteProtectGroupSize = csd_bit->WP_GRP_SIZE + 1;
- + csd->WriteProtectGroupEnable = csd_bit->WP_GRP_ENABLE;
- + csd->WriteSpeedFactor = two_power(csd_bit->R2W_FACTOR);
- + csd->WriteBlockLength = two_power(csd_bit->WRITE_BL_LEN);
- + csd->WriteBlockPartial = csd_bit->WRITE_BL_PARTIAL;
- + csd->CopyFlag = csd_bit->COPY;
- + csd->PermanentWriteProtect = csd_bit->PERM_WRITE_PROTECT;
- + csd->TemporaryWriteProtect = csd_bit->TMP_WRITE_PROTECT;
- +
- + if (csd_bit->FILE_FORMAT_GRP == 0)
- + csd->FileFormat = csd_bit->FILE_FORMAT;
- + else
- + csd->FileFormat = FILE_FORMAT_RESERVED;
- +
- + return TRUE;
- +}
- +
- +int sd_cid_parse(sd_cid_t *cid, uint *cid_word)
- +{
- + unchar *ptr;
- + int i;
- +
- + if ((cid_word[0] & 0x00000001) != 1)
- + {
- + sd_err_code = ERR_CID_REGISTER_ERROR;
- + printk("%s() ERR_CID_REGISTER_ERROR\n", __func__);
- + return FALSE;
- + }
- +
- + cid->ManufacturerID = (cid_word[3] & 0xFF000000) >> 24;
- + cid->ApplicationID = (cid_word[3] & 0x00FFFF00) >> 8;
- +
- + ptr = (unchar *) cid_word;
- + ptr += 15 - 3;
- + for (i = 0; i < 6; i++, ptr--)
- + cid->ProductName[i] = *ptr;
- + cid->ProductName[6] = '\0' ;
- +
- + cid->ProductRevisionLow = (cid_word[1] & 0x00F00000) >> 20;
- + cid->ProductRevisionHigh = (cid_word[1] & 0x000F0000) >> 16;
- + cid->ProductSerialNumber = ((cid_word[1] & 0x0000FFFF) << 16) + ((cid_word[0] & 0xFFFF0000) >> 16);
- + cid->ManufactureMonth = ((cid_word[0] & 0x00000F00) >> 8);
- + cid->ManufactureYear = ((cid_word[0] & 0x0000F000) >> 12) + SD_DEFAULT_YEAR_CODE;
- +
- + return TRUE;
- +}
- +
- +uint sd_read_timeout_cycle(uint clock, sd_csd_t *csd)
- +{
- +#if 1 //ivan for 100ms maximux from document "ProdManualIndGradeSDv1.0[1].pdf" chapter A-2
- + return clock/10; // /10;
- +#else
- + uint ret, total, per;
- +
- + per = 1000000000 / clock;
- + total = (csd->TAAC_u + (csd->NSAC_u * 100 * per)) * 100;
- +
- + if (total > (100 * 1000 * 1000))
- + total = 100 * 1000 * 1000;
- + ret = total / per;
- +
- + return ret;
- +#endif
- +}
- +
- +uint sd_block_size_convert(uint size)
- +{
- + uint ret = 0;
- +
- + while (size >= 2) {
- + size >>= 1;
- + ret++;
- + }
- + return ret;
- +}
- +
- +int sd_select_card(sd_card_t *info)
- +{
- + uint status;
- +
- + /* send CMD7 with valid RCA to select */
- + if (!sdc_send_cmd(SD_SELECT_CARD_CMD | SDC_CMD_REG_NEED_RSP, ((uint)info->RCA) << 16, &status))
- + return FALSE;
- + if (!sd_check_err(status))
- + return FALSE;
- + return TRUE;
- +}
- +
- +int sd_set_transfer_state(sd_card_t *info)
- +{
- + uint state;
- + int count = 0;
- + while (count++ < SD_CARD_STATE_CHANGE_RETRY_COUNT) {
- + if (!sd_get_card_state(info, &state))
- + return FALSE;
- +
- + switch (state) {
- + case SD_IDLE_STATE:
- + case SD_READY_STATE:
- + case SD_IDENT_STATE:
- + printk("%s() error\n", __func__);
- + return FALSE;
- + case SD_DIS_STATE:
- + if (!sd_operation_complete(info, SD_STBY_STATE))
- + return FALSE;
- + break;
- + case SD_TRAN_STATE:
- + return TRUE;
- + case SD_DATA_STATE:
- + if (sd_operation_complete(info, SD_TRAN_STATE))
- + return TRUE;
- + if (sd_err_code != ERR_NO_ERROR)
- + return FALSE;
- + if (!sd_stop_transmission())
- + return FALSE;
- + break;
- + case SD_RCV_STATE:
- + if (sd_operation_complete(info, SD_TRAN_STATE))
- + return TRUE;
- + if (sd_err_code != ERR_NO_ERROR)
- + return FALSE;
- + if (!sd_stop_transmission())
- + return FALSE;
- + break;
- + case SD_PRG_STATE:
- + if (!sd_operation_complete(info, SD_TRAN_STATE))
- + return FALSE;
- + break;
- + case SD_STBY_STATE:
- + if (!sd_select_card(info))
- + return FALSE;
- + }
- + }
- + P_DEBUG("%s() error\n", __func__);
- + return FALSE;
- +}
- +
- +uint sd_write_timeout_cycle(uint clock, sd_csd_t *CSD)
- +{
- +#if 1 //ivan for 250ms maximux from document
- + return clock/4; //ijsung hack
- +#else
- + uint ret, total, pre;
- +
- + pre = 1000000000 / clock;
- + total = CSD->WriteSpeedFactor * 100 * (CSD->TAAC_u + (CSD->NSAC_u * 100 * pre));
- +
- + if (total > (100 * 1000 * 1000))
- + total = 100 * 1000 * 1000;
- + ret = total / pre;
- +
- + return ret;
- +#endif
- +}
- +
- +int sd_card_identify(sd_card_t *info)
- +{
- + uint rca, status, cid[4];
- +
- + /* reset all cards */
- + if (!sdc_send_cmd(SD_GO_IDLE_STATE_CMD, 0, NULL))
- + return FALSE;
- + udelay(1000);
- + /* Do operating voltage range validation */
- + /* get OCR register */
- + if (!sd_get_ocr(info, SDC_OCR, (uint *) &info->OCR))
- + return FALSE;
- + /* ckeck the operation conditions */
- + if ((info->OCR & SDC_OCR) == 0) {
- + sd_err_code = ERR_OUT_OF_VOLF_RANGE;
- + return FALSE;
- + }
- +
- + /* send CMD2 to get CID register */
- + if (!sdc_send_cmd(SD_ALL_SEND_CID_CMD | SDC_CMD_REG_NEED_RSP | SDC_CMD_REG_LONG_RSP, 0, cid))
- + return FALSE;
- + if (info->CardType == MEMORY_CARD_TYPE_SD) {
- + /* send CMD3 to get RCA register */
- + if (!sdc_send_cmd(SD_SEND_RELATIVE_ADDR_CMD | SDC_CMD_REG_NEED_RSP, 0, &rca))
- + return FALSE;
- + info->RCA = (ushort) (rca >> 16);
- + } else {
- + /* so far, we only support one interface, so we can give RCA any value */
- + info->RCA = 0x1;
- + /* send CMD3 to set RCA register */
- + if (!sdc_send_cmd(SD_SEND_RELATIVE_ADDR_CMD | SDC_CMD_REG_NEED_RSP, (info->RCA << 16), &status))
- + return FALSE;
- + if (!sd_check_err(status))
- + return FALSE;
- + }
- +
- + return TRUE;
- +}
- +
- +int sd_card_init(sd_card_t *info)
- +{
- + uint clock;
- +
- + P_DEBUG("--> %s\n", __func__);
- + if ((SDC_R_REG(SDC_STATUS_REG) & SDC_STATUS_REG_CARD_INSERT) != SDC_CARD_INSERT)
- + return FALSE;
- + sd_err_code = ERR_NO_ERROR;
- + /* At first, set card type to SD */
- + info->CardType = MEMORY_CARD_TYPE_SD;
- + /* set memory card type */
- + sdc_set_card_type(info->CardType);
- + /* start card idenfication process */
- + if (!sd_card_identify(info)) {
- + printk("this is not SD card\n");
- + sd_err_code = ERR_NO_ERROR;
- + info->CardType = MEMORY_CARD_TYPE_MMC;
- + /* set memory card type */
- + sdc_set_card_type(info->CardType);
- + if (!sd_card_identify(info))
- + return FALSE;
- + }
- +
- + /* get CSD */
- + if (!sd_set_card_standby(info))
- + return FALSE;
- + /* send CMD9 to get CSD register */
- + if (!sdc_send_cmd(SD_SEND_CSD_CMD | SDC_CMD_REG_NEED_RSP | SDC_CMD_REG_LONG_RSP, ((uint) info->RCA) << 16, info->CSDWord))
- + return FALSE;
- + sd_csd_parse(&info->CSD, info->CSDWord);
- +
- + if (info->CSD.ReadBlockLength != SD_SECTOR_SIZE) {
- + printk("Sector size is mis-matched (SD CSD report=0x%X,SD_SECTOR_SIZE=0x%X)\n", info->CSD.ReadBlockLength, SD_SECTOR_SIZE);
- + info->CSD.ReadBlockLength = SD_SECTOR_SIZE;
- +// return FALSE;
- + }
- +
- + /* get CID */
- + /* send CMD10 to get CID register */
- + if (!sdc_send_cmd(SD_SEND_CID_CMD | SDC_CMD_REG_NEED_RSP | SDC_CMD_REG_LONG_RSP, ((uint) info->RCA) << 16, info->CIDWord))
- + return FALSE;
- + sd_cid_parse(&info->CID, info->CIDWord);
- +
- + /* Set card bus clock. sdc_set_bus_clock() will give the real card bus clock has been set. */
- + clock = sdc_set_bus_clock(info, info->CSD.TransferSpeed);
- + info->ReadAccessTimoutCycle = sd_read_timeout_cycle(clock, &(info->CSD));
- + info->WriteAccessTimoutCycle = sd_write_timeout_cycle(clock, &(info->CSD));
- + /* set bus width */
- + if (!sdc_set_bus_width(info))
- + return FALSE;
- +
- + /* check write protect */
- + info->WriteProtect = ((SDC_R_REG(SDC_STATUS_REG) & SDC_STATUS_REG_CARD_LOCK) == SDC_STATUS_REG_CARD_LOCK) ? TRUE : FALSE;
- + if(info->WriteProtect == TRUE)
- + printk("SD/MMC Card is Write Protected\n");
- + info->ActiveState = TRUE;
- + P_DEBUG("<-- %s\n", __func__);
- +
- + return TRUE;
- +}
- +
- +int sd_card_insert(sd_card_t *info)
- +{
- + P_DEBUG("--> %s\n", __func__);
- + /* reset host interface controller */
- + sdc_reset();
- + /* turn on clock using default clock*/
- + SDC_W_REG(SDC_CLOCK_CTRL_REG, SDC_R_REG(SDC_CLOCK_CTRL_REG)&0xff);
- +
- + if (!sd_card_init(info)) {
- + printk("root initialize failed\n");
- + return FALSE;
- + }
- + /* set interrupt mask register */
- + SDC_W_REG(SDC_INT_MASK_REG, SDC_STATUS_REG_CARD_CHANGE | SDC_STATUS_REG_DATA_TIMEOUT);
- + P_DEBUG("<-- %s\n", __func__);
- +
- + return TRUE;
- +}
- +
- +int sd_card_remove(sd_card_t *info)
- +{
- + sd_err_code = ERR_NO_ERROR;
- +
- + info->ActiveState = FALSE;
- + info->WriteProtect = FALSE;
- + info->RCA = 0;
- + /* reset host interface controller */
- + sdc_reset();
- + /* set interrupt mask register */
- + SDC_W_REG(SDC_INT_MASK_REG, SDC_STATUS_REG_CARD_CHANGE | SDC_STATUS_REG_DATA_TIMEOUT);
- + sd_err_code = ERR_CARD_NOT_EXIST;
- + /* turn off clock */
- + SDC_W_REG(SDC_CLOCK_CTRL_REG, SDC_R_REG(SDC_CLOCK_CTRL_REG) | 0x100);
- + return TRUE;
- +}
- +
- +irqreturn_t sd_hotswap_interrupt_handler(int irq, void *dev_id)
- +{
- + uint status;
- + struct sd_dev *dev = dev_id;
- +
- + P_DEBUG("--> %s, irq=%d\n", __func__, irq);
- + /* When the card is inserted or removed, we must delay a short time to make sure */
- + /* the SDC_STATUS_REG_CARD_INSERT bit of status register is stable */
- + udelay(1000);
- + status = SDC_R_REG(SDC_STATUS_REG);
- + if ((status & SDC_STATUS_REG_CARD_CHANGE) == SDC_STATUS_REG_CARD_CHANGE) {
- + SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_CARD_CHANGE | SDC_STATUS_REG_DATA_TIMEOUT);
- + if ((status & SDC_STATUS_REG_CARD_INSERT) == SDC_CARD_INSERT) {
- + dev->card_state = SD_CARD_INSERT;
- + printk("Card Insert\n");
- + sd_card_insert(&sd_card_info);
- + } else {
- + dev->card_state = SD_CARD_REMOVE;
- + printk("Card Remove\n");
- + sd_card_remove(&sd_card_info);
- + /* remove all current transfers as I/O error*/
- +#if 0 //ASYNC
- + spin_lock_irqsave(&io_request_lock, status);
- + INIT_REQUEST;
- + while(!QUEUE_EMPTY)
- + end_request(0);
- + bh_busy=0;
- + spin_unlock_irqrestore(&io_request_lock, status);
- +#endif
- + }
- + } else if ((status & SDC_STATUS_REG_DATA_TIMEOUT) == SDC_STATUS_REG_DATA_TIMEOUT) {
- + SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_CARD_CHANGE | SDC_STATUS_REG_DATA_TIMEOUT);
- +
- +#if 0 //ASYNC
- + printk("Data timeout. Retry.\n");
- + sd_clustered_bh(2);
- +#else
- + printk("Data timeout. Retry.\n");
- +#endif
- + }
- + P_DEBUGG("card state=%d\n", dev->card_state);
- + P_DEBUG("<-- %s\n", __func__);
- + return IRQ_HANDLED;
- +}
- +
- +/*------------------------------------
- + * Block-driver specific functions
- + */
- +/*
- + * Find the device for this request.
- + */
- +#if 0
- +static inline struct sd_dev *sd_locate_device(const struct request *req)
- +{
- + int devno;
- + struct sd_dev *dev;
- +
- + P_DEBUG("--> %s\n", __func__);
- +#if 0
- + /* Check if the minor number is in range */
- + devno = DEVICE_NR(req->rq_dev);
- + P_DEBUGG("minor=%d\n", devno);
- + if (devno >= SD_DEVS) {
- + static int count = 0;
- +
- + if (count++ < 5) /* print the message at most five times */
- + P_DEBUG("request for unknown device\n");
- + return NULL;
- + }
- +#endif
- + dev = sd_devices + devno;
- + P_DEBUGG("card_state=%d\n", dev->card_state);
- + P_DEBUG("<-- %s\n", __func__);
- + return dev;
- +}
- +
- +int sd_card_check_exist(sd_card_t *info)
- +{
- + /* if card is not exist */
- + if ((SDC_R_REG(SDC_STATUS_REG) & SDC_STATUS_REG_CARD_INSERT) != SDC_CARD_INSERT) {
- + sd_card_remove(info);
- + return FALSE;
- + }
- + /* if card is not active */
- + if (!info->ActiveState)
- + {
- + return sd_card_insert(info);
- + }
- + return TRUE;
- +}
- +#endif
- +
- +void sd_reset_host_controller(void)
- +{
- + uint clock, mask, width;
- +
- + /* read register */
- + clock = SDC_R_REG(SDC_CLOCK_CTRL_REG);
- + width = SDC_R_REG(SDC_BUS_WIDTH_REG);
- + mask = SDC_R_REG(SDC_INT_MASK_REG);
- + /* reset host interface */
- + sdc_reset();
- + /* restore register */
- + SDC_W_REG(SDC_CLOCK_CTRL_REG, clock);
- + SDC_W_REG(SDC_BUS_WIDTH_REG, width);
- + SDC_W_REG(SDC_INT_MASK_REG, mask);
- +}
- +
- +int sd_read_single_block(sd_card_t *info, uint addr, uint size, uint timeout, unchar *buf)
- +{
- + uint status;
- +
- + if (!sdc_set_block_size(size))
- + return FALSE;
- +
- + sdc_config_transfer(info, size, size, SDC_DATA_CTRL_REG_DATA_READ, timeout);
- +
- + if (!sdc_send_cmd(SD_READ_SINGLE_BLOCK_CMD | SDC_CMD_REG_NEED_RSP, addr, &status))
- + return FALSE;
- + if (!sd_check_err(status))
- + return FALSE;
- +
- +#ifdef DELAY_FOR_DMA_READ
- + if (first_run==0) {
- + int i=0;
- + for(i=0;i<10;i++)
- + udelay(1000);
- + first_run=1;
- + }
- +#endif
- + if (!sdc_read_block(info, size, (uint *) buf))
- + return FALSE;
- +
- + if (sd_err_code != ERR_NO_ERROR) {
- + printk("%s() error=0x%X\n", __func__, sd_err_code);
- + sd_reset_host_controller();
- + return FALSE;
- + } else {
- + if (!sdc_check_data_end()) {
- + sd_stop_transmission();
- + printk("%s()2 error=0x%X\n", __func__, sd_err_code);
- + return FALSE;
- + }
- + }
- +
- + return TRUE;
- +}
- +
- +int sd_write_single_block(sd_card_t *info, uint addr, uint size, uint timeout, unchar *buf)
- +{
- + uint status;
- +
- + if (!sdc_set_block_size(size))
- + return FALSE;
- +
- + sdc_config_transfer(info, size, size, SDC_DATA_CTRL_REG_DATA_WRITE, timeout);
- +
- + if (!sdc_send_cmd(SD_WRITE_SINGLE_BLOCK_CMD | SDC_CMD_REG_NEED_RSP, addr, &status))
- + return FALSE;
- + if (!sd_check_err(status))
- + return FALSE;
- +
- + if (!sdc_write_block(info, size, (uint *) buf))
- + return FALSE;
- + if (sd_err_code != ERR_NO_ERROR) {
- + printk("%s() error=0x%X\n", __func__, sd_err_code);
- + sd_reset_host_controller();
- + return FALSE;
- + } else {
- + if (!sdc_check_data_end()) {
- + sd_stop_transmission();
- + printk("%s()2 error=0x%X\n", __func__, sd_err_code);
- + return FALSE;
- + }
- + }
- +
- + return TRUE;
- +}
- +
- +int sd_read_multiple_block(sd_card_t *info, uint addr, uint count, uint size, uint timeout, unchar *buf)
- +{
- + uint err, status;
- +
- + if (!sdc_set_block_size(size))
- + return FALSE;
- +
- + sdc_config_transfer(info, count * size, size, SDC_DATA_CTRL_REG_DATA_READ, timeout);
- +
- + if (!sdc_send_cmd(SD_READ_MULTIPLE_BLOCK_CMD | SDC_CMD_REG_NEED_RSP, addr, &status))
- + return FALSE;
- + if (!sd_check_err(status))
- + return FALSE;
- +
- +#ifdef DELAY_FOR_DMA_READ
- + if (first_run==0) {
- + int i=0;
- + for(i=0;i<10;i++)
- + udelay(1000);
- + first_run=1;
- + }
- +#endif
- +#if 0 //ijsung: Sometimes this will cause IRQ lost, and is slower. Use method below
- + while (count > 0) {
- + if (!sdc_read_block(info, size, (uint *) buf))
- + return FALSE;
- + count--;
- + buf += size;
- + }
- +#else //ijsung: DMA at once.
- + if (!sdc_read_block(info, size*count, (uint *) buf))
- + return FALSE;
- +#endif
- + if (sd_err_code != ERR_NO_ERROR) {
- + err = sd_err_code;
- + sd_stop_transmission();
- + sd_reset_host_controller();
- + sd_err_code |= err;
- + printk("%s() error=0x%X\n", __func__, sd_err_code);
- + return FALSE;
- + } else {
- + if (!sdc_check_data_end()) {
- + err = sd_err_code;
- + sd_stop_transmission();
- + sd_err_code |= err;
- + printk("%s()2 error=0x%X\n", __func__, sd_err_code);
- + return FALSE;
- + }
- + if (!sd_stop_transmission())
- + return FALSE;
- + }
- +
- + return TRUE;
- +}
- +
- +int sd_write_multiple_block(sd_card_t *info, uint addr, uint count, uint size, uint timeout, unchar *buf)
- +{
- + uint ErrorCode, status;
- +
- + if(!sdc_set_block_size(size))
- + return FALSE;
- +
- + sdc_config_transfer(info, count * size, size, SDC_DATA_CTRL_REG_DATA_WRITE, timeout);
- + sdc_pre_erase_cmd(count); //ijsung: pre-erase
- + if (!sdc_send_cmd(SD_WRITE_MULTIPLE_BLOCK_CMD | SDC_CMD_REG_NEED_RSP, addr, &status))
- + return FALSE;
- + if (!sd_check_err(status))
- + return FALSE;
- +#if 0 //ijsung: Sometimes this will cause IRQ lost, and is slower. Use method below
- + while (count > 0) {
- + if (!sdc_write_block(info, size, (uint *) buf))
- + return FALSE;
- + count--;
- + buf += size;
- + }
- +#else //ijsung: DMA at once.
- + if (!sdc_write_block(info, size*count, (uint *) buf))
- + return FALSE;
- +#endif
- +
- + if (sd_err_code != ERR_NO_ERROR)
- + {
- + ErrorCode = sd_err_code;
- + sd_stop_transmission();
- + sd_reset_host_controller();
- + sd_err_code |= ErrorCode;
- + printk("%s() error=0x%X\n", __func__, sd_err_code);
- + return FALSE;
- + } else {
- + if (!sdc_check_data_end()) {
- + ErrorCode = sd_err_code;
- + sd_stop_transmission();
- + sd_err_code |= ErrorCode;
- + printk("%s()2 error=0x%X\n", __func__, sd_err_code);
- + return FALSE;
- + }
- + if (!sd_stop_transmission())
- + return FALSE;
- + }
- +
- + return TRUE;
- +}
- +
- +int sd_wait_transfer_state(sd_card_t *info)
- +{
- + uint state;
- + int count = 0;
- + while (count++ < SD_CARD_WAIT_TRANSFER_STATE_RETRY_COUNT) {
- + if (!sd_get_card_state(info, &state))
- + return FALSE;
- +
- + switch (state) {
- + case SD_IDLE_STATE:
- + case SD_READY_STATE:
- + case SD_IDENT_STATE:
- + case SD_DIS_STATE:
- + case SD_STBY_STATE:
- + printk("%s() error\n", __func__);
- + return FALSE;
- + case SD_TRAN_STATE:
- + return TRUE;
- + case SD_DATA_STATE:
- + case SD_RCV_STATE:
- + case SD_PRG_STATE:
- + break;
- + }
- + }
- + sd_err_code = ERR_SD_CARD_IS_BUSY;
- + P_DEBUG("%s() ERR_SD_CARD_IS_BUSY\n", __func__);
- + return FALSE;
- +}
- +
- +/***************************************************************************
- +SD Card Read/Write/Erase Function
- +***************************************************************************/
- +int sd_read_sector(sd_card_t *info, uint addr, uint count, unchar *buf)
- +{
- + int cnt;
- + uint start;
- + sync_mode=1;
- + P_DEBUG("%s : sector = %d,count = %d\n",__func__,addr,count);
- + if (count > MAX_READ_SECTOR_NR) {
- + P_DEBUG("Readable Block Number Per Commands is 0x%X\n",MAX_READ_SECTOR_NR);
- + return FALSE;
- + }
- +
- + sd_err_code = ERR_NO_ERROR;
- +
- + if (!info->ActiveState) {
- + P_DEBUG("%s : SD card not active!!\n", __func__);
- + return FALSE;
- + }
- +
- + if (!sd_set_transfer_state(info))
- + return FALSE;
- +
- + start = addr * info->CSD.ReadBlockLength;
- + cnt = (int) count;
- +
- + while (cnt > 0) {
- + if (cnt > 1) {
- + if (!sd_read_multiple_block(info, start, (cnt > MAX_MULTI_BLOCK_NUM) ? MAX_MULTI_BLOCK_NUM : cnt,
- + info->CSD.ReadBlockLength, info->ReadAccessTimoutCycle, buf))
- + return FALSE;
- + } else {
- + if (!sd_read_single_block(info, start, info->CSD.ReadBlockLength, info->ReadAccessTimoutCycle, buf))
- + return FALSE;
- + return TRUE;
- + }
- +
- + if (!sd_wait_transfer_state(info))
- + return FALSE;
- +
- + cnt -= MAX_MULTI_BLOCK_NUM;
- + start += MAX_MULTI_BLOCK_NUM * info->CSD.ReadBlockLength;
- + buf += MAX_MULTI_BLOCK_NUM * info->CSD.ReadBlockLength;
- + }
- +
- + return TRUE;
- +}
- +
- +int sd_write_sector(sd_card_t *info, uint addr, uint count, unchar *buf)
- +{
- + int cnt;
- + uint start;
- +
- + if (count > MAX_WRITE_SECTOR_NR) {
- + P_DEBUG("Writable Block Number Per Commands is 0x%X\n",MAX_WRITE_SECTOR_NR);
- + return FALSE;
- + }
- +
- + sd_err_code = ERR_NO_ERROR;
- +
- + if (!info->ActiveState) {
- + P_DEBUG("%s : SD card not active!!\n", __func__);
- + return FALSE;
- + }
- +
- + if (info->WriteProtect == TRUE) {
- + sd_err_code = ERR_SD_CARD_IS_LOCK;
- + printk("Write Protected!!\n");
- + return FALSE;
- + }
- + if (!sd_set_transfer_state(info))
- + return FALSE;
- +
- + start = addr * info->CSD.ReadBlockLength;
- + cnt = (int) count;
- +
- + while (cnt > 0) {
- + if (cnt > 1) {
- + if (!sd_write_multiple_block(info, start, (cnt > MAX_MULTI_BLOCK_NUM) ? MAX_MULTI_BLOCK_NUM : cnt,
- + info->CSD.ReadBlockLength, info->WriteAccessTimoutCycle, buf))
- + return FALSE;
- + } else {
- + if (!sd_write_single_block(info, start, info->CSD.ReadBlockLength, info->WriteAccessTimoutCycle, buf))
- + return FALSE;
- + return TRUE;
- + }
- +
- + if (!sd_wait_transfer_state(info))
- + return FALSE;
- +
- + cnt -= MAX_MULTI_BLOCK_NUM;
- + start += MAX_MULTI_BLOCK_NUM * info->CSD.ReadBlockLength;
- + buf += MAX_MULTI_BLOCK_NUM * info->CSD.ReadBlockLength;
- + }
- +
- + return TRUE;
- +}
- +/*----------------------------------------------
- + * Perform an actual transfer:
- + * Returns: # of sectors transferred. 0 = error
- + */
- +static int sd_transfer(struct sd_dev *device, const struct request *req)
- +{
- + int status = 0;
- + int count = 0;
- +
- + struct bio *bio = req->bio;
- + struct bio_vec *bvec;
- + struct req_iterator iter;
- +
- + spin_unlock_irq( &device->lock);
- +
- +#if 0
- + P_DEBUG("\nreq sector: %d, nr_sectors: %d, hard_cur_sectors: %d phys_seg: %d, buf: 0x%08lx\n",
- + (int)req->sector, (int)req->nr_sectors, (int)req->hard_cur_sectors,
- + (int)req->nr_phys_segments, (ulong)bio_data( bio));
- +#endif
- +
- + rq_for_each_segment( bvec, req, iter) {
- +
- + unsigned char *buf = page_address( bvec->bv_page) + bvec->bv_offset;
- + int sectors = bio_cur_bytes(bio) >> 9;
- +
- + P_DEBUG("bvec[%2d]: sector: %d, count: %d, curr: %d, buf: 0x%08lx, ",
- + iter.i, (int)bio->bi_sector, count, (int)sectors, (unsigned long)buf);
- +
- + sd_card_info.private = (void *)&device->ch_req;
- +
- + if( rq_data_dir(req) == 0) /* Read */
- + status = sd_read_sector( &sd_card_info, sector_offset + bio->bi_sector, sectors, buf);
- + else
- + status = sd_write_sector( &sd_card_info, sector_offset + bio->bi_sector, sectors, buf);
- +
- + P_DEBUG("status: %d\n", status);
- +
- + if (status <= 0) {
- + spin_lock_irq( &device->lock);
- + return count;
- + }
- +
- + count += sectors;
- + bio->bi_sector += sectors;
- + }
- +
- + if( ( req->__sector == 0) && !Do_onetime){
- +
- + unsigned char *buf = bio_data( bio);
- +
- + if( ( buf[ 0x1be] != 0x0) && ( buf[ 0x1be] != 0x80)) /* partition identify */
- + sector_offset = 0; //sector 0 is PBR
- + else
- + sector_offset = ( buf[ 0x1c6]) | ( buf[ 0x1c7] << 8) | ( buf[ 0x1c8] <<16) |( buf[ 0x1c9] << 24);
- +
- + P_DEBUG( "sector_offset = %d\n", sector_offset);
- + Do_onetime = 1;
- + }
- +
- + spin_lock_irq( &device->lock);
- +
- + if( status <= 0)
- + return 0;
- + else
- + return count;
- +}
- +
- +#ifdef SD_DEBUG
- +uint sd_dev_info(void)
- +{
- + sd_csd_t *CSD;
- + sd_cid_t *CID;
- +
- + P_DEBUG("============SDCard=====================================\n");
- +#if 0
- + if (!sd_card_check_exist(&sd_card_info))
- + {
- + P_DEBUG("SD Card does not exist!!!");
- + return FALSE;
- + }
- +#else
- + if (!sd_card_info.ActiveState) {
- + P_DEBUG("%s : SD card not active!!\n", __func__);
- + return FALSE;
- + }
- +#endif
- +
- + /* print OCR, RCA register */
- + P_DEBUG("OCR>> 0x%08X RCA>> 0x%04X\n", (uint) sd_card_info.OCR, sd_card_info.RCA);
- + /* print CID register */
- + P_DEBUG("CID>> 0x%08X 0x%08X 0x%08X 0x%08X\n", sd_card_info.CIDWord[0], sd_card_info.CIDWord[1], sd_card_info.CIDWord[2], sd_card_info.CIDWord[3]);
- + CID = &(sd_card_info.CID);
- + P_DEBUG(" MID:0x%02X OID:0x%04X PNM:%s PRV:%d.%d PSN:0x%08X\n", CID->ManufacturerID, CID->ApplicationID, CID->ProductName,
- + CID->ProductRevisionHigh, CID->ProductRevisionLow, CID->ProductSerialNumber);
- + P_DEBUG(" MDT:%d/%d\n", CID->ManufactureMonth, CID->ManufactureYear);
- + /* print CSD register */
- + P_DEBUG("CSD>> 0x%08X 0x%08X 0x%08X 0x%08X\n", sd_card_info.CSDWord[0], sd_card_info.CSDWord[1], sd_card_info.CSDWord[2], sd_card_info.CSDWord[3]);
- + CSD = &(sd_card_info.CSD);
- + P_DEBUG(" CSDStructure:%d Spec.Version:%d\n", CSD->CSDStructure, CSD->MMCSpecVersion);
- + P_DEBUG(" TAAC:%dns NSAC:%d clock cycles\n", CSD->TAAC_u, CSD->NSAC_u);
- + P_DEBUG(" TransferSpeed:%d bit/s CardCommandClass:0x%03X\n", CSD->TransferSpeed, CSD->CardCmdClass);
- + P_DEBUG(" ReadBlLen:%d ReadBlPartial:%X WriteBlkMisalign:%X ReadBlkMisalign:%X\n", CSD->ReadBlockLength, CSD->ReadBlockPartial, CSD->WriteBlockMisalign, CSD->ReadBlockMisalign);
- + P_DEBUG(" DSP:%X BlockNumber:%d MemorySize:%d \n", CSD->DSRImplemant, CSD->BlockNumber, CSD->MemorySize);
- + P_DEBUG(" VDD_R_MIN:%d/10mA VDD_R_MAX:%dmA\n", (uint) CSD->VDDReadMin_u, (uint) CSD->VDDReadMax_u);
- + P_DEBUG(" VDD_W_MIN:%d/10mA VDD_W_MAX:%dmA\n", (uint) CSD->VDDWriteMin_u, (uint) CSD->VDDWriteMax_u);
- + P_DEBUG(" EraseBlkEnable:%d EraseSectorSize:%d WpGrpSize:%d WpGrpEnable:%X\n", CSD->EraseBlkEnable, CSD->EraseSectorSize, CSD->WriteProtectGroupSize, CSD->WriteProtectGroupEnable);
- + P_DEBUG(" WriteSpeedFactor:%d WriteBlLen:%d WriteBlPartial:%X\n", CSD->WriteSpeedFactor, CSD->WriteBlockLength, CSD->WriteBlockPartial);
- + P_DEBUG(" Copy:%X PermWrProtect:%X TmpWrProtect:%X FileFormat:%X\n", CSD->CopyFlag, CSD->PermanentWriteProtect, CSD->TemporaryWriteProtect, CSD->FileFormat);
- + P_DEBUG(" ReadTimoutCycle:0x%08X WriteTimoutCycle:0x%08X\n", sd_card_info.ReadAccessTimoutCycle, sd_card_info.WriteAccessTimoutCycle);
- + /* print SCR register */
- + P_DEBUG("SCR>> 0x%08X 0x%08X \n", *(((uint *) &sd_card_info.SCR)), *(((uint *) &sd_card_info.SCR) + 1));
- + P_DEBUG(" SCR_STRUCTURE:%d, SD_SPEC:%d, Data_status_after_erase:%d\n", sd_card_info.SCR.SCR_STRUCTURE, sd_card_info.SCR.SD_SPEC, sd_card_info.SCR.DATA_STAT_AFTER_ERASE);
- + P_DEBUG(" sd_security:%d, SD_BUS_WIDTH:%X\n", sd_card_info.SCR.SD_SECURITY, sd_card_info.SCR.SD_BUS_WIDTH);
- +
- + return TRUE;
- +}
- +#endif
- +
- +static int sd_card_setup(struct sd_dev *dev)
- +{
- + uint sd_card_size;
- + int i;
- +
- + P_DEBUG("--> %s\n", __func__);
- + first_run = 0;
- + sd_err_code = ERR_NO_ERROR;
- +
- + sd_card_info.ActiveState = FALSE;
- + sd_card_info.WriteProtect = FALSE;
- + sd_card_info.IOAddr = FTSDC_VA_BASE;
- + sd_card_info.DMAEnable = FALSE;
- +
- + sd_card_info.SysFrequency = AHB_CLK_IN/2;
- + P_DEBUG("DMA Enable is %d, Sys frequency = %d\n", sd_card_info.DMAEnable, sd_card_info.SysFrequency);
- + sd_card_info.RCA = 0;
- + sd_card_info.Drive = 'S';
- +
- + if (!sd_card_insert(&sd_card_info))
- + return FALSE;
- +#ifdef SD_DEBUG
- + if (!sd_dev_info())
- + return FALSE;
- +#endif
- + sd_card_size = sd_card_info.CSD.MemorySize;
- + printk(KERN_NOTICE "FTSDC010: SD Card Capacity=%d MB\n", sd_card_size/1000000); /* Marketing MB is not 1048576 */
- +
- + for (i = 0; i < SD_DEVS; i++) {
- + sd_devices[i].size = sd_card_size / SD_SECTOR_SIZE; //unit is block, not bytes
- +
- +#if 0
- + sd_partitions[i << SD_SHIFT].nr_sects =sd_size * (SD_BLKSIZE / SD_SECTOR_SIZE);
- + P_DEBUG ("%s() %d-th device, size=%d blks(blks=%d),nr_sects=%ld\n", __func__, i, sd_size, SD_BLKSIZE, sd_partitions[i << SD_SHIFT].nr_sects);
- +#endif
- + //sd_devices[i].card_state = SD_CARD_WORK;
- + //sema_init(&(sd_devices[i].sema), 1); // add by Charles Tsai*/
- + }
- +
- + sd_card_info.DMAEnable = dev->dma_enable;
- +
- + P_DEBUG("<-- %s\n", __func__);
- + return TRUE;
- +}
- +
- +/*
- + * Driver stuff
- + */
- +/*------------------------------------
- + * The ioctl implementation
- + */
- +int sd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg)
- +{
- + int size;
- + struct hd_geometry geo;
- + struct sd_dev *device=bdev->bd_disk->private_data;
- + P_DEBUG ("ioctl 0x%x 0x%lx\n", cmd, arg);
- + switch (cmd) {
- + case BLKGETSIZE:
- + /* Return the device size, expressed in sectors */
- + /* FIXME: distinguish between kernel sector size and media sector size */
- + size = device->size;
- + __copy_to_user ((long *) arg, &size, sizeof (long));
- + return 0;
- +#if 0
- + case BLKFLSBUF: /* flush */
- + return blk_ioctl(inode->i_rdev, cmd, arg);
- + case BLKRAGET: /* return the readahead value */
- + return blk_ioctl(inode->i_rdev, cmd, arg);
- + case BLKRASET: /* set the readahead value */
- + if (!capable (CAP_SYS_RAWIO))
- + return -EACCES;
- + if (arg > 0xff)
- + return -EINVAL; /* limit it */
- + return 0;
- +// case BLKRRPART: /* re-read partition table */
- +// return sd_revalidate (inode->i_rdev);
- +#endif
- + case HDIO_GETGEO:
- + /*
- + * get geometry: we have to fake one... trim the size to a
- + * multiple of 64 (32k): tell we have 16 sectors, 4 heads,
- + * whatever cylinders. Tell also that data starts at sector. 4.
- + */
- + geo.cylinders = (device->size/4)/8; /* ?? only for test */
- + geo.heads = 4;
- + geo.sectors = 8;
- + geo.start = 0;
- + __copy_to_user ((void *) arg, &geo, sizeof (geo));
- + return 0;
- + default:
- + /*
- + * For ioctls we don't understand, let the block layer handle them.
- + */
- + return -ENOTTY;//blk_ioctl (inode->i_rdev, cmd, arg);
- + }
- +
- + return -ENOTTY; /* unknown command */
- +}
- +
- +static void sd_request(struct request_queue *q)
- +{
- + struct sd_dev *dev;
- + static int active;
- +#ifndef A320_SD_USE_ASYNC_DMA
- + int ret;
- + struct request *req;
- +#else
- + if(bh_busy)
- + return;
- +#endif
- + if(active)
- + return;
- + active = 1;
- + P_DEBUG("--> %s\n", __func__);
- +repeat:
- + /* Locate the device */
- + if((req=blk_fetch_request(q))==NULL) {
- + active = 0;
- + return;
- + }
- + dev = req->rq_disk->private_data;
- + if (!dev||dev->card_state == SD_CARD_REMOVE) {
- + if(!dev)
- + printk(KERN_NOTICE"SD: locating device error\n");
- + __blk_end_request_cur(req, -EIO);
- + goto repeat;
- + }
- +#ifndef A320_SD_USE_ASYNC_DMA
- + sync_mode=1;
- + //spin_unlock_irq(&io_request_lock);
- + ret = sd_transfer(dev, req);
- + __blk_end_request(req, 0, ret << 9);
- + //spin_lock_irq(&io_request_lock);
- + goto repeat;
- +
- +#else
- + sync_mode=0; //Use new async DMA machanism
- + //printk("%s: set up initial DMA, from sector %d to buffer 0x%X\n", __func__, CURRENT->sector+sector_offset, CURRENT->buffer);
- + //sd_init_async_dma();
- + sd_clustered_bh(1);
- + //bh_busy=1;
- +#endif
- + P_DEBUG("<-- %s\n", __func__);
- +}
- +
- +#if 0
- +/*-----------------------------------------
- + * Support for removable devices
- + */
- +int sd_check_change(kdev_t i_rdev)
- +{
- + int minor = DEVICE_NR(i_rdev);
- + struct sd_dev *dev = sd_devices + minor;
- +
- + P_DEBUG("--> %s\n", __func__);
- + P_DEBUG("minor=%d\n", minor);
- + if (minor >= SD_DEVS) /* paranoid */
- + return 0;
- + P_DEBUG("check change for dev %d\n", minor);
- + if (dev->usage) {
- + P_DEBUG("disk not change\n");
- + P_DEBUG("<-- %s\n", __func__);
- + return 0; /* still valid */
- + }
- + P_DEBUG("disk changed\n");
- + P_DEBUG("<-- %s\n", __func__);
- + return 1; /* expired */
- +}
- +#endif
- +
- +static int sd_dma_ch_alloc(struct sd_dev *dev)
- +{
- + dmad_chreq *ch_req = &dev->ch_req;
- +
- + memset(ch_req, 0, sizeof(dmad_chreq));
- +
- +#ifdef CONFIG_PLATFORM_APBDMA
- +
- + ch_req->apb_req.addr0_ctrl = APBBR_ADDRINC_FIXED; /* (in) APBBR_ADDRINC_xxx */
- +/* for amerald */
- + if((inl(PMU_BASE) & AMERALD_MASK) == AMERALD_PRODUCT_ID){
- + ch_req->apb_req.addr0_reqn = APBBR_REQN_SDC_AMERALD;
- + }else
- + ch_req->apb_req.addr0_reqn = APBBR_REQN_SDC; /* (in) APBBR_REQN_xxx (also used to help determine bus selection) */
- + ch_req->apb_req.addr1_ctrl = APBBR_ADDRINC_I4X; /* (in) APBBR_ADDRINC_xxx */
- + ch_req->apb_req.addr1_reqn = APBBR_REQN_NONE; /* (in) APBBR_REQN_xxx (also used to help determine bus selection) */
- + ch_req->apb_req.burst_mode = 1; /* (in) Burst mode (0: no burst 1-, 1: burst 4- data cycles per dma cycle) */
- + ch_req->apb_req.data_width = APBBR_DATAWIDTH_4; /* (in) APBBR_DATAWIDTH_4(word), APBBR_DATAWIDTH_2(half-word), APBBR_DATAWIDTH_1(byte) */
- + ch_req->apb_req.tx_dir = DMAD_DIR_A0_TO_A1; /* (in) DMAD_DIR_A0_TO_A1, DMAD_DIR_A1_TO_A0 */
- +
- + ch_req->controller = DMAD_DMAC_APB_CORE; /* (in) DMAD_DMAC_AHB_CORE, DMAD_DMAC_APB_CORE */
- + ch_req->flags = DMAD_FLAGS_SLEEP_BLOCK | DMAD_FLAGS_BIDIRECTION;
- +
- + if (dmad_channel_alloc(ch_req) != 0) {
- + memset(ch_req, 0, sizeof(dmad_chreq));
- + printk(KERN_INFO "%s: APB dma channel allocation failed\n", __func__);
- + goto _try_ahb;
- + }
- +
- + P_DEBUG("%s: APB dma channel allocated (ch: %d)\n", __func__, ch_req->channel);
- + //printk("%s: APB dma channel allocated (ch: %d)\n", __func__, ch_req->channel);
- +
- + return 0;
- +
- +_try_ahb:
- +
- +#endif /* CONFIG_PLATFORM_APBDMA */
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- +
- + ch_req->ahb_req.sync = 1; /* (in) non-zero if src and dst have different clock domain */
- + ch_req->ahb_req.priority = DMAC_CSR_CHPRI_1; /* (in) DMAC_CSR_CHPRI_0 (lowest) ~ DMAC_CSR_CHPRI_3 (highest) */
- + ch_req->ahb_req.hw_handshake = 1; /* (in) non-zero to enable hardware handshake mode */
- + ch_req->ahb_req.burst_size = DMAC_CSR_SIZE_4; /* (in) DMAC_CSR_SIZE_1 ~ DMAC_CSR_SIZE_256 */
- + ch_req->ahb_req.addr0_width = DMAC_CSR_WIDTH_32; /* (in) DMAC_CSR_WIDTH_8, DMAC_CSR_WIDTH_16, or DMAC_CSR_WIDTH_32 */
- + ch_req->ahb_req.addr0_ctrl = DMAC_CSR_AD_FIX; /* (in) DMAC_CSR_AD_INC, DMAC_CSR_AD_DEC, or DMAC_CSR_AD_FIX */
- + ch_req->ahb_req.addr0_reqn = DMAC_REQN_SDC; /* (in) DMAC_REQN_xxx (also used to help determine channel number) */
- + ch_req->ahb_req.addr1_width = DMAC_CSR_WIDTH_32; /* (in) DMAC_CSR_WIDTH_8, DMAC_CSR_WIDTH_16, or DMAC_CSR_WIDTH_32 */
- + ch_req->ahb_req.addr1_ctrl = DMAC_CSR_AD_INC; /* (in) DMAC_CSR_AD_INC, DMAC_CSR_AD_DEC, or DMAC_CSR_AD_FIX */
- + ch_req->ahb_req.addr1_reqn = DMAC_REQN_NONE; /* (in) DMAC_REQN_xxx (also used to help determine channel number) */
- + ch_req->ahb_req.tx_dir = DMAD_DIR_A0_TO_A1; /* (in) DMAD_DIR_A0_TO_A1, DMAD_DIR_A1_TO_A0 */
- +
- + ch_req->controller = DMAD_DMAC_AHB_CORE; /* (in) DMAD_DMAC_AHB_CORE, DMAD_DMAC_APB_CORE */
- + ch_req->flags = DMAD_FLAGS_SLEEP_BLOCK | DMAD_FLAGS_BIDIRECTION;
- +
- + if (dmad_channel_alloc(ch_req) != 0) {
- + memset(ch_req, 0, sizeof(dmad_chreq));
- + printk(KERN_INFO "%s: AHB dma channel allocation failed\n", __func__);
- + goto _err_exit;
- + }
- +
- + P_DEBUG("%s: AHB dma channel allocated (ch: %d)\n", __func__, ch_req->channel);
- + //printk("%s: AHB dma channel allocated (ch: %d)\n", __func__, ch_req->channel);
- +
- + return 0;
- +
- +_err_exit:
- +
- +#endif /* CONFIG_PLATFORM_AHBDMA */
- +
- + return -ENODEV;
- +}
- +
- +/*--------------------------------
- + * Note no locks taken out here. In a worst case scenario, we could drop
- + * a chunk of system memory. But that should never happen, since validation
- + * happens at open or mount time, when locks are held.
- + */
- +static int sd_revalidate(struct gendisk *gd)
- +{
- + struct sd_dev *dev = gd->private_data;
- +
- + P_DEBUG("--> %s\n", __func__);
- + P_DEBUG("card state=%s\n", dev->card_state == SD_CARD_INSERT ? "INSERT" : dev->card_state == SD_CARD_WORK ? "WORK" : "REMOVE");
- +
- + if (dev->usage == 0) {
- + if (sd_card_setup(dev) != TRUE) {
- + dev->card_state = SD_CARD_REMOVE;
- + return -1;
- + } else {
- + enable_irq(FTSDC_IRQ);
- + dev->card_state = SD_CARD_WORK;
- + }
- + }
- + P_DEBUG("<-- %s\n", __func__);
- +
- + return 0;
- +}
- +
- +/*
- + * Device open and close
- + * TODO: forbids open for write when WRITE_PROTECT=1
- + */
- +int sd_open(struct block_device *bdev, fmode_t mode)
- +{
- + struct sd_dev *dev= bdev->bd_disk->private_data; /* device information */
- + P_DEBUG("--> %s\n", __func__);
- + /* Early return if there's nothing in the card slot */
- + if ((SDC_R_REG(SDC_STATUS_REG) & SDC_STATUS_REG_CARD_INSERT) != SDC_CARD_INSERT) {
- + P_DEBUG("<-- %s (ENOMEDIUM)\n", __func__);
- + return -ENOMEDIUM;
- + }
- + //spin_lock(&dev->lock);
- + if (!dev->usage) {
- + dev->media_change=1;
- + P_DEBUG("%s: forced check_disk_change check\n", __func__);
- + check_disk_change(bdev);
- + sector_offset=0;
- + Do_onetime=0;
- + } else
- + dev->media_change=0;
- +
- + /* Set size HERE:
- + * must rely on sd_revalidate to set correct size
- + * (seems on check_disk_change()) */
- + P_DEBUG("%s: set_capacity() to %d blocks (%d bytes)\n",__func__, dev->size, dev->size*SD_SECTOR_SIZE);
- + set_capacity(dev->gd, dev->size);
- + dev->usage++;
- + P_DEBUG("<-- %s\n", __func__);
- +
- + return 0; /* success */
- +}
- +
- +int sd_release(struct gendisk *gd, fmode_t mode)
- +{
- + struct sd_dev *dev = gd->private_data;
- +
- + disable_irq(FTSDC_IRQ);
- + printk(" + sd_release : umount SD\n");
- +
- + P_DEBUG("--> %s\n", __func__);
- + dev->usage--;
- + P_DEBUG("<-- %s\n", __func__);
- +
- + return 0;
- +}
- +
- +/*--------------------------------------
- + * The file operations
- + */
- +struct block_device_operations sd_fops = {
- + owner: THIS_MODULE,
- + open: sd_open,
- + release: sd_release,
- + ioctl: sd_ioctl,
- + revalidate_disk: sd_revalidate,
- + media_changed: sd_media_changed,
- +};
- +
- +void init_sd_pmu(void)
- +{
- +
- +#ifdef CONFIG_FIE8100_PLATFORM
- + unsigned int u32temp;
- + u32temp = *(volatile unsigned int *)(A320_PMU_VA_BASE + 0x14);
- + u32temp &= ~0x3000;
- + u32temp |= 0x2000;
- + *(volatile unsigned int *)(A320_PMU_VA_BASE + 0x14)=u32temp;
- +#endif
- +
- +#ifdef CONFIG_FIE7000_PLATFORM
- + *(volatile unsigned int *)(A320_PMU_VA_BASE + 0x114) = (*(volatile unsigned int *)(A320_PMU_VA_BASE + 0x114) & 0xFFFF0FFF) | 0x00002000;
- +#endif
- +}
- +
- +/*
- + * Set up our internal device.
- + */
- +static int setup_device(struct sd_dev *dev)
- +{
- + /*
- + * Get some memory.
- + */
- + memset (dev, 0, sizeof (struct sd_dev));
- + dev->size = 0;//SD_DUMMY_SIZE/SD_SECTOR_SIZE; /* We'll fill this with correct size later*/
- + spin_lock_init(&dev->lock);
- + /* Request Queue */
- + dev->queue = blk_init_queue(sd_request, &dev->lock);
- + if (dev->queue == NULL)
- + return -EFAULT;
- +
- + blk_queue_logical_block_size(dev->queue, hardsect_size);
- + dev->queue->queuedata = dev;
- +
- + dev->card_state = SD_CARD_REMOVE;
- +
- + /*
- + * And the gendisk structure.
- + */
- + dev->gd = alloc_disk(SD_MINORS);
- + if (! dev->gd) {
- + printk (KERN_NOTICE "alloc_disk failure\n");
- + return -EFAULT;
- + }
- +
- + dev->gd->flags = GENHD_FL_REMOVABLE|GENHD_FL_SUPPRESS_PARTITION_INFO;
- + dev->gd->major = sd_major;
- + dev->gd->first_minor = 0;
- + dev->gd->minors = SD_MINORS;
- + dev->gd->fops = &sd_fops;
- + dev->gd->queue = dev->queue;
- + dev->gd->private_data = dev;
- + snprintf (dev->gd->disk_name, 32, "cpesd%c", 'a');
- + set_capacity(dev->gd, 0); //SD_DUMMY_SIZE/SD_SECTOR_SIZE*(hardsect_size/KERNEL_SECTOR_SIZE));
- + add_disk(dev->gd);
- +
- + /*
- + * dma alloc
- + */
- + if (sd_dma_ch_alloc(dev) == 0) {
- + printk(KERN_NOTICE "Faraday SD controller Driver (DMA mode)\n");
- + dev->dma_enable = true;
- + } else {
- + printk(KERN_NOTICE "Faraday SD controller Driver (PIO mode)\n");
- + }
- +
- + return 0;
- +}
- +/*
- + * Look for a media change.
- + */
- +static int sd_media_changed(struct gendisk *gd)
- +{
- + struct sd_dev *dev = gd->private_data;
- + return dev->media_change;
- +}
- +
- +/*
- + * module stuff
- + */
- +static int __init sd_module_init(void)
- +{
- + int result=-ENOMEM;
- + spinlock_t complete_lock;
- + unsigned long iflags;
- + spin_lock_init(&complete_lock);
- +
- +#ifdef CONFIG_PLAT_QEMU
- + SDC_READ_FIFO_LEN = SDC_WRITE_FIFO_LEN = SDC_R_REG(0x44) & 0xff;
- +#else
- + if(SDC_R_REG(0xa0) == 0x00030101)
- + SDC_READ_FIFO_LEN = SDC_WRITE_FIFO_LEN = SDC_R_REG(0x9c) & 0xff;
- + else
- + SDC_READ_FIFO_LEN = SDC_WRITE_FIFO_LEN = SDC_R_REG(SDC_FEATURE_REG) & 0xff;
- +#endif
- + /* Register SD driver */
- + sd_major = register_blkdev(sd_major, DEVICE_NAME);
- + if (sd_major <= 0) {
- + printk(KERN_WARNING DEVICE_NAME ":unable to get major number\n");
- + return -EBUSY;
- + }
- + init_sd_pmu(); /* Power on SDC */
- + P_DEBUG("SD Major Number = %d\n", sd_major);
- + printk(KERN_ALERT "SD: make node with 'mknod /dev/cpesd b %d 0'\n", sd_major);
- +
- + sd_devices = kmalloc(sizeof(struct sd_dev), GFP_KERNEL);
- + if (!sd_devices)
- + goto fail_malloc;
- + memset(sd_devices, 0, sizeof(struct sd_dev));
- +
- + if (setup_device(sd_devices))
- + goto fail_malloc;
- +
- + P_DEBUG("Request SDC IRQ=%d\n", FTSDC_IRQ);
- + spin_lock_irqsave(&complete_lock, iflags);
- + if (request_irq(FTSDC_IRQ, sd_hotswap_interrupt_handler, IRQF_DISABLED, "SD controller", sd_devices) != 0) {
- + printk(KERN_ERR "Unable to allocate SDC IRQ=0x%X\n", FTSDC_IRQ);
- + goto fail_malloc;
- + }
- + disable_irq(FTSDC_IRQ);
- + spin_unlock_irqrestore(&complete_lock, iflags);
- + if (request_region(FTSDC_VA_BASE, 0x48, "SD Controller") == NULL) {
- + printk(KERN_ERR "request io port of sd controller fail\n");
- + goto fail_mem;
- + }
- +
- + return 0; /* succeed */
- +
- +fail_mem:
- + free_irq(FTSDC_IRQ, sd_devices);
- +
- +fail_malloc:
- + if (sd_devices)
- + kfree(sd_devices);
- + unregister_blkdev(sd_major, DEVICE_NAME);
- + return result;
- +}
- +
- +static void sd_module_cleanup(void)
- +{
- + P_DEBUG("--> %s\n", __func__);
- +
- + /* unregister the device now to avoid further operations during cleanup */
- +
- + if (sd_devices) {
- + del_gendisk(sd_devices->gd);
- + put_disk(sd_devices->gd);
- + if(sd_devices->queue)
- + blk_cleanup_queue(sd_devices->queue);
- +
- + if (sd_devices->dma_enable)
- + dmad_channel_free(&sd_devices->ch_req);
- +
- + kfree(sd_devices);
- + }
- +
- + release_region(FTSDC_VA_BASE, 0x48);
- + free_irq(FTSDC_IRQ, sd_devices);
- +
- + unregister_blkdev(sd_major, DEVICE_NAME);
- + P_DEBUG("<-- %s\n", __func__);
- +}
- +
- +module_init(sd_module_init);
- +module_exit(sd_module_cleanup);
- diff -Nur linux-3.4.110.orig/drivers/block/ftsdc010.h linux-3.4.110/drivers/block/ftsdc010.h
- --- linux-3.4.110.orig/drivers/block/ftsdc010.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/block/ftsdc010.h 2016-04-07 10:20:51.022084119 +0200
- @@ -0,0 +1,477 @@
- +/* drivers/block/CPESD/ftsdc010.h
- + *
- + * Faraday FTSDC010 Device Driver
- + *
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + *
- + * All Rights Reserved
- + */
- +
- +#ifndef _FTSDC010_H_
- +#define _FTSDC010_H_
- +
- +#ifndef TRUE
- +#define TRUE 1
- +#endif
- +
- +#ifndef FALSE
- +#define FALSE 0
- +#endif
- +
- +//#define SD_DEBUG
- +#define DELAY_FOR_DMA_READ
- +
- +#ifdef SD_DEBUG
- + #define P_DEBUG(fmt, args...) printk(KERN_ALERT "SD: " fmt, ## args)
- +#else
- + #define P_DEBUG(a...)
- +#endif
- +#define P_DEBUGG(a...)
- +
- +#define MAX_READ_SECTOR_NR 96 //16
- +#define MAX_WRITE_SECTOR_NR MAX_READ_SECTOR_NR
- +
- +#define SD_MAJOR 6 /* default major number, if zero, it means dynamic allocate */
- +#define SD_DEVS 1 /* number of disks */
- +#define SD_MINORS 16 /* minors per disk */
- +#define SD_RAHEAD 2 /* number of sectors */
- +#define SD_BLKSIZE 1024 /* block size */
- +#define SD_SECTOR_SIZE 512 /* sector size */
- +#define SD_DUMMY_SIZE (256*1024*1024) // for sake of hotswap/hotplug
- +#if 0
- +typedef struct _sd_dev_t {
- + int size;
- + int usage;
- + //struct timer_list timer;
- + spinlock_t lock;
- + struct semaphore sema; // synchronization
- + int card_state;
- +} sd_dev_t;
- +#endif
- +//---------SD Card State
- +#define SD_CARD_REMOVE 0
- +#define SD_CARD_INSERT 1
- +#define SD_CARD_WORK 2
- +
- +/* so far, SD controller support 3.2-3.3 VDD */
- +#define SDC_OCR 0x00FF8000
- +
- +/* sd controller register */
- +#define SDC_CMD_REG 0x00000000
- +#define SDC_ARGU_REG 0x00000004
- +#define SDC_RESPONSE0_REG 0x00000008
- +#define SDC_RESPONSE1_REG 0x0000000C
- +#define SDC_RESPONSE2_REG 0x00000010
- +#define SDC_RESPONSE3_REG 0x00000014
- +#define SDC_RSP_CMD_REG 0x00000018
- +#define SDC_DATA_CTRL_REG 0x0000001C
- +#define SDC_DATA_TIMER_REG 0x00000020
- +#define SDC_DATA_LEN_REG 0x00000024
- +#define SDC_STATUS_REG 0x00000028
- +#define SDC_CLEAR_REG 0x0000002C
- +#define SDC_INT_MASK_REG 0x00000030
- +#define SDC_POWER_CTRL_REG 0x00000034
- +#define SDC_CLOCK_CTRL_REG 0x00000038
- +#define SDC_BUS_WIDTH_REG 0x0000003C
- +#define SDC_DATA_WINDOW_REG 0x00000040
- +#ifdef A320D_BUILDIN_SDC
- +#define SDC_FEATURE_REG 0x00000044
- +#define SDC_REVISION_REG 0x00000048
- +#else
- +#define SDC_MMC_INT_RSP_REG 0x00000044
- +#define SDC_GP_OUTPUT_REG 0x00000048
- +#define SDC_FEATURE_REG 0x0000009C
- +#define SDC_REVISION_REG 0x000000A0
- +#endif
- +
- +/* bit mapping of command register */
- +#define SDC_CMD_REG_INDEX 0x0000003F
- +#define SDC_CMD_REG_NEED_RSP 0x00000040
- +#define SDC_CMD_REG_LONG_RSP 0x00000080
- +#define SDC_CMD_REG_APP_CMD 0x00000100
- +#define SDC_CMD_REG_CMD_EN 0x00000200
- +#define SDC_CMD_REG_SDC_RST 0x00000400
- +
- +/* bit mapping of response command register */
- +#define SDC_RSP_CMD_REG_INDEX 0x0000003F
- +#define SDC_RSP_CMD_REG_APP 0x00000040
- +
- +/* bit mapping of data control register */
- +#define SDC_DATA_CTRL_REG_BLK_SIZE 0x0000000F
- +#define SDC_DATA_CTRL_REG_DATA_WRITE 0x00000010
- +#define SDC_DATA_CTRL_REG_DATA_READ 0x00000000
- +#define SDC_DATA_CTRL_REG_DMA_EN 0x00000020
- +#define SDC_DATA_CTRL_REG_DATA_EN 0x00000040
- +
- +#define SDC_DMA_TYPE_1 0x00000000
- +#define SDC_DMA_TYPE_4 0x00000100
- +#define SDC_DMA_TYPE_8 0x00000200
- +
- +/* bit mapping of status/clear/mask register */
- +#define SDC_STATUS_REG_RSP_CRC_FAIL 0x00000001
- +#define SDC_STATUS_REG_DATA_CRC_FAIL 0x00000002
- +#define SDC_STATUS_REG_RSP_TIMEOUT 0x00000004
- +#define SDC_STATUS_REG_DATA_TIMEOUT 0x00000008
- +#define SDC_STATUS_REG_RSP_CRC_OK 0x00000010
- +#define SDC_STATUS_REG_DATA_CRC_OK 0x00000020
- +#define SDC_STATUS_REG_CMD_SEND 0x00000040
- +#define SDC_STATUS_REG_DATA_END 0x00000080
- +#define SDC_STATUS_REG_FIFO_UNDERRUN 0x00000100
- +#define SDC_STATUS_REG_FIFO_OVERRUN 0x00000200
- +#define SDC_STATUS_REG_CARD_CHANGE 0x00000400
- +#define SDC_STATUS_REG_CARD_INSERT 0x00000800
- +#define SDC_STATUS_REG_CARD_LOCK 0x00001000
- +
- +#define SDC_CARD_INSERT 0x0
- +#define SDC_CARD_REMOVE SDC_STATUS_REG_CARD_INSERT
- +
- +/* bit mapping of power control register */
- +#define SDC_POWER_REG_POWER_ON 0x00000010
- +#define SDC_POWER_REG_POWER_BITS 0x0000000F
- +
- +/* bit mapping of clock control register */
- +#define SDC_CLOCK_REG_CARD_TYPE 0x00000080
- +#define SDC_CLOCK_REG_CLK_DIV 0x0000007F
- +
- +/* card type */
- +#define SDC_CARD_TYPE_SD SDC_CLOCK_REG_CARD_TYPE
- +#define SDC_CARD_TYPE_MMC 0x0
- +
- +/* bit mapping of bus width register */
- +#define SDC_BUS_WIDTH_REG_SINGLE_BUS 0x00000001
- +#define SDC_BUS_WIDTH_REG_WIDE_BUS 0x00000004
- +#define SDC_WIDE_BUS_SUPPORT 0x00000008
- +
- +/* data window register */
- +//#define SDC_READ_FIFO_LEN 4
- +//#define SDC_WRITE_FIFO_LEN 4
- +
- +/* card type, sd or mmc */
- +#define MEMORY_CARD_TYPE_SD 0
- +#define MEMORY_CARD_TYPE_MMC 1
- +
- +/********************************************************************/
- +/* SYSTEM ERROR_CODE */
- +/********************************************************************/
- +#define ERR_NO_ERROR 0x00000000
- +
- +/* general error */
- +#define ERR_CARD_NOT_EXIST 0x00000001
- +#define ERR_OUT_OF_VOLF_RANGE 0x00000002
- +#define ERR_SD_PARTITIAL_READ_ERROR 0x00000004
- +#define ERR_SD_PARTITIAL_WRITE_ERROR 0x00000008
- +
- +#define ERR_SD_CARD_IS_LOCK 0x00000010
- +
- +/* command error */
- +#define ERR_DATA_CRC_ERROR 0x00000100
- +#define ERR_RSP_CRC_ERROR 0x00000200
- +#define ERR_DATA_TIMEOUT_ERROR 0x00000400
- +#define ERR_RSP_TIMEOUT_ERROR 0x00000800
- +
- +#define ERR_WAIT_OVERRUN_TIMEOUT 0x00001000
- +#define ERR_WAIT_UNDERRUN_TIMEOUT 0x00002000
- +#define ERR_WAIT_DATA_CRC_TIMEOUT 0x00004000
- +#define ERR_WAIT_TRANSFER_END_TIMEOUT 0x00008000
- +
- +#define ERR_SEND_COMMAND_TIMEOUT 0x00010000
- +
- +/* sd error */
- +#define ERR_SD_CARD_IS_BUSY 0x00100000
- +#define ERR_CID_REGISTER_ERROR 0x00200000
- +#define ERR_CSD_REGISTER_ERROR 0x00400000
- +
- +/* sd card status error */
- +#define ERR_SD_CARD_STATUS_ERROR 0x01000000
- +/* SDC using APB DMA error */
- +#define ERR_DMA_RSP_ERROR 0x02000000
- +
- +#define SD_SCR_1_BIT_BIT 0x0001
- +#define SD_SCR_4_BIT_BIT 0x0004
- +
- +/********************************************************************/
- +/* The bit mapping of SD Status register */
- +/********************************************************************/
- +#define SD_STATUS_OUT_OF_RANGE 0x80000000
- +#define SD_STATUS_ADDRESS_ERROR 0x40000000
- +#define SD_STATUS_BLOCK_LEN_ERROR 0x20000000
- +#define SD_STATUS_ERASE_SEQ_ERROR 0x10000000
- +#define SD_STATUS_ERASE_PARAM 0x08000000
- +#define SD_STATUS_WP_VIOLATION 0x04000000
- +#define SD_STATUS_CARD_IS_LOCK 0x02000000
- +#define SD_STATUS_LOCK_UNLOCK_FILED 0x01000000
- +#define SD_STATUS_COM_CRC_ERROR 0x00800000
- +#define SD_STATUS_ILLEGAL_COMMAND 0x00400000
- +#define SD_STATUS_CARD_ECC_FAILED 0x00200000
- +#define SD_STATUS_CC_ERROR 0x00100000
- +#define SD_STATUS_ERROR 0x00080000
- +#define SD_STATUS_UNDERRUN 0x00040000
- +#define SD_STATUS_OVERRUN 0x00020000
- +#define SD_STATUS_CID_CSD_OVERWRITE 0x00010000
- +#define SD_STATUS_WP_ERASE_SKIP 0x00008000
- +#define SD_STATUS_CARD_ECC_DISABLE 0x00004000
- +#define SD_STATUS_ERASE_RESET 0x00002000
- +#define SD_STATUS_CURRENT_STATE 0x00001E00
- +#define SD_STATUS_READY_FOR_DATA 0x00000100
- +#define SD_STATUS_APP_CMD 0x00000020
- +#define SD_STATUS_AKE_SEQ_ERROR 0x00000008
- +#define SD_STATUS_ERROR_BITS (SD_STATUS_ADDRESS_ERROR | SD_STATUS_BLOCK_LEN_ERROR | SD_STATUS_ERASE_SEQ_ERROR | SD_STATUS_ERASE_PARAM | SD_STATUS_WP_VIOLATION | SD_STATUS_LOCK_UNLOCK_FILED | SD_STATUS_CARD_ECC_FAILED | SD_STATUS_CC_ERROR | SD_STATUS_ERROR | SD_STATUS_UNDERRUN | SD_STATUS_OVERRUN | SD_STATUS_CID_CSD_OVERWRITE | SD_STATUS_WP_ERASE_SKIP | SD_STATUS_AKE_SEQ_ERROR)
- +#define SD_STATUS_CURRENT_STATE_LOC 9
- +
- +/********************************************************************/
- +/* SD command response type */
- +/********************************************************************/
- +#define SD_NO_RESPONSE 0
- +#define SD_RESPONSE_R1 1
- +#define SD_RESPONSE_R1b 2
- +#define SD_RESPONSE_R2 3
- +#define SD_RESPONSE_R3 4
- +#define SD_RESPONSE_R6 5
- +
- +/********************************************************************/
- +/* SD command */
- +/********************************************************************/
- +#define SD_GO_IDLE_STATE_CMD 0
- +#define SD_MMC_OP_COND 1
- +#define SD_ALL_SEND_CID_CMD 2
- +#define SD_SEND_RELATIVE_ADDR_CMD 3
- +#define SD_SET_DSR_CMD 4
- +#define SD_SET_BUS_WIDTH_CMD 6
- +#define SD_SELECT_CARD_CMD 7
- +#define SD_SEND_CSD_CMD 9
- +#define SD_SEND_CID_CMD 10
- +#define SD_STOP_TRANSMISSION_CMD 12
- +#define SD_SEND_STATUS_CMD 13
- +#define SD_GO_INACTIVE_STATE_CMD 15
- +#define SD_SET_BLOCKLEN_CMD 16
- +#define SD_READ_SINGLE_BLOCK_CMD 17
- +#define SD_READ_MULTIPLE_BLOCK_CMD 18
- +#define SD_WRITE_SINGLE_BLOCK_CMD 24
- +#define SD_WRITE_MULTIPLE_BLOCK_CMD 25
- +#define SD_PROGRAM_CSD_CMD 27
- +#define SD_ERASE_SECTOR_START_CMD 32
- +#define SD_ERASE_SECTOR_END_CMD 33
- +#define SD_ERASE_CMD 38
- +#define SD_APP_OP_COND 41
- +#define SD_LOCK_UNLOCK_CMD 42
- +#define SD_SEND_SCR_CMD 51
- +#define SD_APP_CMD 55
- +#define SD_GET_CMD 56
- +
- +/* retry count */
- +#ifndef CONFIG_FTSDC010_USE_TIMER_DELAY
- +#define SD_CARD_GET_OCR_RETRY_COUNT 0x1000
- +#define SD_CARD_WAIT_OPERATION_COMPLETE_RETRY_COUNT 8000
- +#define SD_CARD_STATE_CHANGE_RETRY_COUNT 30000
- +#define SD_CARD_WAIT_TRANSFER_STATE_RETRY_COUNT 30000
- +#define SDC_GET_STATUS_RETRY_COUNT 0x300000
- +#else
- +#define SD_CARD_GET_OCR_RETRY_COUNT 0x1000
- +#define SD_CARD_WAIT_OPERATION_COMPLETE_RETRY_COUNT 8000
- +#define SD_CARD_STATE_CHANGE_RETRY_COUNT 10000
- +#define SD_CARD_WAIT_TRANSFER_STATE_RETRY_COUNT 10000
- +#endif
- +
- +/*
- + * Please refer SanDisk SD Manual v1.9 Section 5.1.9.2 (page 5-76) to set the timeout setting
- + */
- +#ifdef SD_DEBUG
- +#define SDC_TIMEOUT_BASE (HZ/2) // Unit is 500 ms
- +#else
- +#define SDC_TIMEOUT_BASE (HZ/3) // Unit is 333 ms
- +#endif
- +#define SDC_GET_STATUS_RETRY_TIMEOUT_COUNT (HZ*4)
- +
- +/* sd card standby state */
- +#define SD_IDLE_STATE 0
- +#define SD_READY_STATE 1
- +#define SD_IDENT_STATE 2
- +#define SD_STBY_STATE 3
- +#define SD_TRAN_STATE 4
- +#define SD_DATA_STATE 5
- +#define SD_RCV_STATE 6
- +#define SD_PRG_STATE 7
- +#define SD_DIS_STATE 8
- +
- +#define SD_BUS_WIDTH_1_BIT 0
- +#define SD_BUS_WIDTH_4_BIT 2
- +
- +/********************************************************************/
- +/* SD card OCR register */
- +/********************************************************************/
- +#define SD_OCR_BUSY_BIT 0x80000000
- +
- +/********************************************************************/
- +/* SD CID register */
- +/********************************************************************/
- +#define SD_DEFAULT_MONTH_CODE 1
- +#define SD_DEFAULT_YEAR_CODE 2000
- +#define MAX_MULTI_BLOCK_NUM 126
- +
- +typedef struct _sd_cid_t
- +{
- + uint ManufacturerID;
- + uint ApplicationID;
- + unchar ProductName[7];
- + uint ProductRevisionHigh;
- + uint ProductRevisionLow;
- + uint ProductSerialNumber;
- + uint ManufactureMonth;
- + uint ManufactureYear;
- +} sd_cid_t;
- +
- +/********************************************************************/
- +/* SD CSD register */
- +/********************************************************************/
- +#define SD_CSD_STRUCTURE_1_0 0
- +#define SD_CSD_STRUCTURE_1_1 1
- +
- +#define SD_CSD_SPEC_VERS_1_0_1_2 0
- +#define SD_CSD_SPEC_VERS_1_4 1
- +#define SD_CSD_SPEC_VERS_2_1 2
- +
- +#define SD_TAAC_TIME_UINT_BITS 0x07
- +#define SD_TAAC_TIME_VALUE_BITS 0x78
- +
- +typedef struct _sd_csd_t
- +{
- + uint CSDStructure;
- + uint MMCSpecVersion;
- + uint TAAC_u;
- + uint NSAC_u;
- + uint TransferSpeed;
- + uint CardCmdClass;
- + uint ReadBlockLength;
- + uint ReadBlockPartial;
- + uint WriteBlockMisalign;
- + uint ReadBlockMisalign;
- + uint DSRImplemant;
- + uint BlockNumber;
- + uint MemorySize;
- + uint VDDReadMin_u;
- + uint VDDReadMax_u;
- + uint VDDWriteMin_u;
- + uint VDDWriteMax_u;
- + uint EraseBlkEnable;
- + uint EraseSectorSize;
- + uint WriteProtectGroupSize;
- + uint WriteProtectGroupEnable;
- + uint WriteSpeedFactor;
- + uint WriteBlockLength;
- + unchar WriteBlockPartial;
- + unchar CopyFlag;
- + unchar PermanentWriteProtect;
- + unchar TemporaryWriteProtect;
- + unchar FileFormat;
- +} sd_csd_t;
- +
- +typedef struct _sd_csd_bit_t
- +{
- + uint NotUsed:1;
- + uint CRC:7;
- + uint MMCardReserved1:2;
- + uint FILE_FORMAT:2;
- + uint TMP_WRITE_PROTECT:1;
- + uint PERM_WRITE_PROTECT:1;
- + uint COPY:1;
- + uint FILE_FORMAT_GRP:1;
- +
- + uint Reserved2:5;
- + uint WRITE_BL_PARTIAL:1;
- + uint WRITE_BL_LEN:4;
- + uint R2W_FACTOR:3;
- + uint MMCardReserved0:2;
- + uint WP_GRP_ENABLE:1;
- +
- + uint WP_GRP_SIZE:7;
- + uint ERASE_SECTOR_SIZE:7;
- + uint ERASE_BLK_ENABLE:1;
- + uint C_SIZE_MULT:3;
- + uint VDD_W_CURR_MAX:3;
- + uint VDD_W_CURR_MIN:3;
- + uint VDD_R_CURR_MAX:3;
- + uint VDD_R_CURR_MIN:3;
- +
- + uint C_SIZE_1:2;
- + uint C_SIZE_2:10; // divide its into 2, 10bits
- +
- + uint Reserved1:2;
- + uint DSR_IMP:1;
- + uint READ_BLK_MISALIGN:1;
- + uint WRITE_BLK_MISALIGN:1;
- + uint READ_BL_PARTIAL:1;
- +
- + uint READ_BL_LEN:4;
- + uint CCC:12;
- +
- + uint TRAN_SPEED_RateUnit:3;
- + uint TRAN_SPEED_TimeValue:4;
- + uint TRAN_SPEED_Reserved:1;
- +
- + uint NSAC:8;
- +
- + uint TAAC_TimeUnit:3;
- + uint TAAC_TimeValue:4;
- + uint TAAC_Reserved:1;
- +
- + uint Reserved0:2;
- + uint MMC_SPEC_VERS:4;
- + uint CSD_STRUCTURE:2;
- +} sd_csd_bit_t;
- +
- +/********************************************************************/
- +/* SD SCR register */
- +/********************************************************************/
- +typedef struct _sd_scr_t
- +{
- + uint Reserved:16;
- + uint SD_BUS_WIDTH:4;
- + uint SD_SECURITY:3;
- + uint DATA_STAT_AFTER_ERASE:1;
- + uint SD_SPEC:4;
- + uint SCR_STRUCTURE:4;
- +
- + uint ManufacturerReserved;
- +} sd_scr_t;
- +
- +/********************************************************************/
- +/* sd card structure */
- +/********************************************************************/
- +typedef struct _sd_card_t
- +{
- + /* host interface configuration */
- + uint IOAddr; /* host controller register base address */
- + uint DMAEnable;
- +
- + uint CardType;
- +
- + /* card register */
- + uint OCR;
- +
- + uint CIDWord[4];
- + sd_cid_t CID;
- +
- + uint CSDWord[4];
- + sd_csd_t CSD;
- +
- + ushort RCA;
- + sd_scr_t SCR;
- +
- + /* access time out */
- + uint ReadAccessTimoutCycle;
- + uint WriteAccessTimoutCycle;
- +
- + /* Drive Name */
- + uint Drive;
- +
- + /* system configurations */
- + uint SysFrequency;
- +
- + /* card status */
- + int ActiveState;
- + int WriteProtect;
- +
- + void *private;
- +} sd_card_t;
- +
- +#endif
- diff -Nur linux-3.4.110.orig/drivers/block/Kconfig linux-3.4.110/drivers/block/Kconfig
- --- linux-3.4.110.orig/drivers/block/Kconfig 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/block/Kconfig 2016-04-07 10:20:51.022084119 +0200
- @@ -498,6 +498,14 @@
- block device driver. It communicates with a back-end driver
- in another domain which drives the actual block device.
-
- +config FTSDC010
- + tristate "Faraday FTSDC010 driver"
- + depends on NDS32
- +
- +config FTCFC010
- + tristate "Faraday FTCFC010 driver"
- + depends on NDS32
- +
- config XEN_BLKDEV_BACKEND
- tristate "Xen block-device backend driver"
- depends on XEN_BACKEND
- diff -Nur linux-3.4.110.orig/drivers/block/Makefile linux-3.4.110/drivers/block/Makefile
- --- linux-3.4.110.orig/drivers/block/Makefile 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/block/Makefile 2016-04-07 10:20:51.050085202 +0200
- @@ -43,3 +43,5 @@
- obj-$(CONFIG_BLK_DEV_PCIESSD_MTIP32XX) += mtip32xx/
-
- swim_mod-y := swim.o swim_asm.o
- +obj-$(CONFIG_FTSDC010) += ftsdc010.o
- +obj-$(CONFIG_FTCFC010) += ftcfc010.o
- diff -Nur linux-3.4.110.orig/drivers/gpio/gpio-ftgpio010.c linux-3.4.110/drivers/gpio/gpio-ftgpio010.c
- --- linux-3.4.110.orig/drivers/gpio/gpio-ftgpio010.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/gpio/gpio-ftgpio010.c 2016-04-07 10:20:51.050085202 +0200
- @@ -0,0 +1,218 @@
- +#include <linux/module.h>
- +#include <linux/irq.h>
- +#include <linux/interrupt.h>
- +#include <linux/io.h>
- +#include <linux/gpio.h>
- +
- +#define GPIO_DATA_OUT 0x00
- +#define GPIO_DATA_IN 0x04
- +#define PIN_DIR 0x08
- +#define PIN_BYPASS 0x0C
- +#define GPIO_DATA_SET 0x10
- +#define GPIO_DATA_CLEAR 0x14
- +#define PIN_PULL_ENABLE 0x18
- +#define PIN_PULL_TYPE 0x1C
- +#define INT_ENABLE 0x20
- +#define INT_RAW_STATE 0x24
- +#define INT_MASKED_STATE 0x28
- +#define INT_MASK 0x2C
- +#define INT_CLEAR 0x30
- +#define INT_TRIGGER 0x34
- +#define INT_BOTH 0x38
- +#define INT_RISE_NEG 0x3C
- +#define BOUNCE_ENABLE 0x40
- +#define BOUNCE_PRE_SCALE 0x44
- +
- +#define GPIO_READL(offset) \
- + readl(GPIO_FTGPIO010_VA_BASE + (offset))
- +
- +#define GPIO_WRITEL(val, offset) \
- + writel((val), GPIO_FTGPIO010_VA_BASE + (offset))
- +
- +#define FTGPIO010_VIRTUAL_IRQ_BASE 100
- +
- +static int irq_to_gpio(unsigned int irq)
- +{
- + return irq - FTGPIO010_VIRTUAL_IRQ_BASE;
- +}
- +
- +static int ftgpio_to_irq(struct gpio_chip *gc, unsigned int offset)
- +{
- + return FTGPIO010_VIRTUAL_IRQ_BASE + offset;
- +}
- +
- +static int ftgpio_get(struct gpio_chip *gc, unsigned int gpio)
- +{
- + return (GPIO_READL(GPIO_DATA_IN) >> gpio & 1);
- +}
- +
- +static void ftgpio_set(struct gpio_chip *gc, unsigned int gpio, int data)
- +{
- + unsigned long val;
- +
- + if (data)
- + val = GPIO_READL(GPIO_DATA_OUT) | (0x1UL << gpio);
- + else
- + val = GPIO_READL(GPIO_DATA_OUT) & ~(0x1UL << gpio);
- +
- + GPIO_WRITEL(val, GPIO_DATA_OUT);
- +}
- +
- +static int ftgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
- +{
- + unsigned long val;
- +
- + val = GPIO_READL(PIN_DIR) & ~(0x1UL << gpio);
- + GPIO_WRITEL(val, PIN_DIR);
- +
- + return 0;
- +}
- +
- +static int ftgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int data)
- +{
- + unsigned long val;
- +
- + val = GPIO_READL(PIN_DIR) | (0x1UL << gpio);
- + GPIO_WRITEL(val, PIN_DIR);
- +
- + gc->set(gc, gpio, data);
- +
- + return 0;
- +}
- +
- +static struct gpio_chip ftgpio_chip = {
- +
- + .label = "FTGPIO010",
- + .base = 0,
- + .ngpio = 16,
- + .direction_input = ftgpio_dir_in,
- + .direction_output = ftgpio_dir_out,
- + .get = ftgpio_get,
- + .set = ftgpio_set,
- + .to_irq = ftgpio_to_irq,
- +};
- +
- +static void ftgpio_irq_ack(struct irq_data *data)
- +{
- + GPIO_WRITEL(0x1UL << irq_to_gpio(data->irq), INT_CLEAR);
- +}
- +
- +static void ftgpio_irq_mask(struct irq_data *data)
- +{
- + unsigned long val;
- +
- + val = GPIO_READL(INT_MASK) | (0x1UL << irq_to_gpio(data->irq));
- + GPIO_WRITEL(val, INT_MASK);
- +}
- +
- +static void ftgpio_irq_unmask(struct irq_data *data)
- +{
- + unsigned long val;
- + val = GPIO_READL(INT_MASK) & ~(0x1UL << irq_to_gpio(data->irq));
- + GPIO_WRITEL(val, INT_MASK);
- +}
- +
- +static int ftgpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
- +{
- + unsigned long bit = 0x1UL << irq_to_gpio(data->irq);
- + unsigned long val;
- + val = GPIO_READL(INT_BOTH);
- +
- + if (flow_type & IRQF_TRIGGER_RISING && flow_type & IRQF_TRIGGER_FALLING)
- + GPIO_WRITEL(val | bit, INT_BOTH);
- + else
- + GPIO_WRITEL(val & ~bit, INT_BOTH);
- +
- + val = GPIO_READL(INT_RISE_NEG);
- +
- + if (flow_type & IRQF_TRIGGER_FALLING)
- + GPIO_WRITEL(val | bit, INT_RISE_NEG);
- + else if (flow_type & IRQF_TRIGGER_RISING)
- + GPIO_WRITEL(val & ~bit, INT_RISE_NEG);
- +
- + return 0;
- +}
- +
- +static struct irq_chip ftgpio_irq_chip = {
- +
- + .name = "FTGPIO010_irq",
- + .irq_ack = ftgpio_irq_ack,
- + .irq_mask = ftgpio_irq_mask,
- + .irq_unmask = ftgpio_irq_unmask,
- + .irq_set_type = ftgpio_irq_set_type,
- +};
- +
- +static void gpio_irq_router(unsigned int irq, struct irq_desc *desc)
- +{
- + unsigned long status;
- + int i = 0;
- +
- + status = GPIO_READL(INT_RAW_STATE);
- + status &= ~((1 << 22) | (1 << 25) | (1 << 26));
- +
- + while (status) {
- +
- + if (status & 0x1UL)
- + generic_handle_irq(gpio_to_irq(i));
- +
- + status >>= 1;
- + i++;
- + }
- +}
- +
- +static int gpio_init(void)
- +{
- + int i;
- +
- + /* disable interrupt */
- + GPIO_WRITEL(0x00000000UL, INT_ENABLE);
- +
- + /* mask interrupt */
- + GPIO_WRITEL(0x0000FFFFUL, INT_MASK);
- +
- + /* triggered interrupt on both edge */
- + GPIO_WRITEL(0x0000FFFFUL, INT_BOTH);
- +
- + /* clear interrupt */
- + GPIO_WRITEL(0x0000FFFFUL, INT_CLEAR);
- +
- + /* enable de-bouncing */
- + GPIO_WRITEL(0x0000FFFFUL, BOUNCE_ENABLE);
- +
- + /* enable interrupt */
- + GPIO_WRITEL(0x0000FFFFUL, INT_ENABLE);
- +
- + gpiochip_add(&ftgpio_chip);
- +
- + for (i = 0; i < ftgpio_chip.ngpio; i++) {
- +
- + irq_set_chip(gpio_to_irq(i), &ftgpio_irq_chip);
- + irq_set_handler(gpio_to_irq(i), handle_level_irq);
- + }
- +
- + irq_set_chained_handler(GPIO_FTGPIO010_IRQ, gpio_irq_router);
- +
- + pr_info("GPIO module inserted\n");
- +
- + return 0;
- +}
- +
- +static void __exit gpio_exit(void)
- +{
- + int i=0;
- + /* disable interrupt */
- + GPIO_WRITEL(0x00000000UL, INT_ENABLE);
- + while(i<ftgpio_chip.ngpio)
- + gpio_free(i++);
- +
- + if (gpiochip_remove(&ftgpio_chip))
- + pr_info("failed to remove gpiochip\n");
- +
- + pr_info("GPIO module removed\n");
- +}
- +
- +MODULE_DESCRIPTION("FTGPIO010");
- +MODULE_LICENSE("GPL");
- +
- +module_init(gpio_init);
- +module_exit(gpio_exit);
- diff -Nur linux-3.4.110.orig/drivers/gpio/Kconfig linux-3.4.110/drivers/gpio/Kconfig
- --- linux-3.4.110.orig/drivers/gpio/Kconfig 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/gpio/Kconfig 2016-04-07 10:20:51.050085202 +0200
- @@ -492,6 +492,10 @@
- This enables support for the Philips UCB1400 GPIO pins.
- The UCB1400 is an AC97 audio codec.
-
- +config GPIO_FTGPIO010
- + tristate "Farady FTGPIO010 GPIO support"
- + depends on NDS32 && GENERIC_GPIO && ARCH_WANT_OPTIONAL_GPIOLIB
- +
- comment "MODULbus GPIO expanders:"
-
- config GPIO_JANZ_TTL
- diff -Nur linux-3.4.110.orig/drivers/gpio/Makefile linux-3.4.110/drivers/gpio/Makefile
- --- linux-3.4.110.orig/drivers/gpio/Makefile 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/gpio/Makefile 2016-04-07 10:20:51.050085202 +0200
- @@ -64,3 +64,4 @@
- obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o
- obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o
- obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o
- +obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o
- \ No newline at end of file
- diff -Nur linux-3.4.110.orig/drivers/input/touchscreen/cpe_ts/cpe_ts.c linux-3.4.110/drivers/input/touchscreen/cpe_ts/cpe_ts.c
- --- linux-3.4.110.orig/drivers/input/touchscreen/cpe_ts/cpe_ts.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/input/touchscreen/cpe_ts/cpe_ts.c 2016-04-07 10:20:51.050085202 +0200
- @@ -0,0 +1,376 @@
- +#include <linux/input.h>
- +#include <linux/interrupt.h>
- +#include <linux/platform_device.h>
- +#include <linux/io.h>
- +
- +#include <asm/irq.h>
- +#include "cpe_ts.h"
- +
- +
- +#include <linux/module.h>
- +
- +#include <linux/irqnr.h>
- +#include <linux/irq.h>
- +
- +#define TOUCHSCREEN_IRQ 28
- +
- +#define ads_dbg( enabled, tagged, ...) \
- + do{ \
- + if( enabled){ \
- + if( tagged) \
- + printk( "[ %30s() ] ", __func__); \
- + printk( __VA_ARGS__); \
- + } \
- + } while( 0)
- +
- +#define TS_POLL_DELAY ( 1 * 1000000) /* ns delay before the first sample */
- +#define TS_POLL_PERIOD ( delay * 1000000) /* ns delay between samples */
- +
- +static int debug = 0;
- +static int delay = 25;
- +
- +module_param(debug, int, 0);
- +module_param(delay, int, 0);
- +
- +struct ads7846
- +{
- + void __iomem * regs;
- + struct input_dev *input;
- + char phys[32];
- + struct hrtimer timer;
- + int irq;
- + spinlock_t lock;
- + bool disabled;
- +};
- +
- +struct ts_event
- +{
- + int x;
- + int y;
- + int z1, z2;
- + int Rt;
- +};
- +
- +struct ads7846 touchscreen;
- +
- +#define ADS_START ( 0x1UL << 7)
- +#define ADS_A2A1A0_d_y ( 0x1UL << 4) /* differential */
- +#define ADS_A2A1A0_d_z1 ( 0x3UL << 4) /* differential */
- +#define ADS_A2A1A0_d_z2 ( 0x4UL << 4) /* differential */
- +#define ADS_A2A1A0_d_x ( 0x5UL << 4) /* differential */
- +#define ADS_12_BIT ( 0x0UL << 3)
- +#define ADS_SER ( 0x1UL << 2) /* non-differential */
- +#define ADS_DFR ( 0x0UL << 2) /* differential */
- +#define ADS_PD10_PDOWN ( 0x0UL << 0) /* lowpower mode + penirq */
- +#define ADS_PD10_ADC_ON ( 0x1UL << 0) /* ADC on */
- +#define ADS_PD10_REF_ON ( 0x2UL << 0) /* vREF on + penirq */
- +#define ADS_PD10_ALL_ON ( 0x3UL << 0) /* ADC + vREF on */
- +
- +#define MAX_12BIT ( ( 0x1UL << 12) - 1)
- +
- +#define READ_X ( ADS_A2A1A0_d_x | ADS_12_BIT | ADS_DFR)
- +#define READ_Y ( ADS_A2A1A0_d_y | ADS_12_BIT | ADS_DFR)
- +#define READ_Z1 ( ADS_A2A1A0_d_z1 | ADS_12_BIT | ADS_DFR)
- +#define READ_Z2 ( ADS_A2A1A0_d_z2 | ADS_12_BIT | ADS_DFR)
- +
- +static int
- +read_val(struct ads7846 *ts, unsigned long cmd)
- +{
- + unsigned long data = 0;
- + int repeat = 5;
- + int i;
- +
- + ads_dbg(0, 1, "Queuing data: 0x%08lx\n", cmd << 16);
- +
- + for (i = 0; i < repeat; i++)
- + {
- + while (!(REG32(ts->regs + SSP_REG_SR) & SSP_SR_mskTFNF));
- + REG32(ts->regs + SSP_REG_DR) = (ADS_START | cmd | ADS_PD10_ALL_ON) << 16;
- + }
- +
- + for (i = 0; i < repeat; i++)
- + {
- + while (!(REG32(ts->regs + SSP_REG_SR) & SSP_SR_mskRFVE));
- + data = (REG32(ts->regs + SSP_REG_DR) >> 3) & 0xFFF;
- + }
- +
- + while (!(REG32(ts->regs + SSP_REG_SR) & SSP_SR_mskTFNF));
- + REG32(ts->regs + SSP_REG_DR) = (ADS_START | cmd) << 16;
- +
- + while (!(REG32(ts->regs + SSP_REG_SR) & SSP_SR_mskRFVE));
- +
- + data = (REG32(ts->regs + SSP_REG_DR) >> 3) & 0xFFF;
- + ads_dbg(0, 1, "CMD <%02lx> data: 0x%08lx( %ld)\n", cmd, data, data);
- +
- + return data;
- +}
- +
- +static int pendown(struct ads7846 *ts)
- +{
- + return read_val(ts, READ_Z1) > 40;
- +}
- +
- +static void report(struct ads7846 *ts, struct ts_event *e)
- +{
- + e->x = read_val(ts, READ_X);
- + e->y = read_val(ts, READ_Y);
- + e->z1 = read_val(ts, READ_Z1);
- + e->z2 = read_val(ts, READ_Z2);
- +
- + ads_dbg(debug, 1, "x: %4d, y: %4d, z1: %4d, z2: %4d\n", e->x, e->y, e->z1, e->z2);
- +}
- +
- +#define FILTER_LIMIT 35
- +
- +static enum hrtimer_restart ads7846_timer(struct hrtimer *handle)
- +{
- + struct ads7846 *ts = container_of(handle, struct ads7846, timer);
- + struct ts_event e;
- + struct irq_desc *desc = (struct irq_desc *)irq_get_irq_data((unsigned int)ts->irq);
- + static int xp = 0, yp = 0;
- +
- + if (ts->disabled)
- + return HRTIMER_NORESTART;
- +
- + if (!pendown(ts))
- + {
- + ads_dbg(debug, 1, "Release\n");
- +
- + input_report_key(ts->input, BTN_TOUCH, 0);
- + input_report_abs(ts->input, ABS_PRESSURE, 0);
- + input_sync(ts->input);
- +
- + if(desc->irq_data.chip->irq_ack)
- + desc->irq_data.chip->irq_ack(&desc->irq_data);
- + enable_irq(ts->irq);
- + return HRTIMER_NORESTART;
- + }
- + report(ts, &e);
- +
- +#ifdef CONFIG_TOUCHSCREEN_CPE_TS_DEJITTER
- + if (abs(xp - e.x) > FILTER_LIMIT || abs(yp - e.y) > FILTER_LIMIT)
- + {
- +#endif
- + input_report_key(ts->input, BTN_TOUCH, 1);
- + input_report_abs(ts->input, ABS_X, e.x);
- + input_report_abs(ts->input, ABS_Y, e.y);
- + input_report_abs(ts->input, ABS_PRESSURE, 50);
- + xp = e.x;
- + yp = e.y;
- +#ifdef CONFIG_TOUCHSCREEN_CPE_TS_DEJITTER
- + }
- +#endif
- + input_sync(ts->input);
- + hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), HRTIMER_MODE_REL);
- + ads_dbg(0, 1, "Leave\n");
- + return HRTIMER_NORESTART;
- +}
- +
- +static irqreturn_t ads7846_irq(int irq, void *handle)
- +{
- + struct ads7846 *ts = handle;
- +
- + if (ts->disabled)
- + return IRQ_HANDLED;
- +
- + disable_irq_nosync(irq);
- + hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), HRTIMER_MODE_REL);
- +
- + return IRQ_HANDLED;
- +}
- +
- +static int xspi_init_hw(void __iomem *regs_base)
- +{
- + int rev = REG32(regs_base + SSP_REG_REV);
- + int reva = REG32(regs_base + SSP_REG_REV-0x20);
- +
- + if ((((rev & SSP_REV_mskMAJOR_REV) >> SSP_REV_offMAJOR_REV) != 1)&&
- + (((reva & SSP_REV_mskMAJOR_REV) >> SSP_REV_offMAJOR_REV) != 1))
- + {
- + ads_dbg(1, 0, "ADS7846 Touchscreen controller initialized failed:\n"
- + "\tcannot detect Faraday SSP Controller\n");
- + return -ENXIO;
- + }
- + REG32(regs_base + SSP_REG_CR2) |= (1UL << SSP_CR2_offSSPRST);
- +
- + REG32(regs_base + SSP_REG_CR1) =
- + (0UL << SSP_CR1_offPDL) | /* Padding Data Length */
- + (23UL << SSP_CR1_offSDL) | /* Serial Data Length */
- + (5UL << SSP_CR1_offSCLKDIV); /* SCLK Divider */
- +
- + REG32(regs_base + SSP_REG_CR0) =
- + (1UL << SSP_CR0_offFFMT) | /* Frame Format */
- + (3UL << SSP_CR0_offOPM) | /* Operation Mode */
- + (0UL << SSP_CR0_offSCLKPO) | /* SCLK Polarity */
- + (0UL << SSP_CR0_offSCLKPH); /* SCLK Phase */
- +
- + REG32(regs_base + SSP_REG_CR2) |= (1UL << SSP_CR2_offTXFCLR) | (1UL << SSP_CR2_offRXFCLR);
- + REG32(regs_base + SSP_REG_CR2) |= (1UL << SSP_CR2_offSSPEN) | (1UL << SSP_CR2_offTXDOE);
- + return 0;
- +}
- +
- +static int ads7846_probe(struct platform_device *pdev)
- +{
- + struct ads7846 *ts = &touchscreen;
- + struct input_dev *input_dev;
- + int err = 0;
- + platform_set_drvdata(pdev, ts);
- +
- + ts->regs = ioremap(0x98b00000, 44);
- + err = xspi_init_hw(ts->regs);
- + if (err)
- + goto err_unmap;
- + input_dev = input_allocate_device();
- + if (!input_dev)
- + {
- + err = -ENOMEM;
- + goto err_free_mem;
- + }
- +
- + ts->input = input_dev;
- +
- + hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- + ts->timer.function = ads7846_timer;
- +
- + input_dev->name = "ADS7846 Touchscreen";
- + input_dev->phys = ts->phys;
- +
- + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
- + input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
- + input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
- + input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
- + input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
- +
- + ts->irq = TOUCHSCREEN_IRQ;
- +
- + if (request_irq(ts->irq, ads7846_irq, IRQF_TRIGGER_RISING, "touch screen", ts))
- + goto err_free_mem;
- +
- + err = input_register_device(input_dev);
- + if (err)
- + goto err_free_irq;
- +
- + spin_lock_init(&ts->lock);
- + return 0;
- +err_free_irq:
- + free_irq(ts->irq, ts);
- +err_free_mem:
- + input_free_device(input_dev);
- +err_unmap:
- + iounmap(ts->regs);
- +
- + return err;
- +}
- +
- +static int __devexit ads7846_remove(struct platform_device *pdev)
- +{
- + struct ads7846 *ts = platform_get_drvdata(pdev);
- +
- + disable_irq(ts->irq);
- + free_irq(ts->irq, ts);
- + iounmap(ts->regs);
- + input_unregister_device(ts->input);
- +
- + return 0;
- +}
- +
- +#ifdef CONFIG_PM
- +static int ads7846_suspend( struct platform_device *pdev, pm_message_t message)
- +{
- + struct ads7846 *ts = platform_get_drvdata(pdev);
- +
- + spin_lock_irq(&ts->lock);
- + ts->disabled = true;
- + disable_irq(ts->irq);
- + spin_unlock_irq(&ts->lock);
- +
- + return 0;
- +}
- +
- +static int ads7846_resume( struct platform_device *pdev)
- +{
- + struct ads7846 *ts = platform_get_drvdata(pdev);
- +
- + spin_lock_irq(&ts->lock);
- +
- + enable_irq(ts->irq);
- + ts->disabled = false;
- +
- + spin_unlock_irq(&ts->lock);
- +
- + return 0;
- +}
- +#else
- +#define ads7846_suspend NULL
- +#define ads7846_resume NULL
- +#endif
- +
- +static void platform_device_release(struct device *dev){
- +}
- +
- +static struct resource ads7846_resources[] =
- +{
- + [0] = {
- + .start = SSP_FTSSP010_PA_BASE,
- + .end = SSP_FTSSP010_PA_LIMIT,
- + .flags = IORESOURCE_MEM,
- + },
- + [1] = {
- + .start = TOUCHSCREEN_IRQ, //feed me! SSP_FTSSP010_IRQ in spec.h
- + .end = TOUCHSCREEN_IRQ,
- + .flags = IORESOURCE_IRQ,
- + },
- +};
- +
- +static struct platform_device ads7846_device =
- +{
- + .name = "ads7846",
- + .id = -1,
- + .resource = ads7846_resources,
- + .num_resources = ARRAY_SIZE(ads7846_resources),
- + .dev = {
- + .release = platform_device_release,
- + },
- +};
- +
- +#if 0
- +static struct platform_driver ads7846_driver =
- +{
- + .driver = {
- + .name = "ads7846",
- + .owner = THIS_MODULE,
- + },
- + .probe = ads7846_probe,
- + .remove = __devexit_p(ads7846_remove),
- + .suspend = ads7846_suspend,
- + .resume = ads7846_resume,
- +};
- +#else
- +static struct platform_driver ads7846_driver =
- +{
- + .driver = {
- + .name = "ads7846",
- + },
- + .probe = ads7846_probe,
- + .remove = __devexit_p(ads7846_remove),
- + .suspend = ads7846_suspend,
- + .resume = ads7846_resume,
- +};
- +#endif
- +
- +static int __init ads7846_init(void)
- +{
- + platform_device_register(&ads7846_device);
- + return platform_driver_register(&ads7846_driver);
- +}
- +
- +static void __exit ads7846_exit(void)
- +{
- + platform_device_unregister(&ads7846_device);
- + platform_driver_unregister(&ads7846_driver);
- +}
- +
- +module_init(ads7846_init);
- +module_exit(ads7846_exit);
- +MODULE_DESCRIPTION("ADS7846 TouchScreen Driver");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.4.110.orig/drivers/input/touchscreen/cpe_ts/cpe_ts.h linux-3.4.110/drivers/input/touchscreen/cpe_ts/cpe_ts.h
- --- linux-3.4.110.orig/drivers/input/touchscreen/cpe_ts/cpe_ts.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/input/touchscreen/cpe_ts/cpe_ts.h 2016-04-07 10:20:51.050085202 +0200
- @@ -0,0 +1,218 @@
- +#ifndef SSP_FARADAY_H
- +#define SSP_FARADAY_H
- +
- +#define XILINX_SPI_NAME "faraday-spi"
- +
- +/*
- + * Register definitions as per "OPB Serial Peripheral Interface ( SPI) ( v1.00e)
- + * Product Specification", DS464
- + */
- +#define XSPI_CR_OFFSET 0x62 /* 16-bit Control Register */
- +
- +#define XSPI_CR_ENABLE 0x02
- +#define XSPI_CR_MASTER_MODE 0x04
- +#define XSPI_CR_CPOL 0x08
- +#define XSPI_CR_CPHA 0x10
- +#define XSPI_CR_MODE_MASK ( XSPI_CR_CPHA | XSPI_CR_CPOL)
- +#define XSPI_CR_TXFIFO_RESET 0x20
- +#define XSPI_CR_RXFIFO_RESET 0x40
- +#define XSPI_CR_MANUAL_SSELECT 0x80
- +#define XSPI_CR_TRANS_INHIBIT 0x100
- +
- +#define XSPI_SR_OFFSET 0x67 /* 8-bit Status Register */
- +
- +#define XSPI_SR_RX_EMPTY_MASK 0x01 /* Receive FIFO is empty */
- +#define XSPI_SR_RX_FULL_MASK 0x02 /* Receive FIFO is full */
- +#define XSPI_SR_TX_EMPTY_MASK 0x04 /* Transmit FIFO is empty */
- +#define XSPI_SR_TX_FULL_MASK 0x08 /* Transmit FIFO is full */
- +#define XSPI_SR_MODE_FAULT_MASK 0x10 /* Mode fault error */
- +
- +#define XSPI_TXD_OFFSET 0x6b /* 8-bit Data Transmit Register */
- +#define XSPI_RXD_OFFSET 0x6f /* 8-bit Data Receive Register */
- +
- +#define XSPI_SSR_OFFSET 0x70 /* 32-bit Slave Select Register */
- +
- +/* Register definitions as per "OPB IPIF ( v3.01c) Product Specification", DS414
- + * IPIF registers are 32 bit
- + */
- +#define XIPIF_V123B_DGIER_OFFSET 0x1c /* IPIF global int enable reg */
- +#define XIPIF_V123B_GINTR_ENABLE 0x80000000
- +
- +#define XIPIF_V123B_IISR_OFFSET 0x20 /* IPIF interrupt status reg */
- +#define XIPIF_V123B_IIER_OFFSET 0x28 /* IPIF interrupt enable reg */
- +
- +#define XSPI_INTR_MODE_FAULT 0x01 /* Mode fault error */
- +#define XSPI_INTR_SLAVE_MODE_FAULT 0x02 /* Selected as slave while disabled */
- +#define XSPI_INTR_TX_EMPTY 0x04 /* TxFIFO is empty */
- +#define XSPI_INTR_TX_UNDERRUN 0x08 /* TxFIFO was underrun */
- +#define XSPI_INTR_RX_FULL 0x10 /* RxFIFO is full */
- +#define XSPI_INTR_RX_OVERRUN 0x20 /* RxFIFO was overrun */
- +
- +#define XIPIF_V123B_RESETR_OFFSET 0x40 /* IPIF reset register */
- +#define XIPIF_V123B_RESET_MASK 0x0a /* the value to write */
- +
- +/*************************************************************************/
- +#if 0
- +#define SSP_REG_CR0 ( SSP_FTSSP010_VA_BASE + 0x00) /* SSP Control Register 0 */
- +#define SSP_REG_CR1 ( SSP_FTSSP010_VA_BASE + 0x04) /* SSP Control Register 1 */
- +#define SSP_REG_CR2 ( SSP_FTSSP010_VA_BASE + 0x08) /* SSP Control Register 2 */
- +#define SSP_REG_SR ( SSP_FTSSP010_VA_BASE + 0x0c) /* SSP Status Register */
- +#define SSP_REG_ICR ( SSP_FTSSP010_VA_BASE + 0x10) /* SSP Interrupt Control Register */
- +#define SSP_REG_ISR ( SSP_FTSSP010_VA_BASE + 0x14) /* SSP Interrupt Status Register */
- +#define SSP_REG_DR ( SSP_FTSSP010_VA_BASE + 0x18) /* SSP Data Register */
- +#define SSP_REG_ACL ( SSP_FTSSP010_VA_BASE + 0x20) /* AC-Link Slot Valid Register */
- +#define SSP_REG_REV ( SSP_FTSSP010_VA_BASE + 0x40) /* SSP Revision Register */
- +#define SSP_REG_FEA ( SSP_FTSSP010_VA_BASE + 0x44) /* SSP Feature Register */
- +#endif
- +#define SSP_REG_CR0 0x00 /* SSP Control Register 0 */
- +#define SSP_REG_CR1 0x04 /* SSP Control Register 1 */
- +#define SSP_REG_CR2 0x08 /* SSP Control Register 2 */
- +#define SSP_REG_SR 0x0C /* SSP Status Register */
- +#define SSP_REG_ICR 0x10 /* SSP Interrupt Control Register */
- +#define SSP_REG_ISR 0x14 /* SSP Interrupt Status Register */
- +#define SSP_REG_DR 0x18 /* SSP Data Register */
- +#define SSP_REG_ACL 0x20 /* AC-Link Slot Valid Register */
- +#define SSP_REG_REV 0x60 /* SSP Revision Register */
- +#define SSP_REG_FEA 0x64 /* SSP Feature Register */
- +
- +#define SSP_CR0_offFFMT 12 /* Frame Format */
- +#define SSP_CR0_offFSDIST 8 /* Frame/Sync and Data Distance */
- +#define SSP_CR0_offLBM 7 /* Loopback Mode */
- +#define SSP_CR0_offLSB 6 /* Bit Sequence Indicator */
- +#define SSP_CR0_offFSPO 5 /* Frame/Sync Polarity */
- +#define SSP_CR0_offFSJSFY 4 /* Data Justify */
- +#define SSP_CR0_offOPM 2 /* Operation Mode */
- +#define SSP_CR0_offSCLKPO 1 /* SCLK Polarity */
- +#define SSP_CR0_offSCLKPH 0 /* SCLK Phase */
- +
- +#define SSP_CR0_mskFFMT ( 0x07UL << SSP_CR0_offFFMT)
- +#define SSP_CR0_mskFSDIST ( 0x03UL << SSP_CR0_offFSDIST)
- +#define SSP_CR0_mskLBM ( 0x01UL << SSP_CR0_offLBM)
- +#define SSP_CR0_mskLSB ( 0x01UL << SSP_CR0_offLSB)
- +#define SSP_CR0_mskFSPO ( 0x01UL << SSP_CR0_offFSPO)
- +#define SSP_CR0_mskFSJSFY ( 0x01UL << SSP_CR0_offFSJSFY)
- +#define SSP_CR0_mskOPM ( 0x03UL << SSP_CR0_offOPM)
- +#define SSP_CR0_mskSCLKPO ( 0x01UL << SSP_CR0_offSCLKPO)
- +#define SSP_CR0_mskSCLKPH ( 0x01UL << SSP_CR0_offSCLKPH)
- +
- +#define SSP_CR1_offPDL 24 /* Padding Data Length */
- +#define SSP_CR1_offSDL 16 /* Serial Data Length */
- +#define SSP_CR1_offSCLKDIV 0 /* SCLK Divider */
- +
- +#define SSP_CR1_mskPDL ( 0xFFUL << SSP_CR1_offPDL)
- +#define SSP_CR1_mskSDL ( 0x1FUL << SSP_CR1_offSDL)
- +#define SSP_CR1_mskSCLKDIV ( 0xFFUL << SSP_CR1_offSCLKDIV)
- +
- +#define SSP_CR2_offSSPRST 6 /* SSP Reset */
- +#define SSP_CR2_offACCRST 5 /* AC-Link Cold Reset Enable */
- +#define SSP_CR2_offACWRST 4 /* AC-Link Warm Reset Enable */
- +#define SSP_CR2_offTXFCLR 3 /* Transmit FIFO Clear */
- +#define SSP_CR2_offRXFCLR 2 /* Recieve FIFO clear */
- +#define SSP_CR2_offTXDOE 1 /* Transmit Data Output Enable */
- +#define SSP_CR2_offSSPEN 0 /* The SSP Enable */
- +
- +#define SSP_CR2_mskSSPRST ( 0x01UL << SSP_CR2_offSSPRST)
- +#define SSP_CR2_mskACCRST ( 0x01UL << SSP_CR2_offACCRST)
- +#define SSP_CR2_mskACWRST ( 0x01UL << SSP_CR2_offACWRST)
- +#define SSP_CR2_mskTXFCLR ( 0x01UL << SSP_CR2_offTXFCLR)
- +#define SSP_CR2_mskRXFCLR ( 0x01UL << SSP_CR2_offRXFCLR)
- +#define SSP_CR2_mskTXDOE ( 0x01UL << SSP_CR2_offTXDOE)
- +#define SSP_CR2_mskSSPEN ( 0x01UL << SSP_CR2_offSSPEN)
- +
- +#define SSP_SR_offTFVE 12 /* Transmit FIFO Valid Entries */
- +#define SSP_SR_offRFVE 4 /* Recieve FIFO Valid Entries */
- +#define SSP_SR_offBUSY 2 /* Busy Indicator */
- +#define SSP_SR_offTFNF 1 /* Transmit FIFO not full */
- +#define SSP_SR_offRFF 0 /* Recieve FIFO full */
- +
- +#define SSP_SR_mskTFVE ( 0x1FUL << SSP_SR_offTFVE)
- +#define SSP_SR_mskRFVE ( 0x1FUL << SSP_SR_offRFVE)
- +#define SSP_SR_mskBUSY ( 0x01UL << SSP_SR_offBUSY)
- +#define SSP_SR_mskTFNF ( 0x01UL << SSP_SR_offTFNF)
- +#define SSP_SR_mskRFF ( 0x01UL << SSP_SR_offRFF)
- +
- +#define SSP_ICR_offTFTHOD 12 /* Transmit FIFO Threshold */
- +#define SSP_ICR_offRFTHOD 8 /* Recieve FIFO Threshold */
- +#define SSP_ICR_offAC97FCEN 6 /* AC97 Frame Complete */
- +#define SSP_ICR_offTFDMAEN 5 /* Transmit DMA Request Enable */
- +#define SSP_ICR_offRFDMAEN 4 /* Recieve DMA Request Enable */
- +#define SSP_ICR_offTFTHIEN 3 /* Transmit FIFO Threshold Interrupt */
- +#define SSP_ICR_offRFTHIEN 2 /* Recieve FIFO Threshold Interrupt */
- +#define SSP_ICR_offTFURIEN 1 /* Transmit FIFO Underrun Interrupt Enable */
- +#define SSP_ICR_offRFORIEN 0 /* Recieve FIFO Overrun Interrupt Enable */
- +
- +#define SSP_ICR_mskTFTHOD ( 0x0FUL << SSP_ICR_offTFTHOD)
- +#define SSP_ICR_mskRFTHOD ( 0x0FUL << SSP_ICR_offRFTHOD)
- +#define SSP_ICR_mskAC97FCEN ( 0x01UL << SSP_ICR_offAC97FCEN)
- +#define SSP_ICR_mskTFDMAEN ( 0x01UL << SSP_ICR_offTFDMAEN)
- +#define SSP_ICR_mskRFDMAEN ( 0x01UL << SSP_ICR_offRFDMAEN)
- +#define SSP_ICR_mskTFTHIEN ( 0x01UL << SSP_ICR_offTFTHIEN)
- +#define SSP_ICR_mskRFTHIEN ( 0x01UL << SSP_ICR_offRFTHIEN)
- +#define SSP_ICR_mskTFURIEN ( 0x01UL << SSP_ICR_offTFURIEN)
- +#define SSP_ICR_mskRFORIEN ( 0x01UL << SSP_ICR_offRFORIEN)
- +
- +#define SSP_ISR_offAC97FCI 4 /* AC97 Frame Complete Interrupt */
- +#define SSP_ISR_offTFTHI 3 /* Transmit FIFO Threshold Interrupt */
- +#define SSP_ISR_offRFTHI 2 /* Recieve FIFO Threshold Interrupt */
- +#define SSP_ISR_offTFURI 1 /* Transmit FIFO underrun Interrupt */
- +#define SSP_ISR_offRFORI 0 /* Recieve FIFO Overun Interrupt */
- +
- +#define SSP_ISR_mskAC97FCI ( 0x01UL << SSP_ISR_offAC97FCI)
- +#define SSP_ISR_mskTFTHI ( 0x01UL << SSP_ISR_offTFTHI)
- +#define SSP_ISR_mskRFTHI ( 0x01UL << SSP_ISR_offRFTHI)
- +#define SSP_ISR_mskTFURI ( 0x01UL << SSP_ISR_offTFURI)
- +#define SSP_ISR_mskRFORI ( 0x01UL << SSP_ISR_offRFORI)
- +
- +#define SSP_ACL_offSLOT1V 14 /* The 1st Slot is Valid */
- +#define SSP_ACL_offSLOT2V 13 /* The 2nd Slot is Valid */
- +#define SSP_ACL_offSLOT3V 12 /* The 3th Slot is Valid */
- +#define SSP_ACL_offSLOT4V 11 /* The 4th Slot is Valid */
- +#define SSP_ACL_offSLOT5V 10 /* The 5th Slot is Valid */
- +#define SSP_ACL_offSLOT6V 9 /* The 6th Slot is Valid */
- +#define SSP_ACL_offSLOT7V 8 /* The 7th Slot is Valid */
- +#define SSP_ACL_offSLOT8V 7 /* The 8th Slot is Valid */
- +#define SSP_ACL_offSLOT9V 6 /* The 9th Slot is Valid */
- +#define SSP_ACL_offSLOT10V 5 /* The 10th Slot is Valid */
- +#define SSP_ACL_offSLOT11V 4 /* The 11th Slot is Valid */
- +#define SSP_ACL_offSLOT12V 3 /* The 12th Slot is Valid */
- +#define SSP_ACL_offCODECID 0 /* Codec ID, which will be shifted out as tag slot */
- +
- +#define SSP_ACL_mskSLOT1V ( 0x01UL << SSP_ACL_offSLOT1V)
- +#define SSP_ACL_mskSLOT2V ( 0x01UL << SSP_ACL_offSLOT2V)
- +#define SSP_ACL_mskSLOT3V ( 0x01UL << SSP_ACL_offSLOT3V)
- +#define SSP_ACL_mskSLOT4V ( 0x01UL << SSP_ACL_offSLOT4V)
- +#define SSP_ACL_mskSLOT5V ( 0x01UL << SSP_ACL_offSLOT5V)
- +#define SSP_ACL_mskSLOT6V ( 0x01UL << SSP_ACL_offSLOT6V)
- +#define SSP_ACL_mskSLOT7V ( 0x01UL << SSP_ACL_offSLOT7V)
- +#define SSP_ACL_mskSLOT8V ( 0x01UL << SSP_ACL_offSLOT8V)
- +#define SSP_ACL_mskSLOT9V ( 0x01UL << SSP_ACL_offSLOT9V)
- +#define SSP_ACL_mskSLOT10V ( 0x01UL << SSP_ACL_offSLOT10V)
- +#define SSP_ACL_mskSLOT11V ( 0x01UL << SSP_ACL_offSLOT11V)
- +#define SSP_ACL_mskSLOT12V ( 0x01UL << SSP_ACL_offSLOT12V)
- +#define SSP_ACL_mskCODECID ( 0x03UL << SSP_ACL_offCODECID)
- +
- +#define SSP_REV_offMAJOR_REV 16 /* Major Revision Number */
- +#define SSP_REV_offMINOR_REV 8 /* Minor Revision Number */
- +#define SSP_REV_offREL_REV 0 /* Release Number */
- +
- +#define SSP_REV_mskMAJOR_REV ( 0xFFUL << SSP_REV_offMAJOR_REV)
- +#define SSP_REV_mskMINOR_REV ( 0xFFUL << SSP_REV_offMINOR_REV)
- +#define SSP_REV_mskREL_REV ( 0xFFUL << SSP_REV_offREL_REV)
- +
- +#define SSP_FEA_offSSP_FCFG 27 /* The SSP Functional Configurations */
- +#define SSP_FEA_offSPIMWR_FCFG 26 /* Motorola's SPI and National Semiconductor's Microwire Configurations */
- +#define SSP_FEA_offI2S_FCFG 25 /* Philips's I2S Functional Configurations */
- +#define SSP_FEA_offAC97_FCFG 24 /* Intel's AC-Link Functional Configurations */
- +#define SSP_FEA_offTXFIFO_WIDTH 16 /* Transmit FIFO Size Configurations */
- +#define SSP_FEA_offRXFIFO_WIDTH 8 /* Recieve FIFO Size Configuration */
- +#define SSP_FEA_offFIFO_WIDTH 0 /* Transmit/Recieve FIFO Width */
- +
- +#define SSP_FEA_mskSSP_FCFG ( 0x01UL << SSP_FEA_offSSP_FCFG)
- +#define SSP_FEA_mskSPIMWR_FCFG ( 0x01UL << SSP_FEA_offSPIMWR_FCFG)
- +#define SSP_FEA_mskI2S_FCFG ( 0x01UL << SSP_FEA_offI2S_FCFG)
- +#define SSP_FEA_mskAC97_FCFG ( 0x01UL << SSP_FEA_offAC97_FCFG)
- +#define SSP_FEA_mskTXFIFO_WIDTH ( 0xFFUL << SSP_FEA_offTXFIFO_WIDTH)
- +#define SSP_FEA_mskRXFIFO_WIDTH ( 0xFFUL << SSP_FEA_offRXFIFO_WIDTH)
- +#define SSP_FEA_mskFIFO_WIDTH ( 0xFFUL << SSP_FEA_offFIFO_WIDTH)
- +
- +#endif /* SSP_FARADAY */
- diff -Nur linux-3.4.110.orig/drivers/input/touchscreen/cpe_ts/Makefile linux-3.4.110/drivers/input/touchscreen/cpe_ts/Makefile
- --- linux-3.4.110.orig/drivers/input/touchscreen/cpe_ts/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/input/touchscreen/cpe_ts/Makefile 2016-04-07 10:20:51.050085202 +0200
- @@ -0,0 +1 @@
- +obj-$(CONFIG_TOUCHSCREEN_CPE_TS) += cpe_ts.o
- diff -Nur linux-3.4.110.orig/drivers/input/touchscreen/Kconfig linux-3.4.110/drivers/input/touchscreen/Kconfig
- --- linux-3.4.110.orig/drivers/input/touchscreen/Kconfig 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/input/touchscreen/Kconfig 2016-04-07 10:20:51.050085202 +0200
- @@ -86,6 +86,26 @@
- To compile this driver as a module, choose M here: the
- module will be called ad7879-spi.
-
- +config TOUCHSCREEN_CPE_TS
- + tristate "Touchscreen Driver for AG101/XC5"
- + help
- + This driver directly accesses SPI controller to communicate with
- + the ads7846 chip.
- +
- + Once we have a SPI controller driver
- + , we can adopt to the SPI
- + framework that kernel provides.
- +
- +config TOUCHSCREEN_CPE_TS_DEJITTER
- + bool "Dejitter Detection"
- + depends on TOUCHSCREEN_CPE_TS
- + default y
- + help
- + Say Y here to enable dejitter detection in AG101/Leopard Touchscreen Driver.
- +
- + If unsure, say y.
- +
- +
- config TOUCHSCREEN_ATMEL_MXT
- tristate "Atmel mXT I2C Touchscreen"
- depends on I2C
- diff -Nur linux-3.4.110.orig/drivers/input/touchscreen/Makefile linux-3.4.110/drivers/input/touchscreen/Makefile
- --- linux-3.4.110.orig/drivers/input/touchscreen/Makefile 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/input/touchscreen/Makefile 2016-04-07 10:20:51.050085202 +0200
- @@ -69,3 +69,4 @@
- obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
- obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
- obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
- +obj-$(CONFIG_TOUCHSCREEN_CPE_TS) += cpe_ts/
- diff -Nur linux-3.4.110.orig/drivers/mmc/core/bus.c linux-3.4.110/drivers/mmc/core/bus.c
- --- linux-3.4.110.orig/drivers/mmc/core/bus.c 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/mmc/core/bus.c 2016-04-07 10:20:51.050085202 +0200
- @@ -26,7 +26,9 @@
- #include "bus.h"
-
- #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv)
- -
- +#ifdef CONFIG_MMC_TEST
- +static struct mmc_driver *mmc_test_drv;
- +#endif
- static ssize_t mmc_type_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- @@ -109,6 +111,11 @@
- struct mmc_driver *drv = to_mmc_driver(dev->driver);
- struct mmc_card *card = mmc_dev_to_card(dev);
-
- + #ifdef CONFIG_MMC_TEST
- + mmc_test_drv->probe(card);
- + printk("debug mmc_bus_probe\n");
- + #endif
- +
- return drv->probe(card);
- }
-
- @@ -200,6 +207,11 @@
- int mmc_register_driver(struct mmc_driver *drv)
- {
- drv->drv.bus = &mmc_bus_type;
- + #ifdef CONFIG_MMC_TEST
- + printk("debug defined config_mmc_test in mmc_register_driver\n");
- + if(!strcmp(drv->drv.name,"mmc_test"))
- + mmc_test_drv = drv;
- + #endif
- return driver_register(&drv->drv);
- }
-
- diff -Nur linux-3.4.110.orig/drivers/mmc/host/ftsdc010.c linux-3.4.110/drivers/mmc/host/ftsdc010.c
- --- linux-3.4.110.orig/drivers/mmc/host/ftsdc010.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/mmc/host/ftsdc010.c 2016-04-07 10:20:51.050085202 +0200
- @@ -0,0 +1,1586 @@
- +/* drivers/mmc/host/ftsdc010.c
- + * Copyright (C) 2010 Andestech
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/clk.h>
- +#include <linux/mmc/host.h>
- +#include <linux/mmc/mmc.h>
- +#include <linux/mmc/card.h>
- +#include <linux/platform_device.h>
- +#include <linux/debugfs.h>
- +#include <linux/seq_file.h>
- +#include <linux/irq.h>
- +#include <linux/interrupt.h>
- +#include <linux/delay.h>
- +#include <linux/slab.h>
- +
- +#include <asm/io.h>
- +#include <asm/spec.h>
- +#include <asm/dmad.h>
- +
- +#include "ftsdc010.h"
- +
- +#define DRIVER_NAME "ftsdc010"
- +
- +#define REG_READ(addr) readl((host->base + addr))
- +#define REG_WRITE(data, addr) writel((data), (host->base + addr))
- +
- +#define APB_CLK_IN (AHB_CLK_IN / 2)
- +
- +enum dbg_channels {
- + dbg_err = (1 << 0),
- + dbg_debug = (1 << 1),
- + dbg_info = (1 << 2),
- + dbg_irq = (1 << 3),
- + dbg_sg = (1 << 4),
- + dbg_dma = (1 << 5),
- + dbg_pio = (1 << 6),
- + dbg_fail = (1 << 7),
- + dbg_conf = (1 << 8),
- +};
- +
- +static struct workqueue_struct *mywq;
- +
- +static const int dbgmap_err = dbg_fail;
- +static const int dbgmap_info = dbg_info | dbg_conf;
- +static const int dbgmap_debug = dbg_err | dbg_debug | dbg_info | dbg_conf;
- +#if 1
- +#define dbg(host, channels, args...) \
- + do { \
- + if (dbgmap_err & channels) \
- + dev_err(&host->pdev->dev, args); \
- + else if (dbgmap_info & channels) \
- + dev_info(&host->pdev->dev, args); \
- + else if (dbgmap_debug & channels) \
- + dev_dbg(&host->pdev->dev, args); \
- + } while (0)
- +#endif
- +#if 0
- +#define dbg(host, channels, args...) \
- + do { \
- + printk(KERN_INFO "%s: ", "ftsdc");\
- + printk(args); \
- + } while(0)
- +#endif
- +
- +static void finalize_request(struct ftsdc_host *host);
- +static void ftsdc_send_request(struct mmc_host *mmc);
- +
- +#ifdef CONFIG_MMC_DEBUG
- +
- +static void dbg_dumpregs(struct ftsdc_host *host, char *prefix)
- +{
- + u32 con, cmdarg, r0, r1, r2, r3, rcmd, dcon, dtimer,
- + dlen, sta, clr, imask, pcon, ccon, bwidth, scon1,
- + scon2, ssta, fea;
- +
- + con = REG_READ(SDC_CMD_REG);
- + cmdarg = REG_READ(SDC_ARGU_REG);
- + r0 = REG_READ(SDC_RESPONSE0_REG);
- + r1 = REG_READ(SDC_RESPONSE1_REG);
- + r2 = REG_READ(SDC_RESPONSE2_REG);
- + r3 = REG_READ(SDC_RESPONSE3_REG);
- + rcmd = REG_READ(SDC_RSP_CMD_REG);
- + dcon = REG_READ(SDC_DATA_CTRL_REG);
- + dtimer = REG_READ(SDC_DATA_TIMER_REG);
- + dlen = REG_READ(SDC_DATA_LEN_REG);
- + sta = REG_READ(SDC_STATUS_REG);
- + clr = REG_READ(SDC_CLEAR_REG);
- + imask = REG_READ(SDC_INT_MASK_REG);
- + pcon = REG_READ(SDC_POWER_CTRL_REG);
- + ccon = REG_READ(SDC_CLOCK_CTRL_REG);
- + bwidth = REG_READ(SDC_BUS_WIDTH_REG);
- + scon1 = REG_READ(SDC_SDIO_CTRL1_REG);
- + scon2 = REG_READ(SDC_SDIO_CTRL2_REG);
- + ssta = REG_READ(SDC_SDIO_STATUS_REG);
- + fea = REG_READ(SDC_FEATURE_REG);
- +
- + dbg(host, dbg_debug, "%s CON:[%08x] STA:[%08x] INT:[%08x], PWR:[%08x], CLK:[%08x]\n",
- + prefix, con, sta, imask, pcon, ccon);
- +
- + dbg(host, dbg_debug, "%s DCON:[%08x] DTIME:[%08x]"
- + " DLEN:[%08x] DWIDTH:[%08x]\n",
- + prefix, dcon, dtimer, dlen, bwidth);
- +
- + dbg(host, dbg_debug, "%s R0:[%08x] R1:[%08x]"
- + " R2:[%08x] R3:[%08x]\n",
- + prefix, r0, r1, r2, r3);
- +
- + dbg(host, dbg_debug, "%s SCON1:[%08x] SCON2:[%08x]"
- + " SSTA:[%08x] FEA:[%08x]\n",
- + prefix, scon1, scon2, ssta, fea);
- +}
- +
- +static void prepare_dbgmsg(struct ftsdc_host *host, struct mmc_command *cmd,
- + int stop)
- +{
- + snprintf(host->dbgmsg_cmd, 300,
- + "#%u%s op:%i arg:0x%08x flags:0x08%x retries:%u",
- + host->ccnt, (stop ? " (STOP)" : ""),
- + cmd->opcode, cmd->arg, cmd->flags, cmd->retries);
- +
- + if (cmd->data) {
- + snprintf(host->dbgmsg_dat, 300,
- + "#%u bsize:%u blocks:%u bytes:%u",
- + host->dcnt, cmd->data->blksz,
- + cmd->data->blocks,
- + cmd->data->blocks * cmd->data->blksz);
- + } else {
- + host->dbgmsg_dat[0] = '\0';
- + }
- +}
- +
- +static void dbg_dumpcmd(struct ftsdc_host *host, struct mmc_command *cmd,
- + int fail)
- +{
- + unsigned int dbglvl = fail ? dbg_fail : dbg_debug;
- +
- + if (!cmd)
- + return;
- +
- + if (cmd->error == 0) {
- + dbg(host, dbglvl, "CMD[OK] %s R0:0x%08x\n",
- + host->dbgmsg_cmd, cmd->resp[0]);
- + } else {
- + dbg(host, dbglvl, "CMD[ERR %i] %s Status:%s\n",
- + cmd->error, host->dbgmsg_cmd, host->status);
- + }
- +
- + if (!cmd->data)
- + return;
- +
- + if (cmd->data->error == 0) {
- + dbg(host, dbglvl, "DAT[OK] %s\n", host->dbgmsg_dat);
- + } else {
- + dbg(host, dbglvl, "DAT[ERR %i] %s DCNT:0x%08x\n",
- + cmd->data->error, host->dbgmsg_dat,
- + REG_READ(SDC_DATA_LEN_REG));
- + }
- +}
- +#else
- +static void dbg_dumpcmd(struct ftsdc_host *host,
- + struct mmc_command *cmd, int fail) { }
- +
- +static void prepare_dbgmsg(struct ftsdc_host *host, struct mmc_command *cmd,
- + int stop) { }
- +
- +static void dbg_dumpregs(struct ftsdc_host *host, char *prefix) { }
- +
- +#endif /* CONFIG_MMC_DEBUG */
- +
- +static inline bool ftsdc_dmaexist(struct ftsdc_host *host)
- +{
- + return (host->dma_req != NULL);
- +}
- +
- +static inline u32 enable_imask(struct ftsdc_host *host, u32 imask)
- +{
- + u32 newmask;
- +
- +#ifdef CONFIG_MMC_DEBUG
- + if (imask & SDC_STATUS_REG_SDIO_INTR) printk("\n*** E ***\n");
- +#endif
- + newmask = REG_READ(SDC_INT_MASK_REG);
- + newmask |= imask;
- +
- + REG_WRITE(newmask, SDC_INT_MASK_REG);
- +
- + return newmask;
- +}
- +
- +static inline u32 disable_imask(struct ftsdc_host *host, u32 imask)
- +{
- + u32 newmask;
- +
- +#ifdef CONFIG_MMC_DEBUG
- + if (imask & SDC_STATUS_REG_SDIO_INTR) printk("\n*** D ***\n");
- +#endif
- + newmask = REG_READ(SDC_INT_MASK_REG);
- + newmask &= ~imask;
- +
- + REG_WRITE(newmask, SDC_INT_MASK_REG);
- +
- + return newmask;
- +}
- +
- +static inline void clear_imask(struct ftsdc_host *host)
- +{
- + u32 mask = REG_READ(SDC_INT_MASK_REG);
- +
- + /* preserve the SDIO IRQ mask state */
- + mask &= (SDC_INT_MASK_REG_SDIO_INTR | SDC_INT_MASK_REG_CARD_CHANGE);
- + REG_WRITE(mask, SDC_INT_MASK_REG);
- +}
- +
- +//static void ftsdc_check_sdio_irq(struct ftsdc_host *host)
- +//{
- +// if (host->sdio_irqen) {
- +// u32 con = REG_READ(SDC_STATUS_REG);
- +// if (con & SDC_STATUS_REG_SDIO_INTR) {
- +// printk(KERN_DEBUG "%s: signalling irq\n", __func__);
- +// mmc_signal_sdio_irq(host->mmc);
- +// }
- +// }
- +//}
- +
- +static inline void get_data_buffer(struct ftsdc_host *host)
- +{
- + struct scatterlist *sg;
- +
- + BUG_ON(host->buf_sgptr >= host->mrq->data->sg_len);
- +
- + sg = &host->mrq->data->sg[host->buf_sgptr];
- +
- + host->buf_bytes = sg->length;
- + host->buf_ptr = host->dodma ? (u32 *)sg->dma_address : sg_virt(sg);
- + host->buf_sgptr++;
- +}
- +
- +static inline u32 cal_blksz(unsigned int blksz)
- +{
- + u32 blksztwo = 0;
- +
- + while (blksz >>= 1)
- + blksztwo++;
- +
- + return blksztwo;
- +}
- +
- +/**
- + * ftsdc_enable_irq - enable IRQ, after having disabled it.
- + * @host: The device state.
- + * @more: True if more IRQs are expected from transfer.
- + *
- + * Enable the main IRQ if needed after it has been disabled.
- + *
- + * The IRQ can be one of the following states:
- + * - enable after data read/write
- + * - disable when handle data read/write
- + */
- +static void ftsdc_enable_irq(struct ftsdc_host *host, bool enable)
- +{
- + unsigned long flags;
- + local_irq_save(flags);
- +
- + host->irq_enabled = enable;
- +
- + if (enable)
- + enable_irq(host->irq);
- + else
- + disable_irq(host->irq);
- +
- + local_irq_restore(flags);
- +}
- +
- +static void do_pio_read(struct ftsdc_host *host)
- +{
- + u32 fifo;
- + u32 fifo_words;
- + u32 *ptr;
- + u32 status;
- + u32 retry = 0;
- +
- +
- + BUG_ON(host->buf_bytes != 0);
- +
- + while (host->buf_sgptr < host->mrq->data->sg_len) {
- + get_data_buffer(host);
- +
- + dbg(host, dbg_pio,
- + "pio_read(): new target: [%i]@[%p]\n",
- + host->buf_bytes, host->buf_ptr);
- +
- + while (host->buf_bytes) {
- + status = REG_READ(SDC_STATUS_REG);
- +
- + if (status & SDC_STATUS_REG_FIFO_OVERRUN) {
- + fifo = host->fifo_len > host->buf_bytes ?
- + host->buf_bytes : host->fifo_len;
- +
- +#if 1
- + dbg(host, dbg_pio,
- + "pio_read(): fifo:[%02i] buffer:[%03i] dcnt:[%08X]\n",
- + fifo, host->buf_bytes,
- + REG_READ(SDC_DATA_LEN_REG));
- +#endif
- +
- + host->buf_bytes -= fifo;
- + host->buf_count += fifo;
- +
- + fifo_words = fifo >> 2;
- + ptr = host->buf_ptr;
- + while (fifo_words--)
- + *ptr++ = REG_READ(SDC_DATA_WINDOW_REG);
- +
- + host->buf_ptr = ptr;
- + //ADD by river 2010.10.26 for adding some delays for SD card to put data into FIFO again
- + //mdelay(1);
- + udelay(800);
- + //End ADD by river 2010.10.26 for adding some delays for SD card to put data into FIFO again
- +
- + /* sdio allow non-power-of-2 blksz */
- + if (fifo & 3) {
- + u32 n = fifo & 3;
- + u32 data = REG_READ(SDC_DATA_WINDOW_REG);
- + u8 *p = (u8 *)host->buf_ptr;
- +
- + while (n--) {
- + *p++ = data;
- + data >>= 8;
- + }
- + }
- + } else {
- + udelay(1);
- + if (++retry >= SDC_PIO_RETRY) {
- + host->mrq->data->error = -EIO;
- + goto err;
- + }
- + }
- + }
- + }
- +
- +err:
- +
- + host->buf_active = XFER_NONE;
- + host->complete_what = COMPLETION_FINALIZE;
- +}
- +
- +static void do_pio_write(struct ftsdc_host *host)
- +{
- + u32 fifo;
- + u32 *ptr;
- + u32 status;
- + u32 retry = 0;
- +
- + BUG_ON(host->buf_bytes != 0);
- +
- + while (host->buf_sgptr < host->mrq->data->sg_len) {
- + get_data_buffer(host);
- +
- + dbg(host, dbg_pio,
- + "pio_write(): new source: [%i]@[%p]\n",
- + host->buf_bytes, host->buf_ptr);
- +
- + while (host->buf_bytes) {
- + status = REG_READ(SDC_STATUS_REG);
- + if (status & SDC_STATUS_REG_FIFO_UNDERRUN) {
- + fifo = host->fifo_len > host->buf_bytes ?
- + host->buf_bytes : host->fifo_len;
- +
- + dbg(host, dbg_pio,
- + "pio_write(): fifo:[%02i] buffer:[%03i] dcnt:[%08X]\n",
- + fifo, host->buf_bytes,
- + REG_READ(SDC_DATA_LEN_REG));
- +
- + host->buf_bytes -= fifo;
- + host->buf_count += fifo;
- +
- + fifo = (fifo + 3) >> 2;
- + ptr = host->buf_ptr;
- + while (fifo--) {
- + REG_WRITE(*ptr, SDC_DATA_WINDOW_REG);
- + ptr++;
- + }
- + host->buf_ptr = ptr;
- + } else {
- + udelay(1);
- + if (++retry >= SDC_PIO_RETRY) {
- + host->mrq->data->error = -EIO;
- + goto err;
- + }
- + }
- + }
- + }
- +
- +err:
- + host->buf_active = XFER_NONE;
- + host->complete_what = COMPLETION_FINALIZE;
- +}
- +
- +static void do_dma_access(struct ftsdc_host *host)
- +{
- + int res;
- + unsigned long timeout;
- + dmad_chreq *req = host->dma_req;
- + dmad_drb *drb = 0;
- +
- + while (host->buf_sgptr < host->mrq->data->sg_len) {
- +
- + INIT_COMPLETION(host->dma_complete);
- + get_data_buffer(host);
- +
- + dbg(host, dbg_dma,
- + "dma_%s(): new target: [%i]@[%p]\n",
- + host->buf_active == XFER_READ ? "read" : "write",
- + host->buf_bytes, host->buf_ptr);
- +
- + res = dmad_alloc_drb(req, &drb);
- + if (res != 0 || (drb == 0)) {
- + dbg(host, dbg_err, "%s() Failed to allocate dma request block!\n", __func__);
- + host->mrq->data->error = -ENODEV;
- + goto err;
- + }
- +
- + drb->addr0 = SDC_FTSDC010_0_PA_BASE + SDC_DATA_WINDOW_REG;
- + drb->addr1 = (dma_addr_t)host->buf_ptr;
- + drb->req_cycle = dmad_bytes_to_cycles(req, host->buf_bytes);
- + drb->sync = &host->dma_complete;
- +
- + timeout = SDC_TIMEOUT_BASE*((host->buf_bytes+511)>>9);
- +
- + res = dmad_submit_request(req, drb, 1);
- + if (res != 0) {
- + dbg(host, dbg_err, "%s() Failed to submit dma request block!\n", __func__);
- + host->mrq->data->error = -ENODEV;
- + goto err;
- + }
- +
- + dbg(host, dbg_err, "reach here!\n");
- + if (wait_for_completion_timeout(&host->dma_complete, timeout) == 0) {
- + dbg(host, dbg_err, "%s: read timeout\n", __func__);
- + host->mrq->data->error = -ETIMEDOUT;
- + goto err;
- + }
- + }
- +
- + host->dma_finish = true;
- +err:
- + host->buf_active = XFER_NONE;
- + host->complete_what = COMPLETION_FINALIZE;
- +}
- +
- +static void ftsdc_work(struct work_struct *work)
- +{
- + struct ftsdc_host *host =
- + container_of(work, struct ftsdc_host, work);
- +
- + ftsdc_enable_irq(host, false);
- +
- + if (host->dodma) {
- + do_dma_access(host);
- + } else {
- + if (host->buf_active == XFER_WRITE)
- + do_pio_write(host);
- +
- + if (host->buf_active == XFER_READ)
- + do_pio_read(host);
- + }
- +
- + tasklet_schedule(&host->pio_tasklet);
- + ftsdc_enable_irq(host, true);
- +}
- +
- +
- +static void pio_tasklet(unsigned long data)
- +{
- + struct ftsdc_host *host = (struct ftsdc_host *) data;
- +
- + if (host->complete_what == COMPLETION_XFER_PROGRESS) {
- + queue_work(mywq, (struct work_struct *)&host->work);
- + return;
- + }
- +
- + if (host->complete_what == COMPLETION_FINALIZE) {
- + clear_imask(host);
- + if (host->buf_active != XFER_NONE) {
- + dbg(host, dbg_err, "unfinished %s "
- + "- buf_count:[%u] buf_bytes:[%u]\n",
- + (host->buf_active == XFER_READ) ? "read" : "write",
- + host->buf_count, host->buf_bytes);
- +
- + if (host->mrq->data)
- + host->mrq->data->error = -EINVAL;
- + }
- +
- + finalize_request(host);
- + }
- +}
- +
- +
- +static void finalize_request(struct ftsdc_host *host)
- +{
- + struct mmc_request *mrq = host->mrq;
- + struct mmc_command *cmd;
- + u32 con;
- + int debug_as_failure = 0;
- +
- + if (host->complete_what != COMPLETION_FINALIZE)
- + return;
- +
- + if (!mrq)
- + return;
- +
- + cmd = host->cmd_is_stop ? mrq->stop : mrq->cmd;
- +
- + if (cmd->data && (cmd->error == 0) &&
- + (cmd->data->error == 0)) {
- + if (host->dodma && (!host->dma_finish)) {
- + dbg(host, dbg_dma, "DMA Missing (%d)!\n",
- + host->dma_finish);
- + return;
- + }
- + host->dodma = false;
- + }
- +
- + /* Read response from controller. */
- + if (cmd->flags & MMC_RSP_136) {
- + cmd->resp[3] = REG_READ(SDC_RESPONSE0_REG);
- + cmd->resp[2] = REG_READ(SDC_RESPONSE1_REG);
- + cmd->resp[1] = REG_READ(SDC_RESPONSE2_REG);
- + cmd->resp[0] = REG_READ(SDC_RESPONSE3_REG);
- + } else if (cmd->flags & MMC_RSP_PRESENT) {
- + cmd->resp[0] = REG_READ(SDC_RESPONSE0_REG);
- + }
- +
- + if (cmd->error)
- + debug_as_failure = 1;
- +
- + if (cmd->data && cmd->data->error)
- + debug_as_failure = 1;
- +
- + dbg_dumpcmd(host, cmd, debug_as_failure);
- +
- + clear_imask(host);
- + con = REG_READ(SDC_STATUS_REG);
- + con &= ~SDC_CLEAR_REG_SDIO_INTR;
- + REG_WRITE(con, SDC_CLEAR_REG);
- +
- + if (cmd->data && cmd->error)
- + cmd->data->error = cmd->error;
- +
- + if (cmd->data && cmd->data->stop && (!host->cmd_is_stop)) {
- + host->cmd_is_stop = 1;
- + ftsdc_send_request(host->mmc);
- + return;
- + }
- +
- + /* If we have no data transfer we are finished here */
- + if (!mrq->data)
- + goto request_done;
- +
- + /* Calulate the amout of bytes transfer if there was no error */
- + if (mrq->data->error == 0) {
- + mrq->data->bytes_xfered =
- + (mrq->data->blocks * mrq->data->blksz);
- + } else {
- + mrq->data->bytes_xfered = 0;
- + }
- +
- +request_done:
- + host->complete_what = COMPLETION_NONE;
- + host->mrq = NULL;
- +
- + host->last_opcode = mrq->cmd->opcode;
- + mmc_request_done(host->mmc, mrq);
- +}
- +
- +static void ftsdc_send_command(struct ftsdc_host *host,
- + struct mmc_command *cmd)
- +{
- + u32 ccon = 0;
- + u32 newmask = 0;
- + u32 scon;
- +
- + if (cmd->data) {
- + host->complete_what = COMPLETION_XFER_PROGRESS;
- + newmask |= SDC_INT_MASK_REG_RSP_TIMEOUT;
- + } else if (cmd->flags & MMC_RSP_PRESENT) {
- + host->complete_what = COMPLETION_RSPFIN;
- + newmask |= SDC_INT_MASK_REG_RSP_TIMEOUT;
- + } else {
- + host->complete_what = COMPLETION_CMDSENT;
- + newmask |= SDC_INT_MASK_REG_CMD_SEND;
- + }
- +
- + ccon |= cmd->opcode & SDC_CMD_REG_INDEX;
- + ccon |= SDC_CMD_REG_CMD_EN;
- +
- + if (cmd->flags & MMC_RSP_PRESENT) {
- + ccon |= SDC_CMD_REG_NEED_RSP;
- + newmask |= SDC_INT_MASK_REG_RSP_CRC_OK |
- + SDC_INT_MASK_REG_RSP_CRC_FAIL;
- + }
- +
- + if (cmd->flags & MMC_RSP_136)
- + ccon |= SDC_CMD_REG_LONG_RSP;
- +
- + /* applicatiion specific cmd must follow an MMC_APP_CMD. The
- + * value will be updated in finalize_request function */
- + if (host->last_opcode == MMC_APP_CMD)
- + ccon |= SDC_CMD_REG_APP_CMD;
- +
- + enable_imask(host, newmask);
- + REG_WRITE(cmd->arg, SDC_ARGU_REG);
- +
- + scon = REG_READ(SDC_SDIO_CTRL1_REG);
- + if (host->mmc->card != NULL && mmc_card_sdio(host->mmc->card))
- + scon |= SDC_SDIO_CTRL1_REG_SDIO_ENABLE;
- + else
- + scon &= ~SDC_SDIO_CTRL1_REG_SDIO_ENABLE;
- + REG_WRITE(scon, SDC_SDIO_CTRL1_REG);
- +
- + dbg_dumpregs(host, "");
- + dbg(host, dbg_debug, "CON[%x]\n", ccon);
- +
- + REG_WRITE(ccon, SDC_CMD_REG);
- +}
- +
- +static int ftsdc_setup_data(struct ftsdc_host *host, struct mmc_data *data)
- +{
- + u32 dcon, newmask = 0;
- +
- + /* configure data transfer paramter */
- +
- + if (!data)
- + return 0;
- + if(host->mmc->card && host->mmc->card->type==(unsigned int)MMC_TYPE_SD){
- + if (((data->blksz - 1) & data->blksz) != 0) {
- + pr_warning("%s: can't do non-power-of 2 sized block transfers (blksz %d)\n", __func__, data->blksz);
- + return -EINVAL;
- + }
- + }
- +
- + if (data->blksz <= 2) {
- + /* We cannot deal with unaligned blocks with more than
- + * one block being transfered. */
- +
- + if (data->blocks > 1) {
- + pr_warning("%s: can't do non-word sized block transfers (blksz %d)\n", __func__, data->blksz);
- + return -EINVAL;
- + }
- + }
- +
- + /* data length */
- + dcon = data->blksz * data->blocks;
- + REG_WRITE(dcon, SDC_DATA_LEN_REG);
- +
- + /* write data control */
- + dcon = 0;
- + dcon = cal_blksz(data->blksz);
- +
- + /* enable UNDERFUN will trigger interrupt immediatedly
- + * So setup it when rsp is received successfully
- + */
- + if (data->flags & MMC_DATA_WRITE) {
- + dcon |= SDC_DATA_CTRL_REG_DATA_WRITE;
- + } else {
- + dcon &= ~SDC_DATA_CTRL_REG_DATA_WRITE;
- + newmask |= SDC_INT_MASK_REG_FIFO_OVERRUN;
- + }
- +
- + /* always reset fifo since last transfer may fail */
- + dcon |= SDC_DATA_CTRL_REG_FIFO_RST;
- +
- + /* enable data transfer which will be pended until cmd is send */
- + dcon |= SDC_DATA_CTRL_REG_DATA_EN;
- +
- + if (ftsdc_dmaexist(host) &&
- + ((data->blksz * data->blocks) & 0xf) == 0) {
- + newmask &= ~SDC_INT_MASK_REG_FIFO_OVERRUN;
- + dcon |= SDC_DATA_CTRL_REG_DMA_EN;
- + dcon |= SDC_DMA_TYPE_4;
- + host->dodma = true;
- +
- + }
- +
- + REG_WRITE(dcon, SDC_DATA_CTRL_REG);
- +
- + /* add to IMASK register */
- + newmask |= SDC_INT_MASK_REG_DATA_CRC_FAIL |
- + SDC_INT_MASK_REG_DATA_TIMEOUT;
- +
- + enable_imask(host, newmask);
- +
- + /* handle sdio */
- + dcon = SDC_SDIO_CTRL1_REG_READ_WAIT_ENABLE & REG_READ(SDC_SDIO_CTRL1_REG);
- + dcon |= data->blksz | data->blocks << 15;
- + if (1 < data->blocks)
- + dcon |= SDC_SDIO_CTRL1_REG_SDIO_BLK_MODE;
- + REG_WRITE(dcon, SDC_SDIO_CTRL1_REG);
- +
- + return 0;
- +}
- +
- +#define BOTH_DIR (MMC_DATA_WRITE | MMC_DATA_READ)
- +
- +static int ftsdc_prepare_buffer(struct ftsdc_host *host, struct mmc_data *data)
- +{
- + int rw = (data->flags & MMC_DATA_WRITE) ? 1 : 0;
- +
- + if ((!host->mrq) || (!host->mrq->data))
- + return -EINVAL;
- +
- + BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
- +
- + host->buf_sgptr = 0;
- + host->buf_bytes = 0;
- + host->buf_count = 0;
- + host->buf_active = rw ? XFER_WRITE : XFER_READ;
- +
- + if (host->dodma) {
- + u32 dma_len;
- + u32 drb_size;
- + dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
- + rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- + if (dma_len == 0)
- + return -ENOMEM;
- +
- +
- + dmad_config_channel_dir(host->dma_req,
- + rw ? DMAD_DIR_A1_TO_A0 : DMAD_DIR_A0_TO_A1);
- +
- + drb_size = dmad_max_size_per_drb(host->dma_req);
- + if (drb_size < (data->blksz & data->blocks))
- + return -ENODEV;
- +
- + host->dma_finish = false;
- + }
- +
- + return 0;
- +}
- +
- +static irqreturn_t ftsdc_irq(int irq, void *dev_id)
- +{
- + struct ftsdc_host *host = dev_id;
- + struct mmc_command *cmd;
- + u32 mci_status;
- + u32 mci_clear;
- + u32 mci_imsk;
- + unsigned long iflags;
- +
- + mci_status = REG_READ(SDC_STATUS_REG);
- + mci_imsk = REG_READ(SDC_INT_MASK_REG);
- +
- + dbg(host, dbg_debug, "irq: status:0x%08x, mask : %08x\n", mci_status, mci_imsk);
- +
- + if (mci_status & SDC_STATUS_REG_SDIO_INTR) {
- + if (mci_imsk & SDC_INT_MASK_REG_SDIO_INTR) {
- + mci_clear = SDC_CLEAR_REG_SDIO_INTR;
- + REG_WRITE(mci_clear, SDC_CLEAR_REG);
- +
- + mmc_signal_sdio_irq(host->mmc);
- + return IRQ_HANDLED;
- + }
- + }
- +
- + spin_lock_irqsave(&host->complete_lock, iflags);
- +
- + mci_status = REG_READ(SDC_STATUS_REG);
- + mci_clear = 0;
- +
- + if (mci_status & SDC_STATUS_REG_CARD_CHANGE) {
- + if ((mci_status & SDC_STATUS_REG_CARD_DETECT)
- + == SDC_CARD_INSERT) {
- + host->status = "card insert";
- + mmc_detect_change(host->mmc, msecs_to_jiffies(500));
- + } else {
- + host->status = "card remove";
- + }
- +
- + mci_clear |= SDC_CLEAR_REG_CARD_CHANGE;
- + dbg(host, dbg_irq, "%s\n", host->status);
- +
- + if (host->complete_what != COMPLETION_NONE) {
- + host->mrq->cmd->error = -EIO;
- + goto close_transfer;
- + }
- +
- + goto irq_out;
- + }
- +
- + if ((host->complete_what == COMPLETION_NONE) ||
- + (host->complete_what == COMPLETION_FINALIZE)) {
- + host->status = "nothing to complete";
- + mci_clear = -1u;
- + goto irq_out;
- + }
- +
- + if (!host->mrq) {
- + host->status = "no active mrq";
- + clear_imask(host);
- + goto irq_out;
- + }
- +
- + cmd = host->cmd_is_stop ? host->mrq->stop : host->mrq->cmd;
- +
- + if (!cmd) {
- + host->status = "no active cmd";
- + clear_imask(host);
- + goto irq_out;
- + }
- +
- + if (mci_status & SDC_STATUS_REG_CMD_SEND) {
- + mci_clear |= SDC_CLEAR_REG_CMD_SEND;
- +
- + if (host->complete_what == COMPLETION_CMDSENT) {
- + host->status = "ok: command sent";
- + goto close_transfer;
- + } else {
- + host->status = "error: command sent(status not match)";
- + cmd->error = -EINVAL;
- + goto fail_transfer;
- + }
- + }
- +
- + /* handle error status */
- + if (mci_status & SDC_STATUS_REG_RSP_TIMEOUT) {
- + dbg(host, dbg_err, "CMDSTAT: error RSP TIMEOUT\n");
- + mci_clear |= SDC_CLEAR_REG_RSP_TIMEOUT;
- + cmd->error = -ETIMEDOUT;
- + host->status = "error: response timeout";
- + goto fail_transfer;
- + }
- +
- + if (mci_status & SDC_STATUS_REG_RSP_CRC_FAIL) {
- + mci_clear |= SDC_CLEAR_REG_RSP_CRC_FAIL;
- + /* This is wierd hack */
- + if (cmd->flags & MMC_RSP_CRC) {
- + dbg(host, dbg_err, "CMDSTAT: error RSP CRC\n");
- + cmd->error = -EILSEQ;
- + host->status = "error: RSP CRC failed";
- + goto fail_transfer;
- + } else {
- + host->status = "R3 or R4 type command";
- + goto close_transfer;
- + }
- + }
- +
- + if (mci_status & SDC_STATUS_REG_RSP_CRC_OK) {
- + mci_clear |= SDC_CLEAR_REG_RSP_CRC_OK;
- +
- + if (host->complete_what == COMPLETION_XFER_PROGRESS) {
- + REG_WRITE(mci_clear, SDC_CLEAR_REG);
- +
- + host->status = "RSP recv OK";
- + if (!cmd->data)
- + goto close_transfer;
- +
- + if (host->dodma) {
- + tasklet_schedule(&host->pio_tasklet);
- + host->status = "dma access";
- + goto irq_out;
- + }
- +
- + if (host->buf_active == XFER_WRITE)
- + enable_imask(host, SDC_INT_MASK_REG_FIFO_UNDERRUN);
- + } else if (host->complete_what == COMPLETION_RSPFIN) {
- + goto close_transfer;
- + }
- + }
- +
- + /* handler data transfer */
- + if (mci_status & SDC_STATUS_REG_DATA_TIMEOUT) {
- + dbg(host, dbg_err, "CMDSTAT: error DATA TIMEOUT\n");
- + mci_clear |= SDC_CLEAR_REG_DATA_TIMEOUT;
- + cmd->error = -ETIMEDOUT;
- + host->status = "error: data timeout";
- + goto fail_transfer;
- + }
- +
- + if (mci_status & SDC_STATUS_REG_DATA_CRC_FAIL) {
- + dbg(host, dbg_err, "CMDSTAT: error DATA CRC\n");
- + mci_clear |= SDC_CLEAR_REG_DATA_CRC_FAIL;
- + cmd->error = -EILSEQ;
- + host->status = "error: data CRC fail";
- + goto fail_transfer;
- + }
- +
- + if ((mci_status & SDC_STATUS_REG_FIFO_UNDERRUN) ||
- + mci_status & SDC_STATUS_REG_FIFO_OVERRUN) {
- +
- + disable_imask(host, SDC_INT_MASK_REG_FIFO_OVERRUN |
- + SDC_INT_MASK_REG_FIFO_UNDERRUN);
- +
- + if (!host->dodma) {
- + if (host->buf_active == XFER_WRITE) {
- + tasklet_schedule(&host->pio_tasklet);
- + host->status = "pio tx";
- + } else if (host->buf_active == XFER_READ) {
- +
- + tasklet_schedule(&host->pio_tasklet);
- + host->status = "pio rx";
- + }
- + }
- + }
- +
- + goto irq_out;
- +
- +fail_transfer:
- + host->buf_active = XFER_NONE;
- +
- +close_transfer:
- + host->complete_what = COMPLETION_FINALIZE;
- +
- + clear_imask(host);
- + tasklet_schedule(&host->pio_tasklet);
- +
- +irq_out:
- + REG_WRITE(mci_clear, SDC_CLEAR_REG);
- +
- + dbg(host, dbg_debug, "irq: %s\n", host->status);
- + spin_unlock_irqrestore(&host->complete_lock, iflags);
- + return IRQ_HANDLED;
- +}
- +
- +static void ftsdc_send_request(struct mmc_host *mmc)
- +{
- + struct ftsdc_host *host = mmc_priv(mmc);
- + struct mmc_request *mrq = host->mrq;
- + struct mmc_command *cmd = host->cmd_is_stop ? mrq->stop : mrq->cmd;
- +
- + host->ccnt++;
- + prepare_dbgmsg(host, cmd, host->cmd_is_stop);
- + dbg(host, dbg_debug, "%s\n", host->dbgmsg_cmd);
- +
- + if (cmd->data) {
- + int res = ftsdc_setup_data(host, cmd->data);
- +
- + host->dcnt++;
- +
- + if (res) {
- + dbg(host, dbg_err, "setup data error %d\n", res);
- + cmd->error = res;
- + cmd->data->error = res;
- +
- + mmc_request_done(mmc, mrq);
- + return;
- + }
- +
- + res = ftsdc_prepare_buffer(host, cmd->data);
- +
- + if (res) {
- + dbg(host, dbg_err, "data prepare error %d\n", res);
- + cmd->error = res;
- + cmd->data->error = res;
- +
- + mmc_request_done(mmc, mrq);
- + return;
- + }
- + }
- +
- + /* Send command */
- + ftsdc_send_command(host, cmd);
- +}
- +
- +static int ftsdc_get_cd(struct mmc_host *mmc)
- +{
- + struct ftsdc_host *host = mmc_priv(mmc);
- +
- + u32 con = REG_READ(SDC_STATUS_REG);
- + dbg(host, dbg_debug, "get_cd status:%.8x\n\n", con);
- +
- + return (con & SDC_STATUS_REG_CARD_DETECT) ? 0 : 1;
- +}
- +
- +static void ftsdc_request(struct mmc_host *mmc, struct mmc_request *mrq)
- +{
- + struct ftsdc_host *host = mmc_priv(mmc);
- +
- +/* work_around_for_amerald(mrq);*/
- + host->status = "mmc request";
- + host->cmd_is_stop = 0;
- + host->mrq = mrq;
- + if (ftsdc_get_cd(mmc) == 0) {
- + dbg(host, dbg_err, "%s: no medium present\n", __func__);
- + host->mrq->cmd->error = -ENOMEDIUM;
- + mmc_request_done(mmc, mrq);
- + } else {
- + ftsdc_send_request(mmc);
- + }
- +
- + dbg(host, dbg_debug, "send request \n");
- +}
- +
- +static void ftsdc_set_clk(struct ftsdc_host *host, struct mmc_ios *ios)
- +{
- + u32 clk_div = 0;
- + u32 con;
- +
- + dbg(host, dbg_debug, "request clk : %u \n", ios->clock);
- + con = REG_READ(SDC_CLOCK_CTRL_REG);
- + if (ios->clock == 0) {
- + host->real_rate = 0;
- + con |= SDC_CLOCK_CTRL_REG_CLK_DIS;
- + } else {
- + clk_div = (APB_CLK_IN / (ios->clock << 1)) - 1;
- + host->real_rate = APB_CLK_IN / ((clk_div+1)<<1);
- + if (host->real_rate > ios->clock) {
- + ++clk_div;
- + host->real_rate = APB_CLK_IN / ((clk_div+1)<<1);
- + }
- + if (clk_div > 127)
- + dbg(host, dbg_err, "%s: no match clock rate, %u\n", __func__, ios->clock);
- +
- + con = (con & ~SDC_CLOCK_CTRL_REG_CLK_DIV) | (clk_div & SDC_CLOCK_CTRL_REG_CLK_DIV);
- + con &= ~SDC_CLOCK_CTRL_REG_CLK_DIS;
- + }
- +
- + REG_WRITE(con, SDC_CLOCK_CTRL_REG);
- +}
- +
- +static void ftsdc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
- +{
- + struct ftsdc_host *host = mmc_priv(mmc);
- + u32 con;
- +
- + con = REG_READ(SDC_POWER_CTRL_REG);
- + switch (ios->power_mode) {
- + case MMC_POWER_ON:
- + case MMC_POWER_UP:
- + con |= SDC_POWER_CTRL_REG_POWER_ON;
- + break;
- + case MMC_POWER_OFF:
- + default:
- + con &= ~SDC_POWER_CTRL_REG_POWER_ON;
- + break;
- + }
- +
- + REG_WRITE(con, SDC_POWER_CTRL_REG);
- +
- + ftsdc_set_clk(host, ios);
- +
- + if ((ios->power_mode == MMC_POWER_ON) ||
- + (ios->power_mode == MMC_POWER_UP)) {
- + dbg(host, dbg_debug, "running at %ukHz (requested: %ukHz).\n",
- + host->real_rate/1000, ios->clock/1000);
- + } else {
- + dbg(host, dbg_debug, "powered down.\n");
- + }
- +
- + host->bus_width = ios->bus_width;
- + /* write bus configure */
- + con = REG_READ(SDC_BUS_WIDTH_REG);
- +
- + con &= ~(SDC_BUS_WIDTH_REG_SINGLE_BUS |
- + SDC_BUS_WIDTH_REG_WIDE_4_BUS |
- + SDC_BUS_WIDTH_REG_WIDE_8_BUS);
- + if (host->bus_width == MMC_BUS_WIDTH_1)
- + con |= SDC_BUS_WIDTH_REG_SINGLE_BUS;
- + else if (host->bus_width == MMC_BUS_WIDTH_4)
- + con |= SDC_BUS_WIDTH_REG_WIDE_4_BUS;
- + else if (host->bus_width == MMC_BUS_WIDTH_8)
- + con |= SDC_BUS_WIDTH_REG_WIDE_8_BUS;
- + else {
- + dbg(host, dbg_err, "set_ios: can't support bus mode");
- + }
- + REG_WRITE(con, SDC_BUS_WIDTH_REG);
- +
- + /*set rsp and data timeout */
- + con = -1;
- + REG_WRITE(con, SDC_DATA_TIMER_REG);
- +}
- +
- +static int ftsdc_get_ro(struct mmc_host *mmc)
- +{
- + struct ftsdc_host *host = mmc_priv(mmc);
- + u32 con = REG_READ(SDC_STATUS_REG);
- + dbg(host, dbg_debug, "get_ro status:%.8x\n", con);
- +
- + return (con & SDC_STATUS_REG_CARD_LOCK) ? 1 : 0;
- +}
- +
- +
- +static void ftsdc_enable_sdio_irq(struct mmc_host *mmc, int enable)
- +{
- + struct ftsdc_host *host = mmc_priv(mmc);
- + unsigned long flags;
- + u32 con;
- +#ifdef CONFIG_MMC_DEBUG
- + u32 ena;
- +#endif
- +
- + local_irq_save(flags);
- +
- + con = REG_READ(SDC_INT_MASK_REG);
- +#ifdef CONFIG_MMC_DEBUG
- + ena = (con & SDC_STATUS_REG_SDIO_INTR) ? 1:0;
- + if (ena == enable)
- + printk("\n*** XXX ***\n");
- +#endif
- +
- + con = enable ? (con | SDC_STATUS_REG_SDIO_INTR) : (con & ~SDC_STATUS_REG_SDIO_INTR);
- + REG_WRITE(con, SDC_INT_MASK_REG);
- +
- +#ifdef CONFIG_MMC_DEBUG
- + //check and ensure data out to SD host controller
- + ena = (REG_READ(SDC_INT_MASK_REG) & SDC_STATUS_REG_SDIO_INTR) ? 1:0;
- + if (ena != enable) {
- + printk("\n*** YYY ***\n");
- + }
- +#endif
- +
- + local_irq_restore(flags);
- +}
- +
- +static struct mmc_host_ops ftsdc_ops = {
- + .request = ftsdc_request,
- + .set_ios = ftsdc_set_ios,
- + .get_ro = ftsdc_get_ro,
- + .get_cd = ftsdc_get_cd,
- + .enable_sdio_irq = ftsdc_enable_sdio_irq,
- +};
- +
- +#ifdef CONFIG_DEBUG_FS
- +
- +static int ftsdc_state_show(struct seq_file *seq, void *v)
- +{
- + struct ftsdc_host *host = seq->private;
- +
- + seq_printf(seq, "Register base = 0x%08x\n", (u32)host->base);
- + seq_printf(seq, "Clock rate = %u\n", host->real_rate);
- + seq_printf(seq, "host status = %s\n", host->status);
- + seq_printf(seq, "IRQ = %d\n", host->irq);
- + seq_printf(seq, "IRQ enabled = %d\n", host->irq_enabled);
- + seq_printf(seq, "complete what = %d\n", host->complete_what);
- + seq_printf(seq, "dma support = %d\n", ftsdc_dmaexist(host));
- + seq_printf(seq, "use dma = %d\n", host->dodma);
- +
- + return 0;
- +}
- +
- +static int ftsdc_state_open(struct inode *inode, struct file *file)
- +{
- + return single_open(file, ftsdc_state_show, inode->i_private);
- +}
- +
- +static const struct file_operations ftsdc_fops_state = {
- + .owner = THIS_MODULE,
- + .open = ftsdc_state_open,
- + .read = seq_read,
- + .llseek = seq_lseek,
- + .release = single_release,
- +};
- +
- +#define DBG_REG(_r) { .addr = SDC_## _r ## _REG, .name = #_r }
- +
- +struct ftsdc_reg {
- + unsigned short addr;
- + unsigned char *name;
- +} debug_regs[] = {
- + DBG_REG(CMD),
- + DBG_REG(ARGU),
- + DBG_REG(RESPONSE0),
- + DBG_REG(RESPONSE1),
- + DBG_REG(RESPONSE2),
- + DBG_REG(RESPONSE3),
- + DBG_REG(RSP_CMD),
- + DBG_REG(DATA_CTRL),
- + DBG_REG(DATA_TIMER),
- + DBG_REG(DATA_LEN),
- + DBG_REG(STATUS),
- + DBG_REG(CLEAR),
- + DBG_REG(INT_MASK),
- + DBG_REG(POWER_CTRL),
- + DBG_REG(CLOCK_CTRL),
- + DBG_REG(BUS_WIDTH),
- + DBG_REG(SDIO_CTRL1),
- + DBG_REG(SDIO_CTRL2),
- + DBG_REG(SDIO_STATUS),
- + DBG_REG(FEATURE),
- + DBG_REG(REVISION),
- + {}
- +};
- +
- +static int ftsdc_regs_show(struct seq_file *seq, void *v)
- +{
- + struct ftsdc_host *host = seq->private;
- + struct ftsdc_reg *rptr = debug_regs;
- +
- + for (; rptr->name; rptr++)
- + seq_printf(seq, "SDI%s\t=0x%08x\n", rptr->name,
- + REG_READ(rptr->addr));
- +
- + return 0;
- +}
- +
- +static int ftsdc_regs_open(struct inode *inode, struct file *file)
- +{
- + return single_open(file, ftsdc_regs_show, inode->i_private);
- +}
- +
- +static const struct file_operations ftsdc_fops_regs = {
- + .owner = THIS_MODULE,
- + .open = ftsdc_regs_open,
- + .read = seq_read,
- + .llseek = seq_lseek,
- + .release = single_release,
- +};
- +
- +static void ftsdc_debugfs_attach(struct ftsdc_host *host)
- +{
- + struct device *dev = &host->pdev->dev;
- +
- + host->debug_root = debugfs_create_dir(dev_name(dev), NULL);
- + if (IS_ERR(host->debug_root)) {
- + dev_err(dev, "failed to create debugfs root\n");
- + return;
- + }
- +
- + host->debug_state = debugfs_create_file("state", 0444,
- + host->debug_root, host,
- + &ftsdc_fops_state);
- +
- + if (IS_ERR(host->debug_state))
- + dev_err(dev, "failed to create debug state file\n");
- +
- + host->debug_regs = debugfs_create_file("regs", 0444,
- + host->debug_root, host,
- + &ftsdc_fops_regs);
- +
- + if (IS_ERR(host->debug_regs))
- + dev_err(dev, "failed to create debug regs file\n");
- +}
- +
- +static void ftsdc_debugfs_remove(struct ftsdc_host *host)
- +{
- + debugfs_remove(host->debug_regs);
- + debugfs_remove(host->debug_state);
- + debugfs_remove(host->debug_root);
- +}
- +
- +#else
- +static inline void ftsdc_debugfs_attach(struct ftsdc_host *host) { }
- +static inline void ftsdc_debugfs_remove(struct ftsdc_host *host) { }
- +
- +#endif /* CONFIG_DEBUG_FS */
- +
- +#if (defined(CONFIG_PLATFORM_AHBDMA) || defined(CONFIG_PLATFORM_APBDMA))
- +static int ftsdc_alloc_dma(struct ftsdc_host *host)
- +{
- + dmad_chreq *req = host->dma_req;
- +
- + req = kzalloc(sizeof(dmad_chreq), GFP_KERNEL);
- +#ifdef CONFIG_PLATFORM_APBDMA
- +#ifdef CONFIG_PLAT_AG102
- + //ADD by river 2010.10.20
- + outl(inl(PCU_VA_BASE + 0x38) | 0x00000300, PCU_VA_BASE + 0x38);
- + //End ADD by river 2010.10.20
- +#endif
- + req->apb_req.addr0_ctrl = APBBR_ADDRINC_FIXED; /* (in) APBBR_ADDRINC_xxx */
- +/* for amerald */
- + if((inl(PMU_BASE) & AMERALD_MASK) == AMERALD_PRODUCT_ID){
- + req->apb_req.addr0_reqn = APBBR_REQN_SDC_AMERALD;
- + }else
- + {
- + req->apb_req.addr0_reqn = APBBR_REQN_SDC; /* (in) APBBR_REQN_xxx (also used to help determine bus selection) */
- + }
- + req->apb_req.addr1_ctrl = APBBR_ADDRINC_I4X; /* (in) APBBR_ADDRINC_xxx */
- + req->apb_req.addr1_reqn = APBBR_REQN_NONE; /* (in) APBBR_REQN_xxx (also used to help determine bus selection) */
- + req->apb_req.burst_mode = 1; /* (in) Burst mode (0: no burst 1-, 1: burst 4- data cycles per dma cycle) */
- + req->apb_req.data_width = APBBR_DATAWIDTH_4; /* (in) APBBR_DATAWIDTH_4(word), APBBR_DATAWIDTH_2(half-word), APBBR_DATAWIDTH_1(byte) */
- + req->apb_req.tx_dir = DMAD_DIR_A0_TO_A1; /* (in) DMAD_DIR_A0_TO_A1, DMAD_DIR_A1_TO_A0 */
- + req->controller = DMAD_DMAC_APB_CORE; /* (in) DMAD_DMAC_AHB_CORE, DMAD_DMAC_APB_CORE */
- + req->flags = DMAD_FLAGS_SLEEP_BLOCK | DMAD_FLAGS_BIDIRECTION;
- +
- + if (dmad_channel_alloc(req) == 0) {
- + dbg(host, dbg_debug, "%s: APB dma channel allocated (ch: %d)\n", __func__, req->channel);
- + host->dma_req = req;
- + return 0;
- + }
- +
- + memset(req, 0, sizeof(dmad_chreq));
- + dbg(host, dbg_info, "%s: APB dma channel allocation failed\n", __func__);
- +#endif /* CONFIG_PLATFORM_APBDMA */
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + req->ahb_req.sync = 1; /* (in) non-zero if src and dst have different clock domain */
- + req->ahb_req.priority = DMAC_CSR_CHPRI_1; /* (in) DMAC_CSR_CHPRI_0 (lowest) ~ DMAC_CSR_CHPRI_3 (highest) */
- + req->ahb_req.hw_handshake = 1; /* (in) non-zero to enable hardware handshake mode */
- + req->ahb_req.burst_size = DMAC_CSR_SIZE_4; /* (in) DMAC_CSR_SIZE_1 ~ DMAC_CSR_SIZE_256 */
- + req->ahb_req.addr0_width = DMAC_CSR_WIDTH_32; /* (in) DMAC_CSR_WIDTH_8, DMAC_CSR_WIDTH_16, or DMAC_CSR_WIDTH_32 */
- + req->ahb_req.addr0_ctrl = DMAC_CSR_AD_FIX; /* (in) DMAC_CSR_AD_INC, DMAC_CSR_AD_DEC, or DMAC_CSR_AD_FIX */
- + req->ahb_req.addr0_reqn = DMAC_REQN_SDC; /* (in) DMAC_REQN_xxx (also used to help determine channel number) */
- + req->ahb_req.addr1_width = DMAC_CSR_WIDTH_32; /* (in) DMAC_CSR_WIDTH_8, DMAC_CSR_WIDTH_16, or DMAC_CSR_WIDTH_32 */
- + req->ahb_req.addr1_ctrl = DMAC_CSR_AD_INC; /* (in) DMAC_CSR_AD_INC, DMAC_CSR_AD_DEC, or DMAC_CSR_AD_FIX */
- + req->ahb_req.addr1_reqn = DMAC_REQN_NONE; /* (in) DMAC_REQN_xxx (also used to help determine channel number) */
- + req->ahb_req.tx_dir = DMAD_DIR_A0_TO_A1; /* (in) DMAD_DIR_A0_TO_A1, DMAD_DIR_A1_TO_A0 */
- +
- + req->controller = DMAD_DMAC_AHB_CORE; /* (in) DMAD_DMAC_AHB_CORE, DMAD_DMAC_APB_CORE */
- + req->flags = DMAD_FLAGS_SLEEP_BLOCK | DMAD_FLAGS_BIDIRECTION;
- +
- + if (dmad_channel_alloc(req) == 0) {
- + dbg(host, dbg_debug, "%s: AHB dma channel allocated (ch: %d)\n", __func__, req->channel);
- + host->dma_req = req;
- + return 0;
- + }
- +
- + dbg(host, dbg_info, "%s: AHB dma channel allocation failed\n", __func__);
- +#endif
- +
- + kfree(req);
- + return -ENODEV;
- +
- +}
- +#endif
- +
- +static int __devinit ftsdc_probe(struct platform_device *pdev)
- +{
- + struct ftsdc_host *host;
- + struct mmc_host *mmc;
- + int ret = -ENOMEM;
- + u32 con;
- +
- + mmc = mmc_alloc_host(sizeof(struct ftsdc_host), &pdev->dev);
- + if (!mmc) {
- +// ret = -ENOMEM;
- + goto probe_out;
- + }
- +
- + host = mmc_priv(mmc);
- + host->mmc = mmc;
- + host->pdev = pdev;
- +
- + mywq = create_workqueue("atcsdc_queue");
- + if (NULL == mywq)
- + goto probe_free_host;
- +
- + spin_lock_init(&host->complete_lock);
- + tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);
- + init_completion(&host->dma_complete);
- + INIT_WORK(&host->work, ftsdc_work);
- +
- + host->complete_what = COMPLETION_NONE;
- + host->buf_active = XFER_NONE;
- +
- +#if (defined(CONFIG_PLATFORM_AHBDMA) || defined(CONFIG_PLATFORM_APBDMA))
- + ftsdc_alloc_dma(host);
- +#endif
- +
- + host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- + if (!host->mem) {
- + dev_err(&pdev->dev,
- + "failed to get io memory region resouce.\n");
- +
- + ret = -ENOENT;
- + goto probe_free_host;
- + }
- +
- + host->mem = request_mem_region(host->mem->start,
- + resource_size(host->mem), pdev->name);
- +
- + if (!host->mem) {
- + dev_err(&pdev->dev, "failed to request io memory region.\n");
- + ret = -ENOENT;
- + goto probe_free_wq;
- + }
- +
- + host->base = (void __iomem *) SDC_FTSDC010_0_VA_BASE;
- + host->irq = SDC_FTSDC010_IRQ;
- + if (request_irq(host->irq, ftsdc_irq, IRQF_DISABLED, DRIVER_NAME, host)) {
- + dev_err(&pdev->dev, "failed to request mci interrupt.\n");
- + ret = -ENOENT;
- + goto probe_free_mem_region;
- + }
- + host->irq_enabled = true;
- +
- + /* enable card change interruption */
- + con = REG_READ(SDC_INT_MASK_REG);
- + con |= SDC_INT_MASK_REG_CARD_CHANGE;
- + REG_WRITE(con, SDC_INT_MASK_REG);
- +
- + con = REG_READ(SDC_BUS_WIDTH_REG);
- +
- + mmc->ops = &ftsdc_ops;
- + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
- +
- + if (con & SDC_WIDE_4_BUS_SUPPORT)
- + mmc->caps |= MMC_CAP_4_BIT_DATA;
- + else if (con & SDC_WIDE_8_BUS_SUPPORT)
- + mmc->caps |= MMC_CAP_8_BIT_DATA;
- +
- +#ifndef A320D_BUILDIN_SDC
- + mmc->caps |= MMC_CAP_SDIO_IRQ;
- +#endif
- +
- + mmc->f_min = APB_CLK_IN / (2 * 128);
- + mmc->f_max = APB_CLK_IN / 2;
- +
- + /* limit SDIO mode max size */
- + mmc->max_req_size = 128 * 1024 * 1024 - 1;
- + mmc->max_blk_size = 2047;
- + mmc->max_req_size = (mmc->max_req_size + 1) / (mmc->max_blk_size + 1);
- + mmc->max_seg_size = mmc->max_req_size;
- + mmc->max_blk_count = (1<<17)-1;
- +
- + /* kernel default value. see Doc/block/biodocs.txt */
- + /*
- + 'struct mmc_host' has no member named 'max_phys_segs'
- + 'struct mmc_host' has no member named 'max_hw_segs'
- + */
- +// mmc->max_phys_segs = 128;
- +// mmc->max_hw_segs = 128;
- +
- + /* set fifo lenght and default threshold half */
- + con = REG_READ(SDC_FEATURE_REG);
- + host->fifo_len = (con & SDC_FEATURE_REG_FIFO_DEPTH) * sizeof(u32);
- +
- + dbg(host, dbg_debug,
- + "probe: mapped mci_base:%p irq:%u.\n",
- + host->base, host->irq);
- +
- + dbg_dumpregs(host, "");
- +
- + ret = mmc_add_host(mmc);
- + if (ret) {
- + dev_err(&pdev->dev, "failed to add mmc host.\n");
- + goto probe_free_irq;
- + }
- +
- + ftsdc_debugfs_attach(host);
- +
- + platform_set_drvdata(pdev, mmc);
- + dev_info(&pdev->dev, "%s - using %s SDIO IRQ\n", mmc_hostname(mmc),
- + mmc->caps & MMC_CAP_SDIO_IRQ ? "hw" : "sw");
- +
- + return 0;
- +
- + probe_free_irq:
- + free_irq(host->irq, host);
- +
- + probe_free_mem_region:
- + release_mem_region(host->mem->start, resource_size(host->mem));
- +
- +probe_free_wq:
- + destroy_workqueue(mywq);
- +
- + probe_free_host:
- + mmc_free_host(mmc);
- +
- + probe_out:
- + return ret;
- +}
- +
- +static void ftsdc_shutdown(struct platform_device *pdev)
- +{
- + struct mmc_host *mmc = platform_get_drvdata(pdev);
- + struct ftsdc_host *host = mmc_priv(mmc);
- +
- + flush_workqueue(mywq);
- + destroy_workqueue(mywq);
- +
- + ftsdc_debugfs_remove(host);
- + mmc_remove_host(mmc);
- +}
- +
- +static int __devexit ftsdc_remove(struct platform_device *pdev)
- +{
- + struct mmc_host *mmc = platform_get_drvdata(pdev);
- + struct ftsdc_host *host = mmc_priv(mmc);
- +
- + ftsdc_shutdown(pdev);
- +
- + tasklet_disable(&host->pio_tasklet);
- +
- + if (ftsdc_dmaexist(host))
- + kfree(host->dma_req);
- +
- + free_irq(host->irq, host);
- +
- + release_mem_region(host->mem->start, resource_size(host->mem));
- +
- + mmc_free_host(mmc);
- + return 0;
- +}
- +
- +
- +#ifdef CONFIG_PM
- +static int ftsdc_free_dma(struct ftsdc_host *host)
- +{
- + dmad_channel_free(host->dma_req);
- + return 0;
- +}
- +
- +static int ftsdc_suspend(struct platform_device *pdev, pm_message_t state)
- +{
- + struct mmc_host *mmc = platform_get_drvdata(pdev);
- + struct ftsdc_host *host = mmc_priv(mmc);
- + int ret = 0;
- + if (mmc) {
- + ftsdc_free_dma(host);
- + ret = mmc_suspend_host(mmc);
- + }
- + return ret;
- +
- +}
- +
- +static int ftsdc_resume(struct platform_device *pdev)
- +{
- + struct mmc_host *mmc = platform_get_drvdata(pdev);
- + int ret = 0;
- + struct ftsdc_host *host = mmc_priv(mmc);
- + if (mmc) {
- +#if (defined(CONFIG_PLATFORM_AHBDMA) || defined(CONFIG_PLATFORM_APBDMA))
- + ftsdc_alloc_dma(host);
- +#endif
- + ret = mmc_resume_host(mmc);
- + }
- + return ret;
- +}
- +
- +static void platform_device_release(struct device *dev){
- +}
- +
- +
- +#else
- +#define ftsdc_suspend NULL
- +#define ftsdc_resume NULL
- +#endif
- +
- +
- +static struct platform_driver ftsdc_driver = {
- + .driver = {
- + .name = "ftsdc010",
- + .owner = THIS_MODULE,
- + },
- + .probe = ftsdc_probe,
- + .remove = __devexit_p(ftsdc_remove),
- + .shutdown = ftsdc_shutdown,
- + .suspend = ftsdc_suspend,
- + .resume = ftsdc_resume,
- +};
- +
- +static struct resource sdc_resource[] = {
- + [0] = {
- + .start = SDC_FTSDC010_0_VA_BASE,
- + .end = SDC_FTSDC010_0_VA_BASE + 0x1000 - 1,
- + .flags = IORESOURCE_MEM,
- + },
- + [1] = {
- + .start = SDC_FTSDC010_0_IRQ,
- + .flags = IORESOURCE_IRQ,
- + }
- +
- +};
- +
- +struct platform_device sdc_device = {
- + .name = "ftsdc010",
- + .id = 0,
- + .num_resources = ARRAY_SIZE(sdc_resource),
- + .resource = sdc_resource,
- + .dev = {
- + .release = platform_device_release,
- + },
- +};
- +
- +static int __init ftsdc_init(void)
- +{
- + platform_device_register(&sdc_device);
- + return platform_driver_register(&ftsdc_driver);
- +}
- +
- +static void __exit ftsdc_exit(void)
- +{
- + platform_driver_unregister(&ftsdc_driver);
- + platform_device_unregister(&sdc_device);
- +}
- +module_init(ftsdc_init);
- +module_exit(ftsdc_exit);
- +
- +MODULE_DESCRIPTION("Andestech Leopard MMC/SD Card Interface driver");
- +MODULE_LICENSE("GPL v2");
- diff -Nur linux-3.4.110.orig/drivers/mmc/host/ftsdc010.h linux-3.4.110/drivers/mmc/host/ftsdc010.h
- --- linux-3.4.110.orig/drivers/mmc/host/ftsdc010.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/mmc/host/ftsdc010.h 2016-04-07 10:20:51.050085202 +0200
- @@ -0,0 +1,240 @@
- +/*
- + * linux/driver/mmc/ftsdc010.h - Andestech MMC/SD driver
- + * Andestech FTSDC010 Device Driver
- + *
- + * Andestech (C) 2005 Faraday Corp. (http://www.Andestech.com)
- + *
- + * All Rights Reserved
- + */
- +
- +#ifndef _FTSDC010_H_
- +#define _FTSDC010_H_
- +
- +//#define SD_DEBUG
- +#define DELAY_FOR_DMA_READ
- +
- +#ifdef SD_DEBUG
- + #define P_DEBUG(fmt, args...) printk(KERN_ALERT "SD: " fmt, ## args)
- +#else
- + #define P_DEBUG(a...)
- +#endif
- +#define P_DEBUGG(a...)
- +
- +/* used for dma timeout */
- +#define SDC_TIMEOUT_BASE (HZ/2) // Unit is 500 ms
- +
- +/* used for pio retry times */
- +#define SDC_PIO_RETRY 0x300000
- +
- +/* sd controller register */
- +#define SDC_CMD_REG 0x00000000
- +#define SDC_ARGU_REG 0x00000004
- +#define SDC_RESPONSE0_REG 0x00000008
- +#define SDC_RESPONSE1_REG 0x0000000C
- +#define SDC_RESPONSE2_REG 0x00000010
- +#define SDC_RESPONSE3_REG 0x00000014
- +#define SDC_RSP_CMD_REG 0x00000018
- +#define SDC_DATA_CTRL_REG 0x0000001C
- +#define SDC_DATA_TIMER_REG 0x00000020
- +#define SDC_DATA_LEN_REG 0x00000024
- +#define SDC_STATUS_REG 0x00000028
- +#define SDC_CLEAR_REG 0x0000002C
- +#define SDC_INT_MASK_REG 0x00000030
- +#define SDC_POWER_CTRL_REG 0x00000034
- +#define SDC_CLOCK_CTRL_REG 0x00000038
- +#define SDC_BUS_WIDTH_REG 0x0000003C
- +#define SDC_DATA_WINDOW_REG 0x00000040
- +
- +#ifdef A320D_BUILDIN_SDC
- +#define SDC_FEATURE_REG 0x00000044
- +#define SDC_REVISION_REG 0x00000048
- +#else
- +#define SDC_MMC_INT_RSP_REG 0x00000044
- +#define SDC_GP_OUTPUT_REG 0x00000048
- +#define SDC_FEATURE_REG 0x0000009C
- +#define SDC_REVISION_REG 0x000000A0
- +#endif
- +
- +#define SDC_SDIO_CTRL1_REG 0x0000006C
- +#define SDC_SDIO_CTRL2_REG 0x00000070
- +#define SDC_SDIO_STATUS_REG 0x00000074
- +
- +/* bit mapping of command register */
- +#define SDC_CMD_REG_INDEX 0x0000003F
- +#define SDC_CMD_REG_NEED_RSP 0x00000040
- +#define SDC_CMD_REG_LONG_RSP 0x00000080
- +#define SDC_CMD_REG_APP_CMD 0x00000100
- +#define SDC_CMD_REG_CMD_EN 0x00000200
- +#define SDC_CMD_REG_SDC_RST 0x00000400
- +#define SDC_CMD_MMC_INT_STOP 0x00000800
- +
- +/* bit mapping of response command register */
- +#define SDC_RSP_CMD_REG_INDEX 0x0000003F
- +#define SDC_RSP_CMD_REG_APP 0x00000040
- +
- +/* bit mapping of data control register */
- +#define SDC_DATA_CTRL_REG_BLK_SIZE 0x0000000F
- +#define SDC_DATA_CTRL_REG_DATA_WRITE 0x00000010
- +#define SDC_DATA_CTRL_REG_DMA_EN 0x00000020
- +#define SDC_DATA_CTRL_REG_DATA_EN 0x00000040
- +#define SDC_DATA_CTRL_REG_FIFOTH 0x00000080
- +#define SDC_DATA_CTRL_REG_DMA_TYPE 0x00000300
- +#define SDC_DATA_CTRL_REG_FIFO_RST 0x00000400
- +#define SDC_CPRM_DATA_CHANGE_ENDIAN_EN 0x00000800
- +#define SDC_CPRM_DATA_SWAP_HL_EN 0x00001000
- +
- +#define SDC_DMA_TYPE_1 0x00000000
- +#define SDC_DMA_TYPE_4 0x00000100
- +#define SDC_DMA_TYPE_8 0x00000200
- +
- +/* bit mapping of status register */
- +#define SDC_STATUS_REG_RSP_CRC_FAIL 0x00000001
- +#define SDC_STATUS_REG_DATA_CRC_FAIL 0x00000002
- +#define SDC_STATUS_REG_RSP_TIMEOUT 0x00000004
- +#define SDC_STATUS_REG_DATA_TIMEOUT 0x00000008
- +#define SDC_STATUS_REG_RSP_CRC_OK 0x00000010
- +#define SDC_STATUS_REG_DATA_CRC_OK 0x00000020
- +#define SDC_STATUS_REG_CMD_SEND 0x00000040
- +#define SDC_STATUS_REG_DATA_END 0x00000080
- +#define SDC_STATUS_REG_FIFO_UNDERRUN 0x00000100
- +#define SDC_STATUS_REG_FIFO_OVERRUN 0x00000200
- +#define SDC_STATUS_REG_CARD_CHANGE 0x00000400
- +#define SDC_STATUS_REG_CARD_DETECT 0x00000800
- +#define SDC_STATUS_REG_CARD_LOCK 0x00001000
- +#define SDC_STATUS_REG_CP_READY 0x00002000
- +#define SDC_STATUS_REG_CP_BUF_READY 0x00004000
- +#define SDC_STATUS_REG_PLAIN_TEXT_READY 0x00008000
- +#define SDC_STATUS_REG_SDIO_INTR 0x00010000
- +
- +/* bit mapping of clear register */
- +#define SDC_CLEAR_REG_RSP_CRC_FAIL 0x00000001
- +#define SDC_CLEAR_REG_DATA_CRC_FAIL 0x00000002
- +#define SDC_CLEAR_REG_RSP_TIMEOUT 0x00000004
- +#define SDC_CLEAR_REG_DATA_TIMEOUT 0x00000008
- +#define SDC_CLEAR_REG_RSP_CRC_OK 0x00000010
- +#define SDC_CLEAR_REG_DATA_CRC_OK 0x00000020
- +#define SDC_CLEAR_REG_CMD_SEND 0x00000040
- +#define SDC_CLEAR_REG_DATA_END 0x00000080
- +#define SDC_CLEAR_REG_CARD_CHANGE 0x00000400
- +#define SDC_CLEAR_REG_SDIO_INTR 0x00010000
- +
- +/* bit mapping of int_mask register */
- +#define SDC_INT_MASK_REG_RSP_CRC_FAIL 0x00000001
- +#define SDC_INT_MASK_REG_DATA_CRC_FAIL 0x00000002
- +#define SDC_INT_MASK_REG_RSP_TIMEOUT 0x00000004
- +#define SDC_INT_MASK_REG_DATA_TIMEOUT 0x00000008
- +#define SDC_INT_MASK_REG_RSP_CRC_OK 0x00000010
- +#define SDC_INT_MASK_REG_DATA_CRC_OK 0x00000020
- +#define SDC_INT_MASK_REG_CMD_SEND 0x00000040
- +#define SDC_INT_MASK_REG_DATA_END 0x00000080
- +#define SDC_INT_MASK_REG_FIFO_UNDERRUN 0x00000100
- +#define SDC_INT_MASK_REG_FIFO_OVERRUN 0x00000200
- +#define SDC_INT_MASK_REG_CARD_CHANGE 0x00000400
- +#define SDC_INT_MASK_REG_CARD_LOCK 0x00001000
- +#define SDC_INT_MASK_REG_CP_READY 0x00002000
- +#define SDC_INT_MASK_REG_CP_BUF_READY 0x00004000
- +#define SDC_INT_MASK_REG_PLAIN_TEXT_READY 0x00008000
- +#define SDC_INT_MASK_REG_SDIO_INTR 0x00010000
- +
- +
- +#define SDC_CARD_INSERT 0x0
- +#define SDC_CARD_REMOVE SDC_STATUS_REG_CARD_DETECT
- +
- +/* bit mapping of power control register */
- +#define SDC_POWER_CTRL_REG_POWER_ON 0x00000010
- +#define SDC_POWER_CTRL_REG_POWER_BITS 0x0000000F
- +
- +/* bit mapping of clock control register */
- +#define SDC_CLOCK_CTRL_REG_CLK_DIV 0x0000007F
- +#define SDC_CLOCK_CTRL_REG_CARD_TYPE 0x00000080
- +#define SDC_CLOCK_CTRL_REG_CLK_DIS 0x00000100
- +
- +/* card type */
- +#define SDC_CARD_TYPE_SD SDC_CLOCK_REG_CARD_TYPE
- +#define SDC_CARD_TYPE_MMC 0x0
- +
- +/* bit mapping of bus width register */
- +#define SDC_BUS_WIDTH_REG_SINGLE_BUS 0x00000001
- +#define SDC_BUS_WIDTH_REG_WIDE_8_BUS 0x00000002
- +#define SDC_BUS_WIDTH_REG_WIDE_4_BUS 0x00000004
- +#define SDC_BUS_WIDTH_REG_WIDE_BUS_SUPPORT 0x00000018
- +#define SDC_BUS_WIDTH_REG_CARD_DETECT 0x00000020
- +
- +#define SDC_WIDE_4_BUS_SUPPORT 0x00000008
- +#define SDC_WIDE_8_BUS_SUPPORT 0x00000010
- +
- +/* bit mapping of feature register */
- +#define SDC_FEATURE_REG_FIFO_DEPTH 0x000000FF
- +#define SDC_FEATURE_REG_CPRM_FUNCTION 0x00000100
- +
- +/* bit mapping of sdio control register */
- +#define SDC_SDIO_CTRL1_REG_SDIO_BLK_NO 0xFFFF8000
- +#define SDC_SDIO_CTRL1_REG_SDIO_ENABLE 0x00004000
- +#define SDC_SDIO_CTRL1_REG_READ_WAIT_ENABLE 0x00002000
- +#define SDC_SDIO_CTRL1_REG_SDIO_BLK_MODE 0x00001000
- +#define SDC_SDIO_CTRL1_REG_SDIO_BLK_SIZE 0x00000FFF
- +
- +/* bit mapping of sdio status register */
- +#define SDC_SDIO_SDIO_STATUS_REG_FIFO_REMAIN_NO 0x00FE0000
- +#define SDC_SDIO_SDIO_STATUS_REG_SDIO_BLK_CNT 0x0001FFFF
- +
- +enum ftsdc_waitfor {
- + COMPLETION_NONE,
- + COMPLETION_FINALIZE,
- + COMPLETION_CMDSENT,
- + COMPLETION_RSPFIN,
- + COMPLETION_XFER_PROGRESS,
- +};
- +
- +struct ftsdc_host {
- + struct platform_device *pdev;
- + struct mmc_host *mmc;
- + struct resource *mem;
- + struct clk *clk;
- + void __iomem *base;
- + int irq;
- +
- + unsigned int real_rate;
- + bool irq_enabled;
- + unsigned int fifo_len; /* bytes */
- + unsigned int last_opcode; /* keep last successful cmd to judge application specific command */
- +
- + struct mmc_request *mrq;
- + int cmd_is_stop;
- +
- + spinlock_t complete_lock;
- + enum ftsdc_waitfor complete_what;
- +
- + struct completion dma_complete;
- + dmad_chreq *dma_req;
- + bool dodma;
- + bool dma_finish;
- +
- +
- + u32 buf_sgptr; /* keep next scallterlist buffer index */
- + u32 buf_bytes; /* keep current total scallterlist buffer length */
- + u32 buf_count; /* keep real data size rw from sd */
- + u32 *buf_ptr; /* keep current scallterlist buffer address */
- +#define XFER_NONE 0
- +#define XFER_READ 1
- +#define XFER_WRITE 2
- + u32 buf_active; /* keep current transfer mode */
- +
- + int bus_width;
- +
- + char dbgmsg_cmd[301];
- + char dbgmsg_dat[301];
- + char *status;
- +
- + unsigned int ccnt, dcnt;
- + struct tasklet_struct pio_tasklet;
- + struct work_struct work;
- +
- +#ifdef CONFIG_DEBUG_FS
- + struct dentry *debug_root;
- + struct dentry *debug_state;
- + struct dentry *debug_regs;
- +#endif
- +};
- +
- +#endif
- diff -Nur linux-3.4.110.orig/drivers/mmc/host/Kconfig linux-3.4.110/drivers/mmc/host/Kconfig
- --- linux-3.4.110.orig/drivers/mmc/host/Kconfig 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/mmc/host/Kconfig 2016-04-07 10:20:51.050085202 +0200
- @@ -609,3 +609,8 @@
-
- Note: These controllers only support SDIO cards and do not
- support MMC or SD memory cards.
- +
- +config MMC_FTSDC010
- + tristate "Andestech MMC/SD function support"
- + depends on NDS32 && !FTSDC010
- +
- diff -Nur linux-3.4.110.orig/drivers/mmc/host/Makefile linux-3.4.110/drivers/mmc/host/Makefile
- --- linux-3.4.110.orig/drivers/mmc/host/Makefile 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/mmc/host/Makefile 2016-04-07 10:20:51.050085202 +0200
- @@ -45,6 +45,7 @@
- obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o
- obj-$(CONFIG_MMC_VUB300) += vub300.o
- obj-$(CONFIG_MMC_USHC) += ushc.o
- +obj-$(CONFIG_MMC_FTSDC010) += ftsdc010.o
-
- obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
- obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
- diff -Nur linux-3.4.110.orig/drivers/net/ethernet/faraday/ftmac100.c linux-3.4.110/drivers/net/ethernet/faraday/ftmac100.c
- --- linux-3.4.110.orig/drivers/net/ethernet/faraday/ftmac100.c 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/net/ethernet/faraday/ftmac100.c 2016-04-07 10:20:51.054085357 +0200
- @@ -1,1202 +1,1210 @@
- /*
- - * Faraday FTMAC100 10/100 Ethernet
- + * drivers/net/ftmac100.c
- *
- - * (C) Copyright 2009-2011 Faraday Technology
- - * Po-Yu Chuang <ratbert@faraday-tech.com>
- + * Faraday FTMAC100 Device Driver
- *
- - * This program is free software; you can redistribute it and/or modify
- - * it under the terms of the GNU General Public License as published by
- - * the Free Software Foundation; either version 2 of the License, or
- - * (at your option) any later version.
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + *
- + * All Rights Reserved
- *
- - * This program is distributed in the hope that it will be useful,
- - * but WITHOUT ANY WARRANTY; without even the implied warranty of
- - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- - * GNU General Public License for more details.
- - *
- - * You should have received a copy of the GNU General Public License
- - * along with this program; if not, write to the Free Software
- - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
- -
- -#include <linux/dma-mapping.h>
- -#include <linux/etherdevice.h>
- -#include <linux/ethtool.h>
- +#include <linux/module.h>
- #include <linux/init.h>
- +#include <linux/moduleparam.h>
- +
- +#include <linux/sched.h>
- +#include <linux/kernel.h> /* printk() */
- +#include <linux/slab.h> /* kmalloc() */
- +#include <linux/errno.h> /* error codes */
- +#include <linux/types.h> /* size_t */
- #include <linux/interrupt.h>
- -#include <linux/io.h>
- -#include <linux/mii.h>
- -#include <linux/module.h>
- -#include <linux/netdevice.h>
- +
- +#include <linux/in.h>
- #include <linux/platform_device.h>
- +#include <linux/netdevice.h> /* struct device, and other headers */
- +#include <linux/etherdevice.h> /* eth_type_trans */
- +#include <linux/ip.h> /* struct iphdr */
- +#include <linux/tcp.h> /* struct tcphdr */
- +#include <linux/skbuff.h>
- +
- +#include <linux/in6.h>
- +#include <asm/checksum.h>
- +
- +
- +#include <linux/version.h>
- +#include <linux/kernel.h>
- +#include <linux/fcntl.h>
- +#include <linux/ptrace.h>
- +#include <linux/ioport.h>
- +#include <linux/slab.h>
- +#include <linux/string.h>
- +#include <linux/proc_fs.h>
- +#include <asm/bitops.h>
- +#include <asm/io.h>
- +#include <asm/hardware.h>
- +#include <linux/pci.h>
- +#include <linux/delay.h>
- +#include <linux/netdevice.h>
- +#include <linux/etherdevice.h>
- +#include <linux/skbuff.h>
-
- +#include <asm/cacheflush.h> // dma_clean_range
- +#include <asm/spec.h>
- #include "ftmac100.h"
-
- -#define DRV_NAME "ftmac100"
- -#define DRV_VERSION "0.2"
- -
- -#define RX_QUEUE_ENTRIES 128 /* must be power of 2 */
- -#define TX_QUEUE_ENTRIES 16 /* must be power of 2 */
- +#define IPMODULE MAC
- +#define IPNAME FTMAC100
-
- -#define MAX_PKT_SIZE 1518
- -#define RX_BUF_SIZE 2044 /* must be smaller than 0x7ff */
- +#define ENABLE_BOTTOM_HALF 0
- +#define ZERO_COPY 1
-
- -#if MAX_PKT_SIZE > 0x7ff
- -#error invalid MAX_PKT_SIZE
- -#endif
- -
- -#if RX_BUF_SIZE > 0x7ff || RX_BUF_SIZE > PAGE_SIZE
- -#error invalid RX_BUF_SIZE
- -#endif
- -
- -/******************************************************************************
- - * private data
- - *****************************************************************************/
- -struct ftmac100_descs {
- - struct ftmac100_rxdes rxdes[RX_QUEUE_ENTRIES];
- - struct ftmac100_txdes txdes[TX_QUEUE_ENTRIES];
- -};
- -
- -struct ftmac100 {
- - struct resource *res;
- - void __iomem *base;
- - int irq;
- -
- - struct ftmac100_descs *descs;
- - dma_addr_t descs_dma_addr;
- -
- - unsigned int rx_pointer;
- - unsigned int tx_clean_pointer;
- - unsigned int tx_pointer;
- - unsigned int tx_pending;
- -
- - spinlock_t tx_lock;
- -
- - struct net_device *netdev;
- - struct device *dev;
- - struct napi_struct napi;
- +#define FTMAC100_DEBUG 0
- +#define CARDNAME "FTMAC100"
-
- - struct mii_if_info mii;
- -};
- -
- -static int ftmac100_alloc_rx_page(struct ftmac100 *priv,
- - struct ftmac100_rxdes *rxdes, gfp_t gfp);
- -
- -/******************************************************************************
- - * internal functions (hardware register access)
- - *****************************************************************************/
- -#define INT_MASK_ALL_ENABLED (FTMAC100_INT_RPKT_FINISH | \
- - FTMAC100_INT_NORXBUF | \
- - FTMAC100_INT_XPKT_OK | \
- - FTMAC100_INT_XPKT_LOST | \
- - FTMAC100_INT_RPKT_LOST | \
- - FTMAC100_INT_AHB_ERR | \
- - FTMAC100_INT_PHYSTS_CHG)
- +MODULE_AUTHOR("Faraday Corp.");
- +MODULE_LICENSE("GPL");
-
- -#define INT_MASK_ALL_DISABLED 0
- +static const char version[] = "Faraday FTMAC100 Driver (Linux 2.6) 09/28/05 - (C) 2005 Faraday Corp.\n";
- +static volatile int trans_busy = 0;
- +static const char mac_string[] = "Faraday MAC";
-
- -static void ftmac100_enable_all_int(struct ftmac100 *priv)
- -{
- - iowrite32(INT_MASK_ALL_ENABLED, priv->base + FTMAC100_OFFSET_IMR);
- -}
- +#if FTMAC100_DEBUG > 2
- +static void print_packet( unsigned char * buf, int length );
- +#endif
-
- -static void ftmac100_disable_all_int(struct ftmac100 *priv)
- -{
- - iowrite32(INT_MASK_ALL_DISABLED, priv->base + FTMAC100_OFFSET_IMR);
- -}
- +#if FTMAC100_DEBUG > 0
- +#define PRINTK printk
- +#else
- +#define PRINTK(x...)
- +#endif
-
- -static void ftmac100_set_rx_ring_base(struct ftmac100 *priv, dma_addr_t addr)
- -{
- - iowrite32(addr, priv->base + FTMAC100_OFFSET_RXR_BADR);
- +static int ftmac100_open(struct net_device *dev);
- +static void ftmac100_timeout (struct net_device *dev);
- +static int ftmac100_close(struct net_device *dev);
- +static struct net_device_stats * ftmac100_query_statistics( struct net_device *dev);
- +#ifdef HAVE_MULTICAST
- +static void ftmac100_set_multicast_list(struct net_device *dev);
- +#endif
- +static void ftmac100_phy_configure(struct net_device* dev) {};
- +static irqreturn_t ftmac100_interrupt(int irq, void * dev_id);
- +static void ftmac100_rcv(void *dev);
- +static int ftmac100_setup(struct net_device *dev);
- +static int ftmac100_reset( struct net_device* dev );
- +static void ftmac100_enable( struct net_device *dev );
- +
- +static void put_mac(int base, unsigned char *mac_addr)
- +{
- + int val;
- +
- + val = ((u32)mac_addr[0])<<8 | (u32)mac_addr[1];
- + outl(val, base);
- + val = ((((u32)mac_addr[2])<<24)&0xff000000) |
- + ((((u32)mac_addr[3])<<16)&0xff0000) |
- + ((((u32)mac_addr[4])<<8)&0xff00) |
- + ((((u32)mac_addr[5])<<0)&0xff);
- + outl(val, base+4);
- +}
- +
- +static void get_mac(int base, unsigned char *mac_addr)
- +{
- + int val;
- +
- + //printk("+get_mac\n");
- +
- + val = inl(base);
- + mac_addr[0] = (val>>8)&0xff;
- + mac_addr[1] = val&0xff;
- + val = inl(base+4); //john add +4
- + mac_addr[2] = (val>>24)&0xff;
- + mac_addr[3] = (val>>16)&0xff;
- + mac_addr[4] = (val>>8)&0xff;
- + mac_addr[5] = val&0xff;
- +}
- +
- +static void auto_get_mac(int id,unsigned char *mac_addr)
- +{
- + get_mac(MAC_FTMAC100_0_VA_BASE + MAC_MADR_REG, mac_addr);
- +
- + if (memcmp(mac_addr, "\0\0\0\0\0\0", 6) == 0) {
- + mac_addr[0]=0;
- + mac_addr[1]=0x23;
- + mac_addr[2]=0x96;
- + mac_addr[3]=0x00;
- + mac_addr[4]=0xff;
- + mac_addr[5]=0x00;
- + }
- }
-
- -static void ftmac100_set_tx_ring_base(struct ftmac100 *priv, dma_addr_t addr)
- +/*
- + * Print the Ethernet address
- + */
- +static void ft_print_mac(unsigned char *mac_addr)
- {
- - iowrite32(addr, priv->base + FTMAC100_OFFSET_TXR_BADR);
- + printk("ADDR: %pM\n", mac_addr);
- }
-
- -static void ftmac100_txdma_start_polling(struct ftmac100 *priv)
- -{
- - iowrite32(1, priv->base + FTMAC100_OFFSET_TXPD);
- -}
-
- -static int ftmac100_reset(struct ftmac100 *priv)
- +#ifdef HAVE_MULTICAST
- +/*
- + * Finds the CRC32 of a set of bytes.
- + * Again, from Peter Cammaert's code.
- + */
- +static int crc32( char * s, int length )
- {
- - struct net_device *netdev = priv->netdev;
- - int i;
- -
- - /* NOTE: reset clears all registers */
- - iowrite32(FTMAC100_MACCR_SW_RST, priv->base + FTMAC100_OFFSET_MACCR);
- -
- - for (i = 0; i < 5; i++) {
- - unsigned int maccr;
- -
- - maccr = ioread32(priv->base + FTMAC100_OFFSET_MACCR);
- - if (!(maccr & FTMAC100_MACCR_SW_RST)) {
- - /*
- - * FTMAC100_MACCR_SW_RST cleared does not indicate
- - * that hardware reset completed (what the f*ck).
- - * We still need to wait for a while.
- - */
- - udelay(500);
- - return 0;
- + /* indices */
- + int perByte;
- + int perBit;
- + /* crc polynomial for Ethernet */
- + const unsigned long poly = 0xedb88320;
- + /* crc value - preinitialized to all 1's */
- + unsigned long crc_value = 0xffffffff;
- +
- + //printk("+crc32\n");
- +
- + for ( perByte = 0; perByte < length; perByte ++ ) {
- + unsigned char c;
- +
- + c = *(s++);
- + for ( perBit = 0; perBit < 8; perBit++ ) {
- + crc_value = (crc_value>>1)^
- + (((crc_value^c)&0x01)?poly:0);
- + c >>= 1;
- }
- -
- - udelay(1000);
- }
- -
- - netdev_err(netdev, "software reset failed\n");
- - return -EIO;
- -}
- -
- -static void ftmac100_set_mac(struct ftmac100 *priv, const unsigned char *mac)
- -{
- - unsigned int maddr = mac[0] << 8 | mac[1];
- - unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
- -
- - iowrite32(maddr, priv->base + FTMAC100_OFFSET_MAC_MADR);
- - iowrite32(laddr, priv->base + FTMAC100_OFFSET_MAC_LADR);
- + return crc_value;
- }
- +#endif
-
- -#define MACCR_ENABLE_ALL (FTMAC100_MACCR_XMT_EN | \
- - FTMAC100_MACCR_RCV_EN | \
- - FTMAC100_MACCR_XDMA_EN | \
- - FTMAC100_MACCR_RDMA_EN | \
- - FTMAC100_MACCR_CRC_APD | \
- - FTMAC100_MACCR_FULLDUP | \
- - FTMAC100_MACCR_RX_RUNT | \
- - FTMAC100_MACCR_RX_BROADPKT)
- -
- -static int ftmac100_start_hw(struct ftmac100 *priv)
- +static int ftmac100_reset( struct net_device* dev )
- {
- - struct net_device *netdev = priv->netdev;
- + unsigned ioaddr = dev->base_addr;
- + int rcount;
-
- - if (ftmac100_reset(priv))
- - return -EIO;
- + PRINTK("+ftmac100_reset:I/O addr=%X\n", ioaddr);
-
- - /* setup ring buffer base registers */
- - ftmac100_set_rx_ring_base(priv,
- - priv->descs_dma_addr +
- - offsetof(struct ftmac100_descs, rxdes));
- - ftmac100_set_tx_ring_base(priv,
- - priv->descs_dma_addr +
- - offsetof(struct ftmac100_descs, txdes));
- + outl( SW_RST_bit, ioaddr + MACCR_REG );
-
- - iowrite32(FTMAC100_APTC_RXPOLL_CNT(1), priv->base + FTMAC100_OFFSET_APTC);
- + /* this should pause enough for the chip to be happy */
- + for (rcount = 0; (inl( ioaddr + MACCR_REG ) & SW_RST_bit) != 0; rcount++) {
- + //mdelay(10);
- + msleep_interruptible(10);
- + if (rcount > 5) // Retry 5 times
- + return -ENODEV;
- + }
-
- - ftmac100_set_mac(priv, netdev->dev_addr);
- + outl( 0, ioaddr + IMR_REG ); /* Disable all interrupts */
- + if (inl(ioaddr+IMR_REG)!=0)
- + return -ENODEV;
-
- - iowrite32(MACCR_ENABLE_ALL, priv->base + FTMAC100_OFFSET_MACCR);
- - return 0;
- + return 0;
- }
-
- -static void ftmac100_stop_hw(struct ftmac100 *priv)
- -{
- - iowrite32(0, priv->base + FTMAC100_OFFSET_MACCR);
- -}
-
- -/******************************************************************************
- - * internal functions (receive descriptor)
- - *****************************************************************************/
- -static bool ftmac100_rxdes_first_segment(struct ftmac100_rxdes *rxdes)
- -{
- - return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_FRS);
- -}
- -
- -static bool ftmac100_rxdes_last_segment(struct ftmac100_rxdes *rxdes)
- +/*
- + . Function: ftmac100_enable
- + . Purpose: let the chip talk to the outside work
- + . Method:
- + . 1. Enable the transmitter
- + . 2. Enable the receiver
- + . 3. Enable interrupts
- +*/
- +static void ftmac100_enable( struct net_device *dev )
- {
- - return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_LRS);
- -}
- + unsigned int ioaddr = dev->base_addr;
- + int i;
- + struct ftmac100_local *priv = (struct ftmac100_local *)netdev_priv(dev);
- + char mac_addr[6];
-
- -static bool ftmac100_rxdes_owned_by_dma(struct ftmac100_rxdes *rxdes)
- -{
- - return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN);
- -}
- + //printk("+ftmac100_enable\n");
- + PRINTK("%s:ftmac100_enable ioaddr=%X\n", dev->name, ioaddr);
-
- -static void ftmac100_rxdes_set_dma_own(struct ftmac100_rxdes *rxdes)
- -{
- - /* clear status bits */
- - rxdes->rxdes0 = cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN);
- + for (i=0; i<RXDES_NUM; ++i) {
- + priv->rx_descs[i].RXDMA_OWN = OWNBY_FTMAC100; // owned by FTMAC100
- + }
- + priv->rx_idx = 0;
- +
- + for (i=0; i<TXDES_NUM; ++i) {
- + priv->tx_descs[i].TXDMA_OWN = OWNBY_SOFTWARE; // owned by software
- + }
- + priv->tx_idx = 0;
- +
- +
- + /* set the MAC address */
- + put_mac(ioaddr + MAC_MADR_REG, dev->dev_addr);
- +
- + //john add
- + get_mac(ioaddr + MAC_MADR_REG, mac_addr);
- + ft_print_mac(mac_addr);
- +
- + outl( priv->rx_descs_dma, ioaddr + RXR_BADR_REG);
- + outl( priv->tx_descs_dma, ioaddr + TXR_BADR_REG);
- + outl( 0x00001010, ioaddr + ITC_REG); // TODO: threshold too small
- + outl( (0UL<<TXPOLL_CNT)|(0x1<<RXPOLL_CNT), ioaddr + APTC_REG); // TODO: bandwidth overhead maybe too big, polling too often ?!
- + outl( 0x1d8, ioaddr + DBLAC_REG ); //Luke Lee: 1 110 010 111 (0x397)
- +
- + /* now, enable interrupts */
- + outl( PHYSTS_CHG_bit
- + | AHB_ERR_bit
- + | RPKT_LOST_bit
- + | RPKT_SAV_bit
- + | XPKT_LOST_bit
- + | XPKT_OK_bit
- + | NOTXBUF_bit
- + | XPKT_FINISH_bit
- + | NORXBUF_bit
- + | RPKT_FINISH_bit
- + , ioaddr + IMR_REG);
- +
- + /// enable trans/recv,...
- + outl( priv->maccr_val, ioaddr + MACCR_REG );
- + PRINTK("%s:ftmac100_enable DONE\n", dev->name);
- }
-
- -static bool ftmac100_rxdes_rx_error(struct ftmac100_rxdes *rxdes)
- +/*
- + . Function: ftmac100_shutdown
- + . Purpose: closes down the SMC91xxx chip.
- + . Method:
- + . 1. zero the interrupt mask
- + . 2. clear the enable receive flag
- + . 3. clear the enable xmit flags
- + .
- + . TODO:
- + . (1) maybe utilize power down mode.
- + . Why not yet? Because while the chip will go into power down mode,
- + . the manual says that it will wake up in response to any I/O requests
- + . in the register space. Empirical results do not show this working.
- +*/
- +static void ftmac100_shutdown( unsigned int ioaddr )
- {
- - return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ERR);
- -}
- + //printk("+ftmac100_shutdown\n");
-
- -static bool ftmac100_rxdes_crc_error(struct ftmac100_rxdes *rxdes)
- -{
- - return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_CRC_ERR);
- + outl( 0, ioaddr + IMR_REG );
- + outl( 0, ioaddr + MACCR_REG );
- }
-
- -static bool ftmac100_rxdes_frame_too_long(struct ftmac100_rxdes *rxdes)
- +/*
- + * Function: ftmac100_wait_to_send_packet( struct sk_buff * skb, struct device * )
- + * Purpose:
- + * Attempt to allocate memory for a packet, if chip-memory is not
- + * available, then tell the card to generate an interrupt when it
- + * is available*
- + *
- + * Algorithm:
- + *
- + * o if the saved_skb is not currently null, then drop this packet
- + * on the floor. This should never happen, because of TBUSY.
- + * o if the saved_skb is null, then replace it with the current packet,
- + * o See if I can sending it now.
- + * o (NO): Enable interrupts and let the interrupt handler deal with it.
- + * o (YES):Send it now.
- + */
- +static int ftmac100_wait_to_send_packet( struct sk_buff * skb, struct net_device * dev )
- {
- - return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_FTL);
- -}
- + struct ftmac100_local *priv=(struct ftmac100_local *)netdev_priv(dev);
- + unsigned int ioaddr=dev->base_addr;
- + volatile TX_DESC *cur_desc;
- + int length;
- + unsigned long flags;
- +
- + //printk("+ftmac100_wait_to_send_packet\n");
- +
- + spin_lock_irqsave(&priv->lock, flags);
- + if (skb==NULL) {
- + printk("%s(%d): NULL skb???\n", __FILE__,__LINE__);
- + spin_unlock_irqrestore(&priv->lock, flags);
- + return 0;
- + }
- +
- + cur_desc = &priv->tx_descs[priv->tx_idx];
- +#if ZERO_COPY
- + /* Record buffer address to be freed later */
- + priv->tx_skbuff[priv->tx_idx] = skb;
- +#endif
- +
- +#ifdef not_complete_yet
- + if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor
- + {
- + DO_PRINT("no empty transmit descriptor\n");
- + DO_PRINT("jiffies = %d\n", jiffies);
- + lp->stats.tx_dropped++;
- + netif_stop_queue(dev); /// waiting to do:
- + spin_unlock_irqrestore(&lp->lock, flags);
- +
- + return 1;
- + }
- +#endif /* end_of_not */
- +
- + for (; cur_desc->TXDMA_OWN != OWNBY_SOFTWARE; ) {
- + PRINTK( KERN_WARNING "NO empty TX\n"); //printk("no empty TX descriptor:0x%x:0x%x\n",(unsigned)cur_desc,(unsigned)cur_desc[0]);
- + udelay(1);
- + }
- + length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- + length = min(length, TX_BUF_SIZE); // truncate jumbo packets
- +
- +#if FTMAC100_DEBUG > 2
- + printk("Transmitting Packet at 0x%x\n",(unsigned int)cur_desc->VIR_TXBUF_BADR);
- + print_packet( skb->data, length );
- +#endif
-
- -static bool ftmac100_rxdes_runt(struct ftmac100_rxdes *rxdes)
- -{
- - return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RUNT);
- -}
- +#if ZERO_COPY
- + cur_desc->VIR_TXBUF_BADR = (unsigned)skb->data;
- + cur_desc->TXBUF_BADR = virt_to_phys(skb->data);
- + cpu_dma_wb_range((unsigned)skb->data, ((unsigned)(skb->data) + length + CACHE_LINE_SIZE( DCACHE) - 1 )&(~(CACHE_LINE_SIZE( DCACHE)-1)) );
-
- -static bool ftmac100_rxdes_odd_nibble(struct ftmac100_rxdes *rxdes)
- -{
- - return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ODD_NB);
- -}
- +#else
- + memcpy((char *)cur_desc->VIR_TXBUF_BADR, skb->data, length);
- +#endif
-
- -static unsigned int ftmac100_rxdes_frame_length(struct ftmac100_rxdes *rxdes)
- -{
- - return le32_to_cpu(rxdes->rxdes0) & FTMAC100_RXDES0_RFL;
- + cur_desc->TXBUF_Size = length;
- + cur_desc->LTS = 1;
- + cur_desc->FTS = 1;
- +
- + cur_desc->TX2FIC = 0;
- + cur_desc->TXIC = 0;
- +
- + cur_desc->TXDMA_OWN = OWNBY_FTMAC100;
- +
- + outl( 0xffffffff, ioaddr + TXPD_REG );
- +
- + priv->tx_idx = (priv->tx_idx + 1) & (TXDES_NUM-1);
- + priv->stats.tx_packets++;
- + priv->stats.tx_bytes += skb->len;
- +#if !ZERO_COPY
- + dev_kfree_skb_any (skb);
- +#endif
- + dev->trans_start = jiffies;
- + spin_unlock_irqrestore(&priv->lock, flags);
- + return 0;
- }
-
- -static bool ftmac100_rxdes_multicast(struct ftmac100_rxdes *rxdes)
- -{
- - return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_MULTICAST);
- -}
- +//#define dma_allocate(x,y,z,w) dma_alloc_coherent((x),(y),(dma_addr_t*)(z),(w))
- +#define dma_allocate(x,y,z,w) dma_alloc_writecombine((x),(y),(dma_addr_t*)(z),(w))
-
- -static void ftmac100_rxdes_set_buffer_size(struct ftmac100_rxdes *rxdes,
- - unsigned int size)
- +static int ftmac100_ringbuf_alloc(struct net_device *dev,struct ftmac100_local *priv)
- {
- - rxdes->rxdes1 &= cpu_to_le32(FTMAC100_RXDES1_EDORR);
- - rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_RXBUF_SIZE(size));
- -}
- + int i;
-
- -static void ftmac100_rxdes_set_end_of_ring(struct ftmac100_rxdes *rxdes)
- -{
- - rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_EDORR);
- -}
- + //printk("+ftmac100_ringbuf_alloc\n");
-
- -static void ftmac100_rxdes_set_dma_addr(struct ftmac100_rxdes *rxdes,
- - dma_addr_t addr)
- -{
- - rxdes->rxdes2 = cpu_to_le32(addr);
- -}
- + priv->rx_descs = dma_allocate( NULL, sizeof(RX_DESC)*RXDES_NUM, &(priv->rx_descs_dma), GFP_KERNEL );
- + if (priv->rx_descs == NULL || (( (u32)priv->rx_descs & 0xf)!=0)) {
- + printk("Receive Ring Buffer allocation error\n");
- + return -ENOMEM;
- + }
- +#if FTMAC100_DEBUG > 2
- + else
- + printk( KERN_INFO "* Allocated RX descs=%X, bus addr=%X, size=%d*%d=%d\n",
- + (unsigned)priv->rx_descs, (unsigned)priv->rx_descs_dma,
- + sizeof(RX_DESC),RXDES_NUM,sizeof(RX_DESC)*RXDES_NUM );
- +#endif
- + memset((unsigned int *)priv->rx_descs, 0, sizeof(RX_DESC)*RXDES_NUM);
-
- -static dma_addr_t ftmac100_rxdes_get_dma_addr(struct ftmac100_rxdes *rxdes)
- -{
- - return le32_to_cpu(rxdes->rxdes2);
- + priv->rx_buf = dma_allocate( NULL, RX_BUF_SIZE*RXDES_NUM, &(priv->rx_buf_dma), GFP_KERNEL );
- + if (priv->rx_buf == NULL || (( (u32)priv->rx_buf & 3)!=0)) {
- + printk("Receive Ring Buffer allocation error\n");
- + return -ENOMEM;
- + }
- +#if FTMAC100_DEBUG > 2
- + else
- + printk( KERN_INFO "* Allocated RX buf=%X, bus addr=%X, size=%d*%d=%d\n",
- + (unsigned)priv->rx_buf, (unsigned)priv->rx_buf_dma,
- + RX_BUF_SIZE, RXDES_NUM, RX_BUF_SIZE*RXDES_NUM );
- +#endif
- +
- + memset((void *)priv->rx_buf,0,sizeof(RX_BUF_SIZE)*RXDES_NUM);
- +
- + for (i=0; i<RXDES_NUM; ++i) {
- + priv->rx_descs[i].RXBUF_Size = RX_BUF_SIZE;
- + priv->rx_descs[i].EDOTR = 0; // not last descriptor
- + priv->rx_descs[i].RXBUF_BADR = priv->rx_buf_dma+RX_BUF_SIZE*i;
- + priv->rx_descs[i].VIR_RXBUF_BADR=(unsigned int)priv->rx_buf+RX_BUF_SIZE*i;
- + }
- + priv->rx_descs[RXDES_NUM-1].EDOTR = 1; // is last descriptor
- +
- + priv->tx_descs = dma_allocate( NULL, sizeof(TX_DESC)*TXDES_NUM, &(priv->tx_descs_dma), GFP_KERNEL );
- + if (priv->tx_descs == NULL || (( (u32)priv->tx_descs & 0xf)!=0)) {
- + printk("Transmit Ring Buffer allocation error\n");
- + return -ENOMEM;
- + }
- +#if FTMAC100_DEBUG > 2
- + else
- + printk( KERN_INFO "* Allocated TX descs=%X, bus addr=%X, size=%d*%d=%d\n",
- + (unsigned)priv->tx_descs, (unsigned)priv->tx_descs_dma, sizeof(TX_DESC),TXDES_NUM,sizeof(TX_DESC)*TXDES_NUM);
- +#endif
- + memset((void *)priv->tx_descs,0,sizeof(TX_DESC)*TXDES_NUM);
- +
- + priv->tx_buf = dma_allocate( NULL, TX_BUF_SIZE*TXDES_NUM, &(priv->tx_buf_dma), GFP_KERNEL );
- + if (priv->tx_buf == NULL || (( (u32)priv->tx_buf & 0x3)!=0)) {
- + printk("Transmit Ring Buffer allocation error\n");
- + return -ENOMEM;
- + }
- +#if FTMAC100_DEBUG > 2
- + else
- + printk( KERN_INFO "* Allocated TX buf=%X, bus addr=%X, size=%d*%d=%d\n",
- + (unsigned)priv->tx_buf, (unsigned)priv->tx_buf_dma,
- + TX_BUF_SIZE, TXDES_NUM, TX_BUF_SIZE*TXDES_NUM );
- +#endif
- +
- + memset((void *)priv->tx_buf,0,sizeof(TX_BUF_SIZE)*TXDES_NUM);
- +
- + for (i=0; i<TXDES_NUM; ++i) {
- + priv->tx_descs[i].EDOTR = 0; // not last descriptor
- + priv->tx_descs[i].TXBUF_BADR=priv->tx_buf_dma+TX_BUF_SIZE*i;
- + priv->tx_descs[i].VIR_TXBUF_BADR=(unsigned int)priv->tx_buf+TX_BUF_SIZE*i;
- + }
- + priv->tx_descs[TXDES_NUM-1].EDOTR = 1; // is last descriptor
- + return 0;
- }
-
- /*
- - * rxdes3 is not used by hardware. We use it to keep track of page.
- - * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
- + * Function: ftmac100_poll( struct net_device *dev )
- + *
- + * Purpose:
- + * poll interface callback function.
- */
- -static void ftmac100_rxdes_set_page(struct ftmac100_rxdes *rxdes, struct page *page)
- +void ftmac100_poll(struct net_device *dev)
- {
- - rxdes->rxdes3 = (unsigned int)page;
- + disable_irq(dev->irq);
- + ftmac100_interrupt(dev->irq, dev);
- + enable_irq(dev->irq);
- }
-
- -static struct page *ftmac100_rxdes_get_page(struct ftmac100_rxdes *rxdes)
- -{
- - return (struct page *)rxdes->rxdes3;
- -}
- -
- -/******************************************************************************
- - * internal functions (receive)
- - *****************************************************************************/
- -static int ftmac100_next_rx_pointer(int pointer)
- +/*
- + * Function: ftmac100_setup( struct net_device *dev )
- + *
- + * Purpose:
- + * Tests to see if the device 'dev' points to an ftmac100 chip.
- + * Returns a 0 on success
- + */
- +static const struct net_device_ops ftmac100_ops = {
- + .ndo_init = ftmac100_setup,
- + .ndo_open = ftmac100_open,
- + .ndo_stop = ftmac100_close,
- + .ndo_start_xmit = ftmac100_wait_to_send_packet,
- + .ndo_get_stats = ftmac100_query_statistics,
- + .ndo_tx_timeout = ftmac100_timeout,
- +#ifdef HAVE_MULTICAST
- + .ndo_set_multicast_list = ftmac100_set_multicast_list,
- +#endif
- + .ndo_set_mac_address = eth_mac_addr,
- +#ifdef CONFIG_NET_POLL_CONTROLLER
- + .ndo_poll_controller = ftmac100_poll,
- +#endif
- +};
- +static int ftmac100_setup(struct net_device *dev)
- {
- - return (pointer + 1) & (RX_QUEUE_ENTRIES - 1);
- -}
- + int retval;
- + static unsigned version_printed = 0;
- + struct ftmac100_local *priv;
- +
- + if (version_printed++ == 0)
- + printk(KERN_INFO "%s", version);
- +
- + /* Now, print out the card info, in a short format.. */
- + printk(KERN_INFO "%s: device at %#3x IRQ:%d NOWAIT:%d\n",dev->name,
- + (unsigned)dev->base_addr, dev->irq, dev->dma);
- +
- + /* Initialize priviate data */
- + priv = (struct ftmac100_local *)netdev_priv(dev);
- + memset(priv, 0, sizeof(struct ftmac100_local));
- + spin_lock_init(&priv->lock);
- + priv->maccr_val = FULLDUP_bit
- + | CRC_APD_bit
- + | MDC_SEL_bit
- + | RCV_EN_bit
- + | XMT_EN_bit
- + | RDMA_EN_bit
- + | XDMA_EN_bit ;
- + retval = ftmac100_ringbuf_alloc(dev,priv);
- + if (retval)
- + goto err_out;
- +
- + /* now, reset the chip, and put it into a known state */
- + retval = ftmac100_reset( dev );
- + if (retval) {
- + printk( "%s: unable to reset.\n", dev->name );
- + goto err_out;
- + }
- +
- + /* Fill in the fields of the device structure with ethernet values. */
- + ether_setup(dev);
- +
- + /* Grab the IRQ */
- + retval = request_irq(dev->irq, &ftmac100_interrupt, IRQF_DISABLED, dev->name, dev);
- + if (retval) {
- + printk("%s: unable to get IRQ %d (irqval=%d).\n", dev->name, dev->irq, retval);
- + goto err_out;
- + }
- +
- +#if 0
- + if ((proc_ftmac100 = create_proc_entry( "ftmac100", 0, 0 ))) {
- + proc_ftmac100->read_proc = ftmac100_read_proc;
- + proc_ftmac100->data = dev;
- + proc_ftmac100->owner = THIS_MODULE;
- + }
- +#endif
-
- -static void ftmac100_rx_pointer_advance(struct ftmac100 *priv)
- -{
- - priv->rx_pointer = ftmac100_next_rx_pointer(priv->rx_pointer);
- -}
- + return 0;
-
- -static struct ftmac100_rxdes *ftmac100_current_rxdes(struct ftmac100 *priv)
- -{
- - return &priv->descs->rxdes[priv->rx_pointer];
- +err_out:
- + dma_free_coherent( NULL, sizeof(RX_DESC)*RXDES_NUM, (void*)priv->rx_descs, (dma_addr_t)priv->rx_descs_dma );
- + dma_free_coherent( NULL, RX_BUF_SIZE*RXDES_NUM, (void*)priv->rx_buf, (dma_addr_t)priv->rx_buf_dma );
- + dma_free_coherent( NULL, sizeof(TX_DESC)*TXDES_NUM, (void*)priv->tx_descs, (dma_addr_t)priv->tx_descs_dma );
- + dma_free_coherent( NULL, TX_BUF_SIZE*TXDES_NUM, (void*)priv->tx_buf, (dma_addr_t)priv->tx_buf_dma );
- + priv->rx_descs = NULL; priv->rx_descs_dma = 0;
- + priv->rx_buf = NULL; priv->rx_buf_dma = 0;
- + priv->tx_descs = NULL; priv->tx_descs_dma = 0;
- + priv->tx_buf = NULL; priv->tx_buf_dma = 0;
- + return retval;
- }
-
- -static struct ftmac100_rxdes *
- -ftmac100_rx_locate_first_segment(struct ftmac100 *priv)
- -{
- - struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv);
-
- - while (!ftmac100_rxdes_owned_by_dma(rxdes)) {
- - if (ftmac100_rxdes_first_segment(rxdes))
- - return rxdes;
- +#if FTMAC100_DEBUG > 2
- +static void print_packet( unsigned char * buf, int length )
- +{
- +#if FTMAC100_DEBUG > 3
- + int i;
- + int remainder;
- + int lines;
- +#endif
-
- - ftmac100_rxdes_set_dma_own(rxdes);
- - ftmac100_rx_pointer_advance(priv);
- - rxdes = ftmac100_current_rxdes(priv);
- - }
- +// printk("Packet of length %d \n", length );
-
- - return NULL;
- +#if FTMAC100_DEBUG > 3
- + lines = length >> 4;
- + remainder = length & 15;
- +
- + for ( i = 0; i < lines ; i ++ ) {
- + int cur;
- + for ( cur = 0; cur < 8; cur ++ ) {
- + unsigned char a, b;
- + a = *(buf ++ );
- + b = *(buf ++ );
- + printk("%02x%02x ", a, b );
- + }
- + printk("\n");
- + }
- + for ( i = 0; i < remainder/2 ; i++ ) {
- + unsigned char a, b;
- +
- + a = *(buf ++ );
- + b = *(buf ++ );
- + printk("%02x%02x ", a, b );
- + }
- + printk("\n");
- +#endif
- }
- +#endif
-
- -static bool ftmac100_rx_packet_error(struct ftmac100 *priv,
- - struct ftmac100_rxdes *rxdes)
- -{
- - struct net_device *netdev = priv->netdev;
- - bool error = false;
- -
- - if (unlikely(ftmac100_rxdes_rx_error(rxdes))) {
- - if (net_ratelimit())
- - netdev_info(netdev, "rx err\n");
- -
- - netdev->stats.rx_errors++;
- - error = true;
- - }
- -
- - if (unlikely(ftmac100_rxdes_crc_error(rxdes))) {
- - if (net_ratelimit())
- - netdev_info(netdev, "rx crc err\n");
- -
- - netdev->stats.rx_crc_errors++;
- - error = true;
- - }
- -
- - if (unlikely(ftmac100_rxdes_frame_too_long(rxdes))) {
- - if (net_ratelimit())
- - netdev_info(netdev, "rx frame too long\n");
- -
- - netdev->stats.rx_length_errors++;
- - error = true;
- - } else if (unlikely(ftmac100_rxdes_runt(rxdes))) {
- - if (net_ratelimit())
- - netdev_info(netdev, "rx runt\n");
- -
- - netdev->stats.rx_length_errors++;
- - error = true;
- - } else if (unlikely(ftmac100_rxdes_odd_nibble(rxdes))) {
- - if (net_ratelimit())
- - netdev_info(netdev, "rx odd nibble\n");
- -
- - netdev->stats.rx_length_errors++;
- - error = true;
- - }
- -
- - return error;
- -}
-
- -static void ftmac100_rx_drop_packet(struct ftmac100 *priv)
- +/*
- + * Open and Initialize the board
- + *
- + * Set up everything, reset the card, etc ..
- + *
- + */
- +static int ftmac100_open(struct net_device *dev)
- {
- - struct net_device *netdev = priv->netdev;
- - struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv);
- - bool done = false;
- -
- - if (net_ratelimit())
- - netdev_dbg(netdev, "drop packet %p\n", rxdes);
- + int retval = 0;
- + PRINTK("+%s:ftmac100_open\n", dev->name);
-
- - do {
- - if (ftmac100_rxdes_last_segment(rxdes))
- - done = true;
- + //netif_start_queue(dev);
-
- - ftmac100_rxdes_set_dma_own(rxdes);
- - ftmac100_rx_pointer_advance(priv);
- - rxdes = ftmac100_current_rxdes(priv);
- - } while (!done && !ftmac100_rxdes_owned_by_dma(rxdes));
- -
- - netdev->stats.rx_dropped++;
- + /* reset the hardware */
- + ftmac100_reset( dev );
- + retval = ftmac100_reset( dev );
- + if (retval) {
- + printk( "%s: unable to reset.\n", dev->name );
- + retval = -ENODEV;
- + } else {
- + ftmac100_enable( dev );
- +
- + /* Configure the PHY */
- + ftmac100_phy_configure(dev);
- +
- + netif_start_queue(dev);
- +
- + PRINTK("+%s:ftmac100_open DONE\n", dev->name);
- + }
- +
- + return retval;
- }
-
- -static bool ftmac100_rx_packet(struct ftmac100 *priv, int *processed)
- -{
- - struct net_device *netdev = priv->netdev;
- - struct ftmac100_rxdes *rxdes;
- - struct sk_buff *skb;
- - struct page *page;
- - dma_addr_t map;
- - int length;
-
- - rxdes = ftmac100_rx_locate_first_segment(priv);
- - if (!rxdes)
- - return false;
- -
- - if (unlikely(ftmac100_rx_packet_error(priv, rxdes))) {
- - ftmac100_rx_drop_packet(priv);
- - return true;
- - }
- -
- - /*
- - * It is impossible to get multi-segment packets
- - * because we always provide big enough receive buffers.
- - */
- - if (unlikely(!ftmac100_rxdes_last_segment(rxdes)))
- - BUG();
- -
- - /* start processing */
- - skb = netdev_alloc_skb_ip_align(netdev, 128);
- - if (unlikely(!skb)) {
- - if (net_ratelimit())
- - netdev_err(netdev, "rx skb alloc failed\n");
- -
- - ftmac100_rx_drop_packet(priv);
- - return true;
- - }
- -
- - if (unlikely(ftmac100_rxdes_multicast(rxdes)))
- - netdev->stats.multicast++;
- -
- - map = ftmac100_rxdes_get_dma_addr(rxdes);
- - dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
- -
- - length = ftmac100_rxdes_frame_length(rxdes);
- - page = ftmac100_rxdes_get_page(rxdes);
- - skb_fill_page_desc(skb, 0, page, 0, length);
- - skb->len += length;
- - skb->data_len += length;
- -
- - /* page might be freed in __pskb_pull_tail() */
- - if (length > 64)
- - skb->truesize += PAGE_SIZE;
- - __pskb_pull_tail(skb, min(length, 64));
- -
- - ftmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC);
- -
- - ftmac100_rx_pointer_advance(priv);
- -
- - skb->protocol = eth_type_trans(skb, netdev);
- -
- - netdev->stats.rx_packets++;
- - netdev->stats.rx_bytes += skb->len;
- +/*
- + * Called by the kernel to send a packet out into the void
- + * of the net. This routine is largely based on
- + * skeleton.c, from Becker.
- + *
- + */
- +static void ftmac100_timeout (struct net_device *dev)
- +{
- + /* If we get here, some higher level has decided we are broken.
- + There should really be a "kick me" function call instead. */
- + printk(KERN_WARNING "%s: transmit timed out?\n",dev->name);
-
- - /* push packet to protocol stack */
- - netif_receive_skb(skb);
- + //printk("+ftmac100_timeout\n");
-
- - (*processed)++;
- - return true;
- + ftmac100_reset( dev );
- + ftmac100_enable( dev );
- + ftmac100_phy_configure(dev);
- + netif_wake_queue(dev);
- + dev->trans_start = jiffies;
- }
-
- -/******************************************************************************
- - * internal functions (transmit descriptor)
- - *****************************************************************************/
- -static void ftmac100_txdes_reset(struct ftmac100_txdes *txdes)
- +#if ZERO_COPY
- +/*
- + * Free transmitted skb buffer when it's safe.
- + */
- +static void ftmac100_free_tx (struct net_device *dev, int irq)
- {
- - /* clear all except end of ring bit */
- - txdes->txdes0 = 0;
- - txdes->txdes1 &= cpu_to_le32(FTMAC100_TXDES1_EDOTR);
- - txdes->txdes2 = 0;
- - txdes->txdes3 = 0;
- -}
- + struct ftmac100_local *priv = (struct ftmac100_local *)netdev_priv(dev);
- + //volatile TX_DESC *cur_desc;
- + int entry = priv->old_tx & (TXDES_NUM-1);
- +
- + //enter spinlock
- + if (!irq)
- + spin_lock(&priv->lock);
- +
- + /* Free used tx skbuffs */
- + while (entry != priv->tx_idx) {
- + struct sk_buff *skb;
- +
- + skb = priv->tx_skbuff[entry];
- + if(skb) {
- + dev_kfree_skb_any (skb);
- + priv->tx_skbuff[entry] = 0;
- + }
-
- -static bool ftmac100_txdes_owned_by_dma(struct ftmac100_txdes *txdes)
- -{
- - return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN);
- -}
- + entry = (entry + 1) & (TXDES_NUM-1);
- + }
-
- -static void ftmac100_txdes_set_dma_own(struct ftmac100_txdes *txdes)
- -{
- - /*
- - * Make sure dma own bit will not be set before any other
- - * descriptor fields.
- - */
- - wmb();
- - txdes->txdes0 |= cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN);
- -}
- + if (!irq)
- + spin_unlock(&priv->lock);
- + //exit spinloc
-
- -static bool ftmac100_txdes_excessive_collision(struct ftmac100_txdes *txdes)
- -{
- - return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_EXSCOL);
- + priv->old_tx = entry;
- + netif_wake_queue (dev);
- }
- +#endif
-
- -static bool ftmac100_txdes_late_collision(struct ftmac100_txdes *txdes)
- -{
- - return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_LATECOL);
- -}
- +/*
- + .
- + . This is the main routine of the driver, to handle the net_device when
- + . it needs some attention.
- + .
- + . So:
- + . first, save state of the chipset
- + . branch off into routines to handle each case, and acknowledge
- + . each to the interrupt register
- + . and finally restore state.
- + .
- + */
-
- -static void ftmac100_txdes_set_end_of_ring(struct ftmac100_txdes *txdes)
- -{
- - txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_EDOTR);
- -}
- +#if FTMAC100_DEBUG > 2
-
- -static void ftmac100_txdes_set_first_segment(struct ftmac100_txdes *txdes)
- +static void dump_intc(void)
- {
- - txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_FTS);
- + printk( " INTC[0] IRQSRC=%08X,MASK=%08X,MOD=%08X,LEV=%08X,STAT=%08X\n",
- + *((volatile unsigned*)(INTC_FTINTC010_VA_BASE+0)),
- + *((volatile unsigned*)(INTC_FTINTC010_VA_BASE+0x4)),
- + *((volatile unsigned*)(INTC_FTINTC010_VA_BASE+0xc)),
- + *((volatile unsigned*)(INTC_FTINTC010_VA_BASE+0x10)),
- + *((volatile unsigned*)(INTC_FTINTC010_VA_BASE+0x14)) );
- + printk( " INTC[1] IRQSRC=%08X,MASK=%08X,MOD=%08X,LEV=%08X,STAT=%08X\n",
- + *((volatile unsigned*)(INTC_FTINTC010_1_VA_BASE+0)),
- + *((volatile unsigned*)(INTC_FTINTC010_1_VA_BASE+0x4)),
- + *((volatile unsigned*)(INTC_FTINTC010_1_VA_BASE+0xc)),
- + *((volatile unsigned*)(INTC_FTINTC010_1_VA_BASE+0x10)),
- + *((volatile unsigned*)(INTC_FTINTC010_1_VA_BASE+0x14)) );
- }
- +#else
- +#define dump_intc()
- +#endif
-
- -static void ftmac100_txdes_set_last_segment(struct ftmac100_txdes *txdes)
- +#if FTMAC100_DEBUG > 2
- +static void show_intstatus(unsigned char status)
- {
- - txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_LTS);
- + static int count = 0;
- + if (status & PHYSTS_CHG_bit)
- + printk( "[%d]%s ", count, "PHYSTS_CHG" );
- + if (status & AHB_ERR_bit)
- + printk( "[%d]%s ", count, "AHB_ERR" );
- + if (status & RPKT_LOST_bit)
- + printk( "[%d]%s ", count, "RPKT_LOST" );
- + if (status & RPKT_SAV_bit)
- + printk( "[%d]%s ", count, "RPKT_SAV" );
- + if (status & XPKT_LOST_bit)
- + printk( "[%d]%s ", count, "XPKT_LOST" );
- + if (status & XPKT_OK_bit)
- + printk( "[%d]%s ", count, "XPKT_OK" );
- + if (status & NOTXBUF_bit)
- + printk( "[%d]%s ", count, "NOTXBUF" );
- + if (status & XPKT_FINISH_bit)
- + printk( "[%d]%s ", count, "XPKT_FINISH" );
- + if (status & NORXBUF_bit)
- + printk( "[%d]%s ", count, "NORXBUF" );
- + if (status & RPKT_FINISH_bit)
- + printk( "[%d]%s ", count, "RPKT_FINISH" );
- + if (status & ~(PHYSTS_CHG_bit | AHB_ERR_bit | RPKT_LOST_bit | RPKT_SAV_bit
- + | XPKT_LOST_bit | XPKT_OK_bit | NOTXBUF_bit | XPKT_FINISH_bit
- + | NORXBUF_bit | RPKT_FINISH_bit))
- + printk( "[%d]%s ", count, "<Unknown>" );
- + count++;
- }
- +#else
- +#define show_intstatus(x)
- +#endif
- +
-
- -static void ftmac100_txdes_set_txint(struct ftmac100_txdes *txdes)
- +/*
- + * The interrupt handler
- + */
- +static irqreturn_t ftmac100_interrupt(int irq, void * dev_id)
- {
- - txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXIC);
- -}
- + struct net_device *dev = dev_id;
- + unsigned int ioaddr = dev->base_addr;
- + unsigned status; // interrupt status
- + unsigned char mask; // interrupt mask
- + struct ftmac100_local *priv = (struct ftmac100_local *)netdev_priv(dev);
- + unsigned long flags;
- +
- + spin_lock_irqsave(&priv->lock,flags); // Luke 08/18/2005 ins
- + PRINTK(KERN_INFO "+ftmac100_interrupt\n");
- + dump_intc();
- +
- + if (dev == NULL||priv == NULL) {
- + printk(KERN_WARNING "%s: irq %d for unknown device.\n", "ftmac100_interrupt", irq);
- + return IRQ_HANDLED;
- + }
- +
- + /* read the interrupt status register */
- + mask = inl( ioaddr + IMR_REG );
- +
- + /* read the status flag, and mask it */
- + status = inl( ioaddr + ISR_REG ) & mask;
- +
- + show_intstatus(status);
- +
- + if ( status & RPKT_FINISH_bit )
- + ftmac100_rcv(dev);
- +
- + if (status & NORXBUF_bit) {
- + //printk("<0x%x:NORXBUF>",status);
- + outl( mask & ~NORXBUF_bit, ioaddr + IMR_REG);
- + trans_busy = 1;
- +
- +#if ENABLE_BOTTOM_HALF
- + priv->rcv_tq.sync = 0;
- + priv->rcv_tq.routine=ftmac100_rcv;
- + priv->rcv_tq.data = dev;
- + queue_task(&priv->rcv_tq, &tq_timer);
- + //queue_task(&priv->rcv_tq, &tq_immediate);
- +#else
- + ftmac100_rcv( dev );
- +#endif
- + }
- +
- + if (status & AHB_ERR_bit)
- + printk("<0x%x:AHB_ERR>",status);
- +
- + if (status & XPKT_FINISH_bit)
- + printk( "[XPKT_FINISH]" );
- +
- + /*
- + if (status & PHYSTS_CHG_bit) {
- + }
- + */
- + if (status & XPKT_OK_bit) {
- +#if ZERO_COPY
- + ftmac100_free_tx(dev,1);
- +#endif
- + }
- + /*
- + if (status & NOTXBUF_bit) {
- + }
- + */
- +
- + if (status & RPKT_LOST_bit)
- + priv->stats.rx_errors++;
- +
- + if (status & XPKT_LOST_bit) {
- +#if ZERO_COPY
- + ftmac100_free_tx(dev,1);
- +#endif
- + priv->stats.tx_errors++;
- + }
- +
- + PRINTK(KERN_INFO "+ftmac100_interrupt DONE\n");
- + dump_intc();
- + PRINTK(KERN_INFO "\n");
- + spin_unlock_irqrestore(&priv->lock,flags); // Luke 08/18/2005 ins
-
- -static void ftmac100_txdes_set_buffer_size(struct ftmac100_txdes *txdes,
- - unsigned int len)
- -{
- - txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXBUF_SIZE(len));
- + return IRQ_HANDLED;
- }
-
- -static void ftmac100_txdes_set_dma_addr(struct ftmac100_txdes *txdes,
- - dma_addr_t addr)
- -{
- - txdes->txdes2 = cpu_to_le32(addr);
- -}
-
- -static dma_addr_t ftmac100_txdes_get_dma_addr(struct ftmac100_txdes *txdes)
- -{
- - return le32_to_cpu(txdes->txdes2);
- -}
-
- /*
- - * txdes3 is not used by hardware. We use it to keep track of socket buffer.
- - * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
- + . ftmac100_rcv - receive a packet from the card
- + .
- + . There is ( at least ) a packet waiting to be read from
- + . chip-memory.
- + .
- + . o Read the status
- + . o If an error, record it
- + . o otherwise, read in the packet
- */
- -static void ftmac100_txdes_set_skb(struct ftmac100_txdes *txdes, struct sk_buff *skb)
- -{
- - txdes->txdes3 = (unsigned int)skb;
- -}
-
- -static struct sk_buff *ftmac100_txdes_get_skb(struct ftmac100_txdes *txdes)
- +static void ftmac100_rcv(void *devp)
- {
- - return (struct sk_buff *)txdes->txdes3;
- + struct net_device *dev=(struct net_device *)devp;
- + struct ftmac100_local *priv = (struct ftmac100_local *)netdev_priv(dev);
- + unsigned int ioaddr=dev->base_addr;
- + int packet_length;
- + int rcv_cnt;
- + volatile RX_DESC *cur_desc;
- + int cpy_length;
- + int cur_idx;
- + int seg_length;
- + int have_package;
- + int have_frs;
- + int start_idx;
- +
- + struct sk_buff * skb;
- + unsigned char * data;
- +
- + PRINTK("+ ftmac100_rcv\n");
- +
- + start_idx = priv->rx_idx;
- +
- + for (rcv_cnt=0; rcv_cnt<8 ; ++rcv_cnt) {
- + packet_length = 0;
- + cur_idx = priv->rx_idx;
- +
- + have_package = 0;
- + have_frs = 0;
- + for (; (cur_desc = &priv->rx_descs[priv->rx_idx])->RXDMA_OWN==0; ) {
- + have_package = 1;
- + priv->rx_idx = (priv->rx_idx+1) & (RXDES_NUM-1);
- + if (cur_desc->FRS) {
- + have_frs = 1;
- + if (cur_desc->RX_ERR || cur_desc->CRC_ERR || cur_desc->FTL
- + || cur_desc->RUNT || cur_desc->RX_ODD_NB) {
- + priv->stats.rx_errors++; // error frame....
- + break;
- + }
- + if (cur_desc->MULTICAST)
- + priv->stats.multicast++;
- + packet_length = cur_desc->ReceiveFrameLength; // normal frame
- + }
- + if ( cur_desc->LRS ) // packet's last frame
- + break;
- + }
- + if (have_package==0)
- + goto done;
- + if (have_frs == 0)
- + priv->stats.rx_over_errors++;
- +
- + if (packet_length>0) {
- + // Allocate enough memory for entire receive frame, to be safe
- + skb = dev_alloc_skb( packet_length + 2 );
- +
- + if ( skb == NULL ) {
- + printk(KERN_NOTICE "%s: Low memory, packet dropped.\n", dev->name);
- + priv->stats.rx_dropped++;
- + goto done;
- + }
- +
- + skb_reserve( skb, 2 ); /* 16 bit alignment */
- + skb->dev = dev;
- +
- + data = skb_put( skb, packet_length );
- + cpy_length = 0;
- + for (; cur_idx!=priv->rx_idx; cur_idx = (cur_idx+1) & (RXDES_NUM-1)) {
- + seg_length = min(packet_length - cpy_length, RX_BUF_SIZE);
- + memcpy(data+cpy_length, (char *)priv->rx_descs[cur_idx].VIR_RXBUF_BADR, seg_length);
- + cpy_length += seg_length;
- + }
- +
- + skb->protocol = eth_type_trans(skb, dev);
- + netif_rx(skb);
- + dev->last_rx = jiffies;
- + priv->stats.rx_packets++;
- + priv->stats.rx_bytes += skb->len;
- + }
- + }
- +
- +done:
- + if (start_idx != priv->rx_idx) {
- + for (cur_idx = (start_idx+1)%RXDES_NUM; cur_idx != priv->rx_idx; cur_idx = (cur_idx+1)%RXDES_NUM) {
- + priv->rx_descs[cur_idx].RXDMA_OWN = 1;
- + }
- + priv->rx_descs[start_idx].RXDMA_OWN = 1;
- + }
- + if (trans_busy == 1) {
- + outl( priv->maccr_val, ioaddr + MACCR_REG );
- + outl( inl(ioaddr + IMR_REG) | NORXBUF_bit, ioaddr + IMR_REG);
- + }
- +
- + PRINTK("+ ftmac100_rcv DONE\n");
- +
- + return;
- }
-
- -/******************************************************************************
- - * internal functions (transmit)
- - *****************************************************************************/
- -static int ftmac100_next_tx_pointer(int pointer)
- +/*
- + . ftmac100_close
- + .
- + . this makes the board clean up everything that it can
- + . and not talk to the outside world. Caused by
- + . an 'ifconfig ethX down'
- + .
- + */
- +static int ftmac100_close(struct net_device *dev)
- {
- - return (pointer + 1) & (TX_QUEUE_ENTRIES - 1);
- -}
- + //printk("+ftmac100_close\n");
-
- -static void ftmac100_tx_pointer_advance(struct ftmac100 *priv)
- -{
- - priv->tx_pointer = ftmac100_next_tx_pointer(priv->tx_pointer);
- + netif_stop_queue(dev);
- +
- + ftmac100_shutdown( dev->base_addr );
- +#if ZERO_COPY
- + ftmac100_free_tx(dev,0);
- +#endif
- + return 0;
- }
-
- -static void ftmac100_tx_clean_pointer_advance(struct ftmac100 *priv)
- +/*
- + . Get the current statistics.
- + . This may be called with the card open or closed.
- + */
- +static struct net_device_stats* ftmac100_query_statistics(struct net_device *dev)
- {
- - priv->tx_clean_pointer = ftmac100_next_tx_pointer(priv->tx_clean_pointer);
- -}
- + struct ftmac100_local *priv = (struct ftmac100_local *)netdev_priv(dev);
-
- -static struct ftmac100_txdes *ftmac100_current_txdes(struct ftmac100 *priv)
- -{
- - return &priv->descs->txdes[priv->tx_pointer];
- -}
- + PRINTK("+ftmac100_query_statistics\n");
-
- -static struct ftmac100_txdes *ftmac100_current_clean_txdes(struct ftmac100 *priv)
- -{
- - return &priv->descs->txdes[priv->tx_clean_pointer];
- + return &priv->stats;
- }
-
- -static bool ftmac100_tx_complete_packet(struct ftmac100 *priv)
- -{
- - struct net_device *netdev = priv->netdev;
- - struct ftmac100_txdes *txdes;
- - struct sk_buff *skb;
- - dma_addr_t map;
- -
- - if (priv->tx_pending == 0)
- - return false;
-
- - txdes = ftmac100_current_clean_txdes(priv);
- -
- - if (ftmac100_txdes_owned_by_dma(txdes))
- - return false;
- -
- - skb = ftmac100_txdes_get_skb(txdes);
- - map = ftmac100_txdes_get_dma_addr(txdes);
- -
- - if (unlikely(ftmac100_txdes_excessive_collision(txdes) ||
- - ftmac100_txdes_late_collision(txdes))) {
- - /*
- - * packet transmitted to ethernet lost due to late collision
- - * or excessive collision
- - */
- - netdev->stats.tx_aborted_errors++;
- - } else {
- - netdev->stats.tx_packets++;
- - netdev->stats.tx_bytes += skb->len;
- - }
- +#ifdef HAVE_MULTICAST
-
- - dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
- - dev_kfree_skb(skb);
- -
- - ftmac100_txdes_reset(txdes);
- -
- - ftmac100_tx_clean_pointer_advance(priv);
- -
- - spin_lock(&priv->tx_lock);
- - priv->tx_pending--;
- - spin_unlock(&priv->tx_lock);
- - netif_wake_queue(netdev);
- -
- - return true;
- -}
- +/*
- + . Function: ftmac100_setmulticast( unsigned int ioaddr, int count, dev_mc_list * adds )
- + . Purpose:
- + . This sets the internal hardware table to filter out unwanted multicast
- + . packets before they take up memory.
- + */
-
- -static void ftmac100_tx_complete(struct ftmac100 *priv)
- +static void ftmac100_setmulticast( unsigned int ioaddr, int count, struct dev_mc_list * addrs )
- {
- - while (ftmac100_tx_complete_packet(priv))
- - ;
- + struct dev_mc_list * cur_addr;
- + int crc_val;
- +
- + //printk("+ftmac100_setmulticast\n");
- +
- + for (cur_addr = addrs ; cur_addr!=NULL ; cur_addr = cur_addr->next ) {
- + if ( !( *cur_addr->dmi_addr & 1 ) )
- + continue;
- + crc_val = crc32( cur_addr->dmi_addr, 6 );
- + crc_val = (crc_val>>26)&0x3f; // 取 MSB 6 bit
- + if (crc_val >= 32)
- + outl(inl(ioaddr+MAHT1_REG) | (1UL<<(crc_val-32)), ioaddr+MAHT1_REG);
- + else
- + outl(inl(ioaddr+MAHT0_REG) | (1UL<<crc_val), ioaddr+MAHT0_REG);
- + }
- }
-
- -static int ftmac100_xmit(struct ftmac100 *priv, struct sk_buff *skb,
- - dma_addr_t map)
- -{
- - struct net_device *netdev = priv->netdev;
- - struct ftmac100_txdes *txdes;
- - unsigned int len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
- -
- - txdes = ftmac100_current_txdes(priv);
- - ftmac100_tx_pointer_advance(priv);
- -
- - /* setup TX descriptor */
- - ftmac100_txdes_set_skb(txdes, skb);
- - ftmac100_txdes_set_dma_addr(txdes, map);
- -
- - ftmac100_txdes_set_first_segment(txdes);
- - ftmac100_txdes_set_last_segment(txdes);
- - ftmac100_txdes_set_txint(txdes);
- - ftmac100_txdes_set_buffer_size(txdes, len);
-
- - spin_lock(&priv->tx_lock);
- - priv->tx_pending++;
- - if (priv->tx_pending == TX_QUEUE_ENTRIES)
- - netif_stop_queue(netdev);
- -
- - /* start transmit */
- - ftmac100_txdes_set_dma_own(txdes);
- - spin_unlock(&priv->tx_lock);
- +/*
- + . ftmac100_set_multicast_list
- + .
- + . This routine will, depending on the values passed to it,
- + . either make it accept multicast packets, go into
- + . promiscuous mode ( for TCPDUMP and cousins ) or accept
- + . a select set of multicast packets
- +*/
- +static void ftmac100_set_multicast_list(struct net_device *dev)
- +{
- + unsigned int ioaddr = dev->base_addr;
- + struct ftmac100_local *priv = (struct ftmac100_local *)netdev_priv(dev);
- +
- + //printk("+ftmac100_set_multicast_list\n");
- +
- + if (dev->flags & IFF_PROMISC)
- + priv->maccr_val |= RCV_ALL_bit;
- + else
- + priv->maccr_val &= ~RCV_ALL_bit;
- +
- + if ( !(dev->flags & IFF_ALLMULTI) )
- + priv->maccr_val |= RX_MULTIPKT_bit;
- + else
- + priv->maccr_val &= ~RX_MULTIPKT_bit;
- +
- + if (dev->mc_count) {
- + priv->maccr_val |= HT_MULTI_EN_bit;
- + ftmac100_setmulticast( ioaddr, dev->mc_count, dev->mc_list );
- + }
- + else
- + priv->maccr_val &= ~HT_MULTI_EN_bit;
-
- - ftmac100_txdma_start_polling(priv);
- - return NETDEV_TX_OK;
- + outl( priv->maccr_val, ioaddr + MACCR_REG );
- }
- +#endif
-
- -/******************************************************************************
- - * internal functions (buffer)
- - *****************************************************************************/
- -static int ftmac100_alloc_rx_page(struct ftmac100 *priv,
- - struct ftmac100_rxdes *rxdes, gfp_t gfp)
- -{
- - struct net_device *netdev = priv->netdev;
- - struct page *page;
- - dma_addr_t map;
- -
- - page = alloc_page(gfp);
- - if (!page) {
- - if (net_ratelimit())
- - netdev_err(netdev, "failed to allocate rx page\n");
- - return -ENOMEM;
- - }
- -
- - map = dma_map_page(priv->dev, page, 0, RX_BUF_SIZE, DMA_FROM_DEVICE);
- - if (unlikely(dma_mapping_error(priv->dev, map))) {
- - if (net_ratelimit())
- - netdev_err(netdev, "failed to map rx page\n");
- - __free_page(page);
- - return -ENOMEM;
- - }
- -
- - ftmac100_rxdes_set_page(rxdes, page);
- - ftmac100_rxdes_set_dma_addr(rxdes, map);
- - ftmac100_rxdes_set_buffer_size(rxdes, RX_BUF_SIZE);
- - ftmac100_rxdes_set_dma_own(rxdes);
- - return 0;
- -}
- +/*
- + * Module initialization function
- + */
-
- -static void ftmac100_free_buffers(struct ftmac100 *priv)
- +static int ftmac100_probe(struct platform_device *pdev)
- {
- - int i;
- + int result,thisresult;
- + struct net_device *dev;
- + struct resource *iores;
-
- - for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
- - struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i];
- - struct page *page = ftmac100_rxdes_get_page(rxdes);
- - dma_addr_t map = ftmac100_rxdes_get_dma_addr(rxdes);
- + PRINTK("+init_module\n");
-
- - if (!page)
- - continue;
- + result = -ENODEV;
-
- - dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
- - __free_page(page);
- + dev = alloc_etherdev(sizeof(struct ftmac100_local));
- + if (!dev) {
- + printk(KERN_ERR "Fail allocating ethernet device");
- + return -ENODEV;
- }
- -
- - for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
- - struct ftmac100_txdes *txdes = &priv->descs->txdes[i];
- - struct sk_buff *skb = ftmac100_txdes_get_skb(txdes);
- - dma_addr_t map = ftmac100_txdes_get_dma_addr(txdes);
- -
- - if (!skb)
- - continue;
- -
- - dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
- - dev_kfree_skb(skb);
- + iores = platform_get_resource(pdev, IORESOURCE_IO, 0);
- + /* Copy the parameters from the platform specification */
- + dev->base_addr = iores->start;
- + dev->irq = platform_get_irq(pdev, 0);
- + dev->netdev_ops = &ftmac100_ops;
- +
- + //dev->dma = nowait; // Use DMA field for nowait
- + /* Setup initial mac address */
- + auto_get_mac(pdev->id,dev->dev_addr);
- +
- + if ((thisresult = register_netdev(dev)) != 0) {
- + free_irq( dev->irq, dev );
- + free_netdev(dev);
- + } else {
- + platform_set_drvdata(pdev, dev);
- }
- + if (thisresult == 0) // any of the devices initialized, run
- + result = 0;
-
- - dma_free_coherent(priv->dev, sizeof(struct ftmac100_descs),
- - priv->descs, priv->descs_dma_addr);
- + return result;
- }
-
- -static int ftmac100_alloc_buffers(struct ftmac100 *priv)
- -{
- - int i;
- -
- - priv->descs = dma_alloc_coherent(priv->dev, sizeof(struct ftmac100_descs),
- - &priv->descs_dma_addr, GFP_KERNEL);
- - if (!priv->descs)
- - return -ENOMEM;
- -
- - memset(priv->descs, 0, sizeof(struct ftmac100_descs));
- -
- - /* initialize RX ring */
- - ftmac100_rxdes_set_end_of_ring(&priv->descs->rxdes[RX_QUEUE_ENTRIES - 1]);
- -
- - for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
- - struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i];
- -
- - if (ftmac100_alloc_rx_page(priv, rxdes, GFP_KERNEL))
- - goto err;
- - }
- -
- - /* initialize TX ring */
- - ftmac100_txdes_set_end_of_ring(&priv->descs->txdes[TX_QUEUE_ENTRIES - 1]);
- - return 0;
- -
- -err:
- - ftmac100_free_buffers(priv);
- - return -ENOMEM;
- -}
-
- -/******************************************************************************
- - * struct mii_if_info functions
- - *****************************************************************************/
- -static int ftmac100_mdio_read(struct net_device *netdev, int phy_id, int reg)
- +/*
- + * Cleanup when module is removed with rmmod
- + */
- +
- +static int ftmac100_remove(struct platform_device *pdev)
- {
- - struct ftmac100 *priv = netdev_priv(netdev);
- - unsigned int phycr;
- - int i;
- -
- - phycr = FTMAC100_PHYCR_PHYAD(phy_id) |
- - FTMAC100_PHYCR_REGAD(reg) |
- - FTMAC100_PHYCR_MIIRD;
- -
- - iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR);
- -
- - for (i = 0; i < 10; i++) {
- - phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR);
- -
- - if ((phycr & FTMAC100_PHYCR_MIIRD) == 0)
- - return phycr & FTMAC100_PHYCR_MIIRDATA;
- -
- - udelay(100);
- - }
- -
- - netdev_err(netdev, "mdio read timed out\n");
- + struct net_device *dev;
- + struct ftmac100_local *priv;
- + PRINTK("+cleanup_module\n");
- +
- + dev = platform_get_drvdata(pdev);
- +
- + priv = (struct ftmac100_local *)netdev_priv(dev);
- + if (priv->rx_descs)
- + dma_free_coherent( NULL, sizeof(RX_DESC)*RXDES_NUM, (void*)priv->rx_descs, (dma_addr_t)priv->rx_descs_dma );
- + if (priv->rx_buf)
- + dma_free_coherent( NULL, RX_BUF_SIZE*RXDES_NUM, (void*)priv->rx_buf, (dma_addr_t)priv->rx_buf_dma );
- + if (priv->tx_descs)
- + dma_free_coherent( NULL, sizeof(TX_DESC)*TXDES_NUM, (void*)priv->tx_descs, (dma_addr_t)priv->tx_descs_dma );
- + if (priv->tx_buf)
- + dma_free_coherent( NULL, TX_BUF_SIZE*TXDES_NUM, (void*)priv->tx_buf, (dma_addr_t)priv->tx_buf_dma );
- + priv->rx_descs = NULL; priv->rx_descs_dma = 0;
- + priv->rx_buf = NULL; priv->rx_buf_dma = 0;
- + priv->tx_descs = NULL; priv->tx_descs_dma = 0;
- + priv->tx_buf = NULL; priv->tx_buf_dma = 0;
- +
- + /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
- + unregister_netdev(dev);
- +
- + free_irq(dev->irq, dev);
- + //TODO: where is the request_region ?
- + //release_region(devFMAC.base_addr, SMC_IO_EXTENT);
- + free_netdev(dev);
- return 0;
- }
-
- -static void ftmac100_mdio_write(struct net_device *netdev, int phy_id, int reg,
- - int data)
- -{
- - struct ftmac100 *priv = netdev_priv(netdev);
- - unsigned int phycr;
- - int i;
- -
- - phycr = FTMAC100_PHYCR_PHYAD(phy_id) |
- - FTMAC100_PHYCR_REGAD(reg) |
- - FTMAC100_PHYCR_MIIWR;
- -
- - data = FTMAC100_PHYWDATA_MIIWDATA(data);
- -
- - iowrite32(data, priv->base + FTMAC100_OFFSET_PHYWDATA);
- - iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR);
- -
- - for (i = 0; i < 10; i++) {
- - phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR);
- -
- - if ((phycr & FTMAC100_PHYCR_MIIWR) == 0)
- - return;
- -
- - udelay(100);
- - }
- -
- - netdev_err(netdev, "mdio write timed out\n");
- -}
- -
- -/******************************************************************************
- - * struct ethtool_ops functions
- - *****************************************************************************/
- -static void ftmac100_get_drvinfo(struct net_device *netdev,
- - struct ethtool_drvinfo *info)
- -{
- - strcpy(info->driver, DRV_NAME);
- - strcpy(info->version, DRV_VERSION);
- - strcpy(info->bus_info, dev_name(&netdev->dev));
- -}
- -
- -static int ftmac100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
- -{
- - struct ftmac100 *priv = netdev_priv(netdev);
- - return mii_ethtool_gset(&priv->mii, cmd);
- -}
- -
- -static int ftmac100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
- -{
- - struct ftmac100 *priv = netdev_priv(netdev);
- - return mii_ethtool_sset(&priv->mii, cmd);
- -}
- -
- -static int ftmac100_nway_reset(struct net_device *netdev)
- +static int ftmac100_suspend(struct platform_device *pdev, pm_message_t state)
- {
- - struct ftmac100 *priv = netdev_priv(netdev);
- - return mii_nway_restart(&priv->mii);
- -}
- -
- -static u32 ftmac100_get_link(struct net_device *netdev)
- -{
- - struct ftmac100 *priv = netdev_priv(netdev);
- - return mii_link_ok(&priv->mii);
- -}
- -
- -static const struct ethtool_ops ftmac100_ethtool_ops = {
- - .set_settings = ftmac100_set_settings,
- - .get_settings = ftmac100_get_settings,
- - .get_drvinfo = ftmac100_get_drvinfo,
- - .nway_reset = ftmac100_nway_reset,
- - .get_link = ftmac100_get_link,
- -};
- -
- -/******************************************************************************
- - * interrupt handler
- - *****************************************************************************/
- -static irqreturn_t ftmac100_interrupt(int irq, void *dev_id)
- -{
- - struct net_device *netdev = dev_id;
- - struct ftmac100 *priv = netdev_priv(netdev);
- -
- - if (likely(netif_running(netdev))) {
- - /* Disable interrupts for polling */
- - ftmac100_disable_all_int(priv);
- - napi_schedule(&priv->napi);
- - }
- -
- - return IRQ_HANDLED;
- -}
- -
- -/******************************************************************************
- - * struct napi_struct functions
- - *****************************************************************************/
- -static int ftmac100_poll(struct napi_struct *napi, int budget)
- -{
- - struct ftmac100 *priv = container_of(napi, struct ftmac100, napi);
- - struct net_device *netdev = priv->netdev;
- - unsigned int status;
- - bool completed = true;
- - int rx = 0;
- -
- - status = ioread32(priv->base + FTMAC100_OFFSET_ISR);
- -
- - if (status & (FTMAC100_INT_RPKT_FINISH | FTMAC100_INT_NORXBUF)) {
- - /*
- - * FTMAC100_INT_RPKT_FINISH:
- - * RX DMA has received packets into RX buffer successfully
- - *
- - * FTMAC100_INT_NORXBUF:
- - * RX buffer unavailable
- - */
- - bool retry;
- -
- - do {
- - retry = ftmac100_rx_packet(priv, &rx);
- - } while (retry && rx < budget);
- + struct net_device *ndev = platform_get_drvdata(pdev);
-
- - if (retry && rx == budget)
- - completed = false;
- - }
- -
- - if (status & (FTMAC100_INT_XPKT_OK | FTMAC100_INT_XPKT_LOST)) {
- - /*
- - * FTMAC100_INT_XPKT_OK:
- - * packet transmitted to ethernet successfully
- - *
- - * FTMAC100_INT_XPKT_LOST:
- - * packet transmitted to ethernet lost due to late
- - * collision or excessive collision
- - */
- - ftmac100_tx_complete(priv);
- - }
- -
- - if (status & (FTMAC100_INT_NORXBUF | FTMAC100_INT_RPKT_LOST |
- - FTMAC100_INT_AHB_ERR | FTMAC100_INT_PHYSTS_CHG)) {
- - if (net_ratelimit())
- - netdev_info(netdev, "[ISR] = 0x%x: %s%s%s%s\n", status,
- - status & FTMAC100_INT_NORXBUF ? "NORXBUF " : "",
- - status & FTMAC100_INT_RPKT_LOST ? "RPKT_LOST " : "",
- - status & FTMAC100_INT_AHB_ERR ? "AHB_ERR " : "",
- - status & FTMAC100_INT_PHYSTS_CHG ? "PHYSTS_CHG" : "");
- -
- - if (status & FTMAC100_INT_NORXBUF) {
- - /* RX buffer unavailable */
- - netdev->stats.rx_over_errors++;
- - }
- -
- - if (status & FTMAC100_INT_RPKT_LOST) {
- - /* received packet lost due to RX FIFO full */
- - netdev->stats.rx_fifo_errors++;
- - }
- -
- - if (status & FTMAC100_INT_PHYSTS_CHG) {
- - /* PHY link status change */
- - mii_check_link(&priv->mii);
- + if (ndev) {
- + if (netif_running(ndev)) {
- + netif_device_detach(ndev);
- + ftmac100_shutdown(ndev->base_addr);
- }
- }
- -
- - if (completed) {
- - /* stop polling */
- - napi_complete(napi);
- - ftmac100_enable_all_int(priv);
- - }
- -
- - return rx;
- -}
- -
- -/******************************************************************************
- - * struct net_device_ops functions
- - *****************************************************************************/
- -static int ftmac100_open(struct net_device *netdev)
- -{
- - struct ftmac100 *priv = netdev_priv(netdev);
- - int err;
- -
- - err = ftmac100_alloc_buffers(priv);
- - if (err) {
- - netdev_err(netdev, "failed to allocate buffers\n");
- - goto err_alloc;
- - }
- -
- - err = request_irq(priv->irq, ftmac100_interrupt, 0, netdev->name, netdev);
- - if (err) {
- - netdev_err(netdev, "failed to request irq %d\n", priv->irq);
- - goto err_irq;
- - }
- -
- - priv->rx_pointer = 0;
- - priv->tx_clean_pointer = 0;
- - priv->tx_pointer = 0;
- - priv->tx_pending = 0;
- -
- - err = ftmac100_start_hw(priv);
- - if (err)
- - goto err_hw;
- -
- - napi_enable(&priv->napi);
- - netif_start_queue(netdev);
- -
- - ftmac100_enable_all_int(priv);
- -
- - return 0;
- -
- -err_hw:
- - free_irq(priv->irq, netdev);
- -err_irq:
- - ftmac100_free_buffers(priv);
- -err_alloc:
- - return err;
- -}
- -
- -static int ftmac100_stop(struct net_device *netdev)
- -{
- - struct ftmac100 *priv = netdev_priv(netdev);
- -
- - ftmac100_disable_all_int(priv);
- - netif_stop_queue(netdev);
- - napi_disable(&priv->napi);
- - ftmac100_stop_hw(priv);
- - free_irq(priv->irq, netdev);
- - ftmac100_free_buffers(priv);
- -
- return 0;
- }
-
- -static int ftmac100_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
- +static int ftmac100_resume(struct platform_device *pdev)
- {
- - struct ftmac100 *priv = netdev_priv(netdev);
- - dma_addr_t map;
- -
- - if (unlikely(skb->len > MAX_PKT_SIZE)) {
- - if (net_ratelimit())
- - netdev_dbg(netdev, "tx packet too big\n");
- -
- - netdev->stats.tx_dropped++;
- - dev_kfree_skb(skb);
- - return NETDEV_TX_OK;
- - }
- + struct net_device *ndev = platform_get_drvdata(pdev);
-
- - map = dma_map_single(priv->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
- - if (unlikely(dma_mapping_error(priv->dev, map))) {
- - /* drop packet */
- - if (net_ratelimit())
- - netdev_err(netdev, "map socket buffer failed\n");
- -
- - netdev->stats.tx_dropped++;
- - dev_kfree_skb(skb);
- - return NETDEV_TX_OK;
- + if (ndev) {
- + if (netif_running(ndev)) {
- + ftmac100_reset(ndev);
- + ftmac100_enable(ndev);
- + netif_device_attach(ndev);
- + }
- }
- -
- - return ftmac100_xmit(priv, skb, map);
- + return 0;
- }
-
- -/* optional */
- -static int ftmac100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
- -{
- - struct ftmac100 *priv = netdev_priv(netdev);
- - struct mii_ioctl_data *data = if_mii(ifr);
- -
- - return generic_mii_ioctl(&priv->mii, data, cmd, NULL);
- +static void platform_device_release(struct device *dev){
- }
-
- -static const struct net_device_ops ftmac100_netdev_ops = {
- - .ndo_open = ftmac100_open,
- - .ndo_stop = ftmac100_stop,
- - .ndo_start_xmit = ftmac100_hard_start_xmit,
- - .ndo_set_mac_address = eth_mac_addr,
- - .ndo_validate_addr = eth_validate_addr,
- - .ndo_do_ioctl = ftmac100_do_ioctl,
- +static struct platform_driver ftmac100_driver = {
- + .probe = ftmac100_probe,
- + .remove = ftmac100_remove,
- + .suspend = ftmac100_suspend,
- + .resume = ftmac100_resume,
- + .driver = {
- + .name = "ftmac100",
- + },
- };
-
- -/******************************************************************************
- - * struct platform_driver functions
- - *****************************************************************************/
- -static int ftmac100_probe(struct platform_device *pdev)
- -{
- - struct resource *res;
- - int irq;
- - struct net_device *netdev;
- - struct ftmac100 *priv;
- - int err;
- -
- - if (!pdev)
- - return -ENODEV;
- -
- - res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- - if (!res)
- - return -ENXIO;
- -
- - irq = platform_get_irq(pdev, 0);
- - if (irq < 0)
- - return irq;
- -
- - /* setup net_device */
- - netdev = alloc_etherdev(sizeof(*priv));
- - if (!netdev) {
- - err = -ENOMEM;
- - goto err_alloc_etherdev;
- - }
- -
- - SET_NETDEV_DEV(netdev, &pdev->dev);
- - SET_ETHTOOL_OPS(netdev, &ftmac100_ethtool_ops);
- - netdev->netdev_ops = &ftmac100_netdev_ops;
- -
- - platform_set_drvdata(pdev, netdev);
- -
- - /* setup private data */
- - priv = netdev_priv(netdev);
- - priv->netdev = netdev;
- - priv->dev = &pdev->dev;
- -
- - spin_lock_init(&priv->tx_lock);
- -
- - /* initialize NAPI */
- - netif_napi_add(netdev, &priv->napi, ftmac100_poll, 64);
- -
- - /* map io memory */
- - priv->res = request_mem_region(res->start, resource_size(res),
- - dev_name(&pdev->dev));
- - if (!priv->res) {
- - dev_err(&pdev->dev, "Could not reserve memory region\n");
- - err = -ENOMEM;
- - goto err_req_mem;
- - }
- -
- - priv->base = ioremap(res->start, resource_size(res));
- - if (!priv->base) {
- - dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
- - err = -EIO;
- - goto err_ioremap;
- - }
- -
- - priv->irq = irq;
- -
- - /* initialize struct mii_if_info */
- - priv->mii.phy_id = 0;
- - priv->mii.phy_id_mask = 0x1f;
- - priv->mii.reg_num_mask = 0x1f;
- - priv->mii.dev = netdev;
- - priv->mii.mdio_read = ftmac100_mdio_read;
- - priv->mii.mdio_write = ftmac100_mdio_write;
- -
- - /* register network device */
- - err = register_netdev(netdev);
- - if (err) {
- - dev_err(&pdev->dev, "Failed to register netdev\n");
- - goto err_register_netdev;
- - }
- -
- - netdev_info(netdev, "irq %d, mapped at %p\n", priv->irq, priv->base);
- -
- - if (!is_valid_ether_addr(netdev->dev_addr)) {
- - eth_hw_addr_random(netdev);
- - netdev_info(netdev, "generated random MAC address %pM\n",
- - netdev->dev_addr);
- - }
- -
- - return 0;
- -
- -err_register_netdev:
- - iounmap(priv->base);
- -err_ioremap:
- - release_resource(priv->res);
- -err_req_mem:
- - netif_napi_del(&priv->napi);
- - platform_set_drvdata(pdev, NULL);
- - free_netdev(netdev);
- -err_alloc_etherdev:
- - return err;
- -}
- -
- -static int __exit ftmac100_remove(struct platform_device *pdev)
- -{
- - struct net_device *netdev;
- - struct ftmac100 *priv;
- -
- - netdev = platform_get_drvdata(pdev);
- - priv = netdev_priv(netdev);
- -
- - unregister_netdev(netdev);
- -
- - iounmap(priv->base);
- - release_resource(priv->res);
- -
- - netif_napi_del(&priv->napi);
- - platform_set_drvdata(pdev, NULL);
- - free_netdev(netdev);
- - return 0;
- -}
- +static struct resource ftmac100_resources_a320[] = {
- + [0] = {
- + .start = MAC_FTMAC100_0_VA_BASE,
- + .end = MAC_FTMAC100_0_VA_LIMIT,
- + .flags = IORESOURCE_IO,
- + },
- + [1] = {
- + .start = MAC_FTMAC100_0_IRQ,
- + .flags = IORESOURCE_IRQ,
- + },
- +};
-
- -static struct platform_driver ftmac100_driver = {
- - .probe = ftmac100_probe,
- - .remove = __exit_p(ftmac100_remove),
- - .driver = {
- - .name = DRV_NAME,
- - .owner = THIS_MODULE,
- +static struct platform_device ftmac100_device_a320 = {
- + .name = "ftmac100",
- + .id = 0,
- + .num_resources = ARRAY_SIZE(ftmac100_resources_a320),
- + .resource = ftmac100_resources_a320,
- + .dev = {
- + .release = platform_device_release,
- },
- };
-
- -/******************************************************************************
- - * initialization / finalization
- - *****************************************************************************/
- +
- static int __init ftmac100_init(void)
- {
- - pr_info("Loading version " DRV_VERSION " ...\n");
- + platform_device_register(&ftmac100_device_a320);
- return platform_driver_register(&ftmac100_driver);
- }
-
- static void __exit ftmac100_exit(void)
- {
- platform_driver_unregister(&ftmac100_driver);
- + platform_device_unregister(&ftmac100_device_a320);
- }
-
- module_init(ftmac100_init);
- module_exit(ftmac100_exit);
- -
- -MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>");
- -MODULE_DESCRIPTION("FTMAC100 driver");
- -MODULE_LICENSE("GPL");
- diff -Nur linux-3.4.110.orig/drivers/net/ethernet/faraday/ftmac100.h linux-3.4.110/drivers/net/ethernet/faraday/ftmac100.h
- --- linux-3.4.110.orig/drivers/net/ethernet/faraday/ftmac100.h 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/net/ethernet/faraday/ftmac100.h 2016-04-07 10:20:51.054085357 +0200
- @@ -1,180 +1,267 @@
- /*
- - * Faraday FTMAC100 10/100 Ethernet
- + * drivers/net/ftmac100.h
- *
- - * (C) Copyright 2009-2011 Faraday Technology
- - * Po-Yu Chuang <ratbert@faraday-tech.com>
- + * Faraday FTMAC100 Device Driver
- *
- - * This program is free software; you can redistribute it and/or modify
- - * it under the terms of the GNU General Public License as published by
- - * the Free Software Foundation; either version 2 of the License, or
- - * (at your option) any later version.
- + * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
- + *
- + * All Rights Reserved
- *
- - * This program is distributed in the hope that it will be useful,
- - * but WITHOUT ANY WARRANTY; without even the implied warranty of
- - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- - * GNU General Public License for more details.
- - *
- - * You should have received a copy of the GNU General Public License
- - * along with this program; if not, write to the Free Software
- - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- - */
- -
- -#ifndef __FTMAC100_H
- -#define __FTMAC100_H
- -
- -#define FTMAC100_OFFSET_ISR 0x00
- -#define FTMAC100_OFFSET_IMR 0x04
- -#define FTMAC100_OFFSET_MAC_MADR 0x08
- -#define FTMAC100_OFFSET_MAC_LADR 0x0c
- -#define FTMAC100_OFFSET_MAHT0 0x10
- -#define FTMAC100_OFFSET_MAHT1 0x14
- -#define FTMAC100_OFFSET_TXPD 0x18
- -#define FTMAC100_OFFSET_RXPD 0x1c
- -#define FTMAC100_OFFSET_TXR_BADR 0x20
- -#define FTMAC100_OFFSET_RXR_BADR 0x24
- -#define FTMAC100_OFFSET_ITC 0x28
- -#define FTMAC100_OFFSET_APTC 0x2c
- -#define FTMAC100_OFFSET_DBLAC 0x30
- -#define FTMAC100_OFFSET_MACCR 0x88
- -#define FTMAC100_OFFSET_MACSR 0x8c
- -#define FTMAC100_OFFSET_PHYCR 0x90
- -#define FTMAC100_OFFSET_PHYWDATA 0x94
- -#define FTMAC100_OFFSET_FCR 0x98
- -#define FTMAC100_OFFSET_BPR 0x9c
- -#define FTMAC100_OFFSET_TS 0xc4
- -#define FTMAC100_OFFSET_DMAFIFOS 0xc8
- -#define FTMAC100_OFFSET_TM 0xcc
- -#define FTMAC100_OFFSET_TX_MCOL_SCOL 0xd4
- -#define FTMAC100_OFFSET_RPF_AEP 0xd8
- -#define FTMAC100_OFFSET_XM_PG 0xdc
- -#define FTMAC100_OFFSET_RUNT_TLCC 0xe0
- -#define FTMAC100_OFFSET_CRCER_FTL 0xe4
- -#define FTMAC100_OFFSET_RLC_RCC 0xe8
- -#define FTMAC100_OFFSET_BROC 0xec
- -#define FTMAC100_OFFSET_MULCA 0xf0
- -#define FTMAC100_OFFSET_RP 0xf4
- -#define FTMAC100_OFFSET_XP 0xf8
- -
- -/*
- - * Interrupt status register & interrupt mask register
- - */
- -#define FTMAC100_INT_RPKT_FINISH (1 << 0)
- -#define FTMAC100_INT_NORXBUF (1 << 1)
- -#define FTMAC100_INT_XPKT_FINISH (1 << 2)
- -#define FTMAC100_INT_NOTXBUF (1 << 3)
- -#define FTMAC100_INT_XPKT_OK (1 << 4)
- -#define FTMAC100_INT_XPKT_LOST (1 << 5)
- -#define FTMAC100_INT_RPKT_SAV (1 << 6)
- -#define FTMAC100_INT_RPKT_LOST (1 << 7)
- -#define FTMAC100_INT_AHB_ERR (1 << 8)
- -#define FTMAC100_INT_PHYSTS_CHG (1 << 9)
- -
- -/*
- - * Interrupt timer control register
- */
- -#define FTMAC100_ITC_RXINT_CNT(x) (((x) & 0xf) << 0)
- -#define FTMAC100_ITC_RXINT_THR(x) (((x) & 0x7) << 4)
- -#define FTMAC100_ITC_RXINT_TIME_SEL (1 << 7)
- -#define FTMAC100_ITC_TXINT_CNT(x) (((x) & 0xf) << 8)
- -#define FTMAC100_ITC_TXINT_THR(x) (((x) & 0x7) << 12)
- -#define FTMAC100_ITC_TXINT_TIME_SEL (1 << 15)
-
- -/*
- - * Automatic polling timer control register
- - */
- -#define FTMAC100_APTC_RXPOLL_CNT(x) (((x) & 0xf) << 0)
- -#define FTMAC100_APTC_RXPOLL_TIME_SEL (1 << 4)
- -#define FTMAC100_APTC_TXPOLL_CNT(x) (((x) & 0xf) << 8)
- -#define FTMAC100_APTC_TXPOLL_TIME_SEL (1 << 12)
- +#ifndef _FTMAC100_H_
- +#define _FTMAC100_H_
-
- -/*
- - * DMA burst length and arbitration control register
- - */
- -#define FTMAC100_DBLAC_INCR4_EN (1 << 0)
- -#define FTMAC100_DBLAC_INCR8_EN (1 << 1)
- -#define FTMAC100_DBLAC_INCR16_EN (1 << 2)
- -#define FTMAC100_DBLAC_RXFIFO_LTHR(x) (((x) & 0x7) << 3)
- -#define FTMAC100_DBLAC_RXFIFO_HTHR(x) (((x) & 0x7) << 6)
- -#define FTMAC100_DBLAC_RX_THR_EN (1 << 9)
- +#define ISR_REG 0x00 // interrups status register
- +#define IMR_REG 0x04 // interrupt maks register
- +#define MAC_MADR_REG 0x08 // MAC address (Most significant)
- +#define MAC_LADR_REG 0x0c // MAC address (Least significant)
- +
- +#define MAHT0_REG 0x10 // Multicast Address Hash Table 0 register
- +#define MAHT1_REG 0x14 // Multicast Address Hash Table 1 register
- +#define TXPD_REG 0x18 // Transmit Poll Demand register
- +#define RXPD_REG 0x1c // Receive Poll Demand register
- +#define TXR_BADR_REG 0x20 // Transmit Ring Base Address register
- +#define RXR_BADR_REG 0x24 // Receive Ring Base Address register
- +#define ITC_REG 0x28 // interrupt timer control register
- +#define APTC_REG 0x2c // Automatic Polling Timer control register
- +#define DBLAC_REG 0x30 // DMA Burst Length and Arbitration control register
- +
- +
- +
- +#define MACCR_REG 0x88 // MAC control register
- +#define MACSR_REG 0x8c // MAC status register
- +#define PHYCR_REG 0x90 // PHY control register
- +#define PHYWDATA_REG 0x94 // PHY Write Data register
- +#define FCR_REG 0x98 // Flow Control register
- +#define BPR_REG 0x9c // back pressure register
- +#define WOLCR_REG 0xa0 // Wake-On-Lan control register
- +#define WOLSR_REG 0xa4 // Wake-On-Lan status register
- +#define WFCRC_REG 0xa8 // Wake-up Frame CRC register
- +#define WFBM1_REG 0xb0 // wake-up frame byte mask 1st double word register
- +#define WFBM2_REG 0xb4 // wake-up frame byte mask 2nd double word register
- +#define WFBM3_REG 0xb8 // wake-up frame byte mask 3rd double word register
- +#define WFBM4_REG 0xbc // wake-up frame byte mask 4th double word register
- +#define TM_REG 0xcc // test mode register
- +
- +#define PHYSTS_CHG_bit (1UL<<9)
- +#define AHB_ERR_bit (1UL<<8)
- +#define RPKT_LOST_bit (1UL<<7)
- +#define RPKT_SAV_bit (1UL<<6)
- +#define XPKT_LOST_bit (1UL<<5)
- +#define XPKT_OK_bit (1UL<<4)
- +#define NOTXBUF_bit (1UL<<3)
- +#define XPKT_FINISH_bit (1UL<<2)
- +#define NORXBUF_bit (1UL<<1)
- +#define RPKT_FINISH_bit (1UL<<0)
- +
- +
- +#ifdef __NDS32_EB__
- +typedef struct
- +{
- + unsigned int Reserved2:19;
- + unsigned int TXPOLL_TIME_SEL:1;
- + unsigned int TXPOLL_CNT:4;
- + unsigned int Reserved1:3;
- + unsigned int RXPOLL_TIME_SEL:1;
- + unsigned int RXPOLL_CNT:4;
- +}FTMAC100_APTCR_Status;
- +#else
- +typedef struct
- +{
- + unsigned int RXPOLL_CNT:4;
- + unsigned int RXPOLL_TIME_SEL:1;
- + unsigned int Reserved1:3;
- + unsigned int TXPOLL_CNT:4;
- + unsigned int TXPOLL_TIME_SEL:1;
- + unsigned int Reserved2:19;
- +} FTMAC100_APTCR_Status;
- +#endif
- +
- +#define RX_BROADPKT_bit (1UL<<17) // Receiving broadcast packet
- +#define RX_MULTIPKT_bit (1UL<<16) // receiving multicast packet
- +#define FULLDUP_bit (1UL<<15) // full duplex
- +#define CRC_APD_bit (1UL<<14) // append crc to transmit packet
- +#define MDC_SEL_bit (1UL<<13) // set MDC as TX_CK/10
- +#define RCV_ALL_bit (1UL<<12) // not check incoming packet's destination address
- +#define RX_FTL_bit (1UL<<11) // Store incoming packet even its length is great than 1518 byte
- +#define RX_RUNT_bit (1UL<<10) // Store incoming packet even its length is les than 64 byte
- +#define HT_MULTI_EN_bit (1UL<<9)
- +#define RCV_EN_bit (1UL<<8) // receiver enable
- +#define XMT_EN_bit (1UL<<5) // transmitter enable
- +#define CRC_DIS_bit (1UL<<4)
- +#define LOOP_EN_bit (1UL<<3) // Internal loop-back
- +#define SW_RST_bit (1UL<<2) // software reset/
- +#define RDMA_EN_bit (1UL<<1) // enable DMA receiving channel
- +#define XDMA_EN_bit (1UL<<0) // enable DMA transmitting channel
- +
- +
- +// --------------------------------------------------------------------
- +// Receive Ring descriptor structure
- +// --------------------------------------------------------------------
- +#ifdef __NDS32_EB__
- +typedef struct
- +{
- + // RXDES0
- + unsigned int RXDMA_OWN:1; // 1 ==> owned by FTMAC100, 0 ==> owned by software
- + unsigned int Reserved3:1;
- + unsigned int FRS:1;
- + unsigned int LRS:1;
- + unsigned int Reserved2:5;
- + unsigned int RX_ODD_NB:1;
- + unsigned int RUNT:1;
- + unsigned int FTL:1;
- + unsigned int CRC_ERR:1; //19
- + unsigned int RX_ERR:1; //18
- + unsigned int BROARDCAST:1; //17
- + unsigned int MULTICAST:1; //16
- + unsigned int Reserved1:5; //11~15
- + unsigned int ReceiveFrameLength:11;//0~10
- +
- + // RXDES1
- + unsigned int EDOTR:1;
- + unsigned int Reserved:20;
- + unsigned int RXBUF_Size:11;
- +
- + // RXDES2
- + unsigned int RXBUF_BADR;
- +
- + unsigned int VIR_RXBUF_BADR; // not defined, 我們拿來放 receive buffer 的 virtual address
- +
- +}RX_DESC;
- +
- +
- +typedef struct
- +{
- + // TXDES0
- + unsigned int TXDMA_OWN:1;
- + unsigned int Reserved1:29;
- + unsigned int TXPKT_EXSCOL:1;
- + unsigned int TXPKT_LATECOL:1;
- +
- + // TXDES1
- + unsigned int EDOTR:1;
- + unsigned int TXIC:1;
- + unsigned int TX2FIC:1;
- + unsigned int FTS:1;
- + unsigned int LTS:1;
- + unsigned int Reserved2:16;
- + unsigned int TXBUF_Size:11;
- +
- + // RXDES2
- + unsigned int TXBUF_BADR;
- + unsigned int VIR_TXBUF_BADR;
- +}TX_DESC;
- +#else
- +typedef struct
- +{
- + // RXDES0
- + unsigned int ReceiveFrameLength:11;//0~10
- + unsigned int Reserved1:5; //11~15
- + unsigned int MULTICAST:1; //16
- + unsigned int BROARDCAST:1; //17
- + unsigned int RX_ERR:1; //18
- + unsigned int CRC_ERR:1; //19
- + unsigned int FTL:1;
- + unsigned int RUNT:1;
- + unsigned int RX_ODD_NB:1;
- + unsigned int Reserved2:5;
- + unsigned int LRS:1;
- + unsigned int FRS:1;
- + unsigned int Reserved3:1;
- + unsigned int RXDMA_OWN:1; // 1 ==> owned by FTMAC100, 0 ==> owned by software
- +
- + // RXDES1
- + unsigned int RXBUF_Size:11;
- + unsigned int Reserved:20;
- + unsigned int EDOTR:1;
- +
- + // RXDES2
- + unsigned int RXBUF_BADR;
- +
- + unsigned int VIR_RXBUF_BADR; // not defined, 我們拿來放 receive buffer 的 virtual address
- +
- +} RX_DESC;
- +
- +
- +typedef struct
- +{
- + // TXDES0
- + unsigned int TXPKT_LATECOL:1;
- + unsigned int TXPKT_EXSCOL:1;
- + unsigned int Reserved1:29;
- + unsigned int TXDMA_OWN:1;
- +
- + // TXDES1
- + unsigned int TXBUF_Size:11;
- + unsigned int Reserved2:16;
- + unsigned int LTS:1;
- + unsigned int FTS:1;
- + unsigned int TX2FIC:1;
- + unsigned int TXIC:1;
- + unsigned int EDOTR:1;
- +
- + // RXDES2
- + unsigned int TXBUF_BADR;
- + unsigned int VIR_TXBUF_BADR;
- +} TX_DESC;
- +#endif
- +
- +// waiting to do:
- +#define TXPOLL_CNT 8
- +#define RXPOLL_CNT 0
- +
- +#define OWNBY_SOFTWARE 0
- +#define OWNBY_FTMAC100 1
- +
- +// --------------------------------------------------------------------
- +// driver related definition
- +// --------------------------------------------------------------------
- +#define RXDES_NUM 256 // must be 2's power
- +#define RX_BUF_SIZE 1536
- +#define TXDES_NUM 64 // must be 2's power
- +#define TX_BUF_SIZE 1536 // Luke Lee : Just bigger than 1518
- +
- +
- +struct ftmac100_local
- +{
- + // these are things that the kernel wants me to keep, so users
- + // can find out semi-useless statistics of how well the card is
- + // performing
- + struct net_device_stats stats;
- +
- + // Set to true during the auto-negotiation sequence
- + int autoneg_active;
- +
- + // Address of our PHY port
- + unsigned int phyaddr;
- +
- + // Type of PHY
- + unsigned int phytype;
- +
- + // Last contents of PHY Register 18
- + unsigned int lastPhy18;
- +
- + spinlock_t lock;
- +
- + volatile RX_DESC *rx_descs; // receive ring base address
- + unsigned int rx_descs_dma; // receive ring physical base address
- + char *rx_buf; // receive buffer cpu address
- + int rx_buf_dma; // receive buffer physical address
- + int rx_idx; // receive descriptor
- + //struct sk_buff *rx_skbuff[RXDES_NUM];
- +
- + volatile TX_DESC *tx_descs;
- + unsigned int tx_descs_dma;
- + char *tx_buf;
- + int tx_buf_dma;
- + int tx_idx;
- + int old_tx;
- + struct sk_buff *tx_skbuff[RXDES_NUM];
- +
- + int maccr_val;
- +};
-
- -/*
- - * MAC control register
- - */
- -#define FTMAC100_MACCR_XDMA_EN (1 << 0)
- -#define FTMAC100_MACCR_RDMA_EN (1 << 1)
- -#define FTMAC100_MACCR_SW_RST (1 << 2)
- -#define FTMAC100_MACCR_LOOP_EN (1 << 3)
- -#define FTMAC100_MACCR_CRC_DIS (1 << 4)
- -#define FTMAC100_MACCR_XMT_EN (1 << 5)
- -#define FTMAC100_MACCR_ENRX_IN_HALFTX (1 << 6)
- -#define FTMAC100_MACCR_RCV_EN (1 << 8)
- -#define FTMAC100_MACCR_HT_MULTI_EN (1 << 9)
- -#define FTMAC100_MACCR_RX_RUNT (1 << 10)
- -#define FTMAC100_MACCR_RX_FTL (1 << 11)
- -#define FTMAC100_MACCR_RCV_ALL (1 << 12)
- -#define FTMAC100_MACCR_CRC_APD (1 << 14)
- -#define FTMAC100_MACCR_FULLDUP (1 << 15)
- -#define FTMAC100_MACCR_RX_MULTIPKT (1 << 16)
- -#define FTMAC100_MACCR_RX_BROADPKT (1 << 17)
- -
- -/*
- - * PHY control register
- - */
- -#define FTMAC100_PHYCR_MIIRDATA 0xffff
- -#define FTMAC100_PHYCR_PHYAD(x) (((x) & 0x1f) << 16)
- -#define FTMAC100_PHYCR_REGAD(x) (((x) & 0x1f) << 21)
- -#define FTMAC100_PHYCR_MIIRD (1 << 26)
- -#define FTMAC100_PHYCR_MIIWR (1 << 27)
- -
- -/*
- - * PHY write data register
- - */
- -#define FTMAC100_PHYWDATA_MIIWDATA(x) ((x) & 0xffff)
- -
- -/*
- - * Transmit descriptor, aligned to 16 bytes
- - */
- -struct ftmac100_txdes {
- - unsigned int txdes0;
- - unsigned int txdes1;
- - unsigned int txdes2; /* TXBUF_BADR */
- - unsigned int txdes3; /* not used by HW */
- -} __attribute__ ((aligned(16)));
- -
- -#define FTMAC100_TXDES0_TXPKT_LATECOL (1 << 0)
- -#define FTMAC100_TXDES0_TXPKT_EXSCOL (1 << 1)
- -#define FTMAC100_TXDES0_TXDMA_OWN (1 << 31)
- -
- -#define FTMAC100_TXDES1_TXBUF_SIZE(x) ((x) & 0x7ff)
- -#define FTMAC100_TXDES1_LTS (1 << 27)
- -#define FTMAC100_TXDES1_FTS (1 << 28)
- -#define FTMAC100_TXDES1_TX2FIC (1 << 29)
- -#define FTMAC100_TXDES1_TXIC (1 << 30)
- -#define FTMAC100_TXDES1_EDOTR (1 << 31)
- -
- -/*
- - * Receive descriptor, aligned to 16 bytes
- - */
- -struct ftmac100_rxdes {
- - unsigned int rxdes0;
- - unsigned int rxdes1;
- - unsigned int rxdes2; /* RXBUF_BADR */
- - unsigned int rxdes3; /* not used by HW */
- -} __attribute__ ((aligned(16)));
- -
- -#define FTMAC100_RXDES0_RFL 0x7ff
- -#define FTMAC100_RXDES0_MULTICAST (1 << 16)
- -#define FTMAC100_RXDES0_BROADCAST (1 << 17)
- -#define FTMAC100_RXDES0_RX_ERR (1 << 18)
- -#define FTMAC100_RXDES0_CRC_ERR (1 << 19)
- -#define FTMAC100_RXDES0_FTL (1 << 20)
- -#define FTMAC100_RXDES0_RUNT (1 << 21)
- -#define FTMAC100_RXDES0_RX_ODD_NB (1 << 22)
- -#define FTMAC100_RXDES0_LRS (1 << 28)
- -#define FTMAC100_RXDES0_FRS (1 << 29)
- -#define FTMAC100_RXDES0_RXDMA_OWN (1 << 31)
- +#endif
-
- -#define FTMAC100_RXDES1_RXBUF_SIZE(x) ((x) & 0x7ff)
- -#define FTMAC100_RXDES1_EDORR (1 << 31)
-
- -#endif /* __FTMAC100_H */
- diff -Nur linux-3.4.110.orig/drivers/net/ethernet/faraday/Kconfig linux-3.4.110/drivers/net/ethernet/faraday/Kconfig
- --- linux-3.4.110.orig/drivers/net/ethernet/faraday/Kconfig 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/net/ethernet/faraday/Kconfig 2016-04-07 10:20:51.054085357 +0200
- @@ -5,7 +5,7 @@
- config NET_VENDOR_FARADAY
- bool "Faraday devices"
- default y
- - depends on ARM
- + depends on ARM || NDS32
- ---help---
- If you have a network (Ethernet) card belonging to this class, say Y
- and read the Ethernet-HOWTO, available from
- @@ -20,7 +20,7 @@
-
- config FTMAC100
- tristate "Faraday FTMAC100 10/100 Ethernet support"
- - depends on ARM
- + depends on ARM || NDS32
- select NET_CORE
- select MII
- ---help---
- diff -Nur linux-3.4.110.orig/drivers/pci/Makefile linux-3.4.110/drivers/pci/Makefile
- --- linux-3.4.110.orig/drivers/pci/Makefile 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/pci/Makefile 2016-04-07 10:20:51.054085357 +0200
- @@ -49,6 +49,7 @@
- obj-$(CONFIG_MICROBLAZE) += setup-bus.o
- obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o
- obj-$(CONFIG_SPARC_LEON) += setup-bus.o setup-irq.o
- +obj-$(CONFIG_NDS32) += setup-bus.o setup-irq.o
-
- #
- # ACPI Related PCI FW Functions
- diff -Nur linux-3.4.110.orig/drivers/rtc/Kconfig linux-3.4.110/drivers/rtc/Kconfig
- --- linux-3.4.110.orig/drivers/rtc/Kconfig 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/rtc/Kconfig 2016-04-07 10:20:51.054085357 +0200
- @@ -779,6 +779,16 @@
- This driver can also be built as a module. If so, the module
- will be called rtc-ep93xx.
-
- +config RTC_DRV_FTRTC010
- + tristate "Faraday Real Time Clock"
- + depends on NDS32
- + help
- + If you say Y here you will get access to the real time clock
- + built into your AG101 CPU.
- +
- + To compile this driver as a module, choose M here: the
- + module will be called rtc-ftrtc010.
- +
- config RTC_DRV_SA1100
- tristate "SA11x0/PXA2xx/PXA910"
- depends on ARCH_SA1100 || ARCH_PXA || ARCH_MMP
- diff -Nur linux-3.4.110.orig/drivers/rtc/Makefile linux-3.4.110/drivers/rtc/Makefile
- --- linux-3.4.110.orig/drivers/rtc/Makefile 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/rtc/Makefile 2016-04-07 10:20:51.054085357 +0200
- @@ -50,6 +50,7 @@
- obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o
- obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o
- obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o
- +obj-$(CONFIG_RTC_DRV_FTRTC010) += rtc-ftrtc010.o
- obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
- obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o
- obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o
- diff -Nur linux-3.4.110.orig/drivers/rtc/rtc-ftrtc010.c linux-3.4.110/drivers/rtc/rtc-ftrtc010.c
- --- linux-3.4.110.orig/drivers/rtc/rtc-ftrtc010.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/rtc/rtc-ftrtc010.c 2016-04-07 10:20:51.054085357 +0200
- @@ -0,0 +1,371 @@
- +/*
- + * Faraday RTC Support
- + *
- + * Copyright (C) 2006, 2007, 2008 Paul Mundt
- + * Copyright (C) 2006 Jamie Lenehan
- + * Copyright (C) 2008 Angelo Castello
- + * Copyright (C) 2008 Roy Lee
- + *
- + * Based on the old arch/sh/kernel/cpu/rtc.c by:
- + *
- + * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
- + *
- + * This file is subject to the terms and conditions of the GNU General Public
- + * License. See the file "COPYING" in the main directory of this archive
- + * for more details.
- + */
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/rtc.h>
- +#include <linux/delay.h>
- +#include <linux/init.h>
- +#include <linux/platform_device.h>
- +#include <linux/seq_file.h>
- +#include <linux/interrupt.h>
- +#include <linux/io.h>
- +
- +#define PCLK ( AHB_CLK_IN / 2)
- +
- +#define DRV_NAME "faraday-rtc"
- +
- +#define RTC_REG( off) ( *( volatile unsigned long *)( rtc->regbase + ( off)))
- +
- +#define RTC_CR RTC_REG( 0x20) /* Control */
- +#define RTC_CR_IE ( 0x1UL << 0)
- +#define RTC_CR_IES ( 0x1UL << 1)
- +#define RTC_CR_IEM ( 0x1UL << 2)
- +#define RTC_CR_IEH ( 0x1UL << 3)
- +#define RTC_CR_IED ( 0x1UL << 4)
- +#define RTC_CR_ALRM ( 0x1UL << 5)
- +#define RTC_CR_LOAD ( 0x1UL << 6)
- +
- +#define RTC_RR RTC_REG( 0x1C) /* RTC Record Register */
- +#define RTC_DIV RTC_REG( 0x38) /* RTC Divede Register */
- +#define RTC_REV RTC_REG( 0x3C) /* RTC Divede Register */
- +
- +#define RTC_IR RTC_REG( 0x34) /* RTC interrupt state */
- +#define RTC_IR_IES ( 0x1UL << 0) /* RTC interrupt state */
- +#define RTC_IR_IEM ( 0x1UL << 1) /* RTC interrupt state */
- +#define RTC_IR_IEH ( 0x1UL << 2) /* RTC interrupt state */
- +#define RTC_IR_IED ( 0x1UL << 3) /* RTC interrupt state */
- +#define RTC_IR_ALRM ( 0x1UL << 4) /* RTC interrupt state */
- +
- +#define RTC_SECOND RTC_REG( 0x00) /* RTC sec */
- +#define RTC_MINUTE RTC_REG( 0x04) /* RTC min */
- +#define RTC_HOUR RTC_REG( 0x08) /* RTC hour */
- +#define RTC_DAYS RTC_REG( 0x0C) /* RTC day */
- +
- +#define RTC_ALRM_SECOND RTC_REG( 0x10) /* RTC alarm sec */
- +#define RTC_ALRM_MINUTE RTC_REG( 0x14) /* RTC alarm min */
- +#define RTC_ALRM_HOUR RTC_REG( 0x18) /* RTC alarm hour */
- +
- +#define RTC_WRITE_SECOND RTC_REG( 0x24) /* RTC write port for sec */
- +#define RTC_WRITE_MINUTE RTC_REG( 0x28) /* RTC write port for min */
- +#define RTC_WRITE_HOUR RTC_REG( 0x2C) /* RTC write port for hour */
- +#define RTC_WRITE_DAYS RTC_REG( 0x30) /* RTC write port for day */
- +
- +struct ft_rtc{
- +
- + void __iomem *regbase;
- + struct resource *res;
- + unsigned int alarm_irq;
- + unsigned int interrupt_irq;
- + struct rtc_device *rtc_dev;
- + spinlock_t lock; /* Protects this structure */
- +};
- +
- +struct ft_rtc rtc_platform_data;
- +
- +static irqreturn_t ft_rtc_interrupt( int irq, void *dev_id){
- +
- + struct ft_rtc *rtc = dev_id;
- + if( RTC_IR & RTC_IR_IES){
- +
- + RTC_IR &= ~RTC_IR_IES;
- + rtc_update_irq( rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
- +
- + return IRQ_HANDLED;
- + }
- +
- + return IRQ_NONE;
- +}
- +
- +static irqreturn_t ft_rtc_alarm( int irq, void *dev_id){
- +
- + struct ft_rtc *rtc = dev_id;
- + if( RTC_IR & RTC_IR_ALRM){
- +
- + RTC_CR &= ~RTC_CR_ALRM;
- + RTC_IR &= ~RTC_IR_ALRM;
- + rtc_update_irq( rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
- +
- + return IRQ_HANDLED;
- + }
- +
- + return IRQ_NONE;
- +}
- +
- +static void ft_rtc_release( struct device *dev){
- +
- + struct ft_rtc *rtc = dev_get_drvdata( dev);
- +
- + RTC_CR &= ~RTC_CR_IES;
- + RTC_CR &= ~RTC_CR_ALRM;
- +}
- +
- +/* rick add */
- +static int ft_alarm_irq_enable(struct device *dev, unsigned int enabled)
- +{
- +// printk("\n\nft_alarm_irq_enable\n\n");
- +
- + struct ft_rtc *rtc = dev_get_drvdata( dev);
- + spin_lock_irq(&rtc->lock);
- + if (enabled)
- + RTC_CR |= RTC_CR_ALRM;
- + else
- + RTC_CR &= ~RTC_CR_ALRM;
- + spin_unlock_irq(&rtc->lock);
- + return 0;
- +}
- +
- +static int ft_rtc_read_time( struct device *dev, struct rtc_time *tm){
- + struct ft_rtc *rtc = dev_get_drvdata( dev);
- + unsigned long time = RTC_DAYS * 86400 + RTC_HOUR * 3600 + RTC_MINUTE * 60 + RTC_SECOND;
- + rtc_time_to_tm( time, tm);
- + if( rtc_valid_tm( tm) < 0) {
- + dev_err( dev, "invalid date\n");
- + rtc_time_to_tm( 0, tm);
- + }
- + return 0;
- +}
- +
- +static int ft_rtc_set_time( struct device *dev, struct rtc_time *tm){
- +
- + struct ft_rtc *rtc = dev_get_drvdata( dev);
- + unsigned long time = 0;
- +
- + rtc_tm_to_time( tm, &time);
- +
- + RTC_WRITE_DAYS = time / 86400;
- + time %= 86400;
- +
- + RTC_WRITE_HOUR = time / 3600;
- + time %= 3600;
- +
- + RTC_WRITE_MINUTE = time / 60;
- + time %= 60;
- +
- + RTC_WRITE_SECOND = time;
- +
- + RTC_CR |= RTC_CR_LOAD;
- +
- + return 0;
- +}
- +
- +static int ft_rtc_read_alarm( struct device *dev, struct rtc_wkalrm *wkalrm){
- +
- + struct ft_rtc *rtc = dev_get_drvdata( dev);
- + struct rtc_time *tm = &wkalrm->time;
- +
- + tm->tm_sec = RTC_ALRM_SECOND;
- + tm->tm_min = RTC_ALRM_MINUTE;
- + tm->tm_hour = RTC_ALRM_HOUR;
- +
- + wkalrm->enabled = ( RTC_CR & RTC_CR_ALRM) ? 1 : 0;
- +
- + return 0;
- +}
- +
- +static int ft_rtc_set_alarm( struct device *dev, struct rtc_wkalrm *wkalrm){
- +
- + struct ft_rtc *rtc = dev_get_drvdata( dev);
- + struct rtc_time *tm = &wkalrm->time;
- + int err = rtc_valid_tm( tm);
- + if( err < 0){
- +
- + dev_err( dev, "invalid alarm value\n");
- + return err;
- + }
- +
- + /* disable alarm interrupt and clear the alarm flag */
- + RTC_CR &= ~RTC_CR_ALRM;
- +
- + /* set alarm time */
- + RTC_ALRM_SECOND = tm->tm_sec;
- + RTC_ALRM_MINUTE = tm->tm_min;
- + RTC_ALRM_HOUR = tm->tm_hour;
- +
- + if( wkalrm->enabled)
- + RTC_CR |= RTC_CR_ALRM;
- +
- + return 0;
- +}
- +
- +/*
- +static int ft_rtc_irq_set_state( struct device *dev, int enabled){
- + struct ft_rtc *rtc = dev_get_drvdata( dev);
- + if( enabled)
- + RTC_CR |= RTC_CR_IES;
- + else
- + RTC_CR &= ~RTC_CR_IES;
- +
- + return 0;
- +}
- +
- +*/
- +
- +static struct rtc_class_ops ft_rtc_ops = {
- +
- + .release = ft_rtc_release,
- + .alarm_irq_enable = ft_alarm_irq_enable,
- +
- + .read_time = ft_rtc_read_time,
- + .set_time = ft_rtc_set_time,
- + .read_alarm = ft_rtc_read_alarm,
- + .set_alarm = ft_rtc_set_alarm,
- +};
- +
- +static int __devinit ft_rtc_probe( struct platform_device *pdev){
- +
- + struct ft_rtc *rtc = &rtc_platform_data;
- + int ret = -ENOENT;
- + spin_lock_init(&rtc->lock);
- +
- + if( ( rtc->alarm_irq = platform_get_irq( pdev, 0)) < 0)
- + goto err_exit;
- +
- + if( ( rtc->interrupt_irq = platform_get_irq( pdev, 1)) < 0)
- + goto err_exit;
- +
- + if( !( rtc->res = platform_get_resource( pdev, IORESOURCE_MEM, 0)))
- + goto err_exit;
- +
- + if( ( ret = request_irq( rtc->alarm_irq , ft_rtc_alarm, 0, "RTC Alarm : ftrtc010", rtc)))
- + goto err_exit;
- +
- + if( ( ret = request_irq( rtc->interrupt_irq , ft_rtc_interrupt, 0, "RTC Interrupt : ftrtc010", rtc)))
- + goto err_interrupt_irq;
- +
- + ret = -EBUSY;
- +
- + if( !( rtc->res = request_mem_region( rtc->res->start, rtc->res->end - rtc->res->start + 1, pdev->name)))
- + goto err_request_region;
- +
- + ret = -EINVAL;
- +
- + if( !( rtc->regbase = ioremap_nocache( rtc->res->start, rtc->res->end - rtc->res->start + 1)))
- + goto err_ioremap1;
- +
- +
- + //RTC_DIV = ( 0x1UL << 31) | 2; /* AG101 */
- + RTC_CR |= RTC_CR_IE;
- + platform_set_drvdata( pdev, rtc);
- + device_init_wakeup(&pdev->dev, true);
- +
- + rtc->rtc_dev = rtc_device_register( DRV_NAME, &pdev->dev, &ft_rtc_ops, THIS_MODULE);
- +
- + if( IS_ERR( rtc->rtc_dev)) {
- +
- + ret = PTR_ERR( rtc->rtc_dev);
- + goto err_unmap;
- + }
- +
- + rtc->rtc_dev->max_user_freq = 256;
- + rtc->rtc_dev->irq_freq = 1;
- + return 0;
- +
- +err_unmap:
- + iounmap( rtc->regbase);
- +err_ioremap1:
- + release_resource( rtc->res);
- +err_request_region:
- + free_irq( rtc->interrupt_irq, rtc);
- +err_interrupt_irq:
- + free_irq( rtc->alarm_irq, rtc);
- +err_exit:
- + return ret;
- +}
- +
- +static int __devexit ft_rtc_remove( struct platform_device *pdev){
- +
- + struct ft_rtc *rtc = platform_get_drvdata( pdev);
- +
- + rtc_device_unregister( rtc->rtc_dev);
- +
- + RTC_CR &= ~RTC_CR_ALRM;
- +
- + free_irq( rtc->alarm_irq, rtc);
- + free_irq( rtc->interrupt_irq, rtc);
- +
- + iounmap( rtc->regbase);
- +
- + platform_set_drvdata( pdev, NULL);
- +
- + return 0;
- +}
- +
- +static void platform_device_release(struct device *dev){
- +}
- +
- +static struct resource rtc_resources[] = {
- + {
- + .start = RTC_FTRTC010_PA_BASE,
- + .end = RTC_FTRTC010_PA_LIMIT,
- + .flags = IORESOURCE_MEM,
- + },
- + {
- + .start = RTC_FTRTC010_IRQ0,
- + .end = RTC_FTRTC010_IRQ0,
- + .flags = IORESOURCE_IRQ,
- + },
- + {
- + .start = RTC_FTRTC010_IRQ1,
- + .end = RTC_FTRTC010_IRQ1,
- + .flags = IORESOURCE_IRQ,
- + },
- +};
- +
- +static struct platform_driver ft_rtc_platform_driver = {
- +
- + .driver = {
- + .name = DRV_NAME,
- + .owner = THIS_MODULE,
- + },
- + .probe = ft_rtc_probe,
- + .remove = __devexit_p( ft_rtc_remove),
- +};
- +
- +static struct platform_device rtc_device = {
- +
- + .name = DRV_NAME,
- + .id = 0,
- + .resource = rtc_resources,
- + .num_resources = ARRAY_SIZE( rtc_resources),
- + .dev = {
- + .platform_data = &rtc_platform_data,
- + .release = platform_device_release,
- + },
- +};
- +
- +static int __init ft_rtc_init( void){
- + platform_device_register( &rtc_device);
- + return platform_driver_register( &ft_rtc_platform_driver);
- +}
- +
- +static void __exit ft_rtc_exit( void){
- +
- + platform_driver_unregister( &ft_rtc_platform_driver);
- + platform_device_unregister( &rtc_device);
- +}
- +
- +module_init( ft_rtc_init);
- +module_exit( ft_rtc_exit);
- +
- +MODULE_DESCRIPTION( "SuperH on-chip RTC driver");
- +MODULE_AUTHOR( "Paul Mundt <lethal@linux-sh.org>, "
- + "Jamie Lenehan <lenehan@twibble.org>, "
- + "Angelo Castello <angelo.castello@st.com>, "
- + "Roy Lee <roylee@andestech.com>");
- +MODULE_LICENSE( "GPL");
- +MODULE_ALIAS( "platform:" DRV_NAME);
- diff -Nur linux-3.4.110.orig/drivers/tty/serial/8250/8250.c linux-3.4.110/drivers/tty/serial/8250/8250.c
- --- linux-3.4.110.orig/drivers/tty/serial/8250/8250.c 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/tty/serial/8250/8250.c 2016-04-07 10:20:51.054085357 +0200
- @@ -570,6 +570,7 @@
- serial_out(up, UART_ICR, value);
- }
-
- +#ifndef CONFIG_NDS32
- static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
- {
- unsigned int value;
- @@ -581,6 +582,7 @@
-
- return value;
- }
- +#endif
-
- /*
- * FIFO support.
- @@ -722,6 +724,7 @@
- return count;
- }
-
- +#ifndef CONFIG_NDS32
- /*
- * Read UART ID using the divisor method - set DLL and DLM to zero
- * and the revision will be in DLL and device type in DLM. We
- @@ -749,7 +752,9 @@
-
- return id;
- }
- +#endif
-
- +#ifndef CONFIG_NDS32
- /*
- * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
- * When this function is called we know it is at least a StarTech
- @@ -842,6 +847,7 @@
- else
- up->port.type = PORT_16650V2;
- }
- +#endif
-
- /*
- * We detected a chip without a FIFO. Only two fall into
- @@ -865,6 +871,7 @@
- up->port.type = PORT_16450;
- }
-
- +#ifndef CONFIG_NDS32
- static int broken_efr(struct uart_8250_port *up)
- {
- /*
- @@ -877,6 +884,7 @@
-
- return 0;
- }
- +#endif
-
- static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
- {
- @@ -908,7 +916,7 @@
-
- up->port.type = PORT_16550A;
- up->capabilities |= UART_CAP_FIFO;
- -
- +#ifndef CONFIG_NDS32
- /*
- * Check for presence of the EFR when DLAB is set.
- * Only ST16C650V1 UARTs pass this test.
- @@ -937,6 +945,7 @@
- autoconfig_has_efr(up);
- return;
- }
- +#endif
-
- /*
- * Check for a National Semiconductor SuperIO chip.
- @@ -1156,10 +1165,11 @@
- * We also initialise the EFR (if any) to zero for later. The
- * EFR occupies the same register location as the FCR and IIR.
- */
- +#ifndef CONFIG_NDS32
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(up, UART_EFR, 0);
- serial_out(up, UART_LCR, 0);
- -
- +#endif
- serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- scratch = serial_in(up, UART_IIR) >> 6;
-
- diff -Nur linux-3.4.110.orig/drivers/video/FTLCDC100/faradayfb.h linux-3.4.110/drivers/video/FTLCDC100/faradayfb.h
- --- linux-3.4.110.orig/drivers/video/FTLCDC100/faradayfb.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/video/FTLCDC100/faradayfb.h 2016-04-07 10:20:51.058085512 +0200
- @@ -0,0 +1,215 @@
- +#ifndef __FARADAYFB_H
- +#define __FARADAYFB_H
- +
- +#define FARADAYFB_MODULE_NAME "faradayfb"
- +#define DEBUG(enabled, tagged, ...) \
- + do { \
- + if (enabled) { \
- + if (tagged) \
- + printk("[ %30s() ] ", __func__); \
- + printk(__VA_ARGS__); \
- + } \
- + } while (0)
- +
- +#if defined(CONFIG_FFB_MODE_RGB)
- +# define DEFAULT_COLOR FFB_MODE_RGB
- +#elif defined(CONFIG_FFB_MODE_YUV422)
- +# define DEFAULT_COLOR FFB_MODE_YUV422
- +#elif defined(CONFIG_FFB_MODE_YUV420)
- +# define DEFAULT_COLOR FFB_MODE_YUV420
- +#endif
- +
- +#if defined(CONFIG_FFB_MODE_8BPP)
- +# define DEFAULT_BPP FFB_MODE_8BPP
- +#elif defined(CONFIG_FFB_MODE_16BPP)
- +# define DEFAULT_BPP FFB_MODE_16BPP
- +#elif defined(CONFIG_FFB_MODE_24BPP)
- +# define DEFAULT_BPP FFB_MODE_24BPP
- +#endif
- +
- +#define FFB_DEFAULT_MODE (DEFAULT_COLOR | DEFAULT_BPP)
- +
- +struct lcd_param {
- +
- + unsigned long value;
- + unsigned long flags;
- +};
- +
- +inline struct lcd_param* get_lcd_time(struct lcd_param* array, unsigned long num_array, unsigned long type)
- +{
- + int i;
- +
- + for (i = 0; i < num_array; i++) {
- +
- + struct lcd_param *r = &array[i];
- +
- + if (r->flags & type & 0xff)
- + return r;
- + }
- +
- + return NULL;
- +}
- +
- +inline struct lcd_param* get_lcd_ctrl(struct lcd_param* array, unsigned long num_array, unsigned long type)
- +{
- + int i;
- +
- + for (i = 0; i < num_array; i++) {
- +
- + struct lcd_param *r = &array[i];
- +
- + if ((r->flags & type & 0xff) && (r->flags & type & 0xff00))
- + return r;
- + }
- +
- + return NULL;
- +}
- +
- +enum { RGB_8, RGB_16, RGB_24, NR_RGB};
- +
- +struct faradayfb_rgb {
- +
- + struct fb_bitfield red;
- + struct fb_bitfield green;
- + struct fb_bitfield blue;
- + struct fb_bitfield transp;
- +};
- +
- +/* This structure describes the machine which we are running on. */
- +struct faradayfb_mach_info {
- +
- + unsigned long num_time0;
- + struct lcd_param * time0;
- +
- + unsigned long num_time1;
- + struct lcd_param * time1;
- +
- + unsigned long num_time2;
- + struct lcd_param * time2;
- +
- + unsigned long num_control;
- + struct lcd_param * control;
- +
- + unsigned long pixclock;
- +
- + unsigned long xres;
- + unsigned long yres;
- +
- + unsigned int max_bpp;
- + unsigned int sync;
- +
- + unsigned int cmap_greyscale:1,
- + cmap_inverse:1,
- + cmap_static:1,
- + unused:29;
- +};
- +
- +struct faradayfb_info {
- +
- + struct fb_info *info;
- + struct faradayfb_rgb *rgb[NR_RGB];
- +
- + unsigned int xres;
- + unsigned int yres;
- + unsigned int max_bpp;
- +
- + /*
- + * These are the addresses we mapped
- + * the framebuffer memory region to.
- + */
- + dma_addr_t map_dma;
- + unsigned char * map_cpu;
- + unsigned int map_size;
- +
- + unsigned char * screen_cpu;
- + dma_addr_t screen_dma;
- + u32 * palette_cpu;
- + dma_addr_t palette_dma;
- + unsigned int palette_size;
- +
- + unsigned int cmap_inverse:1,
- + cmap_static:1,
- + unused:30;
- +
- + unsigned long time0;
- + unsigned long time1;
- + unsigned long time2;
- + unsigned long control;
- + unsigned long int_mask;
- + unsigned long io_base;
- +
- + unsigned int state;
- + unsigned int task_state;
- + struct semaphore ctrlr_sem;
- + wait_queue_head_t ctrlr_wait;
- + struct work_struct task;
- +
- + unsigned long smode;
- + unsigned long frame420_size;
- +};
- +
- +/*
- + * These are the actions for set_ctrlr_state
- + */
- +#define C_DISABLE 0
- +#define C_ENABLE 1
- +#define C_DISABLE_CLKCHANGE 2
- +#define C_ENABLE_CLKCHANGE 3
- +#define C_REENABLE 4
- +#define C_DISABLE_PM 5
- +#define C_ENABLE_PM 6
- +#define C_STARTUP 7
- +
- +#define FARADAY_LCDTIME0_GET_HBP(x) ((((x) >> 24) & 0xFF) + 1)
- +#define FARADAY_LCDTIME0_GET_HFP(x) ((((x) >> 16) & 0xFF) + 1)
- +#define FARADAY_LCDTIME0_GET_HW(x) ((((x) >> 8) & 0xFF) + 1)
- +#define FARADAY_LCDTIME1_GET_VBP(x) ((((x) >> 24) & 0xFF) )
- +#define FARADAY_LCDTIME1_GET_VFP(x) ((((x) >> 16) & 0xFF) )
- +#define FARADAY_LCDTIME1_GET_VW(x) ((((x) >> 8) & 0xFF) + 1)
- +
- +#define FARADAY_LCDTIME0_HBP(x) ((((x) - 1) & 0xFF) << 24)
- +#define FARADAY_LCDTIME0_HFP(x) ((((x) - 1) & 0xFF) << 16)
- +#define FARADAY_LCDTIME0_HW(x) ((((x) - 1) & 0xFF) << 8)
- +#define FARADAY_LCDTIME0_PL(x) (((((x) >> 4) - 1) & 0x3F) << 2)
- +#define FARADAY_LCDTIME1_VBP(x) ((((x) ) & 0xFF) << 24)
- +#define FARADAY_LCDTIME1_VFP(x) ((((x) ) & 0xFF) << 16)
- +#define FARADAY_LCDTIME1_VW(x) ((((x) - 1) & 0xFF) << 8)
- +#define FARADAY_LCDTIME1_LF(x) ((((x) - 1) & 0x3FF) )
- +
- +#define FFB_MODE_RGB 0x00000001
- +#define FFB_MODE_YUV420 0x00000002
- +#define FFB_MODE_YUV422 0x00000004
- +
- +#define FFB_MODE_8BPP 0x00000100
- +#define FFB_MODE_16BPP 0x00000200
- +#define FFB_MODE_24BPP 0x00000400
- +
- +/* Minimum X and Y resolutions */
- +#define MIN_XRES 64
- +#define MIN_YRES 64
- +
- +typedef struct LCDTag {
- +
- + u32 Timing0; /* 0x00 */
- + u32 Timing1; /* 0x04 */
- + u32 Timing2; /* 0x08 */
- + u32 Timing3; /* 0x0C */
- + u32 UPBase; /* 0x10 */
- + u32 LPBase; /* 0x14 */
- + u32 INTREnable; /* 0x18 */
- + u32 Control; /* 0x1C */
- + u32 Status; /* 0x20 */
- + u32 Interrupt; /* 0x24 */
- + u32 UPCurr; /* 0x28 */
- + u32 LPCurr; /* 0x2C */
- + u32 Reserved1[5]; /* 0x30~0x40 */
- + u32 GPIO; /* 0x44 */
- + u32 Reserved2[0x74 - 6]; /* 0x48~0x1FC */
- +
- + u32 Palette[0x80]; /* 0x200~0x3FC */
- + u32 TestReg[0x100]; /* 0x400~0x7FC */
- +
- +} LCD_Register;
- +
- +#endif /* __FARADAYFB_H */
- +
- diff -Nur linux-3.4.110.orig/drivers/video/FTLCDC100/faradayfb-main.c linux-3.4.110/drivers/video/FTLCDC100/faradayfb-main.c
- --- linux-3.4.110.orig/drivers/video/FTLCDC100/faradayfb-main.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/video/FTLCDC100/faradayfb-main.c 2016-04-07 10:20:51.058085512 +0200
- @@ -0,0 +1,911 @@
- +#include <linux/module.h>
- +#include <linux/fb.h>
- +#include <linux/delay.h>
- +#include <linux/device.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/interrupt.h>
- +#include <linux/platform_device.h>
- +
- +#include <asm/uaccess.h>
- +#include <asm/atomic.h>
- +#include <asm/mach-types.h>
- +
- +#include "faradayfb.h"
- +#include "lcd-info.c"
- +#include "pingpong-module.c"
- +
- +static u32 faradayfb_pseudo_palette[32];
- +static inline void faradayfb_lcd_power(struct fb_info *info, int on)
- +{
- + struct faradayfb_info *fbi = info->par;
- + volatile LCD_Register *plcd = (LCD_Register *)fbi->io_base;
- +
- + if (on)
- + fbi->control |= (1UL << 11);
- + else
- + fbi->control &= ~(1UL << 11);
- +
- + plcd->Control = fbi->control;
- +}
- +
- +static void faradayfb_setup_gpio(struct fb_info *info)
- +{
- + struct faradayfb_info *fbi = info->par;
- + volatile LCD_Register *plcd = (LCD_Register *)fbi->io_base;
- +
- + plcd->GPIO = 0x010000;
- +}
- +
- +static inline void faradayfb_pmu_on(void)
- +{
- + REG32(PMU_FTPMU010_VA_BASE + 0x44) |= 0x00700000;
- +}
- +
- +static inline void faradayfb_pmu_off(void)
- +{
- + REG32(PMU_FTPMU010_VA_BASE + 0x44) &= ~0x00700000;
- +}
- +
- +static void faradayfb_enable_controller(struct fb_info *info)
- +{
- + struct faradayfb_info *fbi = info->par;
- + volatile LCD_Register *plcd = (LCD_Register *)fbi->io_base;
- +
- + plcd->Timing0 = fbi->time0;
- + plcd->Timing1 = fbi->time1;
- + plcd->Timing2 = fbi->time2;
- + plcd->Control = fbi->control & ~0x01;
- +
- + plcd->UPBase = fbi->screen_dma | fbi->frame420_size;
- +
- + faradayfb_pmu_on();
- + plcd->Control |= 0x01;
- +
- + DEBUG(0, 1, "Time0 = 0x%08x\n", plcd->Timing0);
- + DEBUG(0, 1, "Time1 = 0x%08x\n", plcd->Timing1);
- + DEBUG(0, 1, "Time2 = 0x%08x\n", plcd->Timing2);
- + DEBUG(0, 1, "Control = 0x%08x\n", plcd->Control);
- + DEBUG(0, 1, "UPBase = 0x%08x\n", plcd->UPBase);
- +}
- +
- +static void faradayfb_disable_controller(struct fb_info *info)
- +{
- + struct faradayfb_info *fbi = info->par;
- + volatile LCD_Register *plcd = (LCD_Register *)fbi->io_base;
- + DECLARE_WAITQUEUE(wait, current);
- +
- + set_current_state(TASK_UNINTERRUPTIBLE);
- + add_wait_queue(&fbi->ctrlr_wait, &wait);
- +
- + fbi->control &= ~0x0001;
- + plcd->Control = fbi->control;
- + faradayfb_pmu_off();
- +
- + schedule_timeout(20 * HZ / 1000);
- + remove_wait_queue(&fbi->ctrlr_wait, &wait);
- +}
- +
- +static void faradayfb_enable_int(struct fb_info *info)
- +{
- + struct faradayfb_info *fbi = info->par;
- + volatile LCD_Register *plcd = (LCD_Register *)fbi->io_base;
- +
- + plcd->INTREnable = fbi->int_mask;
- +}
- +
- +static void faradayfb_disable_int(struct fb_info *info)
- +{
- + struct faradayfb_info *fbi = info->par;
- + volatile LCD_Register *plcd = (LCD_Register *)fbi->io_base;
- +
- + fbi->int_mask = plcd->INTREnable;
- + plcd->INTREnable = 0;
- + plcd->Status = 0x1e;
- +}
- +
- +static struct faradayfb_rgb def_rgb_8 = {
- +
- + .red = { .offset = 0, .length = 4 },
- + .green = { .offset = 0, .length = 4 },
- + .blue = { .offset = 0, .length = 4 },
- + .transp = { .offset = 0, .length = 0 },
- +};
- +
- +static struct faradayfb_rgb def_rgb_16 = {
- +
- + .red = { .offset = 11, .length = 5, .msb_right = 0 },
- + .green = { .offset = 5, .length = 6, .msb_right = 0 },
- + .blue = { .offset = 0, .length = 5, .msb_right = 0 },
- + .transp = { .offset = 15, .length = 0, .msb_right = 0 },
- +};
- +
- +static struct faradayfb_rgb def_rgb_24 = {
- +
- + .red = { .offset = 16, .length = 8, .msb_right = 0 },
- + .green = { .offset = 8, .length = 8, .msb_right = 0 },
- + .blue = { .offset = 0, .length = 8, .msb_right = 0 },
- + .transp = { .offset = 0, .length = 0, .msb_right = 0 },
- +};
- +
- +static inline void faradayfb_schedule_work(struct fb_info *info, unsigned int state)
- +{
- + struct faradayfb_info *fbi = info->par;
- + unsigned long flags;
- +
- + local_irq_save(flags);
- +
- + /*
- + * We need to handle two requests being made at the same time.
- + * There are two important cases:
- + * 1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE)
- + * We must perform the unblanking, which will do our REENABLE for us.
- + * 2. When we are blanking, but immediately unblank before we have
- + * blanked. We do the "REENABLE" thing here as well, just to be sure.
- + */
- + if (fbi->task_state == C_ENABLE && state == C_REENABLE)
- + state = (unsigned int) - 1;
- +
- + if (fbi->task_state == C_DISABLE && state == C_ENABLE)
- + state = C_REENABLE;
- +
- + if (state != (unsigned int) - 1) {
- +
- + fbi->task_state = state;
- + schedule_work(&fbi->task);
- + }
- +
- + local_irq_restore(flags);
- +}
- +
- +static int faradayfb_setpalettereg(unsigned int regno, unsigned int red,
- + unsigned int green, unsigned int blue, unsigned int trans,
- + struct fb_info *info)
- +{
- + struct faradayfb_info *fbi = info->par;
- +
- + if (regno < fbi->palette_size) {
- +
- + fbi->palette_cpu[regno] = ((red >> 0) & (0x1fUL << 11)) |
- + ((green >> 5) & (0x3F << 5)) |
- + ((blue >> 11) & (0x1f << 0));
- +
- + return 0;
- + }
- +
- + return 1;
- +}
- +
- +static int faradayfb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
- + unsigned int blue, unsigned int trans, struct fb_info *info)
- +{
- + struct faradayfb_info *fbi = info->par;
- + int ret = 1;
- + /*
- + * If inverse mode was selected, invert all the colours
- + * rather than the register number. The register number
- + * is what you poke into the framebuffer to produce the
- + * colour you requested.
- + */
- + if (fbi->cmap_inverse) {
- +
- + red = 0xffff - red;
- + green = 0xffff - green;
- + blue = 0xffff - blue;
- + }
- +
- + /*
- + * If greyscale is true, then we convert the RGB value
- + * to greyscale no mater what visual we are using.
- + */
- + if (info->var.grayscale)
- + red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16;
- +
- + switch(info->fix.visual) {
- +
- + case FB_VISUAL_TRUECOLOR:
- + /*
- + * 12 or 16-bit True Colour. We encode the RGB value
- + * according to the RGB bitfield information.
- + */
- + if (regno < 16) {
- +
- + u32 col;
- + red >>= (16 - info->var.red.length);
- + green >>= (16 - info->var.green.length);
- + blue >>= (16 - info->var.blue.length);
- + col = (red << info->var.red.offset) |
- + (green << info->var.green.offset) |
- + (blue << info->var.blue.offset) ;
- +
- + switch(info->var.bits_per_pixel) {
- +
- + /* is the following code correct?? */
- + case 16:
- + case 32:
- + ((u32 *)(info->pseudo_palette))[regno] = col;
- + ret=0;
- + break;
- + }
- + }
- + break;
- +
- + case FB_VISUAL_STATIC_PSEUDOCOLOR:
- + case FB_VISUAL_PSEUDOCOLOR:
- + if (fbi->smode == FFB_MODE_RGB)
- + ret = faradayfb_setpalettereg(regno, red, green, blue, trans, info);
- + break;
- + }
- +
- + return ret;
- +}
- +
- +/*
- + * Round up in the following order: bits_per_pixel, xres,
- + * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
- + * bitfields, horizontal timing, vertical timing.
- + */
- +static int faradayfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
- +{
- + struct faradayfb_info *fbi = info->par;
- + int rgbidx;
- +
- + var->xres = min(var->xres, (unsigned int)MIN_XRES);
- + var->yres = min(var->yres, (unsigned int)MIN_YRES);
- + var->xres = max(var->xres, fbi->xres);
- + var->yres = max(var->yres, fbi->yres);
- + var->xres_virtual = max(var->xres_virtual, var->xres);
- + var->yres_virtual = max(var->yres_virtual, var->yres);
- +
- + DEBUG(0, 1, "var->bits_per_pixel = %d\n", var->bits_per_pixel);
- +
- + switch (var->bits_per_pixel) {
- +
- + case 1: case 2: case 4: case 8:
- + rgbidx = RGB_8;
- + break;
- +
- + case 16:
- + rgbidx = RGB_16;
- + break;
- +
- + case 32:
- + rgbidx = RGB_24;
- + break;
- +
- + default:
- + return -EINVAL;
- + }
- +
- + /*
- + * Copy the RGB parameters for this display
- + * from the machine specific parameters.
- + */
- + var->red = fbi->rgb[ rgbidx]->red;
- + var->green = fbi->rgb[ rgbidx]->green;
- + var->blue = fbi->rgb[ rgbidx]->blue;
- + var->transp = fbi->rgb[ rgbidx]->transp;
- +
- + DEBUG(0, 1, "RGBT length = %d:%d:%d:%d\n",
- + var->red.length, var->green.length, var->blue.length, var->transp.length);
- +
- + DEBUG(0, 1, "RGBT offset = %d:%d:%d:%d\n",
- + var->red.offset, var->green.offset, var->blue.offset, var->transp.offset);
- +
- + DEBUG(0, 1, "Leave\n");
- +
- + return 0;
- +}
- +
- +/*
- + * Configures LCD Controller based on entries in var parameter. Settings are
- + * only written to the controller if changes were made.
- + */
- +static int faradayfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info)
- +{
- + struct faradayfb_info *fbi = info->par;
- + volatile LCD_Register *plcd = (LCD_Register *)fbi->io_base;
- +
- + DEBUG(0, 1, "var: xres=%d hslen=%d lm=%d rm=%d\n", var->xres, var->hsync_len, var->left_margin, var->right_margin);
- + DEBUG(0, 1, "var: yres=%d vslen=%d um=%d bm=%d\n", var->yres, var->vsync_len, var->upper_margin, var->lower_margin);
- +
- + fbi->time0 = FARADAY_LCDTIME0_HFP(var->left_margin)
- + | FARADAY_LCDTIME0_HBP(var->right_margin)
- + | FARADAY_LCDTIME0_HW(var->hsync_len)
- + | FARADAY_LCDTIME0_PL(var->xres);
- +
- + fbi->time1 = FARADAY_LCDTIME1_VBP(var->upper_margin)
- + | FARADAY_LCDTIME1_VFP(var->lower_margin)
- + | FARADAY_LCDTIME1_VW(var->vsync_len)
- + | FARADAY_LCDTIME1_LF(var->yres);
- +
- + if ((plcd->Timing0 != fbi->time0)
- + || (plcd->Timing1 != fbi->time1)
- + || (plcd->Timing2 != fbi->time2)
- + || (plcd->Control != fbi->control)) {
- +
- + faradayfb_schedule_work(info, C_REENABLE);
- + }
- +
- + return 0;
- +}
- +
- +/* Set the user defined part of the display for the specified console */
- +static int faradayfb_set_par(struct fb_info *info)
- +{
- + struct faradayfb_info *fbi = info->par;
- + struct fb_var_screeninfo *var = &info->var;
- + unsigned long palette_mem_size;
- +
- + if (var->bits_per_pixel == 16 || var->bits_per_pixel == 32)
- + info->fix.visual = FB_VISUAL_TRUECOLOR;
- + else if (!fbi->cmap_static)
- + info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
- + else {
- + /*
- + * Some people have weird ideas about wanting static
- + * pseudocolor maps. I suspect their user space
- + * applications are broken.
- + */
- + info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
- + }
- +
- + info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
- +
- + fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16;
- +
- + palette_mem_size = fbi->palette_size * sizeof(u32);
- +
- + DEBUG(0, 1, "info->fix.line_length = %d\n", info->fix.line_length);
- + DEBUG(0, 1, "palette_mem_size = 0x%08lx\n", (unsigned long) palette_mem_size);
- +
- + fbi->palette_cpu = (u32 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
- +
- + fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
- +
- + /* Set (any) board control register to handle new color depth */
- + faradayfb_activate_var(var, info);
- +
- + DEBUG(0, 1, "Leave\n");
- +
- + return 0;
- +}
- +
- +static irqreturn_t faradayfb_handle_irq(int irq, void *dev_id)
- +{
- +#if 0
- + struct fb_info *info = (struct fb_info*)dev_id;
- + struct faradayfb_info *fbi = info->par;
- + volatile LCD_Register *plcd = (LCD_Register *)fbi->io_base;
- + u32 status = plcd->Interrupt;
- +#endif
- + return IRQ_HANDLED;
- +}
- +
- +/*
- + * This function must be called from task context only, since it will
- + * sleep when disabling the LCD controller, or if we get two contending
- + * processes trying to alter state.
- + */
- +static void set_ctrlr_state(struct fb_info *info, unsigned int state)
- +{
- + struct faradayfb_info *fbi = info->par;
- + unsigned int old_state;
- +
- + down(&fbi->ctrlr_sem);
- +
- + old_state = fbi->state;
- +
- + /* Hack around fbcon initialisation. */
- + if (old_state == C_STARTUP && state == C_REENABLE)
- + state = C_ENABLE;
- +
- + switch (state) {
- + case C_DISABLE_PM:
- + case C_DISABLE:
- +
- + /* Disable controller */
- + if (old_state != C_DISABLE) {
- +
- + fbi->state = state;
- + faradayfb_disable_int(info);
- + faradayfb_lcd_power(info, 0);
- + // faradayfb_disable_controller(info);
- + }
- + break;
- +
- + case C_REENABLE:
- + /*
- + * Re-enable the controller only if it was already
- + * enabled. This is so we reprogram the control
- + * registers.
- + */
- + if (old_state == C_ENABLE) {
- +
- + faradayfb_disable_int(info);
- + faradayfb_lcd_power(info, 0);
- + faradayfb_disable_controller(info);
- +
- + faradayfb_setup_gpio(info);
- + faradayfb_lcd_power(info, 1);
- + faradayfb_enable_controller(info);
- + faradayfb_enable_int(info);
- + }
- + break;
- +
- + case C_ENABLE_PM:
- + /*
- + * Re-enable the controller after PM. This is not
- + * perfect - think about the case where we were doing
- + * a clock change, and we suspended half-way through.
- + */
- + if (old_state != C_DISABLE_PM)
- + break;
- + /* fall through */
- +
- + case C_ENABLE:
- + /*
- + * Power up the LCD screen, enable controller, and
- + * turn on the backlight.
- + */
- + if (old_state != C_ENABLE) {
- +
- + fbi->state = C_ENABLE;
- + faradayfb_setup_gpio(info);
- + faradayfb_lcd_power(info, 1);
- + faradayfb_enable_controller(info);
- + faradayfb_enable_int(info);
- + }
- + break;
- + }
- + up(&fbi->ctrlr_sem);
- +}
- +
- +/*
- + * Blank the display by setting all palette values to zero. Note, the
- + * 12 and 16 bpp modes don't really use the palette, so this will not
- + * blank the display in all modes.
- + */
- +static int faradayfb_blank(int blank, struct fb_info *info)
- +{
- + struct faradayfb_info *fbi = info->par;
- + int i;
- +
- + switch (blank) {
- + case FB_BLANK_POWERDOWN:
- + case FB_BLANK_VSYNC_SUSPEND:
- + case FB_BLANK_HSYNC_SUSPEND:
- + case FB_BLANK_NORMAL:
- +
- + if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR ||
- + info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) {
- +
- + for (i = 0; i < fbi->palette_size; i++)
- + faradayfb_setpalettereg(i, 0, 0, 0, 0, info);
- + }
- +
- + faradayfb_schedule_work(info, C_DISABLE);
- +
- + break;
- +
- + case FB_BLANK_UNBLANK:
- +
- + if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR ||
- + info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
- + fb_set_cmap(&info->cmap, info);
- +
- + faradayfb_schedule_work(info, C_ENABLE);
- +
- + break;
- + }
- +
- + return 0;
- +}
- +
- +/*
- + * Our LCD controller task (which is called when we blank or unblank)
- + * via keventd.
- + */
- +static void faradayfb_task(struct work_struct *dummy)
- +{
- + struct faradayfb_info *fbi = container_of(dummy, struct faradayfb_info, task);
- + struct fb_info *info = fbi->info;
- + unsigned int state;
- +
- + state = xchg(&fbi->task_state, -1);
- + set_ctrlr_state(info, state);
- +}
- +
- +/* Fake monspecs to fill in fbinfo structure */
- +static struct fb_monspecs monspecs = {
- +
- + .hfmin = 30000,
- + .hfmax = 70000,
- + .vfmin = 50,
- + .vfmax = 65,
- +};
- +
- +static int ffb_get_mach_param(struct faradayfb_mach_info *inf, struct fb_info *info, unsigned long smode)
- +{
- + struct faradayfb_info *fbi = info->par;
- + struct lcd_param *tparam;
- + unsigned long bpp_mode;
- +
- + if (!(tparam = get_lcd_time(inf->time0, inf->num_time0, smode)))
- + return -1;
- +
- + fbi->time0 = tparam->value;
- +
- + if (!(tparam = get_lcd_time(inf->time1, inf->num_time1, smode)))
- + return -1;
- +
- + fbi->time1 = tparam->value;
- +
- + if (!(tparam = get_lcd_time(inf->time2, inf->num_time2, smode)))
- + return -1;
- +
- + fbi->time2 = tparam->value;
- +
- + switch(info->var.bits_per_pixel) {
- +
- + case 1: case 2: case 4: case 8:
- + bpp_mode = FFB_MODE_8BPP;
- + break;
- +
- + case 16:
- + bpp_mode = FFB_MODE_16BPP;
- + break;
- +
- + case 32:
- + bpp_mode = FFB_MODE_24BPP;
- + break;
- +
- + default:
- + DEBUG(1, 1, "Unsupported BPP, set default BPP to 16\n");
- + bpp_mode = FFB_MODE_16BPP;
- + break;
- + }
- +
- + if (!(tparam = get_lcd_ctrl(inf->control, inf->num_control, smode | bpp_mode)))
- + return -1;
- +
- + fbi->control = tparam->value;
- +
- + fbi->xres = inf->xres;
- + fbi->yres = inf->yres;
- +
- + return 0;
- +}
- +
- +static int faradayfb_set_var(struct fb_info *info, struct faradayfb_mach_info *inf, unsigned long type)
- +{
- + struct faradayfb_info *fbi = info->par;
- + unsigned long t_smode = 0;
- +
- + if (!type)
- + t_smode = fbi->smode;
- + else
- + t_smode = type;
- +
- + if (ffb_get_mach_param(inf, info, t_smode)) {
- +
- + DEBUG(1, 1, "Not support mode(%lx)\n", t_smode);
- + return -1;
- + }
- +
- + info->var.xres = fbi->xres;
- + info->var.xres_virtual = fbi->xres;
- + info->var.yres = fbi->yres;
- + info->var.yres_virtual = fbi->yres;
- +
- + info->var.upper_margin = FARADAY_LCDTIME1_GET_VBP(fbi->time1);
- + info->var.lower_margin = FARADAY_LCDTIME1_GET_VFP(fbi->time1);
- + info->var.vsync_len = FARADAY_LCDTIME1_GET_VW(fbi->time1);
- + info->var.left_margin = FARADAY_LCDTIME0_GET_HFP(fbi->time0);
- + info->var.right_margin = FARADAY_LCDTIME0_GET_HBP(fbi->time0);
- + info->var.hsync_len = FARADAY_LCDTIME0_GET_HW(fbi->time0);
- +
- + fbi->int_mask = 0;
- +
- + if (t_smode & FFB_MODE_YUV420)
- + fbi->frame420_size = (((info->var.xres * info->var.yres + 0xffff) & 0xffff0000) >> 16) << 2;
- + else
- + fbi->frame420_size = 0;
- +
- + return 0;
- +}
- +
- +static struct fb_ops faradayfb_ops = {
- +
- + .owner = THIS_MODULE,
- + .fb_check_var = faradayfb_check_var,
- + .fb_set_par = faradayfb_set_par,
- + .fb_setcolreg = faradayfb_setcolreg,
- + .fb_fillrect = cfb_fillrect,
- + .fb_copyarea = cfb_copyarea,
- + .fb_imageblit = cfb_imageblit,
- + .fb_blank = faradayfb_blank,
- + .fb_mmap = faradayfb_mmap,
- + .fb_ioctl = faradayfb_ioctl,
- +};
- +
- +static struct fb_info * __init faradayfb_init_fbinfo(struct device *dev)
- +{
- + struct faradayfb_mach_info *inf;
- + struct fb_info *info;
- + struct faradayfb_info *fbi;
- +
- + if (!(info = framebuffer_alloc(sizeof(struct faradayfb_info), dev)))
- + return NULL;
- +
- + fbi = info->par;
- + fbi->info = info;
- +
- + fbi->io_base = LCD_FTLCDC100_0_VA_BASE;
- + strcpy(info->fix.id, FARADAYFB_MODULE_NAME);
- +
- + info->fix.type = FB_TYPE_PACKED_PIXELS;
- + info->fix.type_aux = 0;
- + info->fix.xpanstep = 0;
- + info->fix.ypanstep = 0;
- + info->fix.ywrapstep = 0;
- + info->fix.accel = FB_ACCEL_NONE;
- +
- + info->var.nonstd = 0;
- + info->var.activate = FB_ACTIVATE_NOW;
- + info->var.height = -1;
- + info->var.width = -1;
- + info->var.accel_flags = 0;
- + info->var.vmode = FB_VMODE_NONINTERLACED;
- +
- + info->fbops = &faradayfb_ops;
- + info->flags = FBINFO_DEFAULT;
- + info->monspecs = monspecs;
- + info->pseudo_palette = &faradayfb_pseudo_palette;
- +
- + fbi->rgb[RGB_8] = &def_rgb_8;
- + fbi->rgb[RGB_16] = &def_rgb_16;
- + fbi->rgb[RGB_24] = &def_rgb_24;
- +
- + inf = (struct faradayfb_mach_info*)dev->platform_data;
- +
- + /*
- + * People just don't seem to get this. We don't support
- + * anything but correct entries now, so panic if someone
- + * does something stupid.
- + */
- +
- + fbi->xres = inf->xres;
- + fbi->yres = inf->yres;
- + fbi->max_bpp = 32;
- +#if defined(CONFIG_FFB_MODE_8BPP)
- + info->var.bits_per_pixel = min((u32)8, inf->max_bpp);
- +#elif defined(CONFIG_FFB_MODE_16BPP)
- + info->var.bits_per_pixel = min((u32)16, inf->max_bpp);
- +#elif defined(CONFIG_FFB_MODE_24BPP)
- + info->var.bits_per_pixel = min((u32)32, inf->max_bpp);
- + info->var.bits_per_pixel = 32;
- +#endif
- +
- + info->var.pixclock = inf->pixclock;
- + info->var.sync = inf->sync;
- + info->var.grayscale = inf->cmap_greyscale;
- + fbi->cmap_inverse = inf->cmap_inverse;
- + fbi->cmap_static = inf->cmap_static;
- +
- + fbi->smode = FFB_DEFAULT_MODE;
- +
- + if (faradayfb_set_var(info, inf, 0))
- + goto err;
- +
- + fbi->state = C_STARTUP;
- + fbi->task_state = (unsigned char) - 1;
- + info->fix.smem_len = faradayfb_cal_frame_buf_size(fbi);
- +
- + init_waitqueue_head(&fbi->ctrlr_wait);
- + INIT_WORK(&fbi->task, faradayfb_task);
- + init_MUTEX(&fbi->ctrlr_sem);
- +
- + return info;
- +err:
- + kfree(fbi);
- + kfree(info);
- +
- + return NULL;
- +}
- +
- +static int faradayfb_probe(struct platform_device *pdev)
- +{
- + struct fb_info *info;
- + struct faradayfb_info *fbi;
- + int irq;
- + int ret = 0;
- +
- + ret = -ENOMEM;
- +
- + if (!(info = faradayfb_init_fbinfo(&pdev->dev))) {
- +
- + DEBUG(1, 1, "unable to allocate memory for device info\n");
- + goto err_exit;
- + }
- +
- + fbi = info->par;
- +
- + /* Initialize video memory */
- + if ((ret = faradayfb_map_video_memory(info)) < 0)
- + goto err_free_mem;
- +
- + ret = -EINVAL;
- +
- + if ((irq = platform_get_irq(pdev, 0)) <= 0)
- + goto err_free_map;
- +
- + if (request_irq(irq, faradayfb_handle_irq, IRQF_DISABLED, "LCD", info)) {
- +
- + DEBUG(1, 1, "request_irq failed: %d\n", ret);
- + goto err_free_map;
- + }
- +
- + /*
- + * This makes sure that our colour bitfield
- + * descriptors are correctly initialised.
- + */
- + faradayfb_check_var(&info->var, info);
- + faradayfb_set_par(info);
- +
- + dev_set_drvdata(&pdev->dev, info);
- +
- +// <============================================
- + if ((ret = register_framebuffer(info)) < 0) {
- +
- + DEBUG(1, 1, "register_framebuffer failed\n");
- + goto err_free_irq;
- + }
- +// <============================================
- +
- + faradayfb_clean_screen(info);
- +
- + return 0;
- +
- +err_free_irq:
- + dev_set_drvdata(&pdev->dev, NULL);
- + free_irq(irq, info);
- +err_free_map:
- + faradayfb_unmap_video_memory(info);
- +err_free_mem:
- + kfree(info->par);
- + kfree(info);
- +err_exit:
- + return ret;
- +}
- +
- +/* Called when the device is being detached from the driver */
- +static int faradayfb_remove(struct platform_device *pdev)
- +{
- + struct fb_info *info = platform_get_drvdata(pdev);
- + int irq;
- +
- + set_ctrlr_state(info, C_DISABLE);
- +
- + irq = platform_get_irq(pdev, 0);
- + free_irq(irq, info);
- +
- + unregister_framebuffer(info);
- + faradayfb_unmap_video_memory(info);
- + dev_set_drvdata(&pdev->dev, NULL);
- + kfree(info->par);
- + kfree(info);
- +
- + return 0;
- +}
- +
- +#ifdef CONFIG_PM
- +
- +/* suspend and resume support for the lcd controller */
- +static int faradayfb_suspend(struct platform_device *pdev, pm_message_t mesg)
- +{
- + struct fb_info *info = platform_get_drvdata(pdev);
- +
- + // if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN)
- + if (mesg.event == PM_EVENT_PRETHAW || mesg.event & PM_EVENT_SLEEP)
- + set_ctrlr_state(info, C_DISABLE_PM);
- +
- + return 0;
- +}
- +
- +static int faradayfb_resume(struct platform_device *pdev)
- +{
- + struct fb_info *info = platform_get_drvdata(pdev);
- +
- + // need modify
- + // if (level == RESUME_ENABLE)
- + set_ctrlr_state(info, C_ENABLE_PM);
- +
- + return 0;
- +}
- +
- +#else
- +#define faradayfb_suspend NULL
- +#define faradayfb_resume NULL
- +#endif
- +
- +static struct resource faradayfb_resource[] = {
- +
- + {
- + .start = LCD_FTLCDC100_0_PA_BASE,
- + .end = LCD_FTLCDC100_0_PA_LIMIT,
- + .flags = IORESOURCE_MEM,
- + },
- + {
- + .start = LCD_FTLCDC100_0_IRQ,
- + .end = LCD_FTLCDC100_0_IRQ,
- + .flags = IORESOURCE_IRQ,
- + }
- +};
- +
- +static u64 faradayfb_dmamask = ~(u32)0;
- +
- +static struct platform_device faradayfb_device = {
- +
- + .name = "faraday-lcd",
- + .id = -1,
- + .num_resources = ARRAY_SIZE(faradayfb_resource),
- + .resource = faradayfb_resource,
- + .dev = {
- +
- + .platform_data = &ffb_mach_info,
- + .dma_mask = &faradayfb_dmamask,
- + .coherent_dma_mask = 0xffffffff,
- + }
- +};
- +
- +static struct platform_driver faradayfb_driver = {
- + .probe = faradayfb_probe,
- + .remove = faradayfb_remove,
- + .suspend = faradayfb_suspend,
- + .resume = faradayfb_resume,
- + .driver = {
- + .name = "faraday-lcd",
- + },
- +};
- +
- +/*
- +rick note faraday driver
- +*/
- +
- +/* Register both the driver and the device */
- +int __init faradayfb_init(void)
- +{
- + int ret = 0;
- + /* Register the device with LDM */
- +
- +#if 1
- + if (platform_device_register(&faradayfb_device)) {
- +
- + DEBUG(1, 1, "failed to register faradayfb device\n");
- + ret = -ENODEV;
- + goto exit;
- + }
- +#endif
- + /* Register the driver with LDM */
- + if (platform_driver_register(&faradayfb_driver)) {
- +
- + DEBUG(1, 1, "failed to register faradayfb driver\n");
- + platform_device_unregister(&faradayfb_device);
- + ret = -ENODEV;
- + goto exit;
- + }
- +exit:
- + return ret;
- +}
- +
- +static void __exit faradayfb_cleanup(void)
- +{
- + platform_driver_unregister(&faradayfb_driver);
- + platform_device_unregister(&faradayfb_device);
- +}
- +
- +module_init(faradayfb_init);
- +module_exit(faradayfb_cleanup);
- +MODULE_DESCRIPTION("Faraday LCD driver");
- +MODULE_AUTHOR("Francis Huang <francish@faraday-tech.com>");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.4.110.orig/drivers/video/FTLCDC100/Kconfig linux-3.4.110/drivers/video/FTLCDC100/Kconfig
- --- linux-3.4.110.orig/drivers/video/FTLCDC100/Kconfig 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/video/FTLCDC100/Kconfig 2016-04-07 10:20:51.058085512 +0200
- @@ -0,0 +1,74 @@
- +config FB_FTLCDC100
- + tristate "Faraday FTLCDC100 driver"
- + depends on FB && NDS32
- + select FB_CFB_FILLRECT
- + select FB_CFB_COPYAREA
- + select FB_CFB_IMAGEBLIT
- +
- + choice
- + prompt "Default LCD Panel"
- + depends on FB_FTLCDC100
- + default PANEL_AUA036QN01
- + help
- + This option select a default panel setting for the LCD controller
- +
- + config PANEL_AUA036QN01
- + bool "AU 3.5 inch LCD Panel"
- +
- + config PANEL_CH7013A
- + bool "Chrontel Digital PC to TV Encoder"
- + select I2C
- + select I2C_FARADAY
- + select CH7013A
- +
- + config PANEL_AUA070VW04
- + bool "AU 7.0 inch LCD Panel"
- +
- + config PANEL_LW500AC9601
- + bool "CHIMEI 5.0 inch LCD panel"
- +
- + endchoice
- +
- + # config FTLCD_OSD
- + # bool "Enable OSD (On Screen Display)"
- + # depends on FB_FTLCDC100
- + # default n
- + # ---help---
- + # This enables access to the OSD (On Screen Display) for Faraday
- + # FTLCDC100 LCD control. Disabling OSD will reduce the size of
- + # the kernel by approximately 6kb.
- + #
- +
- + choice
- + prompt "Default Color Mode"
- + depends on FB_FTLCDC100
- + default FFB_MODE_RGB
- + help
- + This option select default color mode
- +
- + config FFB_MODE_RGB
- + bool "RGB Mode"
- + config FFB_MODE_YUV422
- + bool "YUV422 Mode"
- + config FFB_MODE_YUV420
- + bool "YUV420 Mode"
- + endchoice
- +
- + choice
- + prompt "Default BPP"
- + depends on FB_FTLCDC100
- + default FFB_MODE_16BPP
- + help
- + This option select default BPP (bits-per-pixel)
- +
- + config FFB_MODE_8BPP
- + depends on FFB_MODE_RGB || FFB_MODE_YUV420
- + bool "8 bits-per-pixel"
- + config FFB_MODE_16BPP
- + depends on FFB_MODE_RGB || FFB_MODE_YUV422
- + bool "16 bits-per-pixel"
- + config FFB_MODE_24BPP
- + depends on FFB_MODE_RGB
- + bool "24 bits-per-pixel"
- + endchoice
- +
- diff -Nur linux-3.4.110.orig/drivers/video/FTLCDC100/lcd-info.c linux-3.4.110/drivers/video/FTLCDC100/lcd-info.c
- --- linux-3.4.110.orig/drivers/video/FTLCDC100/lcd-info.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/video/FTLCDC100/lcd-info.c 2016-04-07 10:20:51.058085512 +0200
- @@ -0,0 +1,264 @@
- +/*
- + * HBP : Horizontal Back Porch
- + * HFP : Horizontal Front Porch
- + * HSPW: Horizontal Sync. Pulse Width
- + * PPL : Pixels-per-line = 16(PPL+1)
- + */
- +#define ENC_PARAM_TIME0(HBP, HFP, HSPW, PPL) \
- + ((((HBP) - 1) << 24) | \
- + (((HFP) - 1) << 16) | \
- + (((HSPW) - 1) << 8 ) | \
- + ((((PPL) >> 4) - 1) << 2 ))
- +
- +/*
- + * HBP : Vertical Back Porch
- + * HFP : Vertical Front Porch
- + * HSPW: Vertical Sync. Pulse Width
- + * LPP : Lines-per-panel = LPP + 1
- + */
- +#define ENC_PARAM_TIME1(VBP, VFP, VSPW, LPP) \
- + ((((VBP) ) << 24) | \
- + (((VFP) ) << 16) | \
- + (((VSPW) - 1) << 10) | \
- + (((LPP) - 1) ))
- +
- +/*
- + * PRA : Pixel Rate Adaptive
- + * IOE : Invert Panel Output Enable
- + * IPC : Invert Panel Clock (Test Chip Testing)
- + * IHS : Invert Horisontal Sync.
- + * IVS : Invert Versical Sync.
- + * PCD : Panel Clock Divisor
- + */
- +#define ENC_PARAM_TIME2(PRA, IOE, IPC, IHS, IVS, PCD) \
- + (((PRA) << 15) | \
- + ((IOE) << 14) | \
- + ((IPC) << 13) | \
- + ((IHS) << 12) | \
- + ((IVS) << 11) | \
- + (((PCD) - 1) ))
- +
- +/*
- + * Enable YCbCr
- + * Enable YCbCr420
- + * FIFO threadhold
- + * Panel type, 0-6bit, 1-8bit
- + * LcdVComp, when to generate interrupt, 1: start of back_porch
- + * Power Enable
- + * Big Endian Pixel/Byte Ordering
- + * BGR
- + * TFT
- + * LCD bits per pixel
- + * Controller Enable
- + */
- +
- +#define ENC_PARAM_CTRL(ENYUV, ENYUV420, FIFOTH, PTYPE, VCOMP, LCD_ON, ENDIAN, BGR, TFT, BPP, LCD_EN) \
- + ((ENYUV << 18) | \
- + (ENYUV420 << 17) | \
- + (FIFOTH << 16) | \
- + (PTYPE << 15) | \
- + (VCOMP << 12) | \
- + (LCD_ON << 11) | \
- + (ENDIAN << 9) | \
- + (BGR << 8) | \
- + (TFT << 5) | \
- + (BPP << 1) | \
- + (LCD_EN))
- +
- +static struct lcd_param control[] = {
- +
- + {
- + .value = ENC_PARAM_CTRL(0, 0, 1, 1, 0x3, 1, 0x0, 1, 1, 0x3, 1),
- + .flags = FFB_MODE_RGB | FFB_MODE_8BPP,
- + },
- + {
- + .value = ENC_PARAM_CTRL(1, 1, 1, 1, 0x3, 1, 0x0, 0, 1, 0x3, 1),
- + .flags = FFB_MODE_YUV420 | FFB_MODE_8BPP,
- + },
- + {
- + .value = ENC_PARAM_CTRL(1, 0, 1, 1, 0x3, 1, 0x0, 0, 1, 0x4, 1),
- + .flags = FFB_MODE_YUV422 | FFB_MODE_16BPP,
- + },
- + {
- + .value = ENC_PARAM_CTRL(0, 0, 1, 1, 0x3, 1, 0x0, 1, 1, 0x4, 1),
- + .flags = FFB_MODE_RGB | FFB_MODE_16BPP,
- + },
- + {
- + .value = ENC_PARAM_CTRL(0, 0, 1, 1, 0x3, 1, 0x0, 1, 1, 0x5, 1),
- + .flags = FFB_MODE_RGB | FFB_MODE_24BPP,
- + },
- +};
- +
- +#ifdef CONFIG_PANEL_AUA036QN01
- +
- +static struct lcd_param time0[] = {
- +
- + {
- + .value = ENC_PARAM_TIME0(7, 6, 1, 320),
- + .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
- + },
- +};
- +
- +static struct lcd_param time1[] = {
- +
- + {
- + .value = ENC_PARAM_TIME1(1, 1, 1, 240),
- + .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
- + },
- +};
- +
- +static struct lcd_param time2[] = {
- +
- + {
- + .value = ENC_PARAM_TIME2(0, 0, 1, 1, 1, 0x7),
- + .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
- + },
- +};
- +
- +static struct faradayfb_mach_info ffb_mach_info = {
- +
- + .pixclock = 171521,
- + .xres = 320,
- + .yres = 240,
- + .max_bpp = 24,
- + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- + .num_time0 = ARRAY_SIZE(time0),
- + .time0 = time0,
- + .num_time1 = ARRAY_SIZE(time1),
- + .time1 = time1,
- + .num_time2 = ARRAY_SIZE(time2),
- + .time2 = time2,
- + .num_control = ARRAY_SIZE(control),
- + .control = control,
- +};
- +#endif
- +
- +#ifdef CONFIG_PANEL_AUA070VW04
- +static struct lcd_param time0[] = {
- +
- + {
- + .value = ENC_PARAM_TIME0(88, 40, 128, 800),
- + .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
- + },
- +};
- +
- +static struct lcd_param time1[] = {
- +
- + {
- + .value = ENC_PARAM_TIME1(21, 1, 3, 480),
- + .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
- + },
- +};
- +
- +static struct lcd_param time2[] = {
- +
- + {
- + .value = ENC_PARAM_TIME2(0, 1, 1, 1, 1, 0x5),
- + .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
- + },
- +};
- +
- +static struct faradayfb_mach_info ffb_mach_info = {
- +
- + .pixclock = 171521,
- + .xres = 800,
- + .yres = 480,
- + .max_bpp = 24,
- + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- + .num_time0 = ARRAY_SIZE(time0),
- + .time0 = time0,
- + .num_time1 = ARRAY_SIZE(time1),
- + .time1 = time1,
- + .num_time2 = ARRAY_SIZE(time2),
- + .time2 = time2,
- + .num_control = ARRAY_SIZE(control),
- + .control = control,
- +};
- +
- +#endif
- +
- +#ifdef CONFIG_PANEL_LW500AC9601
- +static struct lcd_param time0[] = {
- +
- + {
- + .value = ENC_PARAM_TIME0(88, 40, 128, 800),
- + .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
- + },
- +};
- +
- +static struct lcd_param time1[] = {
- +
- + {
- + .value = ENC_PARAM_TIME1(21, 1, 3, 480),
- + .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
- + },
- +};
- +
- +static struct lcd_param time2[] = {
- +
- + {
- + .value = ENC_PARAM_TIME2( 0, 0, 1, 1, 1, 0x3),
- + .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
- + },
- +};
- +
- +static struct faradayfb_mach_info ffb_mach_info = {
- +
- + .pixclock = 171521,
- + .xres = 800,
- + .yres = 480,
- + .max_bpp = 24,
- + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- + .num_time0 = ARRAY_SIZE(time0),
- + .time0 = time0,
- + .num_time1 = ARRAY_SIZE(time1),
- + .time1 = time1,
- + .num_time2 = ARRAY_SIZE(time2),
- + .time2 = time2,
- + .num_control = ARRAY_SIZE(control),
- + .control = control,
- +};
- +#endif
- +
- +#ifdef CONFIG_CH7013A
- +static struct lcd_param time0[] = {
- +
- + {
- + .value = ENC_PARAM_TIME0(42, 10, 96, 640),
- + .flags = FFB_MODE_RGB,
- + },
- +};
- +
- +static struct lcd_param time1[] = {
- +
- + {
- + .value = ENC_PARAM_TIME1(28, 5, 2, 480),
- + .flags = FFB_MODE_RGB,
- + },
- +};
- +static struct lcd_param time2[] = {
- +
- + {
- + .value = ENC_PARAM_TIME2(0, 1, 1, 0, 0, 0x3),
- + .flags = FFB_MODE_RGB,
- + },
- +};
- +
- +static struct faradayfb_mach_info ffb_mach_info = {
- +
- + .pixclock = 37910,
- + .xres = 640,
- + .yres = 480,
- + .max_bpp = 24,
- + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- + .num_time0 = ARRAY_SIZE(time0),
- + .time0 = time0,
- + .num_time1 = ARRAY_SIZE(time1),
- + .time1 = time1,
- + .num_time2 = ARRAY_SIZE(time2),
- + .time2 = time2,
- + .num_control = ARRAY_SIZE(control),
- + .control = control,
- +};
- +
- +#endif /* CONFIG_CH7013A */
- diff -Nur linux-3.4.110.orig/drivers/video/FTLCDC100/Makefile linux-3.4.110/drivers/video/FTLCDC100/Makefile
- --- linux-3.4.110.orig/drivers/video/FTLCDC100/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/video/FTLCDC100/Makefile 2016-04-07 10:20:51.058085512 +0200
- @@ -0,0 +1 @@
- +obj-$(CONFIG_FB_FTLCDC100) += faradayfb-main.o
- diff -Nur linux-3.4.110.orig/drivers/video/FTLCDC100/pingpong-module.c linux-3.4.110/drivers/video/FTLCDC100/pingpong-module.c
- --- linux-3.4.110.orig/drivers/video/FTLCDC100/pingpong-module.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/video/FTLCDC100/pingpong-module.c 2016-04-07 10:20:51.058085512 +0200
- @@ -0,0 +1,592 @@
- +void *fmem_alloc(size_t size, dma_addr_t *dma_handle, unsigned long flags)
- +{
- + struct page *page;
- + void *cpu_addr = NULL;
- +
- + size = PAGE_ALIGN(size);
- +
- + if (!(page = alloc_pages(GFP_DMA, get_order(size)))) {
- +
- + DEBUG(1, 1, "alloc_pages fail! (requested %#x)", size);
- + goto no_page;
- + }
- +
- + *dma_handle = page_to_phys(page);
- +
- + if ((cpu_addr = __ioremap(*dma_handle, size, flags, 1))) {
- +
- + do {
- + SetPageReserved(page);
- + page++;
- + } while (size -= PAGE_SIZE);
- + }
- + else {
- + __free_pages(page, get_order(size));
- + DEBUG(1, 1, "__ioremap fail! (phy %#x)", *dma_handle);
- + }
- +no_page:
- + return cpu_addr;
- +}
- +
- +void fmem_free(size_t size, void *cpu_addr, dma_addr_t handle)
- +{
- + struct page *page = pfn_to_page(handle >> PAGE_SHIFT);
- +
- + __iounmap(cpu_addr);
- + size = PAGE_ALIGN(size);
- +
- + do {
- + ClearPageReserved(page);
- + __free_page(page);
- + page++;
- +
- + } while (size -= PAGE_SIZE);
- +}
- +
- +static int faradayfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
- +{
- + struct faradayfb_info *fbi = info->par;
- + unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
- + int ret = -EINVAL;
- +
- + DEBUG(0, 1, "Enter\n");
- +
- + if (off < info->fix.smem_len) {
- +
- + off += fbi->screen_dma & PAGE_MASK;
- + vma->vm_pgoff = off >> PAGE_SHIFT;
- + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- + vma->vm_flags |= VM_RESERVED;
- + ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- + vma->vm_end - vma->vm_start, vma->vm_page_prot);
- + }
- + else {
- + DEBUG(1, 1, "buffer mapping error !!\n");
- + }
- +
- + DEBUG(0, 1, "Leave\n");
- +
- + return ret;
- +}
- +
- +/*
- + * Allocates the DRAM memory for the frame buffer. This buffer is
- + * remapped into a non-cached, non-buffered, memory region to
- + * allow palette and pixel writes to occur without flushing the
- + * cache. Once this area is remapped, all virtual memory
- + * access to the video memory should occur at the new region.
- + */
- +static int __init faradayfb_map_video_memory(struct fb_info *info)
- +{
- + struct faradayfb_info *fbi = info->par;
- +
- + /*
- + * We reserve one page for the palette, plus the size
- + * of the framebuffer.
- + */
- + fbi->map_size = PAGE_ALIGN(info->fix.smem_len + PAGE_SIZE);
- +
- + fbi->map_cpu = fmem_alloc(fbi->map_size, &fbi->map_dma, pgprot_writecombine(PAGE_KERNEL));
- + // fbi->map_cpu = dma_alloc_writecombine(fbi->info->dev, fbi->map_size, &fbi->map_dma, GFP_KERNEL);
- +
- + if (fbi->map_cpu) {
- +
- + memset(fbi->map_cpu, 0x1d, fbi->map_size);
- + info->screen_base = fbi->map_cpu + PAGE_SIZE;
- + fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
- + info->fix.smem_start = fbi->screen_dma;
- + }
- +
- + return fbi->map_cpu ? 0 : -ENOMEM;
- +}
- +
- +static inline void faradayfb_clean_screen(struct fb_info *info)
- +{
- + struct faradayfb_info *fbi = info->par;
- + int size = info->var.xres * info->var.yres;
- +
- + if (fbi->smode & FFB_MODE_YUV422) {
- +
- + memset(fbi->map_cpu, 16, size * info->var.bits_per_pixel / 8);
- + }
- + else if (fbi->smode & FFB_MODE_YUV420) {
- +
- + memset(fbi->map_cpu, 16, size);
- + memset(fbi->map_cpu + PAGE_SIZE + ((size + 0xffff) & 0xffff0000), 128, size / 4);
- + memset(fbi->map_cpu + PAGE_SIZE + ((size + 0xffff) & 0xffff0000) * 5 / 4, 128, size / 4);
- + }
- +}
- +
- +static inline void faradayfb_unmap_video_memory(struct fb_info *info)
- +{
- + struct faradayfb_info *fbi = info->par;
- + fmem_free(fbi->map_size, fbi->map_cpu, fbi->map_dma);
- +}
- +
- +#define FRAME_SIZE_RGB(xres, yres, mbpp) ((xres) * (yres) * (mbpp) / 8)
- +#define FRAME_SIZE_YUV422(xres, yres, mbpp) (((xres) * (yres) * (mbpp) / 8) * 2)
- +#define FRAME_SIZE_YUV420(xres, yres, mbpp) (((((xres) * (yres) * (mbpp) / 8) + 0xffff) & 0xffff0000) * 3 / 2)
- +
- +static inline u32 faradayfb_cal_frame_buf_size(struct faradayfb_info *fbi)
- +{
- + u32 size_rgb = FRAME_SIZE_RGB(fbi->xres, fbi->yres, fbi->max_bpp);
- + u32 size_yuv422 = FRAME_SIZE_YUV422(fbi->xres, fbi->yres, 8);
- + u32 size_yuv420 = FRAME_SIZE_YUV420(fbi->xres, fbi->yres, 8);
- +
- + return max(size_rgb, max(size_yuv422, size_yuv420));
- +}
- +
- +#ifdef CONFIG_FTLCD_OSD
- +/************************************
- + * OSD
- + ***********************************/
- +#define FOSD_SETPOS 0x46e1
- +#define FOSD_SETDIM 0x46e2
- +#define FOSD_SETSCAL 0x46e3
- +#define FLCD_SET_TRANSPARENT 0x46e4
- +#define FLCD_SET_STRING 0x46e5
- +#define FOSD_ON 0x46e6
- +#define FOSD_OFF 0x46e7
- +#define FRREG 0x46e8
- +#define FWREG 0x46e9
- +
- +#define dig_alpha (16 * 10) + (16 * 26) + (16 * 3)
- +
- +struct fosd_string {
- +
- + unsigned int Str_row;
- + unsigned int display_mode;
- + unsigned int fg_color;
- + unsigned int bg_color;
- + unsigned char Str_OSD[30];
- +};
- +
- +struct fosd_data {
- +
- + unsigned int HPos;
- + unsigned int VPos;
- + unsigned int HDim;
- + unsigned int VDim;
- + unsigned int transparent_level;
- + unsigned int HScal;
- + unsigned int VScal;
- + struct fosd_string Str_Data[10];
- +};
- +
- +unsigned int OSD_Font[] = {
- +
- + /* 0 */
- + 0x00, 0x00, 0x00, 0x3e, 0x63, 0x67, 0x6f, 0x7b,
- + 0x73, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
- +
- + /* 1 */
- + 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x0c, 0x0c,
- + 0x0c, 0x0c, 0x0c, 0x3f, 0x00, 0x00, 0x00, 0x00,
- +
- + /* 2 */
- + 0x00, 0x00, 0x00, 0x3e, 0x63, 0x03, 0x06, 0x0c,
- + 0x18, 0x30, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00,
- +
- + /* 3 */
- + 0x00, 0x00, 0x00, 0x3E, 0x63, 0x03, 0x03, 0x1e,
- + 0x03, 0x03, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00,
- +
- + /* 4 */
- + 0x00, 0x00, 0x00, 0x06, 0x0e, 0x1e, 0x36, 0x66,
- + 0x7f, 0x06, 0x06, 0x0f, 0x00, 0x00, 0x00, 0x00,
- +
- + /* 5 */
- + 0x00, 0x00, 0x00, 0x7f, 0x60, 0x60, 0x60, 0x7e,
- + 0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
- +
- + /* 6 */
- + 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7e,
- + 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
- +
- + /* 7 */
- + 0x00, 0x00, 0x00, 0x7f, 0x63, 0x03, 0x06, 0x0c,
- + 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
- +
- + /* 8 */
- + 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x3e,
- + 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
- +
- + /* 9 */
- + 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x3f,
- + 0x03, 0x03, 0x06, 0x3c, 0x00, 0x00, 0x00, 0x00,
- +
- + /* A */
- + 0x00, 0x00, 0x00, 0x08, 0x1c, 0x36, 0x63, 0x63,
- + 0x7f, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
- +
- + /* B */
- + 0x00, 0x00, 0x00, 0x7E, 0x33, 0x33, 0x33, 0x3E,
- + 0x33, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00,
- +
- + /* C */
- + 0x00, 0x00, 0x00, 0x1E, 0x33, 0x61, 0x60, 0x60,
- + 0x60, 0x61, 0x33, 0x1E, 0x00, 0x00, 0x00, 0x00,
- +
- + /* D */
- + 0x00, 0x00, 0x00, 0x7c, 0x36, 0x33, 0x33, 0x33,
- + 0x33, 0x33, 0x36, 0x7C, 0x00, 0x00, 0x00, 0x00,
- +
- + /* E */
- + 0x00, 0x00, 0x00, 0x7f, 0x33, 0x31, 0x34, 0x3c,
- + 0x34, 0x31, 0x33, 0x7f, 0x00, 0x00, 0x00, 0x00,
- +
- + /* F */
- + 0x00, 0x00, 0x00, 0x7f, 0x33, 0x31, 0x34, 0x3c,
- + 0x34, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00,
- +
- + /* G */
- + 0x00, 0x00, 0x00, 0x1E, 0x33, 0x61, 0x60, 0x60,
- + 0x6F, 0x63, 0x36, 0x7C, 0x00, 0x00, 0x00, 0x00,
- +
- + /* H */
- + 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x64, 0x7f,
- + 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
- +
- + /* I */
- + 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18,
- + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
- +
- + /* J */
- + 0x00, 0x00, 0x00, 0x0f, 0x06, 0x06, 0x06, 0x06,
- + 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
- +
- + /* K */
- + 0x00, 0x00, 0x00, 0x73, 0x33, 0x36, 0x36, 0x3c,
- + 0x36, 0x36, 0x33, 0x73, 0x00, 0x00, 0x00, 0x00,
- +
- + /* L */
- + 0x00, 0x00, 0x00, 0x78, 0x30, 0x30, 0x30, 0x30,
- + 0x30, 0x31, 0x33, 0x7f, 0x00, 0x00, 0x00, 0x00,
- +
- + /* M */
- + 0x00, 0x00, 0x00, 0x63, 0x77, 0x7f, 0x6b, 0x63,
- + 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
- +
- + /* N */
- + 0x00, 0x00, 0x00, 0x63, 0x73, 0x7b, 0x7f, 0x6f,
- + 0x67, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
- +
- + /* O */
- + 0x00, 0x00, 0x00, 0x1c, 0x36, 0x63, 0x63, 0x63,
- + 0x63, 0x63, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
- +
- + /* P */
- + 0x00, 0x00, 0x00, 0x7e, 0x33, 0x33, 0x33, 0x3e,
- + 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00,
- +
- + /* Q */
- + 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63,
- + 0x6b, 0x6f, 0x3e, 0x06, 0x07, 0x00, 0x00, 0x00,
- +
- + /* R */
- + 0x00, 0x00, 0x00, 0x7e, 0x33, 0x33, 0x33, 0x3e,
- + 0x36, 0x33, 0x33, 0x73, 0x00, 0x00, 0x00, 0x00,
- +
- + /* S */
- + 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x30, 0x1c,
- + 0x06, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
- +
- + /* T */
- + 0x00, 0x00, 0x00, 0xFF, 0x99, 0x18, 0x18, 0x18,
- + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
- +
- + /* U */
- + 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63,
- + 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
- +
- + /* V */
- + 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63,
- + 0x63, 0x36, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00,
- +
- + /* W */
- + 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63,
- + 0x6b, 0x7f, 0x77, 0x63, 0x00, 0x00, 0x00, 0x00,
- +
- + /* X */
- + 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x36, 0x1c,
- + 0x36, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
- +
- + /* Y */
- + 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x36, 0x1c,
- + 0x1c, 0x1c, 0x1c, 0x3e, 0x00, 0x00, 0x00, 0x00,
- +
- + /* Z */
- + 0x00, 0x00, 0x00, 0x7f, 0x63, 0x46, 0x0c, 0x18,
- + 0x30, 0x61, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00,
- +
- + /* space */
- + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- +
- + /* = */
- + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00,
- + 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- +
- + /* , */
- + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- + 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
- +};
- +
- +void OSD_On(struct faradayfb_info *fbi)
- +{
- + REG32(fbi->io_base + 0x34) &= 0xfffffffe;
- + REG32(fbi->io_base + 0x34) |= 1;
- +}
- +
- +void OSD_Off(struct faradayfb_info *fbi)
- +{
- + REG32(fbi->io_base + 0x34) &= 0xfffffffe;
- +}
- +
- +void OSD_Pos(struct faradayfb_info *fbi, int HPos, int VPos)
- +{
- + REG32(fbi->io_base + 0x38) = (HPos << 10) | VPos;
- +}
- +
- +void OSD_Dim(struct faradayfb_info *fbi, int HDim, int VDim)
- +{
- + REG32(fbi->io_base + 0x34) &= 0x0000001f;
- + REG32(fbi->io_base + 0x34) |= ((HDim << 10) | (VDim << 5));
- +}
- +
- +void OSD_transparent(struct faradayfb_info *fbi, int level)
- +{
- + REG32(fbi->io_base + 0x40) &= 0xffffff00;
- + REG32(fbi->io_base + 0x40) |= (level << 6);
- +}
- +
- +void OSD_fg_color(struct faradayfb_info *fbi, int pal0, int pal1, int pal2, int pal3)
- +{
- + REG32(fbi->io_base + 0x3c) = (pal0) | (pal1 << 8) | (pal2 << 16) | (pal3<< 24);
- +}
- +
- +void OSD_bg_color(struct faradayfb_info *fbi, int pal1, int pal2, int pal3)
- +{
- + REG32(fbi->io_base + 0x40) &= 0x000000ff;
- + REG32(fbi->io_base + 0x40) |= (pal1 << 8) | (pal2 << 16) | (pal3 << 24);
- +}
- +
- +void OSD_Scal(struct faradayfb_info *fbi, int HScal, int VScal)
- +{
- + REG32(fbi->io_base + 0x34) &= 0xffffffe1;
- + REG32(fbi->io_base + 0x34) |= (HScal << 3) | (VScal << 1);
- +}
- +
- +void OSD_putc(struct faradayfb_info *fbi, char c, int position, unsigned int value)
- +{
- + if (c >= '0' && c <= '9')
- + REG32(fbi->io_base + 0xc000 + position * 4) = ((c -'0') << 4) | value;
- +
- + else if (c>= 'A' && c <= 'Z')
- + REG32(fbi->io_base + 0xc000 + position * 4) = ((c - 'A' + 10) << 4) | value;
- +
- + if (c == ' ')
- + REG32(fbi->io_base + 0xc000 + position * 4) = (('Z' - 'A' + 10 + 1) << 4) | value;
- +
- + if (c == '=')
- + REG32(fbi->io_base + 0xc000 + position * 4) = (('Z' - 'A' + 10 + 2) << 4) | value;
- +
- + if (c == ',')
- + REG32(fbi->io_base + 0xc000 + position * 4) = (('Z' - 'A' + 10 + 3) << 4) | value;
- +}
- +
- +void OSD_puts(struct faradayfb_info *fbi, char *str, int position, unsigned int value)
- +{
- + int i;
- +
- + for (i = 0; i < strlen(str); i++)
- + OSD_putc(fbi, *(str + i), position + i, value);
- +}
- +
- +void OSD_String(struct faradayfb_info *fbi, int row, int mode, char *str, int fg_color, int bg_color)
- +{
- + int i, j, x, y;
- + unsigned int value = fg_color | bg_color;
- +
- + /* 10 digit & 26 alphabet & ' ' & '=' & ',' */
- + for (i = 0; i < dig_alpha; i++) {
- +
- + x = 0;
- + y = OSD_Font[i];
- +
- + for (j = 0; j < 12; j ++) { /* reorder */
- + if (y & 1)
- + x |= 1;
- + y >>= 1;
- + x <<= 1;
- + }
- +
- + x >>= 1;
- + REG32(fbi->io_base + 0x8000 + i * 4) = x;
- + }
- +
- + OSD_puts(fbi, str, row, value);
- +
- + if (mode == 2) { /* YCbCr */
- +
- + OSD_fg_color(fbi, 0x57, 0x88, 0x3B, 0xFF);
- + OSD_bg_color(fbi, 0x57, 0x88, 0x3B);
- + }
- + else {
- + OSD_fg_color(fbi, 0x07, 0x38, 0xC0, 0xFF);
- + OSD_bg_color(fbi, 0x07, 0x38, 0xc0);
- + }
- +}
- +#endif /* CONFIG_FTLCD_OSD */
- +
- +struct andesIO {
- +
- + unsigned long Regaddr;
- + unsigned long Regoffset;
- + unsigned long Regvalue;
- +};
- +
- +static int faradayfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
- +{
- + int ret = 0;
- +#ifdef CONFIG_FTLCD_OSD
- + struct faradayfb_info *fbi = info->par;
- + int i;
- + struct fosd_data fosd;
- +
- + struct andesIO IOAccess;
- + unsigned long *Regaccess;
- +#endif
- +
- + DEBUG(0, 1, "Enter\n");
- +
- + switch (cmd) {
- +#ifdef CONFIG_FTLCD_OSD
- + case FRREG:
- +
- + if (copy_from_user(&IOAccess, (struct andesIO *)arg, sizeof(struct andesIO))) {
- +
- + ret = -EFAULT;
- + break;
- + }
- +
- + Regaccess = (unsigned long *)(((IOAccess.Regaddr >> 4) | (unsigned long)0xF0000000) + IOAccess.Regoffset);
- +
- + IOAccess.Regvalue = *(Regaccess);
- +
- + if (copy_to_user((struct andesIO *)arg, &IOAccess, sizeof(struct andesIO))) {
- + ret = -EFAULT;
- + break;
- + }
- +
- + break;
- +
- + case FWREG:
- +
- + if (copy_from_user(&IOAccess, (struct andesIO *)arg, sizeof(struct andesIO))) {
- + ret = -EFAULT;
- + break;
- + }
- +
- + Regaccess = (unsigned long *)(((IOAccess.Regaddr >> 4) | (unsigned long)0xF0000000) + IOAccess.Regoffset);
- + *(Regaccess) = IOAccess.Regvalue;
- +
- + break;
- +
- + case FOSD_ON:
- +
- + DEBUG(1, 1, "FOSD_ON:\n");
- + OSD_On(fbi);
- + break;
- +
- + case FOSD_OFF:
- +
- + DEBUG(1, 1, "FOSD_OFF:\n");
- + OSD_Off(fbi);
- + break;
- +
- + case FOSD_SETPOS:
- +
- + DEBUG(1, 1, "FOSD_SETPOS:\n");
- +
- + if (copy_from_user(&fosd, (unsigned int *)arg, 2 * sizeof(unsigned int))) {
- +
- + ret = -EFAULT;
- + break;
- + }
- +
- + OSD_Pos(fbi, fosd.HPos, fosd.VPos);
- + DEBUG(1, 1, "OSD_Pos = %d %d\n", fosd.HPos, fosd.VPos);
- + break;
- +
- + case FOSD_SETDIM:
- +
- + DEBUG(1, 1, "FOSD_SETDIM:\n");
- +
- + if (copy_from_user(&fosd, (unsigned int *)arg, 4 * sizeof(unsigned int))) {
- +
- + ret = -EFAULT;
- + break;
- + }
- +
- + OSD_Dim(fbi, fosd.HDim, fosd.VDim);
- + DEBUG(1, 1, "OSD_Dim = %d %d\n", fosd.HDim, fosd.VDim);
- + break;
- +
- + case FOSD_SETSCAL:
- +
- + DEBUG(1, 1, "FOSD_SETSCAL:\n");
- +
- + if (copy_from_user(&fosd, (unsigned int *)arg, 7 * sizeof(unsigned int))) {
- + ret = -EFAULT;
- + break;
- + }
- +
- + OSD_Scal(fbi, fosd.HScal, fosd.VScal);
- + break;
- +
- + case FLCD_SET_TRANSPARENT:
- +
- + DEBUG(1, 1, "FLCD_SET_TRANSPARENT:\n");
- +
- + if (copy_from_user(&fosd, (unsigned int *)arg, 5 * sizeof(unsigned int))) {
- +
- + ret = -EFAULT;
- + break;
- + }
- +
- + OSD_transparent(fbi, fosd.transparent_level);
- + DEBUG(1, 1, "OSD_transparent = %d\n", fosd.transparent_level);
- + break;
- +
- + case FLCD_SET_STRING:
- +
- + DEBUG(1, 1, "FLCD_SET_STRING:\n");
- +
- + if (copy_from_user(&fosd, (unsigned int *)arg, sizeof(struct fosd_data))) {
- +
- + ret = -EFAULT;
- + break;
- + }
- +
- + for (i = 0; i < fosd.VDim; i++)
- +
- + OSD_String(fbi, fosd.Str_Data[i].Str_row,
- + fosd.Str_Data[i].display_mode,
- + fosd.Str_Data[i].Str_OSD,
- + fosd.Str_Data[i].fg_color,
- + fosd.Str_Data[i].bg_color);
- + break;
- +#endif /* CONFIG_FTLCD_OSD */
- +
- + default:
- +
- + DEBUG(1, 1, "IOCTL CMD(0x%08u) no define!\n", cmd);
- + ret = -EFAULT;
- + break;
- + }
- +
- + DEBUG(0, 1, "Leave\n");
- + return ret;
- +}
- +
- diff -Nur linux-3.4.110.orig/drivers/video/Kconfig linux-3.4.110/drivers/video/Kconfig
- --- linux-3.4.110.orig/drivers/video/Kconfig 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/video/Kconfig 2016-04-07 10:20:51.058085512 +0200
- @@ -2166,6 +2166,8 @@
- ---help---
- Say Y here to enable support for PNX4008 RGB Framebuffer
-
- +source "drivers/video/FTLCDC100/Kconfig"
- +
- config FB_IBM_GXT4500
- tristate "Framebuffer support for IBM GXT4500P adaptor"
- depends on FB && PPC
- diff -Nur linux-3.4.110.orig/drivers/video/Makefile linux-3.4.110/drivers/video/Makefile
- --- linux-3.4.110.orig/drivers/video/Makefile 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/video/Makefile 2016-04-07 10:20:51.058085512 +0200
- @@ -143,6 +143,7 @@
- obj-$(CONFIG_FB_CARMINE) += carminefb.o
- obj-$(CONFIG_FB_MB862XX) += mb862xx/
- obj-$(CONFIG_FB_MSM) += msm/
- +obj-$(CONFIG_FB_FTLCDC100) += FTLCDC100/
- obj-$(CONFIG_FB_NUC900) += nuc900fb.o
- obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
- obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
- diff -Nur linux-3.4.110.orig/drivers/watchdog/ftwdt010_wdt.c linux-3.4.110/drivers/watchdog/ftwdt010_wdt.c
- --- linux-3.4.110.orig/drivers/watchdog/ftwdt010_wdt.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/drivers/watchdog/ftwdt010_wdt.c 2016-04-07 10:20:51.058085512 +0200
- @@ -0,0 +1,127 @@
- +/*
- + * Watchdog driver for the FTWDT010 Watch Dog Driver
- + *
- + * (c) Copyright 2004 Faraday Technology Corp. (www.faraday-tech.com)
- + * Based on sa1100_wdt.c by Oleg Drokin <green@crimea.edu>
- + * Based on SoftDog driver by Alan Cox <alan@redhat.com>
- + *
- + * This program is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU General Public License
- + * as published by the Free Software Foundation; either version
- + * 2 of the License, or (at your option) any later version.
- + *
- + * 27/11/2004 Initial release
- + */
- +#include <linux/module.h>
- +#include <linux/fs.h>
- +#include <linux/miscdevice.h>
- +#include <linux/watchdog.h>
- +#include <linux/delay.h>
- +#include <asm/uaccess.h>
- +
- +#define DEBUG( str, ...) \
- + do{ \
- + if( debug) \
- + printk( str, ##__VA_ARGS__); \
- + } while(0)
- +
- +#define wdcounter (*( volatile unsigned long *)( WDT_FTWDT010_VA_BASE + 0x00))
- +#define wdload (*( volatile unsigned long *)( WDT_FTWDT010_VA_BASE + 0x04))
- +#define wdrestart (*( volatile unsigned long *)( WDT_FTWDT010_VA_BASE + 0x08))
- +#define wdcr (*( volatile unsigned long *)( WDT_FTWDT010_VA_BASE + 0x0C))
- +#define wdstatus (*( volatile unsigned long *)( WDT_FTWDT010_VA_BASE + 0x10))
- +#define wdclear (*( volatile unsigned long *)( WDT_FTWDT010_VA_BASE + 0x14))
- +#define wdintrcter (*( volatile unsigned long *)( WDT_FTWDT010_VA_BASE + 0x18))
- +
- +#define TIMER_MARGIN 60 /* (secs) Default is 1 minute */
- +#define RESTART_MAGIC 0x5AB9
- +#define PCLK (AHB_CLK_IN / 2)
- +
- +static int debug = 0;
- +static int timeout = TIMER_MARGIN; /* in seconds */
- +
- +module_param(debug, int, 0);
- +module_param(timeout, int, 0);
- +
- +static int ftwdt010_dog_open(struct inode *inode, struct file *file){
- +
- +#if 0
- + /* Allow only one person to hold it open */
- + if( test_and_set_bit( 1, &ftwdt010_wdt_users))
- + return -EBUSY;
- +
- + ftwdt010_wdt_users = 1;
- +#endif
- + DEBUG("Activating WDT..\n");
- +
- + wdcr = 0;
- + wdload = PCLK * timeout;
- + wdrestart = RESTART_MAGIC; /* Magic number */
- + wdcr = 0x03; /* Enable WDT */
- +
- + return 0;
- +}
- +
- +static int ftwdt010_dog_release(struct inode *inode, struct file *file){
- +
- +#ifndef CONFIG_WATCHDOG_NOWAYOUT
- + /*
- + * Shut off the timer.
- + * Lock it in if it's a module and we defined ...NOWAYOUT
- + */
- + wdcr = 0;
- + DEBUG( "Deactivating WDT..\n");
- +#endif
- + return 0;
- +}
- +
- +static ssize_t ftwdt010_dog_write(struct file *file, const char *data, size_t len, loff_t *ppos){
- +
- + if(len){
- +
- + wdrestart = RESTART_MAGIC;
- + return 1;
- + }
- +
- + return 0;
- +}
- +
- +static struct file_operations ftwdt010_dog_fops = {
- +
- + .owner = THIS_MODULE,
- + .llseek = no_llseek,
- + .write = ftwdt010_dog_write,
- + .open = ftwdt010_dog_open,
- + .release = ftwdt010_dog_release,
- +};
- +
- +static struct miscdevice ftwdt010_dog_miscdev = {
- +
- + WATCHDOG_MINOR,
- + "FTWDT010 watchdog",
- + &ftwdt010_dog_fops
- +};
- +
- +static int __init ftwdt010_dog_init( void){
- +
- + int ret;
- +
- + ret = misc_register(&ftwdt010_dog_miscdev);
- +
- + if( ret)
- + return ret;
- +
- + DEBUG("FTWDT010 watchdog timer: timer timeout %d sec\n", timeout);
- +
- + return 0;
- +}
- +
- +static void __exit ftwdt010_dog_exit( void){
- +
- + misc_deregister(&ftwdt010_dog_miscdev);
- +}
- +
- +module_init(ftwdt010_dog_init);
- +module_exit(ftwdt010_dog_exit);
- +MODULE_AUTHOR("Faraday Corp.");
- +MODULE_LICENSE("GPL");
- diff -Nur linux-3.4.110.orig/drivers/watchdog/Kconfig linux-3.4.110/drivers/watchdog/Kconfig
- --- linux-3.4.110.orig/drivers/watchdog/Kconfig 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/watchdog/Kconfig 2016-04-07 10:20:51.058085512 +0200
- @@ -64,6 +64,12 @@
- To compile this driver as a module, choose M here: the
- module will be called softdog.
-
- +config FTWDT010_WATCHDOG
- + tristate "FTWDT010_WATCHDOG"
- + help
- + Support for Faraday ftwdt010 watchdog. When the watchdog triigers the
- + system will be reset.
- +
- config WM831X_WATCHDOG
- tristate "WM831x watchdog"
- depends on MFD_WM831X
- diff -Nur linux-3.4.110.orig/drivers/watchdog/Makefile linux-3.4.110/drivers/watchdog/Makefile
- --- linux-3.4.110.orig/drivers/watchdog/Makefile 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/drivers/watchdog/Makefile 2016-04-07 10:20:51.058085512 +0200
- @@ -163,6 +163,7 @@
- obj-$(CONFIG_XEN_WDT) += xen_wdt.o
-
- # Architecture Independent
- +obj-$(CONFIG_FTWDT010_WATCHDOG) += ftwdt010_wdt.o
- obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o
- obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o
- obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o
- diff -Nur linux-3.4.110.orig/include/linux/mm.h linux-3.4.110/include/linux/mm.h
- --- linux-3.4.110.orig/include/linux/mm.h 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/include/linux/mm.h 2016-04-07 10:20:51.058085512 +0200
- @@ -157,6 +157,7 @@
- #define FAULT_FLAG_ALLOW_RETRY 0x08 /* Retry fault if blocking */
- #define FAULT_FLAG_RETRY_NOWAIT 0x10 /* Don't drop mmap_sem and wait when retrying */
- #define FAULT_FLAG_KILLABLE 0x20 /* The fault task is in SIGKILL killable region */
- +#define FAULT_FLAG_TRIED 0x40 /* second try */
-
- /*
- * This interface is used by x86 PAT code to identify a pfn mapping that is
- diff -Nur linux-3.4.110.orig/include/linux/semaphore.h linux-3.4.110/include/linux/semaphore.h
- --- linux-3.4.110.orig/include/linux/semaphore.h 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/include/linux/semaphore.h 2016-04-07 10:20:51.062085666 +0200
- @@ -36,6 +36,9 @@
- lockdep_init_map(&sem->lock.dep_map, "semaphore->lock", &__key, 0);
- }
-
- +#define init_MUTEX(sem) sema_init(sem, 1)
- +#define init_MUTEX_LOCKED(sem) sema_init(sem, 0)
- +
- extern void down(struct semaphore *sem);
- extern int __must_check down_interruptible(struct semaphore *sem);
- extern int __must_check down_killable(struct semaphore *sem);
- diff -Nur linux-3.4.110.orig/init/Kconfig linux-3.4.110/init/Kconfig
- --- linux-3.4.110.orig/init/Kconfig 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/init/Kconfig 2016-04-07 10:20:51.062085666 +0200
- @@ -966,7 +966,7 @@
-
- config UID16
- bool "Enable 16-bit UID system calls" if EXPERT
- - depends on ARM || BLACKFIN || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && COMPAT) || UML || (X86_64 && IA32_EMULATION)
- + depends on ARM || BLACKFIN || CRIS || FRV || H8300 || X86_32 || M68K || NDS32 || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && COMPAT) || UML || (X86_64 && IA32_EMULATION)
- default y
- help
- This enables the legacy 16-bit UID syscall wrappers.
- diff -Nur linux-3.4.110.orig/kernel/Makefile linux-3.4.110/kernel/Makefile
- --- linux-3.4.110.orig/kernel/Makefile 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/kernel/Makefile 2016-04-07 10:20:51.062085666 +0200
- @@ -20,6 +20,7 @@
- CFLAGS_REMOVE_rtmutex-debug.o = -pg
- CFLAGS_REMOVE_cgroup-debug.o = -pg
- CFLAGS_REMOVE_irq_work.o = -pg
- +CFLAGS_REMOVE_kallsyms.o = -pg
- endif
-
- obj-y += sched/
- diff -Nur linux-3.4.110.orig/kernel/trace/Kconfig linux-3.4.110/kernel/trace/Kconfig
- --- linux-3.4.110.orig/kernel/trace/Kconfig 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/kernel/trace/Kconfig 2016-04-07 10:20:51.062085666 +0200
- @@ -141,7 +141,7 @@
- config FUNCTION_TRACER
- bool "Kernel Function Tracer"
- depends on HAVE_FUNCTION_TRACER
- - select FRAME_POINTER if !ARM_UNWIND && !PPC && !S390 && !MICROBLAZE
- + select FRAME_POINTER if !ARM_UNWIND && !PPC && !S390 && !MICROBLAZE && !NDS32
- select KALLSYMS
- select GENERIC_TRACER
- select CONTEXT_SWITCH_TRACER
- diff -Nur linux-3.4.110.orig/lib/Kconfig.debug linux-3.4.110/lib/Kconfig.debug
- --- linux-3.4.110.orig/lib/Kconfig.debug 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/lib/Kconfig.debug 2016-04-07 10:20:51.062085666 +0200
- @@ -615,7 +615,7 @@
- bool
- depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
- select STACKTRACE
- - select FRAME_POINTER if !MIPS && !PPC && !ARM_UNWIND && !S390 && !MICROBLAZE
- + select FRAME_POINTER if !MIPS && !PPC && !ARM_UNWIND && !S390 && !MICROBLAZE && !NDS32
- select KALLSYMS
- select KALLSYMS_ALL
-
- @@ -1122,7 +1122,7 @@
- depends on FAULT_INJECTION_DEBUG_FS && STACKTRACE_SUPPORT
- depends on !X86_64
- select STACKTRACE
- - select FRAME_POINTER if !PPC && !S390 && !MICROBLAZE && !ARM_UNWIND
- + select FRAME_POINTER if !PPC && !S390 && !MICROBLAZE && !ARM_UNWIND && !NDS32
- help
- Provide stacktrace filter for fault-injection capabilities
-
- @@ -1132,7 +1132,7 @@
- depends on DEBUG_KERNEL
- depends on STACKTRACE_SUPPORT
- depends on PROC_FS
- - select FRAME_POINTER if !MIPS && !PPC && !S390 && !MICROBLAZE && !ARM_UNWIND
- + select FRAME_POINTER if !MIPS && !PPC && !S390 && !MICROBLAZE && !ARM_UNWIND && !NDS32
- select KALLSYMS
- select KALLSYMS_ALL
- select STACKTRACE
- diff -Nur linux-3.4.110.orig/sound/Kconfig linux-3.4.110/sound/Kconfig
- --- linux-3.4.110.orig/sound/Kconfig 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/sound/Kconfig 2016-04-07 10:20:51.062085666 +0200
- @@ -93,6 +93,8 @@
-
- source "sound/sh/Kconfig"
-
- +source "sound/nds32/Kconfig"
- +
- # the following will depend on the order of config.
- # here assuming USB is defined before ALSA
- source "sound/usb/Kconfig"
- diff -Nur linux-3.4.110.orig/sound/Makefile linux-3.4.110/sound/Makefile
- --- linux-3.4.110.orig/sound/Makefile 2015-10-22 03:20:09.000000000 +0200
- +++ linux-3.4.110/sound/Makefile 2016-04-07 10:20:51.062085666 +0200
- @@ -6,7 +6,7 @@
- obj-$(CONFIG_SOUND_PRIME) += oss/
- obj-$(CONFIG_DMASOUND) += oss/
- obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
- - firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/
- + firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ nds32/
- obj-$(CONFIG_SND_AOA) += aoa/
-
- # This one must be compilable even if sound is configured out
- diff -Nur linux-3.4.110.orig/sound/nds32/FTSSP010_ALSA.c linux-3.4.110/sound/nds32/FTSSP010_ALSA.c
- --- linux-3.4.110.orig/sound/nds32/FTSSP010_ALSA.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/sound/nds32/FTSSP010_ALSA.c 2016-04-07 10:20:51.062085666 +0200
- @@ -0,0 +1,2020 @@
- +/* FTSSP010 - UDA1345TS module:
- + *
- + * $log$
- + *
- + * 2006/02/23: I-Jui Sung: OSS emulation half-duplex
- + * playback/capture at 48K, 44.1K, 8K
- + * with mono/stereo 16bit/8bit
- + *
- + * 2006/02/22: I-Jui Sung: OSS emulation playback at 44.1KHz
- + * 16-bit mono completed. Relying ALSA to
- + * resample
- + * 2009/02/24: dma upgrade checking list:
- + * - ac97 mode playback ................. ok
- + * - ac97 mode capture .................. ok
- + * - i2s mode playback .................. ok
- + * - i2s mode capture ................... ok
- + * - mixer support (snd_ctl_add, ...) ... todo
- + * - debug /proc entry .................. ok
- + */
- +
- +
- +#include <linux/init.h>
- +#include <linux/module.h>
- +#include <asm/io.h>
- +#include <linux/delay.h>
- +//#include <asm/spec.h>
- +#include <asm/dmad.h>
- +#include <linux/dma-mapping.h>
- +#include <sound/core.h>
- +#include <sound/pcm.h>
- +#include <sound/initval.h>
- +#include <sound/asound.h>
- +#include <linux/i2c.h>
- +#include <sound/control.h>
- +#include <linux/interrupt.h>
- +
- +#include <asm/hardware.h>
- +#include <asm/irq.h>
- +#include <asm/io.h>
- +#include <asm/spec.h>
- +
- +#include "FTSSP010_UDA1345TS.h"
- +
- +//ADD by river 2011.06.02
- +struct alc5630_data;
- +//End ADD by river 2011.06.02
- +
- +void init_hw(unsigned int cardno,unsigned int ac97, struct i2c_client *client);
- +
- +#if (!defined(CONFIG_PLATFORM_AHBDMA) && !defined(CONFIG_PLATFORM_APBDMA))
- +#warning needs ahb/apb dma to wrok
- +#endif
- +
- +/* ---------------------------------------------------------------------------
- + * Define the debug level of FTSSP_DEBUG
- + */
- +#define FTSSP_DEBUG 0
- +#define FTSSP_DEBUG_VERBOSE 0
- +#define FTSSP_PROC_FS 0
- +
- +#undef VVDBG
- +#if (FTSSP_DEBUG_VERBOSE)
- +#define VVDBG(vvar...) (void)0
- +//#define VVDBG(vvar...) printk(KERN_INFO vvar)
- +#else
- +#define VVDBG(vvar...) (void)0
- +#endif
- +
- +#undef ERR
- +#define ERR(vvar...) printk(KERN_ERR vvar)
- +
- +#undef INFO
- +#define INFO(vvar...) printk(KERN_INFO vvar)
- +
- +#if (FTSSP_DEBUG)
- +#undef DBG
- +#define DBG(vvar...) printk(KERN_INFO vvar)
- +#else
- +#define DBG(vvar...) (void)0
- +#endif
- +
- +#if (FTSSP_DEBUG_VERBOSE)
- +#undef VDBG
- +#define VDBG(vvar...) printk(KERN_INFO vvar)
- +#else
- +#define VDBG(vvar...) (void)0
- +#endif
- +
- +#ifdef CONFIG_SND_FTSSP010_I2S
- +//ADD by river 2011.02.11
- +static struct i2c_client *g_i2c_client;
- +
- +////////// ADD by river 2011.01.26
- +// Each client has this additional data
- +struct alc5630_data {
- + struct i2c_client *client;
- + struct delayed_work work;
- + unsigned long gpio2_value;
- + struct mutex mtx;
- +};
- +
- +static int alc5630_i2c_attach(struct i2c_adapter *adapter);
- +static int alc5630_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
- +static int alc5630_i2c_suspend(struct i2c_client *i2c_client, pm_message_t mesg);
- +static int alc5630_i2c_resume(struct i2c_client *i2c_client);
- +
- +static int alc5630_i2c_remove(struct i2c_client *client);
- +static int ftssp_alsa_init(struct i2c_client *client);
- +
- +
- +static int i2s_alc5630_read(unsigned int raddr, char *data, struct i2c_client *client)
- +{
- + struct i2c_adapter *adap = client->adapter;
- + struct i2c_msg msg;
- + int ret, i2c_value;
- +
- + //Reading ALC5630 register
- + msg.addr = raddr;
- + msg.flags = (client->flags & I2C_M_TEN) | I2C_M_RD;
- + msg.len = 1;
- + msg.buf = (char *)data;
- +
- + //ret = i2c_transfer(adap, &msg, 1);
- + #ifndef CONFIG_SND_FTSSP010_AC97
- + ret = i2c_transfer(adap, &msg, 1);
- + #endif
- +
- + if (ret != 0) {
- + printk("i2c read failed\n");
- + return -1;
- + }
- + else
- + {
- + i2c_value = (data[0]&0xff) << 8 | (data[1]&0xff);
- + return i2c_value;
- + }
- +
- +}
- +
- +static void i2s_alc5630_write(unsigned int addr, unsigned int data, struct i2c_client *client)
- +{
- +
- + struct i2c_adapter *adap = client->adapter;
- + struct i2c_msg msg;
- + int ret, i2c_value;
- + char buf[3];
- +
- + //Writing ALC5630 register
- + i2c_value = 0x0;
- + msg.addr = addr;
- + msg.flags = (client->flags & I2C_M_TEN) | ~I2C_M_RD;
- + msg.len = 1;
- +
- + buf[0] = (data >> 8) & 0xff;
- + buf[1] = data & 0xff;
- + msg.buf = (char *)buf;
- +
- + //ret = i2c_transfer(adap, &msg, 1);
- + #ifndef CONFIG_SND_FTSSP010_AC97
- + ret = i2c_transfer(adap, &msg, 1);
- + #endif
- +
- + if (ret != 0) {
- + printk("i2c write failed\n");
- + }
- +
- +}
- +
- +static void i2s_alc5630_read_test(struct i2c_client *client)
- +{
- + char data[3];
- + //printk(">>>>> : i2s_alc5630_read_test().....\n");
- + printk("Reg 0x%02x = 0x%08x\n", 0x0, i2s_alc5630_read(0x0, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x02, i2s_alc5630_read(0x02, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x04, i2s_alc5630_read(0x04, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x06, i2s_alc5630_read(0x06, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x08, i2s_alc5630_read(0x08, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x0a, i2s_alc5630_read(0x0a, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x0c, i2s_alc5630_read(0x0c, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x0e, i2s_alc5630_read(0x0e, data,client));
- +
- + printk("Reg 0x%02x = 0x%08x\n", 0x10, i2s_alc5630_read(0x10, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x12, i2s_alc5630_read(0x12, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x14, i2s_alc5630_read(0x14, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x16, i2s_alc5630_read(0x16, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x18, i2s_alc5630_read(0x18, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x1a, i2s_alc5630_read(0x1a, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x1c, i2s_alc5630_read(0x1c, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x1e, i2s_alc5630_read(0x1e, data,client));
- +
- + printk("Reg 0x%02x = 0x%08x\n", 0x20, i2s_alc5630_read(0x20, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x22, i2s_alc5630_read(0x22, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x24, i2s_alc5630_read(0x24, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x26, i2s_alc5630_read(0x26, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x28, i2s_alc5630_read(0x28, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x2a, i2s_alc5630_read(0x2a, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x2c, i2s_alc5630_read(0x2c, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x2e, i2s_alc5630_read(0x2e, data,client));
- +
- + printk("Reg 0x%02x = 0x%08x\n", 0x30, i2s_alc5630_read(0x30, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x32, i2s_alc5630_read(0x32, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x34, i2s_alc5630_read(0x34, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x36, i2s_alc5630_read(0x36, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x38, i2s_alc5630_read(0x38, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x3a, i2s_alc5630_read(0x3a, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x3c, i2s_alc5630_read(0x3c, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x3e, i2s_alc5630_read(0x3e, data,client));
- +
- + printk("Reg 0x%02x = 0x%08x\n", 0x40, i2s_alc5630_read(0x40, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x42, i2s_alc5630_read(0x42, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x44, i2s_alc5630_read(0x44, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x46, i2s_alc5630_read(0x46, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x48, i2s_alc5630_read(0x48, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x4a, i2s_alc5630_read(0x4a, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x4c, i2s_alc5630_read(0x4c, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x4e, i2s_alc5630_read(0x4e, data,client));
- +
- + printk("Reg 0x%02x = 0x%08x\n", 0x50, i2s_alc5630_read(0x50, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x52, i2s_alc5630_read(0x52, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x54, i2s_alc5630_read(0x54, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x56, i2s_alc5630_read(0x56, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x58, i2s_alc5630_read(0x58, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x5a, i2s_alc5630_read(0x5a, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x5c, i2s_alc5630_read(0x5c, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x5e, i2s_alc5630_read(0x5e, data,client));
- +
- + printk("Reg 0x%02x = 0x%08x\n", 0x60, i2s_alc5630_read(0x60, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x62, i2s_alc5630_read(0x62, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x64, i2s_alc5630_read(0x64, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x66, i2s_alc5630_read(0x66, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x68, i2s_alc5630_read(0x68, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x6a, i2s_alc5630_read(0x6a, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x6c, i2s_alc5630_read(0x6c, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x6e, i2s_alc5630_read(0x6e, data,client));
- +
- + printk("Reg 0x%02x = 0x%08x\n", 0x70, i2s_alc5630_read(0x70, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x72, i2s_alc5630_read(0x72, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x74, i2s_alc5630_read(0x74, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x76, i2s_alc5630_read(0x76, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x78, i2s_alc5630_read(0x78, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x7a, i2s_alc5630_read(0x7a, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x7c, i2s_alc5630_read(0x7c, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x7e, i2s_alc5630_read(0x7e, data,client));
- +
- +}
- +
- +static int alc5630_i2c_attach(struct i2c_adapter *adapter){
- +
- + struct i2c_board_info info;
- + struct i2c_client *client;
- +
- + int ret=0;
- +
- + //i2c_dbg( 1, "alc5630_i2c_attach() is called.\n");
- + //printk(">>>>>>>>>> (2) alc5630_i2c_attach() is called.\n");
- +
- + //ret = i2c_probe(adapter, &addr_data, alc5630_detect);
- + memset(&info, 0, sizeof(struct i2c_board_info));
- + strlcpy(info.type, "alc5630_codec", I2C_NAME_SIZE);
- + //info.addr = 0x3e;
- + info.addr = 0x66;
- + //info.platform_data = node;
- +
- + //client = i2c_new_device(adapter, &info);
- + #ifndef CONFIG_SND_FTSSP010_AC97
- + client = i2c_new_device(adapter, &info);
- + #endif
- + if (!client) {
- + printk("$$$$$????? : i2c_new_device() failed.....\n");
- + return -ENODEV;
- + }
- + /*
- + * We know the driver is already loaded, so the device should be
- + * already bound. If not it means binding failed, and then there
- + * is no point in keeping the device instantiated.
- + */
- + if (!client->driver) {
- + //i2c_unregister_device(client);
- + #ifndef CONFIG_SND_FTSSP010_AC97
- + i2c_unregister_device(client);
- + #endif
- + return -ENODEV;
- + }
- +
- + /*
- + * Let i2c-core delete that device on driver removal.
- + * This is safe because i2c-core holds the core_lock mutex for us.
- + */
- + list_add_tail(&client->detected, &client->driver->clients);
- +
- + return ret;
- +}
- +
- +static irqreturn_t gpio2_irq(int irq, void *dev_id)
- +{
- +
- + struct i2c_client *client = (struct i2c_client *)dev_id;
- + struct alc5630_data *alc5630 = i2c_get_clientdata(client);
- +
- + unsigned long org_mask, org_dir;
- + //printk("@@@@@#####$$$$$!!!!! : gpio2_irq is detected ???....\n");
- +
- + //Mask GPIO interrupt
- + //REG32(AMIC_VA_BASE + 0x80) = REG32(AMIC_VA_BASE + 0x80) & ~(1 << 13); //GPIO interrupt disable
- +
- + //Dump AMIC contents and ir~
- + unsigned long ir0,ir1,ir2, ir3, ir4, ir5;
- + unsigned long ir6, ir7, ir8, ir9, ir10;
- + unsigned long ir11, ir12, ir13, ir14, ir15;
- + unsigned long gpio2_value, value;
- + char data[3];
- +
- +
- + //__asm__ volatile ("setgie.d\n\t");
- + //REG32(AMIC_VA_BASE + 0x80) = 0;
- +
- +
- + //Get original gpio direction
- + org_dir = REG32(GPIO_VA_BASE + 0x08);
- +
- + //Get original gpio interrupt mask
- + org_mask = REG32(GPIO_VA_BASE + 0x2c);
- +
- + //Mask all gpio interrupt
- + REG32(GPIO_VA_BASE + 0x2c) = 0x0000FFFF;
- + //Clear all gpio interrupt
- + REG32(GPIO_VA_BASE + 0x30) = 0x0000FFFF;
- +
- + //Get gpio pin value
- + REG32(GPIO_VA_BASE + 0x08) = REG32(GPIO_VA_BASE + 0x08) & ~(0x1UL << 2); //Set gpio2 direction => input
- + gpio2_value = (REG32(GPIO_VA_BASE + 0x04) >> 2 & 1);
- + //printk("The gpio2 value is 0x%08x\n",gpio2_value);
- +
- +
- + alc5630->gpio2_value = gpio2_value;
- + schedule_delayed_work(&alc5630->work, 1);
- +
- + /*if (gpio3_value==0x1) {
- + i2s_alc5630_write(0x02, 0x0000, g_i2c_client);
- + i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,g_i2c_client)|0x0040 , g_i2c_client);
- + printk("External speaker is plugged in... and Try to mute internal speaker......\n");
- + }
- + else {
- + i2s_alc5630_write(0x02, 0x5F5F, g_i2c_client);
- + i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,g_i2c_client)|0x0440 , g_i2c_client);
- + printk("External speaker is pulled ... and Try to unmute internal speaker......\n");
- + }*/
- +
- +
- + //Set gpio3 pin value to 0
- + //REG32(GPIO_VA_BASE + 0x08) = REG32(GPIO_VA_BASE + 0x08) | (0x1UL << 3); //Set gpio3 direction => output
- + //value = REG32(GPIO_VA_BASE + 0x00) & ~(0x1UL << 3);
- + //REG32(GPIO_VA_BASE + 0x00) = value;
- +
- + //Get gpio pin value again
- + //REG32(GPIO_VA_BASE + 0x08) = REG32(GPIO_VA_BASE + 0x08) & ~(0x1UL << 3); //Set gpio3 direction => input
- + //gpio3_value = (REG32(GPIO_VA_BASE + 0x04) >> 3 & 1);
- + //printk("The gpio3 value is 0x%08x\n",gpio3_value);
- +
- + //restore original gpio interrupt mask
- + REG32(GPIO_VA_BASE + 0x2c) = org_mask;
- +
- + //restore original gpio direction
- + REG32(GPIO_VA_BASE + 0x08) = org_dir;
- +
- + //unmask GPIO interrupt
- + //REG32(AMIC_VA_BASE + 0x80) = REG32(AMIC_VA_BASE + 0x80) | (1 << 13); //GPIO interrupt enable
- + REG32(AMIC_VA_BASE + 0x84) = REG32(AMIC_VA_BASE + 0x84) | (1 << 13); //Clear GPIO interrupt
- + REG32(GPIO_VA_BASE + 0x30) = 0x0000FFFF; //Clear all gpio interrupt
- +
- + //printk("@@@@@#####$$$$$!!!!! : gpio2_irq() is exited....\n");
- +
- + return IRQ_HANDLED;
- +}
- +
- +static void iic_work(struct work_struct *work)
- +{
- + char data[3];
- + struct alc5630_data *alc5630 =
- + container_of(to_delayed_work(work), struct alc5630_data, work);
- +
- +
- + if (alc5630->gpio2_value==0x0) {
- + //i2s_alc5630_write(0x02, 0x0000, alc5630->client);
- + i2s_alc5630_write(0x02, 0x5F5F, alc5630->client);
- + i2s_alc5630_write(0x3A, (i2s_alc5630_read(0x3A, data,alc5630->client) & 0xFBFF) | 0x0040 , alc5630->client);
- + //printk("External speaker is plugged in... and Try to mute internal speaker......\n");
- + //i2s_alc5630_read_test(alc5630->client);
- + }
- + else {
- + //i2s_alc5630_write(0x02, 0x5F5F, alc5630->client);
- + i2s_alc5630_write(0x02, 0x0000, alc5630->client);
- + i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,alc5630->client)|0x0440 , alc5630->client);
- + //printk("External speaker is pulled ... and Try to unmute internal speaker......\n");
- + //i2s_alc5630_read_test(alc5630->client);
- + }
- + //ftsdc_enable_irq(host, false);
- +
- +
- + //ftsdc_enable_irq(host, true);
- +}
- +
- +static int alc5630_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
- +{
- +
- + struct alc5630_data *alc5630;
- + struct i2c_adapter *adap = client->adapter;
- + //unsigned char ret1, ret2;
- + struct i2c_msg msg;
- + char rbuf[3], wbuf[3];
- + int ret, i2c_rvalue, i2c_wvalue;
- + unsigned int gpio2_value;
- + char data[3];
- +
- + //i2c_dbg( 1, "alc5630_i2c_probe() is called.\n");
- + //printk(">>>>>>>>>> (3) alc5630_i2c_probe() is called.\n");
- +
- + alc5630 = kzalloc(sizeof(struct alc5630_data), GFP_KERNEL);
- +
- + if (!alc5630)
- + return -ENOMEM;
- +
- + mutex_init(&alc5630->mtx);
- + client-> flags = 0;
- + alc5630->client = client;
- + i2c_set_clientdata(client, alc5630);
- +
- + //ADD by river 2011.05.18 for GPIO2 interrupt => edge trigger and rising edge
- + REG32(GPIO_VA_BASE + 0x20) = 0x00000000;
- + REG32(GPIO_VA_BASE + 0x2c) = 0x00000000;
- + REG32(GPIO_VA_BASE + 0x2c) = 0x00000000;
- + REG32(GPIO_VA_BASE + 0x30) = 0x0000FFFF;
- + REG32(GPIO_VA_BASE + 0x38) = 0x0000FFFF;
- + REG32(GPIO_VA_BASE + 0x40) = 0x0000FFFF;
- +
- +
- + REG32(GPIO_VA_BASE + 0x08) = REG32(GPIO_VA_BASE + 0x08) & ~(1 << 2); //GPIO2 as input
- + REG32(GPIO_VA_BASE + 0x34) = REG32(GPIO_VA_BASE + 0x34) & ~(1 << 2); //GPIO2 edge trigger
- + //REG32(GPIO_VA_BASE + 0x38) = REG32(GPIO_VA_BASE + 0x38) & ~(1 << 2); //GPIO2 single edge
- + REG32(GPIO_VA_BASE + 0x38) = REG32(GPIO_VA_BASE + 0x38) | (1 << 2); //GPIO2 both edge
- + REG32(GPIO_VA_BASE + 0x3c) = REG32(GPIO_VA_BASE + 0x3c) & ~(1 << 2); //GPIO2 rising edge
- + REG32(GPIO_VA_BASE + 0x20) = REG32(GPIO_VA_BASE + 0x20) | (1 << 2); //GPIO2 pin interrupt enable
- +
- + REG32(AMIC_VA_BASE + 0x20) = REG32(AMIC_VA_BASE + 0x20) | (1 << 13); //Interrupt Trigger Mode (edge trigger)
- + REG32(AMIC_VA_BASE + 0x24) = REG32(AMIC_VA_BASE + 0x24) & ~(1 << 13); //Interrupt Trigger edge(rising edge)
- + REG32(AMIC_VA_BASE + 0x80) = REG32(AMIC_VA_BASE + 0x80) | (1 << 13); //GPIO interrupt enabled
- + //REG32(AMIC_VA_BASE + 0x80) = 0; //GPIO interrupt enabled
- +
- + if (request_irq(GPIO_FTGPIO010_IRQ, gpio2_irq, IRQF_SHARED, "gpio2", client)) {
- + printk("Failed to request GPIO2 interrupt.\n");
- + goto fail;
- + }
- +
- + //ADD by river 2011.07.11
- + //REG32(GPIO_VA_BASE + 0x08) = REG32(GPIO_VA_BASE + 0x08) & ~(0x1UL << 3); //Set gpio3 direction => input
- + gpio2_value = (REG32(GPIO_VA_BASE + 0x04) >> 2 & 1);
- + //printk("The gpio2 value is 0x%08x\n",gpio2_value);
- + alc5630->gpio2_value = gpio2_value;
- +
- + if (gpio2_value==0x0) {
- + i2s_alc5630_write(0x02, 0x5F5F, alc5630->client);
- + i2s_alc5630_write(0x3A, (i2s_alc5630_read(0x3A, data,alc5630->client) & 0xFBFF) | 0x0040 , alc5630->client);
- + //printk("@@@@@ alc5630_i2c_probe : External speaker is plugged in... and Try to mute internal speaker......\n");
- + //i2s_alc5630_read_test(alc5630->client);
- + }
- + else {
- + i2s_alc5630_write(0x02, 0x0000, alc5630->client);
- + i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,alc5630->client)|0x0440 , alc5630->client);
- + //printk("@@@@@ alc5630_i2c_probe : External speaker is pulled ... and Try to unmute internal speaker......\n");
- + //i2s_alc5630_read_test(alc5630->client);
- + }
- +
- + //End ADD by river 2011.07.11
- +
- + //ADD by river 2011.06.02
- + INIT_DELAYED_WORK(&alc5630->work, iic_work);
- + //End ADD by river 2011.06.02
- + //End ADD by river 2011.05.18
- +
- + ftssp_alsa_init(client);
- +
- + return 0;
- + fail:
- + mutex_destroy(&alc5630->mtx);
- + kfree(alc5630);
- + return -EINVAL;
- +
- +}
- +
- +////////End ADD by river 2011.01.26
- +#endif
- +
- +/* ---------------------------------------------------------------------------
- + * Preserved size of memory space for audio DMA ring
- + */
- +#define FTSSP_HW_DMA_SIZE (512 * 1024)
- +
- +/* Buffer sizes reported to ALSA layer - AC97 mode */
- +
- +/* ring size, exported to application */
- +#define AC97_HW_BUFFER_BYTES_MAX (42 * 1024)
- +/* should not exceed AC97_HW_PERIOD_BYTES_MAX */
- +#define AC97_HW_PERIOD_BYTES_MIN (2 * 1024)
- +/* AC97_HW_PERIOD_BYTES_MAX * AC97_HW_PERIODS_MAX <= AC97_HW_BUFFER_SIZE */
- +#define AC97_HW_PERIOD_BYTES_MAX (8 * 1024)
- +/* 3 <= AC97_HW_PERIODS_MIN <= AC97_HW_PERIODS_MAX */
- +#define AC97_HW_PERIODS_MIN 3
- +/* AC97_HW_PERIOD_BYTES_MAX * AC97_HW_PERIODS_MAX <= AC97_HW_BUFFER_SIZE */
- +#define AC97_HW_PERIODS_MAX 5
- +
- +/* Driver internal dma buffer size, x2 for S16_LE(16-bits) to AC97 (20-bits),
- + * x6 for sampling rate converion from minimum 8k to AC97 48k.
- + *
- + * Note that AC97 mode cannot do playback and recording simultaneouly. So we
- + * use up all FTSSP_HW_DMA_SIZE of memory.
- + */
- +#define AC97_HW_DMA_SIZE (AC97_HW_BUFFER_BYTES_MAX * 2 * 6)
- +
- +/* Buffer sizes reported to ALSA layer - I2S mode */
- +
- +/* ring size, exported to application */
- +#define I2S_HW_BUFFER_BYTES_MAX (256 * 1024)
- +/* should not exceed I2S_HW_PERIOD_BYTES_MAX */
- +#define I2S_HW_PERIOD_BYTES_MIN (2 * 1024)
- +/* I2S_HW_PERIOD_BYTES_MAX * I2S_HW_PERIODS_MAX <= I2S_HW_BUFFER_SIZE */
- +#define I2S_HW_PERIOD_BYTES_MAX (32 * 1024)
- +/* 3 <= I2S_HW_PERIODS_MIN <= I2S_HW_PERIODS_MAX */
- +#define I2S_HW_PERIODS_MIN 3
- +/* I2S_HW_PERIOD_BYTES_MAX * I2S_HW_PERIODS_MAX <= I2S_HW_BUFFER_SIZE */
- +#define I2S_HW_PERIODS_MAX 8
- +
- +/* Page-in size for playback and capture each. Note that I2S mode can do
- + * playback and recording simultaneouly, so this size should be less than or
- + * equal to FTSSP_HW_DMA_SIZE/2
- + */
- +#define I2S_HW_DMA_SIZE (I2S_HW_BUFFER_BYTES_MAX)
- +
- +/* ---------------------------------------------------------------------------
- + * Audio formats
- + */
- +#define AC97_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
- +#define AC97_CODEC_SAMPLE_RATES (SNDRV_PCM_RATE_48000 | \
- + SNDRV_PCM_RATE_16000 | \
- + SNDRV_PCM_RATE_8000)
- +#define AC97_CODEC_SAMPLE_RATE_MIN (8000)
- +#define AC97_CODEC_SAMPLE_RATE_MAX (48000)
- +
- +#define I2S_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
- +#define I2S_CODEC_SAMPLE_RATES (SNDRV_PCM_RATE_48000 | \
- + SNDRV_PCM_RATE_44100 | \
- + SNDRV_PCM_RATE_32000 | \
- + SNDRV_PCM_RATE_22050 | \
- + SNDRV_PCM_RATE_16000 | \
- + SNDRV_PCM_RATE_11025 | \
- + SNDRV_PCM_RATE_8000)
- +#define I2S_CODEC_SAMPLE_RATE_MIN (8000)
- +#define I2S_CODEC_SAMPLE_RATE_MAX (48000)
- +
- +
- +/* ---------------------------------------------------------------------------
- + * Configuration
- + */
- +#if (CONFIG_PROC_FS == 0)
- +#undef FTSSP_PROC_FS
- +#define FTSSP_PROC_FS 0
- +#else
- +#if (FTSSP_PROC_FS)
- +#include <sound/info.h>
- +#endif /* FTSSP_PROC_FS */
- +#endif /* CONFIG_PROC_FS */
- +
- +#define FTSSP_CARD_ID "ftssp010"
- +#define FTSSP_DRIVER_NAME "ftssp"
- +
- +MODULE_LICENSE("GPL");
- +MODULE_AUTHOR("Faraday Technology Corp.");
- +MODULE_DESCRIPTION("FTSSP010 Linux 2.6 Driver");
- +
- +static int cardno = 0;
- +//static const unsigned int SSP_FTSSP010_pa_base[SSP_FTSSP010_IRQ_COUNT] =
- +// { SSP_FTSSP010_PA_BASE };
- +
- +/* Driver mode */
- +#ifdef CONFIG_SND_FTSSP010_AC97
- +static int ac97 = 1;
- +#else
- +static int ac97 = 0;
- +#endif
- +
- +// ----------------------------------------------
- +module_param(cardno, int, 0);
- +MODULE_PARM_DESC(cardno, "FTSSP No.");
- +
- +module_param(ac97, int, 0);
- +MODULE_PARM_DESC(ac97, "AC97 mode");
- +// ----------------------------------------------
- +
- +/* ---------------------------------------------------------------------------
- + * Structures
- + */
- +
- +/* private data for card */
- +typedef struct {
- + struct snd_card *card;
- + struct snd_pcm *pcm;
- + struct snd_pcm_substream *substream_tx;
- + struct snd_pcm_substream *substream_rx;
- +#if (FTSSP_PROC_FS)
- + struct snd_info_entry *info_buf_max;
- + struct snd_info_entry *info_period_min;
- + struct snd_info_entry *info_period_max;
- + struct snd_info_entry *info_periods_min;
- + struct snd_info_entry *info_periods_max;
- +#endif
- +} ftssp_chip;
- +
- +/* dma request descriptors */
- +dmad_chreq dma_chreq_tx = {
- + .channel = -1,
- + .drq = NULL,
- +};
- +
- +dmad_chreq dma_chreq_rx = {
- + .channel = -1,
- + .drq = NULL,
- +};
- +
- +/* Holds ALSA card instance pointers */
- +struct snd_card *ftssp_cards[SSP_FTSSP010_COUNT];
- +
- +/* snd_pcm_hardware */
- +static struct snd_pcm_hardware snd_ftssp_pcm_hw =
- +{
- + .info = SNDRV_PCM_INFO_INTERLEAVED,
- + .formats = I2S_CODEC_FORMATS,
- + .rates = I2S_CODEC_SAMPLE_RATES,
- + .rate_min = I2S_CODEC_SAMPLE_RATE_MIN,
- + .rate_max = I2S_CODEC_SAMPLE_RATE_MAX,
- + .channels_min = 1,
- + .channels_max = 2,
- + .buffer_bytes_max = I2S_HW_BUFFER_BYTES_MAX,
- + .period_bytes_min = I2S_HW_PERIOD_BYTES_MIN,
- + .period_bytes_max = I2S_HW_PERIOD_BYTES_MAX,
- + .periods_min = I2S_HW_PERIODS_MIN,
- + .periods_max = I2S_HW_PERIODS_MAX,
- +};
- +
- +/* private data for a substream (playback or capture) */
- +/* function pointer for set up AHBDMA for this substream */
- +typedef void (*start_t)(int cardno, unsigned use_dma);
- +typedef void (*pmu_set_clocking_t)(unsigned int);
- +typedef void (*ftssp010_config_t)(int cardno, unsigned is_stereo,
- + unsigned speed, int use8bit);
- +
- +typedef struct {
- + u32 busy;
- + spinlock_t dma_lock;
- + unsigned dma_area_va;
- + int dma_width;
- + unsigned int tx_period;
- + unsigned int rx_period;
- +
- + start_t start;
- + pmu_set_clocking_t pmu_set_clocking;
- + ftssp010_config_t hw_config;
- +} ftssp_substream;
- +
- +static ftssp_substream ftssp010_substreams[2] = {
- + /* Playback substream */
- + {
- + busy : 0,
- + start : ftssp010_start_tx,
- + pmu_set_clocking : pmu_set_i2s_clocking,
- + hw_config : ftssp010_config_tx,
- + },
- + /* Capture substream */
- + {
- + busy : 0,
- + start : ftssp010_start_rx,
- + pmu_set_clocking : pmu_set_i2s_clocking,
- + hw_config : ftssp010_config_rx,
- + }
- +};
- +
- +/* (AC97 only) Convert 16 bits PCM data in user buffer to/from 20 bits PCM data
- + * (32 bits actaully in dma buffer) for AC97 codec.
- + */
- +static int snd_ftssp_playback_copy(struct snd_pcm_substream *substream,
- + int channel, snd_pcm_uframes_t pos, void *usr_buf,
- + snd_pcm_uframes_t count)
- +{
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + ftssp_substream *ftssp010_substream =
- + (ftssp_substream *) runtime->private_data;
- +
- +
- + //printk("~~~~~ : snd_ftssp_playback_copy() is invoked....\n");
- + u32 *dma_va = NULL;
- + u16 *usr_va = usr_buf;
- + int copy_words;
- + int pcm_data;
- +
- + dmad_chreq *dma_chreq;
- +
- + /* frames_to_bytes(runtime, pos + count) * 2(bytes/per pcm) /
- + * 4(bytes per dma unit) */
- + u32 sw_ptr = (u32)frames_to_bytes(runtime, pos + count) >> 1;
- +
- + switch (runtime->rate) {
- + case 8000:
- + sw_ptr *= 6;
- +
- + dma_va = (unsigned *)(ftssp010_substream->dma_area_va +
- + frames_to_bytes(runtime, pos * 6) * 2);
- +
- + VVDBG("%s: pos(0x%08x) count(0x%08x) next_pos(0x%08x)\n",
- + __func__, (u32)pos, (u32)count, (u32)(pos + count));
- + VVDBG("%s: va base(0x%08x) range (0x%08x ~ 0x%08x)\n",
- + __func__, (u32)ftssp010_substream->dma_area_va,
- + (u32)dma_va,
- + (u32)dma_va +
- + (u32)2 * frames_to_bytes(runtime, count * 6));
- +
- + if (runtime->channels == 1) {
- + while (count--) {
- + dma_va[0] = (u32)(*usr_va++) << 4;
- + dma_va[1] = dma_va[2] = dma_va[3] =
- + dma_va[4] = dma_va[5] = dma_va[0];
- + //memcpy(&dma_va[1], &dma_va[0], 5 * 4 * 1);
- + dma_va += 6;
- + }
- + } else { // assume 2 channels
- + while (count--) {
- + dma_va[0] = (u32)(*usr_va++) << 4;
- + dma_va[1] = (u32)(*usr_va++) << 4;
- + dma_va[2] = dma_va[4] = dma_va[6] =
- + dma_va[8] = dma_va[10] = dma_va[0];
- + dma_va[3] = dma_va[5] = dma_va[7] =
- + dma_va[9] = dma_va[11] = dma_va[0];
- + //memcpy(&dma_va[2], &dma_va[0], 5 * 4 * 2);
- + dma_va += 12;
- + }
- + }
- + break;
- + case 16000:
- + sw_ptr *= 3;
- +
- + dma_va = (unsigned *)(ftssp010_substream->dma_area_va +
- + frames_to_bytes(runtime, pos * 3) * 2);
- +
- + VVDBG("%s: pos(0x%08x) count(0x%08x) next_pos(0x%08x)\n",
- + __func__, (u32)pos, (u32)count, (u32)(pos + count));
- + VVDBG("%s: va base(0x%08x) range (0x%08x ~ 0x%08x)\n",
- + __func__, (u32)ftssp010_substream->dma_area_va,
- + (u32)dma_va,
- + (u32)dma_va +
- + (u32)2 * frames_to_bytes(runtime, count * 3));
- +
- + if (runtime->channels == 1) {
- + while (count--) {
- + dma_va[0] = (u32)(*usr_va++) << 4;
- + dma_va[1] = dma_va[2] = dma_va[0];
- + //memcpy(&dma_va[1], &dma_va[0], 2 * 4 * 1);
- + dma_va += 3;
- + }
- + } else { // assume 2 channels
- + while (count--) {
- + dma_va[0] = (u32)(*usr_va++) << 4;
- + dma_va[1] = (u32)(*usr_va++) << 4;
- + dma_va[2] = dma_va[4] = dma_va[0];
- + dma_va[3] = dma_va[5] = dma_va[1];
- + //memcpy(&dma_va[2], &dma_va[0], 2 * 4 * 2);
- + dma_va += 6;
- + }
- + }
- + break;
- + case 48000:
- + default:
- + dma_va = (unsigned *)(ftssp010_substream->dma_area_va +
- + frames_to_bytes(runtime, pos) * 2);
- + copy_words = 2 * frames_to_bytes(runtime, count) / sizeof(u32);
- +
- + VVDBG("%s: pos(0x%08x) count(0x%08x) next_pos(0x%08x)\n",
- + __func__, (u32)pos, (u32)count, (u32)(pos + count));
- + VVDBG("%s: va base(0x%08x) range (0x%08x ~ 0x%08x)\n",
- + __func__, (u32)ftssp010_substream->dma_area_va,
- + (u32)dma_va,
- + (u32)dma_va + (u32)copy_words*4);
- +
- + while (copy_words--) {
- + pcm_data = (*usr_va++);
- + *dma_va++= pcm_data << 4;
- + }
- + break;
- + }
- +
- + dma_chreq = &dma_chreq_tx;
- +
- + if (dmad_update_ring_sw_ptr(dma_chreq, sw_ptr,
- + (runtime->status->state == SNDRV_PCM_STATE_RUNNING) ? 1:0) != 0)
- + {
- + ERR("%s: failed to update sw-pointer!\n", __func__);
- + return -ENODEV;
- + }
- +
- + return 0;
- +}
- +
- +static int snd_ftssp_capture_copy(struct snd_pcm_substream *substream,
- + int channel, snd_pcm_uframes_t pos, void *usr_buf,
- + snd_pcm_uframes_t count)
- +{
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + ftssp_substream *ftssp010_substream =
- + (ftssp_substream *) runtime->private_data;
- +
- + //printk("~~~~~ : snd_ftssp_capture_copy() is invoked....\n");
- + //printk(">>>>>>>>>> : snd_ftssp_capture_copy() for recording....\n");
- + u32 *dma_va = NULL;
- + u16 *usr_va = usr_buf;
- +
- + switch (runtime->rate) {
- + case 8000:
- + dma_va = (unsigned *)(ftssp010_substream->dma_area_va +
- + frames_to_bytes(runtime, pos * 6) * 2);
- +
- + VVDBG("%s: pos(0x%08x) count(0x%08x) next_pos(0x%08x)\n",
- + __func__, (u32)pos, (u32)count, (u32)(pos + count));
- + VVDBG("%s: va base(0x%08x) range (0x%08x ~ 0x%08x)\n",
- + __func__, (u32)ftssp010_substream->dma_area_va,
- + (u32)dma_va,
- + (u32)dma_va +
- + (u32)2 * frames_to_bytes(runtime, count * 6));
- +
- + if (runtime->channels == 1) {
- + while (count--) {
- + *usr_va++ = (u16)(dma_va[0] >> 4);
- + dma_va += 6;
- + }
- + } else {
- + while (count--) {
- + usr_va[0] = (u16)(dma_va[0] >> 4);
- +
- + /* [hw-limit] only slot-3 has valid data in
- + * recording mode -- check TAG_DATA_MONO
- + * defined in "FTSSP010_lib.c". Mask out
- + * one channel to avoid hi-freq noise.
- + */
- + usr_va[1] = usr_va[0];
- + usr_va += 2;
- + dma_va += 12;
- + }
- + }
- + break;
- + case 16000:
- + dma_va = (unsigned *)(ftssp010_substream->dma_area_va +
- + frames_to_bytes(runtime, pos * 3) * 2);
- +
- + VVDBG("%s: pos(0x%08x) count(0x%08x) next_pos(0x%08x)\n",
- + __func__, (u32)pos, (u32)count, (u32)(pos + count));
- + VVDBG("%s: va base(0x%08x) range (0x%08x ~ 0x%08x)\n",
- + __func__, (u32)ftssp010_substream->dma_area_va,
- + (u32)dma_va,
- + (u32)dma_va +
- + (u32)2 * frames_to_bytes(runtime, count * 3));
- +
- + if (runtime->channels == 1) {
- + while (count--) {
- + *usr_va++ = (u16)(dma_va[0] >> 4);
- + dma_va += 3;
- + }
- + } else {
- + while (count--) {
- + usr_va[0] = (u16)(dma_va[0] >> 4);
- +
- + /* [hw-limit] only slot-3 has valid data in
- + * recording mode -- check TAG_DATA_MONO
- + * defined in "FTSSP010_lib.c". Mask out
- + * one channel to avoid hi-freq noise.
- + */
- + usr_va[1] = usr_va[0];
- + usr_va += 2;
- + dma_va += 6;
- + }
- + }
- + break;
- + case 48000:
- + default:
- + dma_va = (unsigned *)(ftssp010_substream->dma_area_va +
- + frames_to_bytes(runtime, pos) * 2);
- +
- + VVDBG("%s: pos(0x%08x) count(0x%08x) next_pos(0x%08x)\n",
- + __func__, (u32)pos, (u32)count, (u32)(pos + count));
- + VVDBG("%s: va base(0x%08x) range (0x%08x ~ 0x%08x)\n",
- + __func__, (u32)ftssp010_substream->dma_area_va,
- + (u32)dma_va,
- + (u32)dma_va +
- + (u32)2 * frames_to_bytes(runtime, count));
- +
- + if (runtime->channels == 1) {
- + while (count--) {
- + *usr_va++ = (u16)(*dma_va++ >> 4);
- + }
- + } else {
- + while (count--) {
- + usr_va[0] = (u16)(dma_va[0] >> 4);
- +
- + /* [hw-limit] only slot-3 has valid data in
- + * recording mode -- check TAG_DATA_MONO
- + * defined in "FTSSP010_lib.c". Mask out
- + * one channel to avoid hi-freq noise.
- + */
- + usr_va[1] = usr_va[0];
- + usr_va += 2;
- + dma_va += 2;
- + }
- + }
- + break;
- + }
- +
- + return 0;
- +}
- +
- +/**
- + * These dma callbacks are called in interrupt context.
- + * @data: pointer to the chip-wide structure.
- + * TODO: use stream-specifc data
- + */
- +__attribute__((__unused__))
- +static void ftssp_dma_callback_tx(int ch, u16 int_status, void *data)
- +{
- + ftssp_chip *chip = (ftssp_chip *)data;
- +
- + //printk("~~~~~ : ftssp_dma_callback_tx() is invoked....\n");
- + if (!ac97) {
- + /* in i2s mode, no indication to driver for user data length.
- + * For simplicity, just go ahead by one period */
- +
- + struct snd_pcm_runtime *runtime = chip->substream_tx->runtime;
- + ftssp_substream *ftssp010_substream =
- + (ftssp_substream *)runtime->private_data;
- + u32 sw_ptr;
- + u32 tx_period = ftssp010_substream->tx_period + 1;
- +
- + if (tx_period == runtime->periods)
- + sw_ptr = runtime->buffer_size;
- + else
- + sw_ptr = tx_period * runtime->period_size;
- +
- + sw_ptr = (u32)frames_to_bytes(runtime, sw_ptr) >> 1;
- +
- + if (dmad_update_ring_sw_ptr(&dma_chreq_tx, (u32)sw_ptr, 0)) {
- + ERR("%s: failed to update sw-pointer!\n", __func__);
- + }
- +
- + ftssp010_substream->tx_period = tx_period % runtime->periods;
- + }
- +
- + snd_pcm_period_elapsed(chip->substream_tx);
- +}
- +
- +__attribute__((__unused__))
- +static void ftssp_dma_callback_rx(int ch, u16 int_status, void *data)
- +{
- + ftssp_chip *chip = (ftssp_chip *)data;
- + struct snd_pcm_runtime *runtime = chip->substream_rx->runtime;
- + ftssp_substream *ftssp010_substream =
- + (ftssp_substream *)runtime->private_data;
- +
- + //printk("~~~~~ : ftssp_dma_callback_rx() is invoked....\n");
- + //printk(">>>>>>>>>> : ftssp_dma_callback_rx() for recording....\n");
- +
- + u32 sw_ptr;
- + u32 rx_period = ftssp010_substream->rx_period + 1;
- +
- + if (rx_period == runtime->periods)
- + sw_ptr = runtime->buffer_size;
- + else
- + sw_ptr = rx_period * runtime->period_size;
- +
- + if (ac97) {
- + switch (runtime->rate) {
- + case 8000:
- + sw_ptr = sw_ptr * 6;
- + break;
- + case 16000:
- + sw_ptr = sw_ptr * 3;
- + break;
- + case 48000:
- + default:
- + break;
- + }
- + }
- + sw_ptr = (u32)frames_to_bytes(runtime, sw_ptr) >> 1;
- +
- + if (dmad_update_ring_sw_ptr(&dma_chreq_rx, (u32)sw_ptr, 0) != 0) {
- + ERR("%s: failed to update sw-pointer!\n", __func__);
- + }
- +
- + ftssp010_substream->rx_period = rx_period % runtime->periods;
- +
- + snd_pcm_period_elapsed(chip->substream_rx);
- +}
- +
- +static inline int snd_ftssp_dma_ch_alloc(struct snd_pcm_substream *substream)
- +{
- + dmad_chreq *ch_req __attribute__((__unused__)) = 0;
- +
- + //printk("~~~~~ WATCH : snd_ftssp_dma_ch_alloc() is invoked....\n");
- +#ifdef CONFIG_PLATFORM_APBDMA
- +
- + if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- + ch_req = &dma_chreq_tx;
- + ch_req->completion_cb = ftssp_dma_callback_tx;
- + ch_req->apb_req.tx_dir = DMAD_DIR_A0_TO_A1;
- + /*for amerald ac97 ssp2 */
- + if((inl(PMU_BASE) & AMERALD_MASK) == AMERALD_PRODUCT_ID)
- + {
- + ch_req->apb_req.dev_reqn = APBBR_REQN_I2SAC97TX_AMERALD;
- + }
- + else
- + ch_req->apb_req.dev_reqn = APBBR_REQN_I2SAC97TX;
- + } else {
- + ch_req = &dma_chreq_rx;
- + ch_req->completion_cb = ftssp_dma_callback_rx;
- + ch_req->apb_req.tx_dir = DMAD_DIR_A1_TO_A0;
- + /*for amerald ac97 ssp2 */
- + if((inl(PMU_BASE) & AMERALD_MASK) == AMERALD_PRODUCT_ID)
- + {
- + ch_req->apb_req.dev_reqn = APBBR_REQN_I2SAC97RX_AMERALD;
- + }
- + else
- + ch_req->apb_req.dev_reqn = APBBR_REQN_I2SAC97RX;
- + }
- +
- + ch_req->controller = DMAD_DMAC_APB_CORE;
- + ch_req->flags = DMAD_FLAGS_RING_MODE;
- + ch_req->ring_base = 0;
- + ch_req->dev_addr = (dma_addr_t)FTSSP010_DATA_PA(cardno);
- + ch_req->periods = 0;
- + ch_req->period_size = 0;
- +
- + if (ac97) {
- + ch_req->apb_req.ring_ctrl = APBBR_ADDRINC_I4X;
- + ch_req->apb_req.ring_reqn = APBBR_REQN_NONE;
- + ch_req->apb_req.dev_ctrl = APBBR_ADDRINC_FIXED;
- + ch_req->apb_req.burst_mode = 0;
- + ch_req->apb_req.data_width = APBBR_DATAWIDTH_4;
- + } else {
- + ch_req->apb_req.ring_ctrl = APBBR_ADDRINC_I2X;
- + ch_req->apb_req.ring_reqn = APBBR_REQN_NONE;
- + ch_req->apb_req.dev_ctrl = APBBR_ADDRINC_FIXED;
- + ch_req->apb_req.burst_mode = 0;
- + ch_req->apb_req.data_width = APBBR_DATAWIDTH_2;
- + }
- +
- + ch_req->completion_data = (void *)snd_pcm_substream_chip(substream);
- +
- + if (dmad_channel_alloc(ch_req) != 0) {
- + ERR("%s: APBDMA channel allocation failed\n",__func__);
- + goto _try_ahb;
- + }
- +
- + DBG("%s: APBDMA channel allocated (ch: %d) ring_mode\n",
- + __func__, ch_req->channel);
- +
- + return 0;
- +
- +_try_ahb:
- +
- +#endif /* CONFIG_PLATFORM_APBDMA */
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- + if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- + ch_req = &dma_chreq_tx;
- + ch_req->completion_cb = ftssp_dma_callback_tx;
- + ch_req->ahb_req.tx_dir = DMAD_DIR_A0_TO_A1;
- + if((inl(PMU_BASE) & AMERALD_MASK) == AMERALD_PRODUCT_ID)
- + {
- + ch_req->ahb_req.dev_reqn = DMAC_REQN_I2SAC97TX_AMERALD;
- + }
- + else
- + ch_req->ahb_req.dev_reqn = DMAC_REQN_I2SAC97TX;
- + } else {
- + ch_req = &dma_chreq_rx;
- + ch_req->completion_cb = ftssp_dma_callback_rx;
- + ch_req->ahb_req.tx_dir = DMAD_DIR_A1_TO_A0;
- + if((inl(PMU_BASE) & AMERALD_MASK) == AMERALD_PRODUCT_ID)
- + {
- + ch_req->ahb_req.dev_reqn = DMAC_REQN_I2SAC97RX_AMERALD;
- + }
- + else
- + ch_req->ahb_req.dev_reqn = DMAC_REQN_I2SAC97RX;
- + }
- +
- + ch_req->controller = DMAD_DMAC_AHB_CORE;
- + ch_req->flags = DMAD_FLAGS_RING_MODE;
- + ch_req->ring_base = 0;
- + ch_req->dev_addr = (dma_addr_t)FTSSP010_DATA_PA(cardno);
- + ch_req->periods = 0;
- + ch_req->period_size = 0;
- +
- + ch_req->ahb_req.sync = 1;
- + ch_req->ahb_req.priority = DMAC_CSR_CHPRI_2;
- + ch_req->ahb_req.hw_handshake = 1;
- + ch_req->ahb_req.burst_size = DMAC_CSR_SIZE_1;
- +
- + if (ac97) {
- + ch_req->ahb_req.ring_width = DMAC_CSR_WIDTH_32;
- + ch_req->ahb_req.ring_ctrl = DMAC_CSR_AD_INC;
- + ch_req->ahb_req.ring_reqn = DMAC_REQN_NONE;
- + ch_req->ahb_req.dev_width = DMAC_CSR_WIDTH_32;
- + ch_req->ahb_req.dev_ctrl = DMAC_CSR_AD_FIX;
- + } else {
- + ch_req->ahb_req.ring_width = DMAC_CSR_WIDTH_16;
- + ch_req->ahb_req.ring_ctrl = DMAC_CSR_AD_INC;
- + ch_req->ahb_req.ring_reqn = DMAC_REQN_NONE;
- + ch_req->ahb_req.dev_width = DMAC_CSR_WIDTH_16;
- + ch_req->ahb_req.dev_ctrl = DMAC_CSR_AD_FIX;
- + }
- +
- + ch_req->completion_data = (void *)snd_pcm_substream_chip(substream);
- +
- + if (dmad_channel_alloc(ch_req) != 0) {
- + ERR("%s: AHBDMA channel allocation failed\n", __func__);
- + goto _err_exit;
- + }
- +
- + DBG("%s: AHBDMA channel allocated (ch: %d) ring_mode\n",
- + __func__, ch_req->channel);
- +
- + return 0;
- +
- +_err_exit:
- +
- +#endif /* CONFIG_PLATFORM_AHBDMA */
- +
- + return -ENODEV;
- +}
- +
- +static inline ftssp_substream *ftssp010_substream_new(int stream_id)
- +{
- + ftssp_substream *s = NULL;
- +
- + //printk("~~~~~ : ftssp010_substream_new() is invoked....\n");
- +
- + switch (stream_id) {
- + case SNDRV_PCM_STREAM_PLAYBACK:
- + s = &ftssp010_substreams[0];
- + break;
- + case SNDRV_PCM_STREAM_CAPTURE:
- + s = &ftssp010_substreams[1];
- + break;
- + default:
- + ERR("%s: wrong stream type (%d)\n", __func__, stream_id);
- + return NULL;
- + }
- +
- + if (s->busy) {
- + ERR("%s: device busy!\n", __func__);
- + return NULL;
- + }
- + s->busy = 1;
- +
- + spin_lock_init(&s->dma_lock);
- +
- + return s;
- +}
- +
- +static int snd_ftssp_pcm_open(struct snd_pcm_substream *substream)
- +{
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + int stream_id = substream->pstr->stream;
- +
- + VDBG("%s, %s\n", __func__,
- + (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
- + "playback" : "capture");
- +
- + //printk("~~~~~ : snd_ftssp_pcm_open() is invoked....\n");
- +
- + /* Both playback and capture share a hardware description */
- + runtime->hw = snd_ftssp_pcm_hw;
- +
- + /* Allocate & Initialize stream-specific data */
- + runtime->private_data = ftssp010_substream_new(stream_id);
- +
- + if (runtime->private_data) {
- + //printk("~~~~~ YAYAYA @@@@@ : Calling snd_ftssp_dma_ch_alloc().\n");
- + return snd_ftssp_dma_ch_alloc(substream);
- + }
- + else
- + return -EBUSY;
- +}
- +
- +static int snd_ftssp_pcm_close(struct snd_pcm_substream *substream)
- +{
- + int stream_id = substream->pstr->stream;
- + ftssp_substream *ftssp010_substream =
- + (ftssp_substream *)substream->runtime->private_data;
- +
- + VDBG("%s, %s\n", __func__,
- + (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
- + "playback" : "capture");
- +
- + //printk("~~~~~ : snd_ftssp_pcm_close() is invoked....\n");
- +
- + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
- + dmad_channel_free(&dma_chreq_tx);
- + else
- + dmad_channel_free(&dma_chreq_rx);
- +
- + ftssp010_substream->busy = 0;
- + return 0;
- +}
- +
- +static int snd_ftssp_pcm_hw_params(struct snd_pcm_substream *substream,
- + struct snd_pcm_hw_params *hw_params)
- +{
- + VDBG("%s, %s\n", __func__,
- + (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
- + "playback" : "capture");
- +
- + //printk("~~~~~ : snd_ftssp_pcm_hw_params() is invoked....\n");
- +
- + if (ac97)
- + return snd_pcm_lib_malloc_pages(substream, AC97_HW_DMA_SIZE);
- + else
- + return snd_pcm_lib_malloc_pages(substream, I2S_HW_DMA_SIZE);
- +}
- +
- +static int snd_ftssp_pcm_hw_free(struct snd_pcm_substream *substream)
- +{
- + VDBG("%s, %s\n", __func__,
- + (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
- + "playback" : "capture");
- + //printk("~~~~~ : snd_ftssp_pcm_hw_free() is invoked....\n");
- +
- + if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK)
- + dmad_drain_requests(&dma_chreq_tx, 1);
- + else
- + dmad_drain_requests(&dma_chreq_rx, 1);
- +
- + return snd_pcm_lib_free_pages(substream);
- +}
- +
- +/* Prepare FTSSP010 AHBDMA for playback & capture */
- +static int snd_ftssp_pcm_prepare(struct snd_pcm_substream *substream)
- +{
- + ftssp_chip *chip = snd_pcm_substream_chip(substream);
- + struct snd_pcm_runtime *runtime = substream->runtime;
- +
- + //printk("~~~~~ : snd_ftssp_pcm_prepare() is invoked....\n");
- + //printk("@@@@@ >>>>> : snd_ftssp_pcm_prepare() is called.\n");
- +
- + ftssp_substream *ftssp010_substream =
- + (ftssp_substream *)runtime->private_data;
- +
- + int stream_id = substream->pstr->stream;
- + dmad_chreq *dma_chreq;
- + unsigned period_size, buffer_size;
- +
- + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
- + dma_chreq = &dma_chreq_tx;
- + else
- + dma_chreq = &dma_chreq_rx;
- +
- + period_size = frames_to_bytes(runtime, runtime->period_size);
- + buffer_size = frames_to_bytes(runtime, runtime->buffer_size);
- +
- + if (runtime->format != SNDRV_PCM_FORMAT_S16_LE)
- + return -ENODEV;
- +
- + if (ac97) {
- + switch (runtime->rate) {
- + case 8000:
- + period_size *= 12;
- + buffer_size *= 12;
- + break;
- + case 16000:
- + period_size *= 6;
- + buffer_size *= 6;
- + break;
- + case 48000:
- + default:
- + period_size *= 2;
- + buffer_size *= 2;
- + break;
- + }
- +
- + ftssp010_substream->dma_width = 4;
- + } else {
- + ftssp010_substream->dma_width = 2;
- + }
- +
- + dmad_drain_requests(dma_chreq, 1);
- +
- + dma_chreq->ring_base = (dma_addr_t)runtime->dma_addr;
- + dma_chreq->periods = (dma_addr_t)runtime->periods;
- + if (ac97) {
- + dma_chreq->period_size = (dma_addr_t)(period_size >> 2);
- + dma_chreq->ring_size = (dma_addr_t)(buffer_size >> 2);
- + } else {
- + dma_chreq->period_size = (dma_addr_t)(period_size >> 1);
- + dma_chreq->ring_size = (dma_addr_t)(buffer_size >> 1);
- + }
- + dmad_update_ring(dma_chreq);
- +
- + /* Set PMU, FTSSP010, and DMA */
- + spin_lock(&ftssp010_substream->dma_lock);
- +
- + /* keep DMA buffer VA for copy() callback */
- + // todo: support playback/capture simultaneously
- + ftssp010_substream->dma_area_va = (u32)runtime->dma_area;
- +
- + if (ac97) {
- + ftssp010_substream->pmu_set_clocking(48000);
- + ftssp010_substream->hw_config(cardno,
- + runtime->channels > 1 ? 1 : 0, /* 1: stereo, 0: mono */
- + 48000, ftssp010_substream->dma_width);
- + } else {
- +
- + ftssp010_substream->pmu_set_clocking(runtime->rate);
- + ftssp010_substream->hw_config(cardno,
- + runtime->channels > 1 ? 1 : 0, /* 1: stereo, 0: mono */
- + runtime->rate, ftssp010_substream->dma_width);
- + }
- +
- + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
- + ftssp010_substream->tx_period = 0;
- + chip->substream_tx = substream;
- + } else {
- + ftssp010_substream->rx_period = 0;
- + chip->substream_rx = substream;
- + }
- +
- + spin_unlock(&ftssp010_substream->dma_lock);
- +
- + VVDBG("%s <<\n", __func__);
- +
- + return 0;
- +}
- +
- +static inline int snd_ftssp_start_play(ftssp_substream *ftssp010_substream,
- + struct snd_pcm_runtime *runtime)
- +{
- + int err = 0;
- +
- + //printk("~~~~~ : snd_ftssp_start_play() is invoked....\n");
- +
- + if (ac97) {
- + /* in ac97 mode, user data was fed to dma buffer through
- + * driver-provided copy callback */
- + err = dmad_kickoff_requests(&dma_chreq_tx);
- + if (err != 0) {
- + ERR("%s: failed to kickoff dma!\n", __func__);
- + return err;
- + }
- + } else {
- + /* in i2s mode, no indication to driver for user data length
- + * (except start threshold). For simplicity at start, just go
- + * ahead by one cycle */
- +
- + u32 sw_ptr =
- + (u32)frames_to_bytes(runtime, runtime->buffer_size) >>1;
- +
- + err = dmad_update_ring_sw_ptr(&dma_chreq_tx, sw_ptr, 0);
- + if (err != 0) {
- + ERR("%s: failed to update sw-pointer!\n", __func__);
- + return err;
- + }
- +
- + err = dmad_kickoff_requests(&dma_chreq_tx);
- + if (err != 0) {
- + ERR("%s: failed to kickoff dma!\n", __func__);
- + return err;
- + }
- + }
- +
- + ftssp010_substream->start(cardno, 1);
- +
- + //ADD by river 2011.03.08
- + //i2s_alc5630_write(0x02, 0x0000, g_i2c_client);
- + //i2s_alc5630_write(0x04, 0x0000, g_i2c_client);
- + //i2s_alc5630_write(0x0c, 0x1010, g_i2c_client);
- + //i2s_alc5630_write(0x10, 0xff03, g_i2c_client);
- + //End ADD by river 2011.03.08
- +
- + return 0;
- +}
- +
- +static inline int snd_ftssp_start_record(ftssp_substream *ftssp010_substream,
- + struct snd_pcm_runtime *runtime)
- +{
- + int err = 0;
- +
- + //printk("~~~~~ : snd_ftssp_start_record() is invoked....\n");
- +
- + u32 sw_ptr = (u32)frames_to_bytes(runtime, runtime->buffer_size);
- +
- + if (ac97) {
- + switch (runtime->rate) {
- + case 8000:
- + sw_ptr = (sw_ptr * 3);
- + break;
- + case 16000:
- + sw_ptr = (sw_ptr * 3) >> 1;
- + break;
- + case 48000:
- + default:
- + sw_ptr = sw_ptr >> 1;
- + break;
- + }
- + } else {
- +
- + //printk(">>>>>>>>>> : snd_ftssp_start_record() for recording....\n");
- + sw_ptr = sw_ptr >> 1;
- + }
- +
- + err = dmad_update_ring_sw_ptr(&dma_chreq_rx, sw_ptr, 0);
- + if (err != 0) {
- + ERR("%s: failed to update sw-pointer!\n", __func__);
- + return err;
- + }
- +
- + err = dmad_kickoff_requests(&dma_chreq_rx);
- + if (err != 0) {
- + ERR("%s: failed to kickoff dma!\n", __func__);
- + return err;
- + }
- +
- + ftssp010_substream->start(cardno, 1);
- +
- + return 0;
- +}
- +
- +/* Triggers AHBDMA for playback & capture */
- +static int snd_ftssp_pcm_trigger(struct snd_pcm_substream * substream, int cmd)
- +{
- + ftssp_substream *ftssp010_substream =
- + (ftssp_substream *)substream->runtime->private_data;
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + int err = 0;
- + int stream_id = substream->pstr->stream;
- +
- + //printk("~~~~~ : snd_ftssp_pcm_trigger() is invoked....\n");
- +
- + /* note local interrupts are already disabled in the midlevel code */
- + spin_lock(&ftssp010_substream->dma_lock);
- +
- + switch (cmd) {
- + case SNDRV_PCM_TRIGGER_START:
- +
- + VDBG("%s: SNDRV_PCM_TRIGGER_START state(0x%08x)\n",
- + __func__, (u32)runtime->status->state);
- +
- + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
- + err = snd_ftssp_start_play(ftssp010_substream, runtime);
- + } else {
- + err = snd_ftssp_start_record(ftssp010_substream,
- + runtime);
- + }
- + break;
- +
- + case SNDRV_PCM_TRIGGER_STOP:
- +
- + VDBG("%s: SNDRV_PCM_TRIGGER_STOP state(0x%08x)\n",
- + __func__, (u32)substream->runtime->status->state);
- +
- + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
- + ftssp010_stop_tx(cardno);
- + dmad_drain_requests(&dma_chreq_tx, 1);
- + } else {
- + ftssp010_stop_rx(cardno);
- + dmad_drain_requests(&dma_chreq_rx, 1);
- + }
- + break;
- + default:
- + err = -EINVAL;
- + break;
- + }
- +
- + spin_unlock(&ftssp010_substream->dma_lock);
- + return err;
- +}
- +
- +// pcm middle-layer call this function within irq (snd_pcm_period_elapsed) or
- +// with local irq disabled (snd_pcm_lib_write1)
- +static snd_pcm_uframes_t snd_ftssp_pcm_pointer(
- + struct snd_pcm_substream *substream)
- +{
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + u32 hw_ptr;
- + snd_pcm_uframes_t ret;
- + int stream_id = substream->pstr->stream;
- +
- + //printk("~~~~~ : snd_ftssp_pcm_pointer() is invoked....\n");
- +
- +
- + /* Fetch DMA pointer, with spin lock */
- + //spin_lock_irqsave(&ftssp010_substream->dma_lock, flags);
- +
- + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
- + hw_ptr = dmad_probe_ring_hw_ptr(&dma_chreq_tx);
- + } else {
- + hw_ptr = dmad_probe_ring_hw_ptr(&dma_chreq_rx);
- + }
- +
- + //spin_unlock_irqrestore(&ftssp010_substream->dma_lock, flags);
- +
- + if (ac97) {
- + ret = bytes_to_frames(runtime, hw_ptr << 1);
- +
- + switch (runtime->rate) {
- + case 8000:
- + ret = ret / 6;
- + break;
- + case 16000:
- + ret = ret / 3;
- + break;
- + case 48000:
- + default:
- + break;
- + }
- + } else {
- + ret = bytes_to_frames(runtime, hw_ptr << 1);
- + }
- +
- +
- + VVDBG("%s: hw_ptr(0x%08x) ret(0x%08x)\n",
- + (stream_id == SNDRV_PCM_STREAM_PLAYBACK) ? "p" : "c",
- + (u32)hw_ptr, (u32)ret);
- +
- + /* ALSA requires return value 0 <= ret < buffer_size */
- + if (ret >= runtime->buffer_size)
- + return 0;
- + return ret;
- +}
- +
- +/* For FTSSP010 driver, operations are shared among playback & capture */
- +static struct snd_pcm_ops snd_ftssp_playback_ops = {
- + .open = snd_ftssp_pcm_open,
- + .close = snd_ftssp_pcm_close,
- + .ioctl = snd_pcm_lib_ioctl,
- + .hw_params = snd_ftssp_pcm_hw_params,
- + .hw_free = snd_ftssp_pcm_hw_free,
- + .prepare = snd_ftssp_pcm_prepare,
- + .trigger = snd_ftssp_pcm_trigger,
- + .pointer = snd_ftssp_pcm_pointer,
- + .copy = NULL,
- +};
- +
- +static struct snd_pcm_ops snd_ftssp_capture_ops = {
- + .open = snd_ftssp_pcm_open,
- + .close = snd_ftssp_pcm_close,
- + .ioctl = snd_pcm_lib_ioctl,
- + .hw_params = snd_ftssp_pcm_hw_params,
- + .hw_free = snd_ftssp_pcm_hw_free,
- + .prepare = snd_ftssp_pcm_prepare,
- + .trigger = snd_ftssp_pcm_trigger,
- + .pointer = snd_ftssp_pcm_pointer,
- + .copy = NULL,
- +};
- +
- +/* ALSA PCM constructor */
- +static int snd_ftssp_new_pcm(ftssp_chip *chip)
- +{
- + struct snd_pcm *pcm;
- + int err;
- +
- + //printk("~~~~~ : snd_ftssp_new_pcm() is invoked....\n");
- +
- + /* PCM device #0 with 1 playback and 1 capture */
- + if ((err = snd_pcm_new(chip->card, "ftssp_pcm", 0, 1, 1, &pcm)) < 0)
- + return err;
- +
- + pcm->private_data = chip;
- + strcpy(pcm->name, "ftssp_pcm device");
- + chip->pcm = pcm;
- +
- + /* set operators for playback and capture*/
- + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
- + &snd_ftssp_playback_ops);
- +
- + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
- + &snd_ftssp_capture_ops);
- +
- + /* Pre-allocate buffer, as suggested by ALSA driver document */
- + // todo: support playback/capture simultaneously
- + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- + NULL, FTSSP_HW_DMA_SIZE, FTSSP_HW_DMA_SIZE);
- +
- + /* Force half-duplex (on A320D, or AC97 mode) */
- + if (ac97)
- + pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
- +
- + return 0;
- +}
- +
- +#if (FTSSP_PROC_FS)
- +static void snd_ftssp_buf_max_read(struct snd_info_entry *entry,
- + struct snd_info_buffer *buffer)
- +{
- + snd_iprintf(buffer, "%d\n", snd_ftssp_pcm_hw.buffer_bytes_max);
- +}
- +
- +static void snd_ftssp_buf_max_write(struct snd_info_entry *entry,
- + struct snd_info_buffer *buffer)
- +{
- + char tmp[128];
- + char *ptr_e;
- + u32 val;
- +
- + if (buffer->size == 0)
- + return;
- +
- + memset(tmp, 0, 128);
- + snd_info_get_str(tmp, buffer->buffer, 127);
- +
- + val = simple_strtoul(tmp, &ptr_e, 10);
- + if (*ptr_e == 'k')
- + val *= 1024;
- + else if (*ptr_e == 'm')
- + val *= 1024 * 1024;
- +
- + if (ac97) {
- + if (val > AC97_HW_BUFFER_BYTES_MAX)
- + val = AC97_HW_BUFFER_BYTES_MAX;
- + } else {
- + if (val > I2S_HW_BUFFER_BYTES_MAX)
- + val = I2S_HW_BUFFER_BYTES_MAX;
- + }
- +
- + snd_ftssp_pcm_hw.buffer_bytes_max = (size_t)val;
- +}
- +
- +static void snd_ftssp_period_min_read(struct snd_info_entry *entry,
- + struct snd_info_buffer *buffer)
- +{
- + snd_iprintf(buffer, "%d\n", snd_ftssp_pcm_hw.period_bytes_min);
- +}
- +
- +static void snd_ftssp_period_min_write(struct snd_info_entry *entry,
- + struct snd_info_buffer *buffer)
- +{
- + char tmp[128];
- + char *ptr_e;
- + u32 val;
- +
- + if (buffer->size == 0)
- + return;
- +
- + memset(tmp, 0, 128);
- + snd_info_get_str(tmp, buffer->buffer, 127);
- +
- + val = simple_strtoul(tmp, &ptr_e, 10);
- + if (*ptr_e == 'k')
- + val *= 1024;
- + else if (*ptr_e == 'm')
- + val *= 1024 * 1024;
- +
- + snd_ftssp_pcm_hw.period_bytes_min = (size_t)val;
- +
- + if ((val * snd_ftssp_pcm_hw.periods_max) >
- + snd_ftssp_pcm_hw.buffer_bytes_max) {
- + INFO("\nWarning: period_bytes(%d) * periods(%d) exceeds "
- + "hw_buffer_size(%d).\n",
- + snd_ftssp_pcm_hw.period_bytes_min,
- + snd_ftssp_pcm_hw.periods_max,
- + snd_ftssp_pcm_hw.buffer_bytes_max);
- + INFO(" Unexpected access violation may occur!\n");
- + }
- +}
- +
- +static void snd_ftssp_period_max_read(struct snd_info_entry *entry,
- + struct snd_info_buffer *buffer)
- +{
- + snd_iprintf(buffer, "%d\n", snd_ftssp_pcm_hw.period_bytes_max);
- +}
- +
- +static void snd_ftssp_period_max_write(struct snd_info_entry *entry,
- + struct snd_info_buffer *buffer)
- +{
- + char tmp[128];
- + char *ptr_e;
- + u32 val;
- +
- + if (buffer->size == 0)
- + return;
- +
- + memset(tmp, 0, 128);
- + snd_info_get_str(tmp, buffer->buffer, 127);
- +
- + val = simple_strtoul(tmp, &ptr_e, 10);
- + if (*ptr_e == 'k')
- + val *= 1024;
- + else if (*ptr_e == 'm')
- + val *= 1024 * 1024;
- +
- + snd_ftssp_pcm_hw.period_bytes_max = (size_t)val;
- +
- + if ((val * snd_ftssp_pcm_hw.periods_max) >
- + snd_ftssp_pcm_hw.buffer_bytes_max) {
- + INFO("\nWarning: period_bytes(%d) * periods(%d) exceeds "
- + "hw_buffer_size(%d).\n",
- + snd_ftssp_pcm_hw.period_bytes_max,
- + snd_ftssp_pcm_hw.periods_max,
- + snd_ftssp_pcm_hw.buffer_bytes_max);
- + INFO(" Unexpected access violation may occur!\n");
- + }
- +}
- +
- +static void snd_ftssp_periods_min_read(struct snd_info_entry *entry,
- + struct snd_info_buffer *buffer)
- +{
- + snd_iprintf(buffer, "%d\n", snd_ftssp_pcm_hw.periods_min);
- +}
- +
- +static void snd_ftssp_periods_min_write(struct snd_info_entry *entry,
- + struct snd_info_buffer *buffer)
- +{
- + char tmp[128];
- + char *ptr_e;
- + u32 val;
- +
- + if (buffer->size == 0)
- + return;
- +
- + memset(tmp, 0, 128);
- + snd_info_get_str(tmp, buffer->buffer, 127);
- +
- + val = simple_strtoul(tmp, &ptr_e, 10);
- + if (*ptr_e == 'k')
- + val *= 1024;
- + else if (*ptr_e == 'm')
- + val *= 1024 * 1024;
- +
- + snd_ftssp_pcm_hw.periods_min = (size_t)val;
- +
- + if ((val * snd_ftssp_pcm_hw.period_bytes_max) >
- + snd_ftssp_pcm_hw.buffer_bytes_max) {
- + INFO("\nWarning: period_bytes(%d) * periods(%d) exceeds "
- + "hw_buffer_size(%d).\n",
- + snd_ftssp_pcm_hw.period_bytes_max,
- + snd_ftssp_pcm_hw.periods_min,
- + snd_ftssp_pcm_hw.buffer_bytes_max);
- + INFO(" Unexpected access violation may occur!\n");
- + }
- +}
- +
- +static void snd_ftssp_periods_max_read(struct snd_info_entry *entry,
- + struct snd_info_buffer *buffer)
- +{
- + snd_iprintf(buffer, "%d\n", snd_ftssp_pcm_hw.periods_max);
- +}
- +
- +static void snd_ftssp_periods_max_write(struct snd_info_entry *entry,
- + struct snd_info_buffer *buffer)
- +{
- + char tmp[128];
- + char *ptr_e;
- + u32 val;
- +
- + if (buffer->size == 0)
- + return;
- +
- + memset(tmp, 0, 128);
- + snd_info_get_str(tmp, buffer->buffer, 127);
- +
- + val = simple_strtoul(tmp, &ptr_e, 10);
- + if (*ptr_e == 'k')
- + val *= 1024;
- + else if (*ptr_e == 'm')
- + val *= 1024 * 1024;
- +
- + snd_ftssp_pcm_hw.periods_max = (size_t)val;
- +
- + if ((val * snd_ftssp_pcm_hw.period_bytes_max) >
- + snd_ftssp_pcm_hw.buffer_bytes_max) {
- + INFO("\nWarning: period_bytes(%d) * periods(%d) exceeds "
- + "hw_buffer_size(%d).\n",
- + snd_ftssp_pcm_hw.period_bytes_max,
- + snd_ftssp_pcm_hw.periods_max,
- + snd_ftssp_pcm_hw.buffer_bytes_max);
- + INFO(" Unexpected access violation may occur!\n");
- + }
- +}
- +#endif //FTSSP_PROC_FS
- +
- +static inline void ftssp_ac97_init(void)
- +{
- + //driver_name = AC97_DRIVER_NAME;
- + //codec_info = AC97_CODEC_NAME;
- +
- + /* Change codec-dependent callbacks to AC97 */
- + ftssp010_substreams[0].pmu_set_clocking = pmu_set_ac97_clocking;
- + ftssp010_substreams[0].hw_config = ftssp010_config_ac97_play;
- + ftssp010_substreams[1].pmu_set_clocking = pmu_set_ac97_clocking;
- + ftssp010_substreams[1].hw_config = ftssp010_config_ac97_rec;
- +
- + snd_ftssp_playback_ops.copy = snd_ftssp_playback_copy;
- + snd_ftssp_capture_ops.copy = snd_ftssp_capture_copy;
- +
- + snd_ftssp_pcm_hw.rates = AC97_CODEC_SAMPLE_RATES;
- + snd_ftssp_pcm_hw.rate_min = AC97_CODEC_SAMPLE_RATE_MIN;
- + snd_ftssp_pcm_hw.rate_max = AC97_CODEC_SAMPLE_RATE_MAX;
- + snd_ftssp_pcm_hw.formats = AC97_CODEC_FORMATS;
- + snd_ftssp_pcm_hw.buffer_bytes_max = AC97_HW_BUFFER_BYTES_MAX;
- + snd_ftssp_pcm_hw.period_bytes_min = AC97_HW_PERIOD_BYTES_MIN;
- + snd_ftssp_pcm_hw.period_bytes_max = AC97_HW_PERIOD_BYTES_MAX;
- + snd_ftssp_pcm_hw.periods_min = AC97_HW_PERIODS_MIN;
- + snd_ftssp_pcm_hw.periods_max = AC97_HW_PERIODS_MAX;
- +}
- +
- +static int ftssp_alsa_init(struct i2c_client *client)
- +{
- + ftssp_chip *chip;
- + int err;
- +
- + //ADD by river 2011.03.08
- + //g_i2c_client = client;
- + //End ADD by river 2011.03.08
- + //printk(">>>>>>>>> (4) ftssp_alsa_init().\n");
- + init_hw(cardno, ac97, client);
- +
- + if (ac97)
- + ftssp_ac97_init();
- +
- + DBG("%s: FTSSP010 #%d (Physical Addr=0x%08X), mode: %s\n",
- + __func__,
- + cardno, SSP_FTSSP010_pa_base[cardno],
- + ac97 ? "ac97" : "i2s");
- +
- + err = snd_card_create(cardno, FTSSP_CARD_ID, THIS_MODULE,
- + sizeof(ftssp_chip), &ftssp_cards[cardno]);
- + if (err < 0)
- + return err;
- +
- + if (ac97) {
- + sprintf(ftssp_cards[cardno]->driver, FTSSP_DRIVER_NAME);
- + sprintf(ftssp_cards[cardno]->shortname,
- + FTSSP_DRIVER_NAME "_ac97");
- + sprintf(ftssp_cards[cardno]->longname,
- + FTSSP_DRIVER_NAME "_ac97 controller");
- + } else {
- + sprintf(ftssp_cards[cardno]->driver, FTSSP_DRIVER_NAME);
- + sprintf(ftssp_cards[cardno]->shortname,
- + FTSSP_DRIVER_NAME "_i2s");
- + sprintf(ftssp_cards[cardno]->longname,
- + FTSSP_DRIVER_NAME "_i2s controller");
- + }
- +
- + // PCM
- + chip = (ftssp_chip *)(ftssp_cards[cardno]->private_data);
- + chip->card = ftssp_cards[cardno];
- +
- + if ((err = snd_ftssp_new_pcm(chip))) {
- + ERR("%s, Can't new PCM devices\n",__func__);
- + return -ENODEV;
- + }
- +
- +#if (FTSSP_PROC_FS)
- + // new a proc entries subordinate to card->proc_root for debugging
- + // /proc/card#/buf_max
- + snd_card_proc_new(chip->card, "buf_max", &chip->info_buf_max);
- + if (chip->info_buf_max) {
- + chip->info_buf_max->c.text.read = snd_ftssp_buf_max_read;
- + chip->info_buf_max->c.text.write = snd_ftssp_buf_max_write;
- + }
- + // /proc/card#/period_min
- + snd_card_proc_new(chip->card, "period_size_min",
- + &chip->info_period_min);
- + if (chip->info_period_min) {
- + chip->info_period_min->c.text.read = snd_ftssp_period_min_read;
- + chip->info_period_min->c.text.write =
- + snd_ftssp_period_min_write;
- + }
- + // /proc/card#/period_max
- + snd_card_proc_new(chip->card, "period_size_max",
- + &chip->info_period_max);
- + if (chip->info_period_max) {
- + chip->info_period_max->c.text.read = snd_ftssp_period_max_read;
- + chip->info_period_max->c.text.write =
- + snd_ftssp_period_max_write;
- + }
- + // /proc/card#/periods_min
- + snd_card_proc_new(chip->card, "periods_min", &chip->info_periods_min);
- + if (chip->info_periods_min) {
- + chip->info_periods_min->c.text.read =
- + snd_ftssp_periods_min_read;
- + chip->info_periods_min->c.text.write =
- + snd_ftssp_periods_min_write;
- + }
- + // /proc/card#/periods_max
- + snd_card_proc_new(chip->card, "periods_max", &chip->info_periods_max);
- + if (chip->info_periods_max) {
- + chip->info_periods_max->c.text.read =
- + snd_ftssp_periods_max_read;
- + chip->info_periods_max->c.text.write =
- + snd_ftssp_periods_max_write;
- + }
- +#endif
- +
- + // Register the card to ALSA
- + if ((err = snd_card_register(chip->card)) == 0) {
- + INFO("%s card registered!\n", FTSSP_CARD_ID);
- + }
- +
- + return 0;
- +}
- +
- +#ifdef CONFIG_SND_FTSSP010_I2S
- +//ADD by river 2011.01.26
- +static int alc5630_i2c_remove(struct i2c_client *client)
- +{
- + struct alc5630_data *alc5630 = i2c_get_clientdata(client);
- +
- + // power down codec chip
- + //tas_write_reg(tas, TAS_REG_ACR, 1, &tmp);
- +
- + mutex_destroy(&alc5630->mtx);
- + kfree(alc5630);
- + return 0;
- +}
- +
- +static const struct i2c_device_id alc5630_i2c_id[] = {
- + { "alc5630_codec", 0 },
- + { }
- +};
- +
- +// This is the driver that will be inserted
- +static struct i2c_driver alc5630_driver = {
- + .driver = {
- + .name = "alc5630_codec",
- + .owner = THIS_MODULE,
- + },
- + .attach_adapter = alc5630_i2c_attach,
- + .probe = alc5630_i2c_probe,
- + .remove = alc5630_i2c_remove,
- + .suspend = alc5630_i2c_suspend,
- + .resume = alc5630_i2c_resume,
- + .id_table = alc5630_i2c_id,
- +};
- +
- +static int alc5630_i2c_suspend(struct i2c_client *i2c_client, pm_message_t mesg)
- +{
- + //printk("@@@@@ TRACE by river 2011.05.10 : alc5630_i2c_suspend() is invoked.\n");
- +
- + //i2c_del_driver(&alc5630_driver);
- + //#ifndef CONFIG_SND_FTSSP010_AC97
- + // i2c_del_driver(&alc5630_driver);
- + //#endif
- + //printk("@@@@@ TRACE by river 2011.05.10 : alc5630_i2c_suspend() -2 is invoked.\n");
- + dmad_channel_free(&dma_chreq_tx);
- + dmad_channel_free(&dma_chreq_rx);
- + //printk("@@@@@ TRACE by river 2011.05.10 : alc5630_i2c_suspend() -3 is invoked.\n");
- + //snd_card_free(ftssp_cards[cardno]);
- +
- + return 0;
- +
- +}
- +
- +static int alc5630_i2c_resume(struct i2c_client *i2c_client)
- +{
- +
- + //printk("@@@@@ TRACE by river 2011.05.10 : alc5630_i2c_resume() is invoked.\n");
- + //#ifdef CONFIG_SND_FTSSP010_AC97
- + // ftssp_alsa_init(NULL);
- + //#else
- + // return i2c_add_driver(&alc5630_driver);
- + //#endif
- +
- + return 0;
- +
- +}
- +#endif
- +
- +static __init int ftssp_alsa_i2c_i2s_init(void)
- +{
- +
- + //printk(">>>>>>>>>> (1) ftssp_alsa_i2c_i2s_init().\n");
- + //return i2c_add_driver(&alc5630_driver);
- + #ifdef CONFIG_SND_FTSSP010_AC97
- + return ftssp_alsa_init(NULL);
- + #else
- + return i2c_add_driver(&alc5630_driver);
- + #endif
- +}
- +//End ADD by river 2011.01.26
- +
- +static __exit void ftssp_alsa_i2c_i2s_exit(void)
- +{
- + DBG("%s, cleaning up\n",__func__);
- +
- + //i2c_del_driver(&alc5630_driver);
- + #ifndef CONFIG_SND_FTSSP010_AC97
- + i2c_del_driver(&alc5630_driver);
- + #endif
- +
- + dmad_channel_free(&dma_chreq_tx);
- + dmad_channel_free(&dma_chreq_rx);
- +
- + snd_card_free(ftssp_cards[cardno]);
- +}
- +
- +/*static __exit void ftssp_alsa_exit(void)
- +{
- + DBG("%s, cleaning up\n",__func__);
- +
- + dmad_channel_free(&dma_chreq_tx);
- + dmad_channel_free(&dma_chreq_rx);
- +
- + snd_card_free(ftssp_cards[cardno]);
- +}*/
- +
- +//MOD by river 2011.01.26
- +//module_init(ftssp_alsa_init);
- +//module_exit(ftssp_alsa_exit);
- +module_init(ftssp_alsa_i2c_i2s_init);
- +module_exit(ftssp_alsa_i2c_i2s_exit);
- +//End MOD by river 2011.01.26
- diff -Nur linux-3.4.110.orig/sound/nds32/FTSSP010_HDA.c linux-3.4.110/sound/nds32/FTSSP010_HDA.c
- --- linux-3.4.110.orig/sound/nds32/FTSSP010_HDA.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/sound/nds32/FTSSP010_HDA.c 2016-04-07 10:20:51.062085666 +0200
- @@ -0,0 +1,745 @@
- +/* FTSSP010 - UDA1345TS module:
- + *
- + * $log$
- + *
- + * 2006/02/23: I-Jui Sung: OSS emulation half-duplex
- + * playback/capture at 48K, 44.1K, 8K
- + * with mono/stereo 16bit/8bit
- + *
- + * 2006/02/22: I-Jui Sung: OSS emulation playback at 44.1KHz
- + * 16-bit mono completed. Relying ALSA to
- + * resample
- + * 2009/02/24: dma upgrade checking list:
- + * - ac97 mode playback ................. ok
- + * - ac97 mode capture .................. ok
- + * - i2s mode playback .................. ok
- + * - i2s mode capture ................... ok
- + * - mixer support (snd_ctl_add, ...) ... todo
- + * - debug /proc entry .................. ok
- + */
- +
- +
- +#include <linux/init.h>
- +#include <linux/module.h>
- +#include <asm/io.h>
- +#include <linux/delay.h>
- +#include <asm/spec.h>
- +#include <asm/dmad.h>
- +#include <linux/dma-mapping.h>
- +#include <sound/core.h>
- +#include <sound/pcm.h>
- +#include <sound/initval.h>
- +#include <sound/asound.h>
- +#include <sound/control.h>
- +#include "FTSSP010_HDA.h"
- +void init_hw(unsigned int cardno);
- +
- +#if (!defined(CONFIG_PLATFORM_AHBDMA) && !defined(CONFIG_PLATFORM_APBDMA))
- +#warning needs ahb/apb dma to wrok
- +#endif
- +
- +/* ---------------------------------------------------------------------------
- + * Define the debug level of FTSSP_DEBUG
- + */
- +#define FTSSP_DEBUG 0
- +#define FTSSP_DEBUG_VERBOSE 0
- +#define FTSSP_PROC_FS 1
- +
- +#undef VVDBG
- +#if (FTSSP_DEBUG_VERBOSE)
- +//#define VVDBG(vvar...) (void)0
- +#define VVDBG(vvar...) printk(KERN_INFO vvar)
- +#else
- +#define VVDBG(vvar...) (void)0
- +#endif
- +
- +#undef ERR
- +#define ERR(vvar...) printk(KERN_ERR vvar)
- +
- +#undef INFO
- +#define INFO(vvar...) printk(KERN_INFO vvar)
- +
- +#if (FTSSP_DEBUG)
- +#undef DBG
- +#define DBG(vvar...) printk(KERN_INFO vvar)
- +#else
- +#define DBG(vvar...) (void)0
- +#endif
- +
- +#if (FTSSP_DEBUG_VERBOSE)
- +#undef VDBG
- +#define VDBG(vvar...) printk(KERN_INFO vvar)
- +#else
- +#define VDBG(vvar...) (void)0
- +#endif
- +
- +/* ---------------------------------------------------------------------------
- + * Preserved size of memory space for audio DMA ring
- + */
- +#define FTSSP_HW_DMA_SIZE (512 * 1024)
- +
- +
- +/* HDA HW configuration*/
- +/* ring size, exported to application */
- +#define HDA_HW_BUFFER_BYTES_MAX (256 * 1024)
- +#define HDA_HW_PERIOD_BYTES_MIN (2 * 1024)
- +#define HDA_HW_PERIOD_BYTES_MAX (32 * 1024)
- +#define HDA_HW_PERIODS_MIN 3
- +#define HDA_HW_PERIODS_MAX 8
- +
- +#define HDA_HW_DMA_SIZE (HDA_HW_BUFFER_BYTES_MAX)
- +
- +
- +/* ---------------------------------------------------------------------------
- + * Audio formats
- + */
- +
- +/* HDA formats */
- +#define HDA_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
- +#define HDA_CODEC_SAMPLE_RATES (SNDRV_PCM_RATE_192000 | \
- + SNDRV_PCM_RATE_176400| \
- + SNDRV_PCM_RATE_96000 | \
- + SNDRV_PCM_RATE_88200 | \
- + SNDRV_PCM_RATE_48000 | \
- + SNDRV_PCM_RATE_44100 | \
- + SNDRV_PCM_RATE_32000 | \
- + SNDRV_PCM_RATE_22050 | \
- + SNDRV_PCM_RATE_16000 | \
- + SNDRV_PCM_RATE_11025 | \
- + SNDRV_PCM_RATE_8000)
- +#define HDA_CODEC_SAMPLE_RATE_MIN (8000)
- +#define HDA_CODEC_SAMPLE_RATE_MAX (192000)
- +
- +/* ---------------------------------------------------------------------------
- + * Configuration
- + */
- +#if (CONFIG_PROC_FS == 0)
- +#undef FTSSP_PROC_FS
- +#define FTSSP_PROC_FS 0
- +#else
- +#if (FTSSP_PROC_FS)
- +#include <sound/info.h>
- +#endif /* FTSSP_PROC_FS */
- +#endif /* CONFIG_PROC_FS */
- +
- +#define FTSSP_CARD_ID "ftssp010"
- +#define FTSSP_DRIVER_NAME "ftssp"
- +
- +MODULE_LICENSE("Faraday License");
- +MODULE_AUTHOR("Faraday Technology Corp.");
- +MODULE_DESCRIPTION("FTSSP010 Linux 2.6 Driver");
- +
- +static int cardno = 0;
- +static const unsigned int SSP_FTSSP010_pa_base[SSP_FTSSP010_IRQ_COUNT] =
- + { SSP_FTSSP010_PA_BASE };
- +
- +/* Driver mode */
- +
- +// ----------------------------------------------
- +module_param(cardno, int, 0);
- +MODULE_PARM_DESC(cardno, "FTSSP No.");
- +
- +// ----------------------------------------------
- +
- +/* ---------------------------------------------------------------------------
- + * Structures
- + */
- +
- +/* private data for card */
- +typedef struct {
- + struct snd_card *card;
- + struct snd_pcm *pcm;
- + struct snd_pcm_substream *substream_tx;
- + struct snd_pcm_substream *substream_rx;
- +} ftssp_chip;
- +
- +/* dma request descriptors */
- +dmad_chreq dma_chreq_tx = {
- + .channel = -1,
- + .drq = NULL,
- +};
- +
- +dmad_chreq dma_chreq_rx = {
- + .channel = -1,
- + .drq = NULL,
- +};
- +
- +/* Holds ALSA card instance pointers */
- +struct snd_card *ftssp_cards[SSP_FTSSP010_COUNT];
- +
- +/* snd_pcm_hardware */
- +static struct snd_pcm_hardware snd_ftssp_pcm_hw =
- +{
- + .info = SNDRV_PCM_INFO_INTERLEAVED,
- + .formats = HDA_CODEC_FORMATS,
- + .rates = HDA_CODEC_SAMPLE_RATES,
- + .rate_min = HDA_CODEC_SAMPLE_RATE_MIN,
- + .rate_max = HDA_CODEC_SAMPLE_RATE_MAX,
- + .channels_min = 1,
- + .channels_max = 2,
- + .buffer_bytes_max = HDA_HW_BUFFER_BYTES_MAX,
- + .period_bytes_min = HDA_HW_PERIOD_BYTES_MIN,
- + .period_bytes_max = HDA_HW_PERIOD_BYTES_MAX,
- + .periods_min = HDA_HW_PERIODS_MIN,
- + .periods_max = HDA_HW_PERIODS_MAX,
- +};
- +
- +/* private data for a substream (playback or capture) */
- +/* function pointer for set up AHBDMA for this substream */
- +typedef void (*start_t)(int cardno, unsigned use_dma);
- +typedef void (*ftssp010_config_t)(int cardno, unsigned is_stereo,
- + unsigned speed, int use8bit);
- +
- +typedef struct {
- + u32 busy;
- + spinlock_t dma_lock;
- + unsigned dma_area_va;
- + int dma_width;
- + unsigned int tx_period;
- + unsigned int rx_period;
- +
- + start_t start;
- + ftssp010_config_t hw_config;
- +} ftssp_substream;
- +
- +static ftssp_substream ftssp010_substreams[2] = {
- + /* Playback substream */
- + {
- + busy : 0,
- + hw_config : ftssp010_config_hda_play,
- + },
- + /* Capture substream */
- + {
- + busy : 0,
- + hw_config : ftssp010_config_hda_rec,
- + }
- +};
- +
- +
- +/**
- + * These dma callbacks are called in interrupt context.
- + * @data: pointer to the chip-wide structure.
- + * TODO: use stream-specifc data
- + */
- +__attribute__((__unused__))
- +static void ftssp_dma_callback_tx(int ch, u16 int_status, void *data)
- +{
- + ftssp_chip *chip = (ftssp_chip *)data;
- + struct snd_pcm_runtime *runtime = chip->substream_tx->runtime;
- + ftssp_substream *ftssp010_substream =
- + (ftssp_substream *)runtime->private_data;
- + u32 sw_ptr;
- + u32 tx_period = ftssp010_substream->tx_period + 1;
- +
- + if (tx_period == runtime->periods)
- + sw_ptr = runtime->buffer_size;
- + else
- + sw_ptr = tx_period * runtime->period_size;
- +
- + sw_ptr = (u32)frames_to_bytes(runtime, sw_ptr) >> 1;
- +
- + if (dmad_update_ring_sw_ptr(&dma_chreq_tx, (u32)sw_ptr, 0)) {
- + ERR("%s: failed to update sw-pointer!\n", __func__);
- + }
- +
- + ftssp010_substream->tx_period = tx_period % runtime->periods;
- + snd_pcm_period_elapsed(chip->substream_tx);
- +}
- +
- +__attribute__((__unused__))
- +static void ftssp_dma_callback_rx(int ch, u16 int_status, void *data)
- +{
- + ftssp_chip *chip = (ftssp_chip *)data;
- + struct snd_pcm_runtime *runtime = chip->substream_rx->runtime;
- + ftssp_substream *ftssp010_substream =
- + (ftssp_substream *)runtime->private_data;
- + u32 sw_ptr;
- + u32 rx_period = ftssp010_substream->rx_period + 1;
- +
- + if (rx_period == runtime->periods)
- + sw_ptr = runtime->buffer_size;
- + else
- + sw_ptr = rx_period * runtime->period_size;
- + sw_ptr = (u32)frames_to_bytes(runtime, sw_ptr) >> 1;
- +
- + if (dmad_update_ring_sw_ptr(&dma_chreq_rx, (u32)sw_ptr, 0) != 0) {
- + ERR("%s: failed to update sw-pointer!\n", __func__);
- + }
- +
- + ftssp010_substream->rx_period = rx_period % runtime->periods;
- +
- + snd_pcm_period_elapsed(chip->substream_rx);
- +}
- +
- +static inline int snd_ftssp_dma_ch_alloc(struct snd_pcm_substream *substream)
- +{
- + dmad_chreq *ch_req __attribute__((__unused__)) = 0;
- +
- +#ifdef CONFIG_PLATFORM_APBDMA
- +
- + if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- + ch_req = &dma_chreq_tx;
- + ch_req->completion_cb = ftssp_dma_callback_tx;
- + ch_req->apb_req.tx_dir = DMAD_DIR_A0_TO_A1;
- + ch_req->apb_req.dev_reqn = APBBR_REQN_I2SAC97TX;
- + } else {
- + ch_req = &dma_chreq_rx;
- + ch_req->completion_cb = ftssp_dma_callback_rx;
- + ch_req->apb_req.tx_dir = DMAD_DIR_A1_TO_A0;
- + ch_req->apb_req.dev_reqn = APBBR_REQN_I2SAC97RX;
- + }
- +
- + ch_req->controller = DMAD_DMAC_APB_CORE;
- + ch_req->flags = DMAD_FLAGS_RING_MODE;
- + ch_req->ring_base = 0;
- + ch_req->dev_addr = (dma_addr_t)FTSSP010_DATA_PA(cardno);
- + ch_req->periods = 0;
- + ch_req->period_size = 0;
- +
- + ch_req->apb_req.ring_ctrl = APBBR_ADDRINC_I2X;
- + ch_req->apb_req.ring_reqn = APBBR_REQN_NONE;
- + ch_req->apb_req.dev_ctrl = APBBR_ADDRINC_FIXED;
- + ch_req->apb_req.burst_mode = 0;
- + ch_req->apb_req.data_width = APBBR_DATAWIDTH_2;
- + ch_req->completion_data = (void *)snd_pcm_substream_chip(substream);
- +
- + ch_req->completion_data = (void *)snd_pcm_substream_chip(substream);
- +
- + if (dmad_channel_alloc(ch_req) != 0) {
- + ERR("%s: APBDMA channel allocation failed\n",__func__);
- + goto _try_ahb;
- + }
- +
- + DBG("%s: APBDMA channel allocated (ch: %d) ring_mode\n",
- + __func__, ch_req->channel);
- +
- + return 0;
- +
- +_try_ahb:
- +
- +#endif /* CONFIG_PLATFORM_APBDMA */
- +
- +#ifdef CONFIG_PLATFORM_AHBDMA
- +
- + if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- + ch_req = &dma_chreq_tx;
- + ch_req->completion_cb = ftssp_dma_callback_tx;
- + ch_req->ahb_req.tx_dir = DMAD_DIR_A0_TO_A1;
- + ch_req->ahb_req.dev_reqn = DMAC_REQN_I2SAC97TX;
- + } else {
- + ch_req = &dma_chreq_rx;
- + ch_req->completion_cb = ftssp_dma_callback_rx;
- + ch_req->ahb_req.tx_dir = DMAD_DIR_A1_TO_A0;
- + ch_req->ahb_req.dev_reqn = DMAC_REQN_I2SAC97RX;
- + }
- +
- + ch_req->controller = DMAD_DMAC_AHB_CORE;
- + ch_req->flags = DMAD_FLAGS_RING_MODE;
- + ch_req->ring_base = 0;
- + ch_req->dev_addr = (dma_addr_t)FTSSP010_DATA_PA(cardno);
- + ch_req->periods = 0;
- + ch_req->period_size = 0;
- +
- + ch_req->ahb_req.sync = 1;
- + ch_req->ahb_req.priority = DMAC_CSR_CHPRI_2;
- + ch_req->ahb_req.hw_handshake = 1;
- + ch_req->ahb_req.burst_size = DMAC_CSR_SIZE_1;
- +
- + ch_req->ahb_req.ring_width = DMAC_CSR_WIDTH_32;
- + ch_req->ahb_req.ring_ctrl = DMAC_CSR_AD_INC;
- + ch_req->ahb_req.ring_reqn = DMAC_REQN_NONE;
- + ch_req->ahb_req.dev_width = DMAC_CSR_WIDTH_32;
- + ch_req->ahb_req.dev_ctrl = DMAC_CSR_AD_FIX;
- +
- + ch_req->completion_data = (void *)snd_pcm_substream_chip(substream);
- +
- + if (dmad_channel_alloc(ch_req) != 0) {
- + ERR("%s: AHBDMA channel allocation failed\n", __func__);
- + goto _err_exit;
- + }
- +
- + DBG("%s: AHBDMA channel allocated (ch: %d) ring_mode\n",
- + __func__, ch_req->channel);
- +
- + return 0;
- +
- +_err_exit:
- +
- +#endif /* CONFIG_PLATFORM_AHBDMA */
- +
- + return -ENODEV;
- +}
- +
- +static inline ftssp_substream *ftssp010_substream_new(int stream_id)
- +{
- + ftssp_substream *s = NULL;
- +
- + switch (stream_id) {
- + case SNDRV_PCM_STREAM_PLAYBACK:
- + s = &ftssp010_substreams[0];
- + break;
- + case SNDRV_PCM_STREAM_CAPTURE:
- + s = &ftssp010_substreams[1];
- + break;
- + default:
- + ERR("%s: wrong stream type (%d)\n", __func__, stream_id);
- + return NULL;
- + }
- +
- + if (s->busy) {
- + ERR("%s: device busy!\n", __func__);
- + return NULL;
- + }
- + s->busy = 1;
- +
- + spin_lock_init(&s->dma_lock);
- +
- + return s;
- +}
- +
- +static int snd_ftssp_pcm_open(struct snd_pcm_substream *substream)
- +{
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + int stream_id = substream->pstr->stream;
- +
- + VDBG("%s, %s\n", __func__,
- + (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
- + "playback" : "capture");
- +
- + /* Both playback and capture share a hardware description */
- + runtime->hw = snd_ftssp_pcm_hw;
- +
- + /* Allocate & Initialize stream-specific data */
- + runtime->private_data = ftssp010_substream_new(stream_id);
- +
- + if (runtime->private_data)
- + return snd_ftssp_dma_ch_alloc(substream);
- + else
- + return -EBUSY;
- +}
- +
- +static int snd_ftssp_pcm_close(struct snd_pcm_substream *substream)
- +{
- + int stream_id = substream->pstr->stream;
- + ftssp_substream *ftssp010_substream =
- + (ftssp_substream *)substream->runtime->private_data;
- +
- + VDBG("%s, %s\n", __func__,
- + (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
- + "playback" : "capture");
- +
- + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
- + dmad_channel_free(&dma_chreq_tx);
- + else
- + dmad_channel_free(&dma_chreq_rx);
- +
- + ftssp010_substream->busy = 0;
- + return 0;
- +}
- +
- +static int snd_ftssp_pcm_hw_params(struct snd_pcm_substream *substream,
- + struct snd_pcm_hw_params *hw_params)
- +{
- + VDBG("%s, %s\n", __func__,
- + (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
- + "playback" : "capture");
- +
- + return snd_pcm_lib_malloc_pages(substream, HDA_HW_DMA_SIZE);
- +}
- +
- +static int snd_ftssp_pcm_hw_free(struct snd_pcm_substream *substream)
- +{
- + VDBG("%s, %s\n", __func__,
- + (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
- + "playback" : "capture");
- +
- + if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK)
- + dmad_drain_requests(&dma_chreq_tx, 1);
- + else
- + dmad_drain_requests(&dma_chreq_rx, 1);
- +
- + return snd_pcm_lib_free_pages(substream);
- +}
- +
- +/* Prepare FTSSP010 AHBDMA for playback & capture */
- +static int snd_ftssp_pcm_prepare(struct snd_pcm_substream *substream)
- +{
- + ftssp_chip *chip = snd_pcm_substream_chip(substream);
- + struct snd_pcm_runtime *runtime = substream->runtime;
- +
- + ftssp_substream *ftssp010_substream =
- + (ftssp_substream *)runtime->private_data;
- +
- + int stream_id = substream->pstr->stream;
- + dmad_chreq *dma_chreq;
- + unsigned period_size, buffer_size;
- + VVDBG("%s before spin_lock<<\n", __func__);
- + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
- + dma_chreq = &dma_chreq_tx;
- + else
- + dma_chreq = &dma_chreq_rx;
- +
- + period_size = frames_to_bytes(runtime, runtime->period_size);
- + buffer_size = frames_to_bytes(runtime, runtime->buffer_size);
- +
- + if (runtime->format != SNDRV_PCM_FORMAT_S16_LE)
- + return -ENODEV;
- +
- + ftssp010_substream->dma_width = 4;
- +
- + dmad_drain_requests(dma_chreq, 1);
- +
- + dma_chreq->ring_base = (dma_addr_t)runtime->dma_addr;
- + dma_chreq->periods = (dma_addr_t)runtime->periods;
- + dma_chreq->period_size = (dma_addr_t)(period_size >> 1);
- + dma_chreq->ring_size = (dma_addr_t)(buffer_size >> 1);
- + dmad_update_ring(dma_chreq);
- +
- + /* Set PMU, FTSSP010, and DMA */
- + spin_lock(&ftssp010_substream->dma_lock);
- +
- + /* keep DMA buffer VA for copy() callback */
- + // todo: support playback/capture simultaneously
- + ftssp010_substream->dma_area_va = (u32)runtime->dma_area;
- + VVDBG("%s before hw_config<<\n", __func__);
- + ftssp010_substream->hw_config(cardno,
- + runtime->channels > 1 ? 1 : 0, /* 1: stereo, 0: mono */
- + runtime->rate, ftssp010_substream->dma_width);
- + VVDBG("%s after hw_config<<\n", __func__);
- + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
- + ftssp010_substream->tx_period = 0;
- + chip->substream_tx = substream;
- + } else {
- + ftssp010_substream->rx_period = 0;
- + chip->substream_rx = substream;
- + }
- +
- + spin_unlock(&ftssp010_substream->dma_lock);
- + VVDBG("%s after spin_unlock <<\n", __func__);
- +
- + return 0;
- +}
- +
- +static inline int snd_ftssp_start_play(ftssp_substream *ftssp010_substream,
- + struct snd_pcm_runtime *runtime)
- +{
- + int err = 0;
- + u32 sw_ptr =
- + (u32)frames_to_bytes(runtime, runtime->buffer_size) >> 1;
- +
- + err = dmad_update_ring_sw_ptr(&dma_chreq_tx, sw_ptr, 0);
- + if (err != 0) {
- + ERR("%s: failed to update sw-pointer!\n", __func__);
- + return err;
- + }
- + err = dmad_kickoff_requests(&dma_chreq_tx);
- + if (err != 0) {
- + ERR("%s: failed to kickoff dma!\n", __func__);
- + return err;
- + }
- +
- + return 0;
- +}
- +
- +static inline int snd_ftssp_start_record(ftssp_substream *ftssp010_substream,
- + struct snd_pcm_runtime *runtime)
- +{
- + int err = 0;
- + u32 sw_ptr = (u32)frames_to_bytes(runtime, runtime->buffer_size);
- +
- + sw_ptr = sw_ptr >> 1;
- + printk(">>>>>>>>>> : snd_ftssp_start_record() for recording....\n");
- + err = dmad_update_ring_sw_ptr(&dma_chreq_rx, sw_ptr, 0);
- + if (err != 0) {
- + ERR("%s: failed to update sw-pointer!\n", __func__);
- + return err;
- + }
- +
- + err = dmad_kickoff_requests(&dma_chreq_rx);
- + if (err != 0) {
- + ERR("%s: failed to kickoff dma!\n", __func__);
- + return err;
- + }
- +
- +
- + return 0;
- +}
- +
- +/* Triggers AHBDMA for playback & capture */
- +static int snd_ftssp_pcm_trigger(struct snd_pcm_substream * substream, int cmd)
- +{
- + ftssp_substream *ftssp010_substream =
- + (ftssp_substream *)substream->runtime->private_data;
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + int err = 0;
- + int stream_id = substream->pstr->stream;
- +
- + /* note local interrupts are already disabled in the midlevel code */
- + spin_lock(&ftssp010_substream->dma_lock);
- +
- + switch (cmd) {
- + case SNDRV_PCM_TRIGGER_START:
- +
- + VDBG("%s: SNDRV_PCM_TRIGGER_START state(0x%08x)\n",
- + __func__, (u32)runtime->status->state);
- +
- + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
- + err = snd_ftssp_start_play(ftssp010_substream, runtime);
- + } else {
- + err = snd_ftssp_start_record(ftssp010_substream,
- + runtime);
- + }
- + break;
- +
- + case SNDRV_PCM_TRIGGER_STOP:
- +
- + VDBG("%s: SNDRV_PCM_TRIGGER_STOP state(0x%08x)\n",
- + __func__, (u32)substream->runtime->status->state);
- +
- + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
- + ftssp010_stop_tx(cardno);
- + dmad_drain_requests(&dma_chreq_tx, 1);
- + } else {
- + ftssp010_stop_rx(cardno);
- + dmad_drain_requests(&dma_chreq_rx, 1);
- + }
- + break;
- + default:
- + err = -EINVAL;
- + break;
- + }
- +
- + spin_unlock(&ftssp010_substream->dma_lock);
- + return err;
- +}
- +
- +// pcm middle-layer call this function within irq (snd_pcm_period_elapsed) or
- +// with local irq disabled (snd_pcm_lib_write1)
- +static snd_pcm_uframes_t snd_ftssp_pcm_pointer(
- + struct snd_pcm_substream *substream)
- +{
- + struct snd_pcm_runtime *runtime = substream->runtime;
- + u32 hw_ptr;
- + snd_pcm_uframes_t ret;
- + int stream_id = substream->pstr->stream;
- +
- + /* Fetch DMA pointer, with spin lock */
- + //spin_lock_irqsave(&ftssp010_substream->dma_lock, flags);
- +
- + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
- + hw_ptr = dmad_probe_ring_hw_ptr(&dma_chreq_tx);
- + } else {
- + hw_ptr = dmad_probe_ring_hw_ptr(&dma_chreq_rx);
- + }
- + ret = bytes_to_frames(runtime, hw_ptr << 1);
- + //spin_unlock_irqrestore(&ftssp010_substream->dma_lock, flags);
- + VVDBG("%s: hw_ptr(0x%08x) ret(0x%08x)\n",
- + (stream_id == SNDRV_PCM_STREAM_PLAYBACK) ? "p" : "c",
- + (u32)hw_ptr, (u32)ret);
- +
- + /* ALSA requires return value 0 <= ret < buffer_size */
- + if (ret >= runtime->buffer_size)
- + return 0;
- + return ret;
- +}
- +
- +/* For FTSSP010 driver, operations are shared among playback & capture */
- +static struct snd_pcm_ops snd_ftssp_playback_ops = {
- + .open = snd_ftssp_pcm_open,
- + .close = snd_ftssp_pcm_close,
- + .ioctl = snd_pcm_lib_ioctl,
- + .hw_params = snd_ftssp_pcm_hw_params,
- + .hw_free = snd_ftssp_pcm_hw_free,
- + .prepare = snd_ftssp_pcm_prepare,
- + .trigger = snd_ftssp_pcm_trigger,
- + .pointer = snd_ftssp_pcm_pointer,
- + .copy = NULL,
- +};
- +
- +static struct snd_pcm_ops snd_ftssp_capture_ops = {
- + .open = snd_ftssp_pcm_open,
- + .close = snd_ftssp_pcm_close,
- + .ioctl = snd_pcm_lib_ioctl,
- + .hw_params = snd_ftssp_pcm_hw_params,
- + .hw_free = snd_ftssp_pcm_hw_free,
- + .prepare = snd_ftssp_pcm_prepare,
- + .trigger = snd_ftssp_pcm_trigger,
- + .pointer = snd_ftssp_pcm_pointer,
- + .copy = NULL,
- +};
- +
- +/* ALSA PCM constructor */
- +static int snd_ftssp_new_pcm(ftssp_chip *chip)
- +{
- + struct snd_pcm *pcm;
- + int err;
- +
- + /* PCM device #0 with 1 playback and 1 capture */
- + if ((err = snd_pcm_new(chip->card, "ftssp_pcm", 0, 1, 1, &pcm)) < 0)
- + return err;
- +
- + pcm->private_data = chip;
- + strcpy(pcm->name, "ftssp_pcm device");
- + chip->pcm = pcm;
- +
- + /* set operators for playback and capture*/
- + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
- + &snd_ftssp_playback_ops);
- +
- + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
- + &snd_ftssp_capture_ops);
- +
- + /* Pre-allocate buffer, as suggested by ALSA driver document */
- + // todo: support playback/capture simultaneously
- + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- + NULL, FTSSP_HW_DMA_SIZE, FTSSP_HW_DMA_SIZE);
- +
- + return 0;
- +}
- +
- +static __init int ftssp_alsa_init(void)
- +{
- + ftssp_chip *chip;
- + int err;
- + init_hw(cardno);
- + INFO("After init_hw!\n");
- + err = snd_card_create(cardno, FTSSP_CARD_ID, THIS_MODULE,
- + sizeof(ftssp_chip), &ftssp_cards[cardno]);
- + INFO("After snd_card_create!\n");
- + if (err < 0)
- + return err;
- + sprintf(ftssp_cards[cardno]->driver, FTSSP_DRIVER_NAME);
- + sprintf(ftssp_cards[cardno]->shortname,
- + FTSSP_DRIVER_NAME "_HDA");
- + sprintf(ftssp_cards[cardno]->longname,
- + FTSSP_DRIVER_NAME "_HDA controller");
- + /* PCM */
- + chip = (ftssp_chip *)(ftssp_cards[cardno]->private_data);
- + chip->card = ftssp_cards[cardno];
- +
- + if ((err = snd_ftssp_new_pcm(chip))) {
- + ERR("%s, Can't new PCM devices\n",__func__);
- + return -ENODEV;
- + }
- +
- +
- + /* Register the card to ALSA */
- + if ((err = snd_card_register(chip->card)) == 0) {
- + INFO("%s card registered!\n", FTSSP_CARD_ID);
- + }
- +
- + return 0;
- +}
- +
- +static __exit void ftssp_alsa_exit(void)
- +{
- + DBG("%s, cleaning up\n",__func__);
- +
- + dmad_channel_free(&dma_chreq_tx);
- + dmad_channel_free(&dma_chreq_rx);
- +
- + snd_card_free(ftssp_cards[cardno]);
- +}
- +
- +module_init(ftssp_alsa_init);
- +module_exit(ftssp_alsa_exit);
- diff -Nur linux-3.4.110.orig/sound/nds32/FTSSP010_HDA.h linux-3.4.110/sound/nds32/FTSSP010_HDA.h
- --- linux-3.4.110.orig/sound/nds32/FTSSP010_HDA.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/sound/nds32/FTSSP010_HDA.h 2016-04-07 10:20:51.062085666 +0200
- @@ -0,0 +1,34 @@
- +/* FTSSP010 - HDA supporting library header */
- +/*
- + *
- + * $log$
- + *
- + */
- +#include <linux/init.h>
- +#include <linux/module.h>
- +#include <asm/io.h>
- +#include <linux/delay.h>
- +#include <asm/spec.h>
- +#include <linux/dma-mapping.h>
- +
- +
- +#define FTSSP010_DATA(x) (SSP_FTSSP010_va_base[(x)]+0x18)
- +#define FTSSP010_DATA_PA(x) (SSP_FTSSP010_pa_base[(x)]+0x18)
- +
- +
- +/* Returns FTSSP010 status */
- +extern void ftssp010_set_int_control(int cardno, unsigned val);
- +extern int ftssp010_get_status(int cardno);
- +extern unsigned ftssp010_get_int_status(int cardno);
- +/* Polls FIFO full register */
- +extern int ftssp010_tx_fifo_not_full(int cardno);
- +
- +/* Configure FTSSP010 to a given sampling rate and channel number */
- +extern void ftssp010_config_hda_play(int cardno, unsigned is_stereo, unsigned speed, int use8bit);
- +
- +extern void ftssp010_config_hda_rec(int cardno, unsigned is_stereo, unsigned speed, int use8bit);
- +
- +extern void ftssp010_stop_tx(int cardno);
- +extern void ftssp010_stop_rx(int cardno);
- +
- +
- diff -Nur linux-3.4.110.orig/sound/nds32/FTSSP010_HDA_lib.c linux-3.4.110/sound/nds32/FTSSP010_HDA_lib.c
- --- linux-3.4.110.orig/sound/nds32/FTSSP010_HDA_lib.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/sound/nds32/FTSSP010_HDA_lib.c 2016-04-07 10:20:51.062085666 +0200
- @@ -0,0 +1,477 @@
- +/* FTSSP010 - UDA1345TS module
- + *
- + * $log$
- + */
- +
- +#include <linux/init.h>
- +#include <linux/module.h>
- +#include <asm/io.h>
- +#include <linux/delay.h>
- +#include <asm/spec.h>
- +#include <asm/dmad.h>
- +#include <linux/dma-mapping.h>
- +#include "hda.h"
- +
- +#if 0
- +MODULE_LICENSE("Faraday License");
- +MODULE_AUTHOR("Faraday Technology Corp.");
- +MODULE_DESCRIPTION("FTSSP010 - UDA1345TS Linux 2.6 Library");
- +#endif
- +#undef ERR
- +#define ERR(vvar...) printk(KERN_ERR vvar)
- +#define DBG(vvar...) printk(KERN_INFO vvar)
- +
- +#define SSP_TXFCLR 0x8
- +#define SSP_RXFCLR 0x4
- +#define SSP_RFIEN 0x4
- +#define SSP_TFIEN 0x8
- +#define SSP_SSPEN 0x1
- +#define SSP_TXDOE 0x2
- +#define SSP_RXDMAEN 0x10
- +#define SSP_TXDMAEN 0x20
- +#define SSP_RFURIEN 0x1
- +#define SSP_TFURIEN 0x2
- +#define HDA_STRNUM_RX 1
- +#define HDA_STRNUM_TX 2
- +#define HDA_CHANUM 0
- +#define HDA_CRST_MASK 0x20
- +/* Initialize FTSSP010 to output to UDA1345TS via I2S */
- +#define FTSSP010_CONTROL0(x) (SSP_FTSSP010_va_base[(x)]+0x0)
- +#define FTSSP010_CONTROL0_OPM_STEREO 0xC
- +#define FTSSP010_CONTROL0_OPM_MONO 0x8
- +
- +#define FTSSP010_CONTROL1(x) (SSP_FTSSP010_va_base[(x)]+0x4)
- +#define FTSSP010_CONTROL2(x) (SSP_FTSSP010_va_base[(x)]+0x8)
- +
- +#define FTSSP010_INT_CONTROL(x) (SSP_FTSSP010_va_base[(x)]+0x10)
- +#define FTSSP010_STATUS(x) (SSP_FTSSP010_va_base[(x)]+0xC)
- +#define FTSSP010_INT_STATUS(x) (SSP_FTSSP010_va_base[(x)]+0x14)
- +#define FTSSP010_DATA(x) (SSP_FTSSP010_va_base[(x)]+0x18)
- +#define FTSSP010_INFO(x) (SSP_FTSSP010_va_base[(x)]+0x1C)
- +#define FTSSP010_AC_COMMAND(x) (SSP_FTSSP010_va_base[(x)]+0x28)
- +#define FTSSP010_IRSPR(x) (SSP_FTSSP010_va_base[(x)]+0x2C)
- +#define FTSSP010_ICMDST(x) (SSP_FTSSP010_va_base[(x)]+0x30)
- +#define HDA_REG_OSDC(x) (SSP_FTSSP010_va_base[(x)]+0x50)
- +#define HDA_REG_ISDC(x) (SSP_FTSSP010_va_base[(x)]+0x54)
- +
- +static const unsigned int SSP_FTSSP010_va_base[SSP_FTSSP010_IRQ_COUNT] = { SSP_FTSSP010_VA_BASE };
- +static const unsigned int SSP_FTSSP010_pa_base[SSP_FTSSP010_IRQ_COUNT] = { SSP_FTSSP010_PA_BASE };
- +
- +void SetSSP_Enable(int cardno, int enable)
- +{
- + volatile unsigned int ctrl = 0;
- +
- + ctrl = inl(FTSSP010_CONTROL2(cardno));
- + if(enable)
- + ctrl |= SSP_SSPEN + SSP_TXDOE;
- + else
- + ctrl &= ~(SSP_SSPEN + SSP_TXDOE);
- +
- + outl(ctrl, FTSSP010_CONTROL2(cardno));
- +}
- +void SetSSP_Enable_rx(int cardno, int enable)
- +{
- + volatile unsigned int ctrl = 0;
- +
- + ctrl = inl(FTSSP010_CONTROL2(cardno));
- + if(enable)
- + ctrl |= SSP_SSPEN ;
- + else
- + ctrl &= ~(SSP_SSPEN);
- +
- + outl(ctrl, FTSSP010_CONTROL2(cardno));
- +}
- +
- +void SetSSP_FIFO_Threshold(int cardno, unsigned int trans_len,unsigned int rec_len)
- +{
- + volatile unsigned int ctrl = 0;
- + ctrl = inl(FTSSP010_INT_CONTROL(cardno));
- +
- + ctrl &= ~0x0000FF00;
- + ctrl |= ((trans_len << 12) + (rec_len << 8)) & 0x0000FF00;
- +
- + outl(ctrl, FTSSP010_INT_CONTROL(cardno));
- +}
- +void SetSSP_IntMask(int cardno,int Mask)
- +{
- + volatile unsigned int ctrl = 0;
- + ctrl = inl(FTSSP010_INT_CONTROL(cardno));
- + ctrl &= ~0x3F;
- + ctrl |= Mask;
- + outw(ctrl, FTSSP010_INT_CONTROL(cardno));
- +}
- +void SetSSP_TXFIFO(int cardno, unsigned int threshold,unsigned int underrun)
- +{
- + volatile unsigned int data = 0;
- +
- + data = inl(FTSSP010_INT_CONTROL(cardno));
- +
- + if (threshold)
- + data |= SSP_TFIEN;
- + else
- + data &= ~SSP_TFIEN; //Howard@2007-4-13
- +
- + if (underrun)
- + data |= SSP_TFURIEN;
- + else
- + data &= ~SSP_TFURIEN; //Howard@2007-4-13
- +
- + outl(data, FTSSP010_INT_CONTROL(cardno));
- +}
- +void SetSSP_RXFIFO(int cardno,unsigned int threshold,unsigned int underrun)
- +{
- + volatile unsigned int data = 0;
- +
- + data = inl(FTSSP010_INT_CONTROL(cardno));
- +
- + if (threshold)
- + data |= SSP_RFIEN;
- + else
- + data &= ~SSP_RFIEN; //Howard@2007-4-13
- +
- + if (underrun)
- + data |= SSP_RFURIEN;
- + else
- + data &= ~SSP_RFURIEN; //Howard@2007-4-13
- +
- + outl(data, FTSSP010_INT_CONTROL(cardno));
- +}
- +void SetSSP_DMA(int cardno, unsigned int trans,unsigned int rec)
- +{
- + volatile unsigned int data = 0;
- +
- + data = inl(FTSSP010_INT_CONTROL(cardno));
- +
- + if (trans)
- + data |= SSP_TXDMAEN;
- + else
- + data &= ~SSP_TXDMAEN;
- +
- + if (rec)
- + data |= SSP_RXDMAEN;
- + else
- + data &= ~SSP_RXDMAEN;
- +
- + outl(data, FTSSP010_INT_CONTROL(cardno));
- +}
- +void SSPClearTxFIFO(int cardno)
- +{
- + volatile unsigned int data = 0;
- +
- + data = inl(FTSSP010_CONTROL2(cardno));
- + data |= SSP_TXFCLR;
- + outl(data, FTSSP010_CONTROL2(cardno));
- +}
- +
- +
- +void SSPClearRxFIFO(int cardno)
- +{
- + volatile unsigned int data = 0;
- +
- + data = inl(FTSSP010_CONTROL2(cardno));
- + data |= SSP_RXFCLR;
- + outl(data, FTSSP010_CONTROL2(cardno));
- +}
- +
- +void ftssp010_set_int_control(int cardno, unsigned val)
- +{
- + outl(val, FTSSP010_INT_CONTROL(cardno));
- +}
- +
- +unsigned ftssp010_get_int_status(int cardno)
- +{
- + return (inl(FTSSP010_INT_STATUS(cardno)));
- +}
- +
- +int ftssp010_get_status(int cardno)
- +{
- + return (inl(FTSSP010_STATUS(cardno)));
- +}
- +
- +int ftssp010_tx_fifo_not_full(int cardno)
- +{
- + return (inl(FTSSP010_STATUS(cardno))&0x2)==0x2;
- +}
- +
- +int ftssp010_tx_fifo_vaild_entries(int cardno)
- +{
- + return (inl(FTSSP010_STATUS(cardno))>>12) & 0x1f;
- +}
- +
- +/* Configure FTSSP010 to a given sampling rate and channel number
- + * for HDA mode in playback mode
- + */
- +void init_hw(unsigned int cardno)
- +{
- + /* Step 1: Set HDA Mode & HDA Format */
- + outl(HDA_MODE | 0x4000, FTSSP010_CONTROL0(cardno)); /* set FTSSP010 to HDA mode */
- + mdelay(50);
- + outl(HDA_CRST_CLR | (5 << HDA_RST_FCNT_OFS), FTSSP010_CONTROL2(cardno)); /* Cold Reset AC-Link */
- + mdelay(50);
- + while((inl(FTSSP010_CONTROL2(cardno)) & HDA_CRST_MASK) != HDA_CRST_CLR);
- + SetSSP_IntMask(cardno, 0);
- +
- +}
- +void SSPClearFIFO(int cardno, unsigned int tx, unsigned int rx)
- +{
- + unsigned int data;
- +
- + if (tx == 1) {
- + //clear TX
- + data = inl(FTSSP010_CONTROL2(cardno));
- + //data = REG32(SSP_REG_CTRL2);
- + data |= SSP_TXFCLR;
- + outl(data, FTSSP010_CONTROL2(cardno));
- + //REG32(SSP_REG_CTRL2) = data;
- + }
- +
- + if (rx == 1) {
- + //clear RX
- + data = inl(FTSSP010_CONTROL2(cardno));
- + //data = REG32(SSP_REG_CTRL2);
- + data |= SSP_RXFCLR;
- + //REG32(SSP_REG_CTRL2) = data;
- + outl(data, FTSSP010_CONTROL2(cardno));
- + }
- +}
- +void hda_cmd_rsp(int cardno, unsigned int node_num, unsigned int verb_num, unsigned int func_num)
- +{
- + //unsigned int HDA_REG_ICMDST;
- + volatile unsigned int hda_cmd = HDA_COD_DEVADDR | (node_num << 20) | (verb_num << 8) | func_num;
- + //Wait CMD Bus Not Busy
- + while((inl(FTSSP010_ICMDST(cardno)) & HDA_ICB_MASK) != 0);
- + //Write CMD into ICW
- + outl(hda_cmd, FTSSP010_AC_COMMAND(cardno));
- + mdelay(50);
- + //Wait new resp is latched into IRR
- + while((inl(FTSSP010_ICMDST(cardno)) & HDA_IRV_MASK) == 0);
- + //Get Resp From IRR & Compare with Expected Resp
- + //clear IRV
- + outl(inl(FTSSP010_ICMDST(cardno)) | (1 << HDA_IRV_OFFSET), FTSSP010_ICMDST(cardno));
- + mdelay(50);
- +}
- +void hda_cmdrsp_proc(int cardno, unsigned int node_num, unsigned int issue_cmd, unsigned int expect_rsp)
- +{
- + unsigned int hda_cmd = HDA_COD_DEVADDR | node_num | issue_cmd;
- + unsigned int HDA_REG_ICMDST;
- + //Wait CMD Bus Not Busy
- + while((inl(FTSSP010_ICMDST(cardno)) & HDA_ICB_MASK) != 0);
- +
- + //Write CMD into ICW
- + //REG32(HDA_REG_ICMDW) = hda_cmd;
- + outl(hda_cmd, FTSSP010_AC_COMMAND(cardno));
- + mdelay(50);
- + //Wait new resp is latched into IRR
- + while((inl(FTSSP010_ICMDST(cardno)) & HDA_IRV_MASK) == 0);
- + //Get Resp From IRR & Compare with Expected Resp
- + if (inl(FTSSP010_IRSPR(cardno)) != expect_rsp) {
- + ERR("%s: unexpected rsp!",__func__);
- + }
- + else {
- + //clear IRV
- + outl(inl(FTSSP010_ICMDST(cardno)) | (1 << HDA_IRV_OFFSET), FTSSP010_ICMDST(cardno));
- + }
- +}
- +unsigned int hda_covfmt_setup(unsigned int type, unsigned int base, unsigned int mult, unsigned int div, unsigned int bits, unsigned int chnum)
- +{
- + unsigned int hda_fmt = type << HDA_FMT_TYPE_OFS |
- + base << HDA_FMT_BASE_OFS |
- + mult << HDA_FMT_MULT_OFS |
- + div << HDA_FMT_DIV_OFS |
- + bits << HDA_FMT_BITS_OFS |
- + chnum << HDA_FMT_CHNUM_OFS;
- + return hda_fmt;
- +}
- +unsigned int hda_covstr_setup(unsigned int stream, unsigned int channel)
- +{
- + unsigned int hda_str = stream << HDA_STR_STR_OFS |
- + channel << HDA_STR_CHA_OFS ;
- + return hda_str;
- +}
- +unsigned int hda_converter_setup(int cardno, unsigned int mode, unsigned int type, unsigned int base, unsigned mult, unsigned int div, unsigned int bits, unsigned int chnum, unsigned int stream, unsigned int channel)
- +{
- + unsigned int hda_fmt = 0;
- + unsigned int hda_str = 0;
- + unsigned int exp_rsp = 0;
- + unsigned int node_num = 0;
- +
- + if (mode == HDA_OUT_STR) {
- + node_num = HDA_OUTCOV_NODE;
- + }
- + else {
- + node_num = HDA_INCOV_NODE;
- + }
- + //a: Set Converter Format to Converter
- + hda_fmt = hda_covfmt_setup(type, base, mult, div, bits, chnum);
- + exp_rsp = HDA_RESP_ZERO_VAL;
- + hda_cmdrsp_proc(cardno, node_num, (HDA_CMD_SETCVTFMT | hda_fmt), exp_rsp);
- + //b: Get Converter Format from Converter
- + exp_rsp = hda_fmt;
- + hda_cmdrsp_proc(cardno, node_num, HDA_CMD_GETCVTFMT, exp_rsp);
- + //c: Set Converter Stream to Converter
- + hda_str = hda_covstr_setup(stream, channel);
- + exp_rsp = HDA_RESP_ZERO_VAL;
- + hda_cmdrsp_proc(cardno, node_num, (HDA_CMD_SETCVTSTR | hda_str), exp_rsp);
- + //d: Get Converter Stream from Converter
- + exp_rsp = hda_str;
- + hda_cmdrsp_proc(cardno, node_num, HDA_CMD_GETCVTSTR, exp_rsp);
- +
- + return hda_fmt;
- +}
- +void hda_iosdc_setup(int cardno, unsigned int io_sel, unsigned int ctrl, unsigned int stream_num, unsigned int hda_fmt)
- +{
- + unsigned int hda_reg_base = (io_sel == 1)? HDA_REG_OSDC(cardno) : HDA_REG_ISDC(cardno);
- + if (ctrl == 1) {//run
- + outl((stream_num << HDA_SDC_STNUM_OFFSET) | hda_fmt, hda_reg_base);
- + outl((inl(hda_reg_base) | (1 << HDA_SDC_SRUN_OFFSET)),hda_reg_base);
- + }
- +
- +}
- +static void _ftssp010_config_hda(int cardno, unsigned is_stereo, unsigned speed, int is_rec)
- +{
- + unsigned int hda_fmt = 0;
- + unsigned int div = 0,mult = 0, base = 0;
- + switch (speed) {
- + case 44100:
- + base = 1;
- + div = 0;
- + break;
- + case 48000:
- + div = 0;
- + break;
- + case 96000:
- + mult = 1;
- + break;
- + case 192000:
- + mult = 3;
- + break;
- + }
- +
- + if (is_rec) { /* Recording */
- + /* ------------------------------------------------ */
- + /* Codec initialization */
- + /* ------------------------------------------------ */
- + /* Step 3: Codec Evaluation */
- + /* root_node -> node 1(Audio Func Group) */
- + /* -> node 2(Output Converter) */
- + /* -> node 3(Input Converter) */
- + /* ------------------------------------------------ */
- + //input
- + hda_cmd_rsp(cardno, 0x1a, 0x707, 0x20); //pin complex => input enable, port-c LINE1
- + hda_cmd_rsp(cardno, 0x08, 0x3f0, 0x3f);//pin amp => max LINE ADC amplifier gain
- + hda_cmd_rsp(cardno, 0x1a, 0x3f0, 0x00);//pin complex => no mute
- + hda_cmd_rsp(cardno, 0x23, 0x3f2, 0x3f);//pin complex => no mute
- + /* ------------------------------ */
- + /* Step 4: Output Converter Setup */
- + /* ------------------------------ */
- + /* Set Converter Format & Stream to Node 2(Output Converter) */
- + /* type = PCM, base = 48K, mult = xN, div = /M, bits = 8~32bits/sample, chnum = 1 */
- + /* stream = 1, lowest channel = 0 */
- +
- + hda_fmt = hda_converter_setup(cardno, HDA_IN_STR, //MODE
- + 0, base, mult, div, 1, 1, //FORMAT
- + HDA_STRNUM_RX, HDA_CHANUM); //STREAM
- + /* ---------------------------- */
- + /* Step 5: Enable Output Stream */
- + /* ---------------------------- */
- + hda_iosdc_setup(cardno, HDA_IN_STR, HDA_STR_RUN, HDA_STRNUM_RX, hda_fmt);
- + SetSSP_Enable_rx(cardno, 1);
- + SetSSP_RXFIFO(cardno, 0, 0);
- + SetSSP_TXFIFO(cardno, 0, 0);
- + SetSSP_FIFO_Threshold(cardno,12,12);
- + SetSSP_DMA(cardno, 0, 1);
- +
- + SSPClearTxFIFO(cardno);
- + SSPClearRxFIFO(cardno);
- +
- + //SetSSP_Enable_rx(cardno, 0);
- +
- + } else { /* Playback */
- + /* ------------------------------------------------ */
- + /* Codec initialization */
- + /* ------------------------------------------------ */
- + /* Step 3: Codec Evaluation */
- + /* root_node -> node 1(Audio Func Group) */
- + /* -> node 2(Output Converter) */
- + /* -> node 3(Input Converter) */
- + /* ------------------------------------------------ */
- + //DBG("%s before_cmd_rsp<<",__func__);
- + hda_cmd_rsp(cardno, 0x14, 0x707, 0x40);//pin complex => output
- + //DBG("%s after hda_cmd_rsp<<pin complex => output>>",__func__);
- + hda_cmd_rsp(cardno, 0x0c, 0x3f0, 0x3f);//pin amp => 0x3f
- + hda_cmd_rsp(cardno, 0x14, 0x3f0, 0x00);//pin complex => no mute
- + //DBG("%s after hda_cmd_rsp",__func__);
- + //msleep_interruptible(10);
- + /* ------------------------------ */
- + /* Step 4: Output Converter Setup */
- + /* ------------------------------ */
- + /* Set Converter Format & Stream to Node 2(Output Converter) */
- + /* type = PCM, base = 48K, mult = xN, div = /M, bits = 8~32bits/sample, chnum = 1 */
- + /* stream = 1, lowest channel = 0 */
- + hda_fmt = hda_converter_setup(cardno, HDA_OUT_STR, //MODE
- + 0, base, mult, div, 1, 1, //FORMAT
- + HDA_STRNUM_TX, HDA_CHANUM); //STREAM
- + //DBG("%s after hda_converter_setup",__func__);
- + /* ---------------------------- */
- + /* Step 5: Enable Output Stream */
- + /* ---------------------------- */
- + hda_iosdc_setup(cardno, HDA_OUT_STR, HDA_STR_RUN, HDA_STRNUM_TX, hda_fmt);
- + SetSSP_Enable(cardno, 1);
- + SetSSP_RXFIFO(cardno, 0, 0);
- + SetSSP_TXFIFO(cardno, 0, 0);
- + //outl(0xC, FTSSP010_CONTROL2(cardno)); /* Disable FTSSP010, clear RX/TX Fifo. */
- + SetSSP_FIFO_Threshold(cardno,12,12);
- + SetSSP_DMA(cardno,1,0);
- +
- + SSPClearTxFIFO(cardno);
- + SSPClearRxFIFO(cardno);
- + }
- +
- + while(inl(FTSSP010_INT_STATUS(cardno))&0x3);
- +}
- +/* for HDA */
- +void ftssp010_config_hda_play(int cardno, unsigned is_stereo, unsigned speed, int use8bit)
- +{
- + _ftssp010_config_hda(cardno, is_stereo, speed, 0);
- +}
- +
- +void ftssp010_config_hda_rec(int cardno, unsigned is_stereo, unsigned speed, int use8bit)
- +{
- + _ftssp010_config_hda(cardno, is_stereo, speed, 1);
- +}
- +
- +
- +
- +void ftssp010_stop_tx(int cardno)
- +{
- + unsigned int hda_reg_base = HDA_REG_OSDC(cardno);
- + SetSSP_Enable(cardno,0);
- + SetSSP_DMA(cardno,0,0);
- +
- + /* turn off output node */
- + hda_cmd_rsp(cardno,0x14, 0x707, 0); //pin complex => input enable, port-c LINE1
- + hda_cmd_rsp(cardno,0x0c, 0x3f0, 0x80); //pin amp => max LINE ADC amplifier gain
- + hda_cmd_rsp(cardno,0x14, 0x3f0, 0x80); //pin complex => no mute
- +
- + outl(0, hda_reg_base);
- + SSPClearFIFO(cardno, 1, 0);
- + //outl(inl(FTSSP010_INT_CONTROL(cardno)) & (~0x22), FTSSP010_INT_CONTROL(cardno));
- +}
- +
- +void ftssp010_stop_rx(int cardno)
- +{
- + unsigned int hda_reg_base = HDA_REG_ISDC(cardno);
- + SetSSP_Enable_rx(cardno, 0);
- + SetSSP_DMA(cardno, 0, 0);
- +
- + /* turn off output node */
- + hda_cmd_rsp(cardno,0x1a, 0x707, 0); //pin complex => input enable, port-c LINE1
- + hda_cmd_rsp(cardno,0x08, 0x3f0, 0x80);//pin amp => LINE ADC amplifier gain
- + hda_cmd_rsp(cardno,0x1a, 0x3f0, 0x80);//pin complex => mute
- + hda_cmd_rsp(cardno,0x23, 0x3f2, 0x80);//pin complex => no mute
- +
- + outl(0, hda_reg_base);
- + SSPClearFIFO(cardno, 0, 1);
- + //outl(inl(FTSSP010_INT_CONTROL(cardno)) & (~0x11), FTSSP010_INT_CONTROL(cardno));
- +}
- +
- diff -Nur linux-3.4.110.orig/sound/nds32/FTSSP010_lib.c linux-3.4.110/sound/nds32/FTSSP010_lib.c
- --- linux-3.4.110.orig/sound/nds32/FTSSP010_lib.c 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/sound/nds32/FTSSP010_lib.c 2016-04-07 10:20:51.062085666 +0200
- @@ -0,0 +1,795 @@
- +/* FTSSP010 - UDA1345TS module
- + *
- + * $log$
- + */
- +
- +#include <linux/init.h>
- +#include <linux/module.h>
- +#include <asm/io.h>
- +#include <linux/delay.h>
- +#include <linux/i2c.h>
- +#include <asm/spec.h>
- +#include <asm/dmad.h>
- +#include <linux/dma-mapping.h>
- +#include "FTSSP010_UDA1345TS.h"
- +
- +#if 0
- +MODULE_LICENSE("Faraday License");
- +MODULE_AUTHOR("Faraday Technology Corp.");
- +MODULE_DESCRIPTION("FTSSP010 - UDA1345TS Linux 2.6 Library");
- +#endif
- +
- +#define PMU_PDLLCR1 (PMU_FTPMU010_VA_BASE+0x34)
- +#define PMU_MFPSR (PMU_FTPMU010_VA_BASE+0x28)
- +#define PMU_I2SAC97_REQACKCFG (PMU_FTPMU010_VA_BASE+0xbc)
- +#define PMU_C4 (PMU_FTPMU010_VA_BASE+0xc4)
- +
- +#define SSPCLK_TO_SCLKDIV(sspclk_div2,bps) ((sspclk_div2)/(bps)-1)
- +
- +// Each client has this additional data
- +struct alc5630_data {
- + struct i2c_client *client;
- + struct delayed_work work;
- + unsigned long gpio2_value;
- + struct mutex mtx;
- +};
- +
- +//ADD by river 2011.01.26
- +static int i2s_alc5630_read(unsigned int raddr, char *data, struct i2c_client *client)
- +{
- +#ifndef CONFIG_SND_FTSSP010_AC97
- + struct i2c_adapter *adap = client->adapter;
- + int ret;
- +#endif
- + struct i2c_msg msg;
- + int i2c_value;
- +
- + //Reading ALC5630 register
- + msg.addr = raddr;
- + msg.flags = (client->flags & I2C_M_TEN) | I2C_M_RD;
- + msg.len = 1;
- + msg.buf = (char *)data;
- +
- + //ret = i2c_transfer(adap, &msg, 1);
- +#ifndef CONFIG_SND_FTSSP010_AC97
- + ret = i2c_transfer(adap, &msg, 1);
- + if (ret != 0) {
- + printk("i2c read failed\n");
- + return -1;
- + }
- + else
- +#endif
- + {
- + i2c_value = (data[0]&0xff) << 8 | (data[1]&0xff);
- + return i2c_value;
- + }
- +}
- +
- +static void i2s_alc5630_write(unsigned int raddr, unsigned int data, struct i2c_client *client)
- +{
- +#ifndef CONFIG_SND_FTSSP010_AC97
- + struct i2c_adapter *adap = client->adapter;
- + int ret;
- +#endif
- + struct i2c_msg msg;
- + char buf[3];
- +
- + //Writing ALC5630 register
- + msg.addr = raddr;
- + msg.flags = (client->flags & I2C_M_TEN) | ~I2C_M_RD;
- + msg.len = 1;
- +
- + buf[0] = (data >> 8) & 0xff;
- + buf[1] = data & 0xff;
- + msg.buf = (char *)buf;
- +
- + //ret = i2c_transfer(adap, &msg, 1);
- +#ifndef CONFIG_SND_FTSSP010_AC97
- + ret = i2c_transfer(adap, &msg, 1);
- + if (ret != 0)
- + {
- + printk("i2c write failed\n");
- + }
- +#endif
- +}
- +
- +/*
- +static void i2s_alc5630_master_stereo_mode(struct i2c_client *client)
- +{
- + //printk(">>>>>>>>> (7) i2s_alc5630_master_stereo_mode() is called.\n");
- + i2s_alc5630_write(0x02, 0x5f5f, client);
- + mdelay(50);
- + i2s_alc5630_write(0x04, 0x5f5f, client);
- + mdelay(50);
- + i2s_alc5630_write(0x26, 0x000f, client);
- + mdelay(50);
- + i2s_alc5630_write(0x34, 0x0000, client); // codec master mode
- + //i2s_alc5630_write(0x34, 0x8000, client); // codec slave mode
- + mdelay(50);
- + i2s_alc5630_write(0x3a, 0x0801, client);
- + mdelay(50);
- + i2s_alc5630_write(0x3c, 0xffff, client);
- + mdelay(50);
- + i2s_alc5630_write(0x3e, 0xffff, client);
- + mdelay(50);
- + i2s_alc5630_write(0x60, 0x3075, client); // codec master mode. divider.
- + mdelay(50);
- + i2s_alc5630_write(0x62, 0x1010, client); // codec master mode. divider.
- +
- +}
- +*/
- +
- +/*
- +static void i2s_alc5630_read_test(struct i2c_client *client)
- +{
- + char data[3];
- + printk(">>>>> : i2s_alc5630_read_test().....\n");
- + printk("Reg 0x%02x = 0x%08x\n", 0x0, i2s_alc5630_read(0x0, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x02, i2s_alc5630_read(0x02, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x04, i2s_alc5630_read(0x04, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x06, i2s_alc5630_read(0x06, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x08, i2s_alc5630_read(0x08, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x0a, i2s_alc5630_read(0x0a, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x0c, i2s_alc5630_read(0x0c, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x0e, i2s_alc5630_read(0x0e, data,client));
- +
- + printk("Reg 0x%02x = 0x%08x\n", 0x10, i2s_alc5630_read(0x10, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x12, i2s_alc5630_read(0x12, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x14, i2s_alc5630_read(0x14, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x16, i2s_alc5630_read(0x16, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x18, i2s_alc5630_read(0x18, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x1a, i2s_alc5630_read(0x1a, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x1c, i2s_alc5630_read(0x1c, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x1e, i2s_alc5630_read(0x1e, data,client));
- +
- + printk("Reg 0x%02x = 0x%08x\n", 0x20, i2s_alc5630_read(0x20, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x22, i2s_alc5630_read(0x22, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x24, i2s_alc5630_read(0x24, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x26, i2s_alc5630_read(0x26, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x28, i2s_alc5630_read(0x28, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x2a, i2s_alc5630_read(0x2a, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x2c, i2s_alc5630_read(0x2c, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x2e, i2s_alc5630_read(0x2e, data,client));
- +
- + printk("Reg 0x%02x = 0x%08x\n", 0x30, i2s_alc5630_read(0x30, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x32, i2s_alc5630_read(0x32, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x34, i2s_alc5630_read(0x34, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x36, i2s_alc5630_read(0x36, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x38, i2s_alc5630_read(0x38, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x3a, i2s_alc5630_read(0x3a, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x3c, i2s_alc5630_read(0x3c, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x3e, i2s_alc5630_read(0x3e, data,client));
- +
- + printk("Reg 0x%02x = 0x%08x\n", 0x40, i2s_alc5630_read(0x40, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x42, i2s_alc5630_read(0x42, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x44, i2s_alc5630_read(0x44, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x46, i2s_alc5630_read(0x46, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x48, i2s_alc5630_read(0x48, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x4a, i2s_alc5630_read(0x4a, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x4c, i2s_alc5630_read(0x4c, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x4e, i2s_alc5630_read(0x4e, data,client));
- +
- + printk("Reg 0x%02x = 0x%08x\n", 0x50, i2s_alc5630_read(0x50, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x52, i2s_alc5630_read(0x52, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x54, i2s_alc5630_read(0x54, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x56, i2s_alc5630_read(0x56, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x58, i2s_alc5630_read(0x58, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x5a, i2s_alc5630_read(0x5a, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x5c, i2s_alc5630_read(0x5c, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x5e, i2s_alc5630_read(0x5e, data,client));
- +
- + printk("Reg 0x%02x = 0x%08x\n", 0x60, i2s_alc5630_read(0x60, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x62, i2s_alc5630_read(0x62, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x64, i2s_alc5630_read(0x64, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x66, i2s_alc5630_read(0x66, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x68, i2s_alc5630_read(0x68, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x6a, i2s_alc5630_read(0x6a, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x6c, i2s_alc5630_read(0x6c, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x6e, i2s_alc5630_read(0x6e, data,client));
- +
- + printk("Reg 0x%02x = 0x%08x\n", 0x70, i2s_alc5630_read(0x70, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x72, i2s_alc5630_read(0x72, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x74, i2s_alc5630_read(0x74, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x76, i2s_alc5630_read(0x76, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x78, i2s_alc5630_read(0x78, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x7a, i2s_alc5630_read(0x7a, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x7c, i2s_alc5630_read(0x7c, data,client));
- + printk("Reg 0x%02x = 0x%08x\n", 0x7e, i2s_alc5630_read(0x7e, data,client));
- +
- +}
- +*/
- +
- +static void i2s_al5630_slave_stereo_mode(struct i2c_client *client)
- +{
- +
- +
- + i2s_alc5630_write(0x34, 0x8000, client); // codec slave mode
- + i2s_alc5630_write(0x0c, 0x1010, client);
- + i2s_alc5630_write(0x10, 0xee03, client);
- + i2s_alc5630_write(0x1c, 0x0748, client);
- + //i2s_alc5630_write(0x02, 0x8080, client);
- + //i2s_alc5630_write(0x04, 0x8888, client);
- + i2s_alc5630_write(0x62, 0x0000, client);
- +
- +}
- +
- +//End ADD by river 2011.01.26
- +
- +
- +/* Drive PMU to generate I2S main clocking signal. Also configures PMU to set correct DMA REQ/ACK pair */
- +void pmu_set_i2s_clocking(unsigned int speed)
- +{
- + unsigned int pmu_pdllcr1; /* PLL/DLL Control Register 1 */
- + /* Configure PMU to generate I2S main clock */
- + #ifdef CONFIG_PLAT_AG101
- + pmu_pdllcr1 = inl(PMU_PDLLCR1)&0xfff0ffff; /* Bit 19-16 are relevent */
- + #endif
- +
- + switch (speed) {
- + case 8000:
- + pmu_pdllcr1 |= 0x00000000; /* 2.048MHz x2 */
- + break;
- + case 11025:
- + pmu_pdllcr1 |= 0x00010000; /* 2.8224MHz x2 */
- + break;
- + case 16000:
- + pmu_pdllcr1 |= 0x00020000; /* 4.096MHz x2 */
- + break;
- + case 22050:
- + pmu_pdllcr1 |= 0x00030000; /* 5.6448MHz x2 */
- + break;
- + case 32000:
- + pmu_pdllcr1 |= 0x00040000; /* 8.192MHz x2 */
- + break;
- + case 44100:
- + pmu_pdllcr1 |= 0x00050000; /* 11.2896Mhz x2 */
- + break;
- + case 48000:
- + pmu_pdllcr1 |= 0x00060000; /* 12.2880MHz x2 */
- + break;
- + default:
- + printk("%s: Unknown i2s speed %d\n",__func__,speed);
- + };
- +
- + #ifdef CONFIG_PLAT_AG101
- + outl(pmu_pdllcr1, PMU_PDLLCR1);
- + /* Configure PMU to select I2S output (instead of AC97) */
- + outl(inl(PMU_MFPSR)&(~(1<<3)), PMU_MFPSR); /* clear bit 3 of MFPSR*/
- + #endif
- +}
- +
- +/* Drive PMU to generate AC97 main clocking signal. Also configures PMU to set correct DMA REQ/ACK pair */
- +void pmu_set_ac97_clocking(unsigned int speed)
- +{
- + /* Configure PMU to select AC97 output (instead of I2S) */
- + /* Set GPIO[26] to AC97 clock, use 49.152MHz main clock (AC97 CLK1) */
- + //outl(inl(PMU_MFPSR)|((1<<13)|(1<<3)), PMU_MFPSR); /* Set bit 13 & 3 of MFPSR*/
- + #ifndef CONFIG_PLAT_AG102
- + outl(inl(PMU_MFPSR)|((1<<13)|(1<<3)), PMU_MFPSR); /* Set bit 13 & 3 of MFPSR*/
- + #endif
- +}
- +
- +/* Programs PMU to set I2S/AC97 DMA Channel, ch=0-7 */
- +void pmu_set_i2s_dma_channel(unsigned ch)
- +{
- + #ifdef CONFIG_PLAT_AG101
- + ch&=0x7;
- + //outl((inl(PMU_I2SAC97_REQACKCFG)&(~0x7))|ch, PMU_I2SAC97_REQACKCFG);
- + outl(0xa, PMU_I2SAC97_REQACKCFG);
- + outl(0xb, PMU_C4);
- + #endif
- +}
- +
- +/* Initialize FTSSP010 to output to UDA1345TS via I2S */
- +#define FTSSP010_CONTROL0(x) (SSP_FTSSP010_va_base[(x)]+0x0)
- +#define FTSSP010_CONTROL0_OPM_STEREO 0xC
- +#define FTSSP010_CONTROL0_OPM_MONO 0x8
- +
- +#define FTSSP010_CONTROL1(x) (SSP_FTSSP010_va_base[(x)]+0x4)
- +#define FTSSP010_CONTROL2(x) (SSP_FTSSP010_va_base[(x)]+0x8)
- +
- +#define FTSSP010_INT_CONTROL(x) (SSP_FTSSP010_va_base[(x)]+0x10)
- +#define FTSSP010_STATUS(x) (SSP_FTSSP010_va_base[(x)]+0xC)
- +#define FTSSP010_INT_STATUS(x) (SSP_FTSSP010_va_base[(x)]+0x14)
- +#define FTSSP010_DATA(x) (SSP_FTSSP010_va_base[(x)]+0x18)
- +#define FTSSP010_INFO(x) (SSP_FTSSP010_va_base[(x)]+0x1C)
- +
- +//static const unsigned int SSP_FTSSP010_va_base[SSP_FTSSP010_IRQ_COUNT] = { SSP_FTSSP010_VA_BASE };
- +//static const unsigned int SSP_FTSSP010_pa_base[SSP_FTSSP010_IRQ_COUNT] = { SSP_FTSSP010_PA_BASE };
- +
- +//ADD by river 2011.02.11
- +static struct i2c_client *g_i2c_client;
- +
- +
- +#define FTSSP010_ACLINK_SLOT_VALID(x) (SSP_FTSSP010_va_base[(x)]+0x20)
- +
- +void ftssp010_set_int_control(int cardno, unsigned val)
- +{
- + outl(val, FTSSP010_INT_CONTROL(cardno));
- +}
- +
- +unsigned ftssp010_get_int_status(int cardno)
- +{
- + return (inl(FTSSP010_INT_STATUS(cardno)));
- +}
- +
- +int ftssp010_get_status(int cardno)
- +{
- + return (inl(FTSSP010_STATUS(cardno)));
- +}
- +
- +int ftssp010_tx_fifo_not_full(int cardno)
- +{
- + return (inl(FTSSP010_STATUS(cardno))&0x2)==0x2;
- +}
- +
- +int ftssp010_tx_fifo_vaild_entries(int cardno)
- +{
- + return (inl(FTSSP010_STATUS(cardno))>>12) & 0x1f;
- +}
- +
- +#include "FTSSP010_W83972D.h"
- +
- +// AC97 codec tags
- +#define TAG_COMMAND 0xe000
- +#define TAG_DATA 0x9800 /* Slot 3/4 */
- +#define TAG_DATA_MONO 0x9000 /* Slot 3 */
- +//#define TAG_DATA_LINE_IN 0x9000 /* Slot 3 */
- +
- +void ftssp010_ac97_write_codec_start(unsigned int cardno)
- +{
- + outl(0x0, FTSSP010_INT_CONTROL(cardno));/*Disable interrupts & DMA req */
- + outl(0xC, FTSSP010_CONTROL2(cardno)); /* Disable FTSSP010, clear RX/TX Fifo. */
- + outl(TAG_COMMAND, FTSSP010_ACLINK_SLOT_VALID(cardno));
- +}
- +
- +void ftssp010_ac97_write_codec(unsigned int cardno,unsigned int reg,unsigned int data)
- +{
- + outl(reg << 12, FTSSP010_DATA(cardno));
- + mdelay(50);
- + outl(data << 4, FTSSP010_DATA(cardno));
- + mdelay(50);
- +}
- +
- +void ftssp010_ac97_write_codec_commit(unsigned int cardno)
- +{
- + while((inl(FTSSP010_CONTROL2(cardno))&0x1)==0) {
- + outl(0x3 , FTSSP010_CONTROL2(cardno)); /* SSPEN + TXDOE */
- + }
- + while(ftssp010_tx_fifo_vaild_entries(cardno))
- + ;
- + /* Wait for frame completion */
- + while((inl(FTSSP010_INT_STATUS(cardno))&0x10)==0)
- + ;
- + outl(0x0, FTSSP010_CONTROL2(cardno));
- +}
- +
- +/* Configure FTSSP010 to a given sampling rate and channel number
- + * for AC97 mode in playback mode
- + */
- +void init_hw(unsigned int cardno,unsigned int ac97, struct i2c_client *client)
- +{
- +
- + //printk(">>>>>>>>>> (5) init_hw() is called.\n");
- + g_i2c_client = client;
- +
- + if(ac97)
- + {
- + //pmu_set_ac97_clocking(48000);
- + #ifndef CONFIG_PLAT_AG102
- + pmu_set_ac97_clocking(48000);
- + #endif
- + outl(0x400c, FTSSP010_CONTROL0(cardno)); /* set FTSSP010 to AC97 mode */
- + mdelay(50);
- + outl(0xc400, FTSSP010_INT_CONTROL(cardno));
- + mdelay(50);
- + outl(0x20, FTSSP010_CONTROL2(cardno)); /* Cold Reset AC-Link */
- + mdelay(50);
- + while(inl(FTSSP010_CONTROL2(cardno)))
- + mdelay(50);
- + outl(0x40, FTSSP010_CONTROL2(cardno)); /* Reset AC-Link */
- + mdelay(1500);
- + }
- + else
- + {
- +
- + //printk(">>>>>>>>> (6) I2S mode selected....YAYAYA......\n");
- + #ifdef CONFIG_PLAT_AG101
- + outl(inl(PMU_MFPSR)&(~(1<<3)), PMU_MFPSR); /* clear bit 3 of MFPSR*/
- + outl(0xa, PMU_I2SAC97_REQACKCFG);
- + outl(0xb, PMU_C4);
- + #endif
- +
- + //MOD by river 2011.01.26
- + //i2s_alc5630_master_stereo_mode(client);
- + i2s_al5630_slave_stereo_mode(client);
- + //ssp_slave_stereo_mode();
- + //End MOD by river 2011.01.26
- + outl(0x311c, FTSSP010_CONTROL0(cardno)); /* I2S Master */
- + outl(0, FTSSP010_CONTROL1(cardno)); /* I2S Master */
- + outl(0xc400, FTSSP010_INT_CONTROL(cardno)); /* I2S Master */
- + outl(0x40, FTSSP010_CONTROL2(cardno)); /* Reset AC-Link */
- +
- + //i2s_alc5630_read_test(client);
- + }
- +}
- +static void _ftssp010_config_ac97(int cardno, unsigned is_stereo, unsigned speed, int is_rec)
- +{
- + /* Codec initialization */
- + ftssp010_ac97_write_codec_start(cardno);
- + ftssp010_ac97_write_codec(cardno, W83972D_RESET, 0);
- + ftssp010_ac97_write_codec_commit(cardno);
- +
- + msleep_interruptible(10);
- + ftssp010_ac97_write_codec_start(cardno);
- +
- + if (is_rec) { /* Recording */
- + /* Mute output */
- + //ftssp010_ac97_write_codec(cardno, W83972D_STEREO_OUTPUT_CONTROL, 0x8000);
- + /* Mute PCM */
- + //ftssp010_ac97_write_codec(cardno, W83972D_PCM_OUTPUT_CONTROL, 0x8000);
- +
- + /* Register 0x10, Line-In/Mic Gain */
- + ftssp010_ac97_write_codec(cardno, W83972D_LINE_IN_VOLUME, 0x808);
- + //ftssp010_ac97_write_codec(cardno, W83972D_AUX_INPUT_CONTROL, 0x808);
- + ftssp010_ac97_write_codec(cardno, W83972D_MIC_VOLUME, 0x8);
- + /* FIXME: REC from line-in only */
- +
- + /* Register 0x1A, Record Select=StereoMix */
- + ftssp010_ac97_write_codec(cardno, W83972D_RECORD_SELECT, 0x505 /*404*/);
- + /* Register 0x1C, Record Gain=0db */
- + ftssp010_ac97_write_codec(cardno, W83972D_RECORD_GAIN, 0x808);
- + ftssp010_ac97_write_codec(cardno, W83972D_RECORD_GAIN_MIC, 0x8);
- + } else { /* Playback */
- + /* Register 0x10, Mute Line-In/Mic Gain */
- + ftssp010_ac97_write_codec(cardno, W83972D_LINE_IN_VOLUME, 0x8000);
- + ftssp010_ac97_write_codec(cardno, W83972D_MIC_VOLUME, 0x8000);
- +
- + /* Register 0x1A, Mute Record Gains */
- + ftssp010_ac97_write_codec(cardno, W83972D_RECORD_GAIN, 0x8000);
- + ftssp010_ac97_write_codec(cardno, W83972D_RECORD_GAIN_MIC, 0x8000);
- +
- + /* Output */
- + ftssp010_ac97_write_codec(cardno, W83972D_STEREO_OUTPUT_CONTROL, 0);
- + ftssp010_ac97_write_codec(cardno, W83972D_PCM_OUTPUT_CONTROL, 0x808);
- + }
- +
- +#if 0
- + ftssp010_ac97_write_codec(cardno, W83972D_EXT_AUDIO_CONTROL, 0x1);
- + ftssp010_ac97_write_codec(cardno, W83972D_DAC_SAMPLE_RATE_CONTROL, speed);
- +#endif
- +
- + ftssp010_ac97_write_codec_commit(cardno);
- + msleep_interruptible(10);
- +
- + /* Start data transfer */
- +// if(is_rec) {
- +// outl(TAG_DATA_LINE_IN, FTSSP010_ACLINK_SLOT_VALID(cardno));
- +// } else {
- + if(is_stereo)
- + outl(TAG_DATA, FTSSP010_ACLINK_SLOT_VALID(cardno));
- + else
- + outl(TAG_DATA_MONO, FTSSP010_ACLINK_SLOT_VALID(cardno));
- +// }
- + while(inl(FTSSP010_INT_STATUS(cardno))&0x3);
- +// msleep_interruptible(10);
- +}
- +
- +void ftssp010_config_ac97_play(int cardno, unsigned is_stereo, unsigned speed, int use8bit)
- +{
- + _ftssp010_config_ac97(cardno, is_stereo, speed, 0);
- +}
- +
- +void ftssp010_config_ac97_rec(int cardno, unsigned is_stereo, unsigned speed, int use8bit)
- +{
- + _ftssp010_config_ac97(cardno, is_stereo, speed, 1);
- +}
- +/*
- + * Configure FTSSP010 to a given sampling rate and channel number
- + * for I2S mode
- + */
- +void ftssp010_config(int cardno, unsigned is_stereo, unsigned speed, int width, int is_rec)
- +{
- + int use8bit = (width == 1 ? 1 : 0);
- + unsigned opm, bps = 2 * (use8bit ? 8 : 16); /* bits per 1 second audio data. */
- + unsigned fpclkdiv = 0;
- +
- + //ADD by river 2011.06.02
- + struct alc5630_data *alc5630;
- + char data[3];
- + opm = is_stereo ? FTSSP010_CONTROL0_OPM_STEREO : FTSSP010_CONTROL0_OPM_MONO;
- + //MOD by river 2011.01.27
- + outl(0x3100 | opm, FTSSP010_CONTROL0(cardno)); /* I2S Master */
- + //End MOD by river 2011.01.27
- +
- +#if 0
- + printk("%s: use %dHz %d-bit %s \n",__func__,
- + speed,
- + use8bit?8:16,
- + is_stereo?"stereo":"mono"
- + );
- +#endif
- +
- + /* configures CONTROL1 to use suitable clock divider.
- + the I2S clock is generated from PMU. */
- + bps *= speed;
- + switch(speed) {
- + case 8000: /* SCLK : 256KHZ */
- + i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client); //?
- + i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
- + i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
- + //i2s_alc5630_write(0x44, 0x6a0, g_i2c_client); //?
- + //i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
- + //i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
- + fpclkdiv = 0xBB;
- +
- + //fpclkdiv=SSPCLK_TO_SCLKDIV(2048000, bps);
- + break;
- + case 11025: /* SCLK : 352.8KHZ */
- + i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client); //?
- + i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
- + i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
- + fpclkdiv = 0x88;
- + //fpclkdiv=SSPCLK_TO_SCLKDIV(2822400, bps);
- + break;
- + case 16000: /* SCLK : 512KHZ */
- + i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client); //?
- + i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
- + i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
- + fpclkdiv = 0x5f;
- + //fpclkdiv=SSPCLK_TO_SCLKDIV(4096000, bps);
- + break;
- + case 22050: /* SCLK : 705.6KHZ */
- + i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client);
- + i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
- + i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
- + fpclkdiv = 0x45;
- + //fpclkdiv=SSPCLK_TO_SCLKDIV(5644800, bps);
- + break;
- + case 24000: /* SCLK : 768KHZ */
- + i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client);
- + i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
- + i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
- + fpclkdiv = 0x3e;
- + //fpclkdiv=SSPCLK_TO_SCLKDIV(5644800, bps);
- + break;
- + case 32000: /* SCLK : 1024KHZ */
- + i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client);
- + i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
- + i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
- + //fpclkdiv = 0x2e;
- + fpclkdiv = 0x2f;
- + //fpclkdiv=SSPCLK_TO_SCLKDIV(8192000, bps);
- + break;
- + case 44100: /* SCLK : 1.4112 MHZ */ /* 96 MHZ */
- + i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client);
- + i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
- + i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
- + fpclkdiv = 0x22;
- + //fpclkdiv=SSPCLK_TO_SCLKDIV(11289600, bps);
- + break;
- + case 48000: /* SCLK : 1.536 MHZ */
- + i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client);
- + i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
- + i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
- + fpclkdiv = 0x1f;
- + //fpclkdiv=SSPCLK_TO_SCLKDIV(12288000, bps);
- +
- + break;
- + default:
- + printk("%s: unsupported speed %d\n", __func__,speed);
- + return;
- + };
- +
- +
- + if(!use8bit) {
- + outl(0xf0000|fpclkdiv, FTSSP010_CONTROL1(cardno)); /* 16bits */
- + //outl(0xf0000|0x10, FTSSP010_CONTROL1(cardno)); /* 16bits */
- + //outl(0xf0000|0x22, FTSSP010_CONTROL1(cardno)); /* 16bits */
- + } else {
- + outl(0x70000|fpclkdiv, FTSSP010_CONTROL1(cardno)); /* 8bits */
- + }
- +
- + //printk("#####$$$$$ : bps = %d\n", bps);
- + //printk("#####$$$$$ : speed = %d\n", speed);
- + //printk("#####$$$$$ : fpclkdiv = 0x%08x\n", fpclkdiv);
- + //printk("#####$$$$$ : FTSSP010_CONTROL1(cardno) = 0x%08x\n", inl(FTSSP010_CONTROL1(cardno)));
- +
- + if(is_rec)
- + outl(inl(FTSSP010_INT_CONTROL(cardno))&(~0x0f15), FTSSP010_INT_CONTROL(cardno)); /* Disable all interrupts */
- + else
- + outl(inl(FTSSP010_INT_CONTROL(cardno))&(~0xf02a) , FTSSP010_INT_CONTROL(cardno)); /* Disable all interrupts */
- +
- + outl(0xc, FTSSP010_CONTROL2(cardno)); /* clear FIFOs */
- +
- + //ADD by river 2011.06.02
- + alc5630 = i2c_get_clientdata(g_i2c_client);
- + //End
- +
- + if(is_rec) {
- + printk("ftssp010_config() for I2S mode in record.\n");
- + //ADD by river 2011.03.21
- + //TEST by river 2011.03.22 for recording => workable
- + //i2s_alc5630_write(0x0e, 0x8888, g_i2c_client);
- + i2s_alc5630_write(0x0e, 0x0808, g_i2c_client);
- + i2s_alc5630_write(0x10, 0xee03, g_i2c_client);
- + i2s_alc5630_write(0x22, 0x0500, g_i2c_client);
- + i2s_alc5630_write(0x1c, 0x0748, g_i2c_client);
- + i2s_alc5630_write(0x14, 0x1f1f, g_i2c_client);
- + i2s_alc5630_write(0x12, 0xdfdf, g_i2c_client);
- +
- + i2s_alc5630_write(0x26, 0x000f, g_i2c_client);
- + i2s_alc5630_write(0x3a, 0xffff, g_i2c_client);
- + i2s_alc5630_write(0x3c, 0xffff, g_i2c_client);
- + //i2s_alc5630_write(0x3e, 0xffff, g_i2c_client);
- + i2s_alc5630_write(0x3e, 0x80cf, g_i2c_client);
- +
- + i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client);
- + i2s_alc5630_write(0x42, 0x2000, g_i2c_client);
- + i2s_alc5630_write(0x40, 0x8c0a, g_i2c_client);
- +
- + //i2s_alc5630_write(0x02, 0x0000, g_i2c_client);
- + i2s_alc5630_write(0x02, 0x8080, g_i2c_client);
- + i2s_alc5630_write(0x04, 0x0000, g_i2c_client);
- + //End TEST by river 2011.03.22
- +
- + //printk("ftssp010_config() for I2S mode (Recording) ===> Dump register.\n");
- + //i2s_alc5630_read_test(g_i2c_client);
- +
- + }
- + else {
- + //printk("ftssp010_config() for I2S mode in playback.\n");
- + //ADD by river 2011.03.24 for record and playback case
- + i2s_alc5630_write(0x0e, 0x0808, g_i2c_client);
- + i2s_alc5630_write(0x12, 0xcbcb, g_i2c_client);
- + i2s_alc5630_write(0x14, 0x7f7f, g_i2c_client);
- + i2s_alc5630_write(0x22, 0x0000, g_i2c_client);
- + i2s_alc5630_write(0x3e, 0x8000, g_i2c_client);
- + i2s_alc5630_write(0x40, 0x0c0a, g_i2c_client);
- + i2s_alc5630_write(0x42, 0x0000, g_i2c_client);
- + //End ADD by river 2011.03.24 for record and playback case
- +
- + //TEST by river 2011.03.23
- + i2s_alc5630_write(0x26, 0x0000, g_i2c_client);
- + i2s_alc5630_write(0x3c, 0x2000, g_i2c_client);
- + i2s_alc5630_write(0x3a, 0x0002, g_i2c_client);
- + i2s_alc5630_write(0x3c, 0xa330, g_i2c_client);
- + i2s_alc5630_write(0x3a, 0xc843, g_i2c_client);
- + //End TEST by river 2011.03.23
- +
- + //ADD by river 2011.03.23 for HP Out De-pop
- + i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,g_i2c_client)|0x0002 , g_i2c_client);
- + i2s_alc5630_write(0x04, i2s_alc5630_read(0x04, data,g_i2c_client)|0x8080 , g_i2c_client);
- + i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,g_i2c_client)|0x0040 , g_i2c_client);
- + i2s_alc5630_write(0x3c, i2s_alc5630_read(0x3C, data,g_i2c_client)|0x2000 , g_i2c_client);
- + i2s_alc5630_write(0x3E, i2s_alc5630_read(0x3E, data,g_i2c_client)|0xfC00 , g_i2c_client);
- + i2s_alc5630_write(0x5E, i2s_alc5630_read(0x5E, data,g_i2c_client)|0x0100 , g_i2c_client);
- + mdelay(500);
- + i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,g_i2c_client)|0x0200 , g_i2c_client);
- + i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,g_i2c_client)|0x0100 , g_i2c_client);
- + i2s_alc5630_write(0x5E, i2s_alc5630_read(0x5E, data,g_i2c_client)& 0xfeff ,g_i2c_client);
- + //End ADD by river 2011.03.23 for HP Out De-pop
- +
- +
- + //TEST by river 2011.03.22
- + i2s_alc5630_write(0x1c, 0x0748, g_i2c_client);
- + //End TEST by river 2011.03.22
- +
- +
- + //TEST by river 2011.03.16
- + //i2s_alc5630_write(0x02, 0x8080, g_i2c_client);
- + i2s_alc5630_write(0x26, 0x000f, g_i2c_client);
- + //End TEST by river 2011.03.16
- +
- + //ADD by river 2011.03.23
- + if (alc5630->gpio2_value==0x0)
- + i2s_alc5630_write(0x3A, (i2s_alc5630_read(0x3A, data,g_i2c_client) & 0xFBFF)|0x0040 , g_i2c_client);
- + else
- + i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,g_i2c_client)|0x0440 , g_i2c_client);
- +
- +
- + i2s_alc5630_write(0x5E, i2s_alc5630_read(0x5E, data,g_i2c_client)|0x0020 , g_i2c_client);
- + i2s_alc5630_write(0x5E, i2s_alc5630_read(0x5E, data,g_i2c_client)|0x00c0 , g_i2c_client);
- + i2s_alc5630_write(0x04, i2s_alc5630_read(0x04, data,g_i2c_client)& 0x7f7f , g_i2c_client);
- + mdelay(30);
- +
- + if (alc5630->gpio2_value==0x0) {
- + //printk(">>>>>>>>>>>> Turn off internal speaker.....\n");
- + i2s_alc5630_write(0x02, 0x5F5F, g_i2c_client);
- + //i2s_alc5630_write(0x02, 0x0000, g_i2c_client);
- + }
- + else {
- + //printk(">>>>>>>>>>>> Turn on internal speaker.....\n");
- + i2s_alc5630_write(0x02, 0x0000, g_i2c_client);
- + //i2s_alc5630_write(0x02, 0x5F5F, g_i2c_client);
- + }
- + //End ADD by river 2011.03.23
- +
- +
- + //printk("ftssp010_config() for I2S mode (Playback) ===> Dump register.\n");
- + //i2s_alc5630_read_test(g_i2c_client);
- + }
- +
- +#if 0
- + /* Stuff TX fifo */
- + while(ftssp010_tx_fifo_not_full(cardno)) {
- + outl(0x0, FTSSP010_DATA(cardno));
- + }
- +#endif
- +}
- +
- +void ftssp010_config_tx(int cardno, unsigned is_stereo, unsigned speed, int width)
- +{
- + return ftssp010_config(cardno, is_stereo, speed, width, 0);
- +}
- +
- +void ftssp010_config_rx(int cardno, unsigned is_stereo, unsigned speed, int width)
- +{
- + return ftssp010_config(cardno, is_stereo, speed, width, 1);
- +}
- +
- +/* Configures FTSSP010 to start TX. If use_dma being nonzero,
- + * FTSSP010 will use hardware handshake for DMA */
- +void ftssp010_start_tx(int cardno, unsigned use_dma)
- +{
- + unsigned bogus=0x800*3;
- + if(use_dma) {
- + /* Enable H/W DMA Request and set TX DMA threshold to 12*/
- +// outl(0xC022, FTSSP010_INT_CONTROL(cardno));
- + outl(inl(FTSSP010_INT_CONTROL(cardno)) | 0xc422, FTSSP010_INT_CONTROL(cardno));
- +#if 0
- + printk("%s: enable DMA request\n", __func__);
- +#endif
- + }
- +// outl(0x3, FTSSP010_CONTROL2(cardno));
- + outl(inl(FTSSP010_CONTROL2(cardno)) | 0x3, FTSSP010_CONTROL2(cardno));
- +// printk("%s\n",__func__);
- +// printk("int_control 0x%x\n",inl(FTSSP010_INT_CONTROL(cardno)));
- +// printk("control2 0x%x\n",inl(FTSSP010_CONTROL2(cardno)));
- + if(!use_dma) {
- + while(bogus>0) {
- + while(!ftssp010_tx_fifo_not_full(cardno))
- + udelay(50);
- + outl(0, FTSSP010_DATA(cardno));
- + bogus--;
- + }
- + }
- +}
- +
- +/* Configures FTSSP010 to start RX. If use_dma being nonzero,
- + * FTSSP010 will use hardware handshake for DMA */
- +void ftssp010_start_rx(int cardno, unsigned use_dma)
- +{
- + if(use_dma) {
- + /* Enable H/W DMA Request and set RX DMA threshold to 2*/
- +// outl(0x0111, FTSSP010_INT_CONTROL(cardno));
- + outl(inl(FTSSP010_INT_CONTROL(cardno)) | 0xc411, FTSSP010_INT_CONTROL(cardno));
- +#if 0
- + printk("%s: enable DMA request\n", __func__);
- +#endif
- + }
- +// outl(0x3, FTSSP010_CONTROL2(cardno));
- + outl(inl(FTSSP010_CONTROL2(cardno)) | 0x3, FTSSP010_CONTROL2(cardno));
- +// printk("%s\n",__func__);
- +// printk("int_control 0x%x\n",inl(FTSSP010_INT_CONTROL(cardno)));
- +// printk("control2 0x%x\n",inl(FTSSP010_CONTROL2(cardno)));
- +}
- +
- +void ftssp010_stop_tx(int cardno)
- +{
- +// outl(0, FTSSP010_CONTROL2(cardno));
- + outl(inl(FTSSP010_INT_CONTROL(cardno)) & (~0x22), FTSSP010_INT_CONTROL(cardno));
- +// printk("%s\n",__func__);
- +// printk("int_control 0x%x\n",inl(FTSSP010_INT_CONTROL(cardno)));
- +// printk("control2 0x%x\n",inl(FTSSP010_CONTROL2(cardno)));
- +}
- +
- +void ftssp010_stop_rx(int cardno)
- +{
- + //outl(0, FTSSP010_CONTROL2(cardno));
- + outl(inl(FTSSP010_INT_CONTROL(cardno)) & (~0x11), FTSSP010_INT_CONTROL(cardno));
- + //printk("%s\n",__func__);
- + //printk("int_control 0x%x\n",inl(FTSSP010_INT_CONTROL(cardno)));
- + //printk("control2 0x%x\n",inl(FTSSP010_CONTROL2(cardno)));
- +}
- +
- diff -Nur linux-3.4.110.orig/sound/nds32/FTSSP010_UDA1345TS.h linux-3.4.110/sound/nds32/FTSSP010_UDA1345TS.h
- --- linux-3.4.110.orig/sound/nds32/FTSSP010_UDA1345TS.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/sound/nds32/FTSSP010_UDA1345TS.h 2016-04-07 10:20:51.066085821 +0200
- @@ -0,0 +1,81 @@
- +/* FTSSP010 - UDA1345TS supporting library header */
- +/*
- + *
- + * $log$
- + *
- + */
- +#include <linux/init.h>
- +#include <linux/module.h>
- +#include <asm/io.h>
- +#include <linux/delay.h>
- +#include <asm/spec.h>
- +#include <linux/dma-mapping.h>
- +
- +/* Programming sequence:
- + * Suppose your playback format is 44.1KHz, 16 bit stereo
- + * PIO mode:
- + * pmu_set_i2s_clocking(44100);
- + * ftssp010_config(1, 44100, 0);
- + * ftssp010_start_tx(0);
- + * while(ftssp010_tx_fifo_not_full()) {
- + * Poke_your_PCM_data_to_FTSSP_data_port
- + *
- + * DMA mode:
- + * pmu_set_i2s_clocking(44100);
- + * ftssp010_config(1, 44100);
- + * <setup DMA controller, acquire DMA channel>
- + * pmu_set_i2s_dma_channel(ch);
- + * ftssp010_start_tx(1);
- + * <wait DMA to complete..>
- + * ftssp010_stop_tx();
- + */
- +#define FTSSP010_DATA(x) (SSP_FTSSP010_va_base[(x)]+0x18)
- +#define FTSSP010_DATA_PA(x) (SSP_FTSSP010_pa_base[(x)]+0x18)
- +
- +/* Initialize FTSSP010 to output to UDA1345TS via I2S */
- +#define FTSSP010_CONTROL0(x) (SSP_FTSSP010_va_base[(x)]+0x0)
- +#define FTSSP010_CONTROL0_OPM_STEREO 0xC
- +#define FTSSP010_CONTROL0_OPM_MONO 0x8
- +
- +#define FTSSP010_CONTROL1(x) (SSP_FTSSP010_va_base[(x)]+0x4)
- +#define FTSSP010_CONTROL2(x) (SSP_FTSSP010_va_base[(x)]+0x8)
- +
- +#define FTSSP010_INT_CONTROL(x) (SSP_FTSSP010_va_base[(x)]+0x10)
- +#define FTSSP010_STATUS(x) (SSP_FTSSP010_va_base[(x)]+0xC)
- +#define FTSSP010_INT_STATUS(x) (SSP_FTSSP010_va_base[(x)]+0x14)
- +#define FTSSP010_DATA(x) (SSP_FTSSP010_va_base[(x)]+0x18)
- +#define FTSSP010_INFO(x) (SSP_FTSSP010_va_base[(x)]+0x1C)
- +
- +static const unsigned int SSP_FTSSP010_va_base[SSP_FTSSP010_IRQ_COUNT] = { SSP_FTSSP010_VA_BASE };
- +static const unsigned int SSP_FTSSP010_pa_base[SSP_FTSSP010_IRQ_COUNT] = { SSP_FTSSP010_PA_BASE };
- +
- +/* Drive PMU to generate I2S main clocking signal. Also configures PMU to set correct DMA REQ/ACK pair */
- +extern void pmu_set_i2s_clocking(unsigned int speed);
- +/* Programs PMU to set I2S/AC97 DMA Channel, ch=0-7 */
- +extern void pmu_set_i2s_dma_channel(unsigned ch);
- +
- +/* Drive PMU to generate AC97 main clocking signal. Also configures PMU to set correct DMA REQ/ACK pair */
- +extern void pmu_set_ac97_clocking(unsigned int speed);
- +
- +/* Returns FTSSP010 status */
- +extern void ftssp010_set_int_control(int cardno, unsigned val);
- +extern int ftssp010_get_status(int cardno);
- +extern unsigned ftssp010_get_int_status(int cardno);
- +/* Polls FIFO full register */
- +extern int ftssp010_tx_fifo_not_full(int cardno);
- +/* Configure FTSSP010 to a given sampling rate and channel number */
- +extern void ftssp010_config_tx(int cardno, unsigned is_stereo, unsigned speed, int use8bit);
- +extern void ftssp010_config_rx(int cardno, unsigned is_stereo, unsigned speed, int use8bit);
- +
- +/* Configure FTSSP010 to a given sampling rate and channel number */
- +extern void ftssp010_config_ac97_play(int cardno, unsigned is_stereo, unsigned speed, int use8bit);
- +
- +extern void ftssp010_config_ac97_rec(int cardno, unsigned is_stereo, unsigned speed, int use8bit);
- +
- +/* Initialize FTSSP010 to output to UDA1345TS via I2S */
- +extern void ftssp010_start_tx(int cardno, unsigned use_dma);
- +extern void ftssp010_start_rx(int cardno, unsigned use_dma);
- +extern void ftssp010_stop_tx(int cardno);
- +extern void ftssp010_stop_rx(int cardno);
- +
- +
- diff -Nur linux-3.4.110.orig/sound/nds32/FTSSP010_W83972D.h linux-3.4.110/sound/nds32/FTSSP010_W83972D.h
- --- linux-3.4.110.orig/sound/nds32/FTSSP010_W83972D.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/sound/nds32/FTSSP010_W83972D.h 2016-04-07 10:20:51.066085821 +0200
- @@ -0,0 +1,17 @@
- +/* AC97 Codec related */
- +
- +
- +/* Register Index for Winbond W83972D AC97 Codec */
- +#define W83972D_RESET 0x0
- +#define W83972D_STEREO_OUTPUT_CONTROL 0x2
- +#define W83972D_MIC_VOLUME 0xE
- +#define W83972D_LINE_IN_VOLUME 0x10
- +#define W83972D_AUX_INPUT_CONTROL 0x16
- +#define W83972D_PCM_OUTPUT_CONTROL 0x18
- +#define W83972D_RECORD_SELECT 0x1A
- +#define W83972D_RECORD_GAIN 0x1C
- +#define W83972D_RECORD_GAIN_MIC 0x1E
- +#define W83972D_EXT_AUDIO_CONTROL 0x2A
- +#define W83972D_DAC_SAMPLE_RATE_CONTROL 0x2C
- +#define W83972D_VER1 0x7C
- +#define W83972D_VER2 0x7E
- diff -Nur linux-3.4.110.orig/sound/nds32/hda.h linux-3.4.110/sound/nds32/hda.h
- --- linux-3.4.110.orig/sound/nds32/hda.h 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/sound/nds32/hda.h 2016-04-07 10:20:51.066085821 +0200
- @@ -0,0 +1,106 @@
- +// HDA Mode definition
- + #define HDA_MODE 0x80000000
- +
- + // HDA CTRL definition
- + #define HDA_CRST_SET 0x00
- + #define HDA_CRST_CLR 0x20
- + #define HDA_CRST_MASK 0x20
- + #define HDA_RST_FCNT_OFS 8
- +
- + // HDA LNKST definition
- + #define HDA_COD_ALIVE 0x20000000
- +
- + // HDA INTC definition
- + #define HDA_INTC_USOLEN 0x40000
- + #define HDA_INTC_SDIWEN 0x20000
- + #define HDA_INTC_CRINTE 0x10000
- +
- + // HDA INTST definition
- + #define HDA_INTST_USOLEN 0x80
- + #define HDA_INTST_SDIWEN 0x40
- + #define HDA_INTST_CRINTE 0x20
- +
- + // HDA ICMDST mask & offset
- + #define HDA_IRRADD_MASK 0xf0
- + #define HDA_IRRUNSOL_MASK 0x08
- + #define HDA_IRV_MASK 0x02
- + #define HDA_ICB_MASK 0x01
- + #define HDA_IRRADD_OFFSET 4
- + #define HDA_IRRUNSOL_OFFSET 3
- + #define HDA_IRV_OFFSET 1
- + #define HDA_ICB_OFFSET 0
- + //HDA OSDC/ISDC bit offset
- + #define HDA_SDC_STNUM_OFFSET 28
- + #define HDA_SDC_SRUN_OFFSET 15
- + #define HDA_SDC_BASE_OFFSET 14
- + #define HDA_SDC_MULT_OFFSET 11
- + #define HDA_SDC_DIV_OFFSET 8
- + #define HDA_SDC_BITS_OFFSET 4
- + #define HDA_SDC_CHAN_OFFSET 0
- +
- + // HDA Codec CMD
- + #define HDA_COD_DEVADDR 0x00000000
- + #define HDA_ROOT_NODE 0x00000000
- + #define HDA_AUDIO_NODE 0x00100000
- + #define HDA_OUTCOV_NODE 0x00200000
- + //#define HDA_INCOV_NODE 0x0FF00000
- + #define HDA_INCOV_NODE 0x00800000 //kane, for real CODEC node mapping
- + #define HDA_CMD_FGRST 0x0007FF00
- + #define HDA_CMD_GETVID 0x000F0000
- + #define HDA_CMD_SUBNCNT 0x000F0004
- + #define HDA_CMD_FGTYPE 0x000F0005
- + #define HDA_CMD_AUDIOWCAP 0x000F0009
- + #define HDA_CMD_SETCVTSTR 0x00070600
- + #define HDA_CMD_GETCVTSTR 0x000F0600
- + #define HDA_CMD_SETCVTFMT 0x00020000
- + #define HDA_CMD_GETCVTFMT 0x000A0000
- + #define HDA_CMD_SETPROCST 0x00070300
- + #define HDA_CMD_TRIGUNSOL 0x00070400
- + //HDA Codec Resp
- + #define HDA_RESP_ZERO_VAL 0x00000000
- + #define HDA_RESP_EXP_VID 0x10ec0888
- + #define HDA_RSP_NODNUM_MSK 0xff0000
- + #define HDA_RSP_NODCNT_MSK 0x0000ff
- + #define HDA_RSP_NODNUM_OFS 16
- + #define HDA_RSP_NODCNT_OFS 0
- + #define HDA_RSP_FGNTYPE_MSK 0xff
- + #define HDA_RSP_FGNUSCAP_MSK 0x100
- + #define HDA_RSP_FGNTYPE_OFS 0
- + #define HDA_RSP_FGNUSCAP_OFS 8
- + #define HDA_RSP_AWCTYPE_MSK 0xf00000
- + #define HDA_RSP_AWCUSCAP_MSK 0x000080
- + #define HDA_RSP_AWCSTE_MSK 0x000001
- + #define HDA_RSP_AWCTYPE_OFS 20
- + #define HDA_RSP_AWCUSCAP_OFS 7
- + #define HDA_RSP_AWCSTE_OFS 0
- + #define HDA_RSP_CVTCHA_MSK 0x00
- + #define HDA_RSP_CVTSTR_MSK 0xf0
- + #define HDA_RSP_FMTTYPE_MSK 0x8000
- + #define HDA_RSP_FMTBASE_MSK 0x4000
- + #define HDA_RSP_FMTMULT_MSK 0x3800
- + #define HDA_RSP_FMTDIV_MSK 0x0700
- + #define HDA_RSP_FMTBITS_MSK 0x0070
- + #define HDA_RSP_FMTCHNUM_MSK 0x000f
- + //HDA Func Group definition
- + #define HDA_FG_AUDIO 0x1
- + // HDA Audio Widiget definition
- + #define HDA_AWC_INPUT 0x1
- + #define HDA_AWC_OUTPUT 0x0
- + #define HDA_AWC_MONO 0x0
- + #define HDA_AWC_STEREO 0x1
- + // HDA Converter Format definition
- + #define HDA_FMT_TYPE_OFS 15
- + #define HDA_FMT_BASE_OFS 14
- + #define HDA_FMT_MULT_OFS 11
- + #define HDA_FMT_DIV_OFS 8
- + #define HDA_FMT_BITS_OFS 4
- + #define HDA_FMT_CHNUM_OFS 0
- + // HDA Coverter Stream definition
- + #define HDA_STR_STR_OFS 4
- + #define HDA_STR_CHA_OFS 0
- + // HDA IOSDC definition
- + #define HDA_IN_STR 0
- + #define HDA_OUT_STR 1
- + #define HDA_STR_STOP 0
- + #define HDA_STR_RUN 1
- +
- diff -Nur linux-3.4.110.orig/sound/nds32/Kconfig linux-3.4.110/sound/nds32/Kconfig
- --- linux-3.4.110.orig/sound/nds32/Kconfig 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/sound/nds32/Kconfig 2016-04-07 10:20:51.066085821 +0200
- @@ -0,0 +1,22 @@
- +menu "ALSA NDS32 devices"
- + depends on SND!=n && NDS32
- +
- +config SND_FTSSP010
- + tristate "Faraday FTSSP010 audio Driver"
- + depends on SND && NDS32
- + select SND_PCM
- +# select SND_AC97_CODEC
- +
- +choice
- + prompt "AC97/I2S/HDA selection"
- + depends on SND_FTSSP010
- + default SND_FTSSP010_AC97
- +config SND_FTSSP010_AC97
- + bool "AC97"
- +config SND_FTSSP010_I2S
- + bool "I2S"
- +config SND_FTSSP010_HDA
- + bool "HDA"
- +endchoice
- +endmenu
- +
- diff -Nur linux-3.4.110.orig/sound/nds32/Makefile linux-3.4.110/sound/nds32/Makefile
- --- linux-3.4.110.orig/sound/nds32/Makefile 1970-01-01 01:00:00.000000000 +0100
- +++ linux-3.4.110/sound/nds32/Makefile 2016-04-07 10:20:51.066085821 +0200
- @@ -0,0 +1,10 @@
- +ifeq ($(CONFIG_SND_FTSSP010_AC97),y)
- +snd-ftssp010-objs := FTSSP010_ALSA.o FTSSP010_lib.o
- +endif
- +ifeq ($(CONFIG_SND_FTSSP010_I2S),y)
- +snd-ftssp010-objs := FTSSP010_ALSA.o FTSSP010_lib.o
- +endif
- +ifeq ($(CONFIG_SND_FTSSP010_HDA),y)
- +snd-ftssp010-objs := FTSSP010_HDA.o FTSSP010_HDA_lib.o
- +endif
- +obj-$(CONFIG_SND_FTSSP010) += snd-ftssp010.o
|