| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484 |
- From 70b2bd01829b38a1a79caeda05d436b2e5fecf82 Mon Sep 17 00:00:00 2001
- From: Kurt Mahan <[email protected]>
- Date: Wed, 31 Oct 2007 17:00:18 -0600
- Subject: [PATCH] Core Coldfire/MCF5445x specific code.
- LTIBName: mcfv4e-coldfire-code
- Signed-off-by: Kurt Mahan <[email protected]>
- ---
- arch/m68k/coldfire/Makefile | 11 +
- arch/m68k/coldfire/cache.c | 215 +++++++++
- arch/m68k/coldfire/config.c | 420 ++++++++++++++++++
- arch/m68k/coldfire/entry.S | 701 ++++++++++++++++++++++++++++++
- arch/m68k/coldfire/head.S | 474 ++++++++++++++++++++
- arch/m68k/coldfire/ints.c | 384 ++++++++++++++++
- arch/m68k/coldfire/iomap.c | 54 +++
- arch/m68k/coldfire/mcf5445x-pci.c | 427 ++++++++++++++++++
- arch/m68k/coldfire/muldi3.S | 64 +++
- arch/m68k/coldfire/pci.c | 245 +++++++++++
- arch/m68k/coldfire/signal.c | 868 +++++++++++++++++++++++++++++++++++++
- arch/m68k/coldfire/traps.c | 454 +++++++++++++++++++
- arch/m68k/coldfire/vmlinux-cf.lds | 92 ++++
- 13 files changed, 4409 insertions(+), 0 deletions(-)
- create mode 100644 arch/m68k/coldfire/Makefile
- create mode 100644 arch/m68k/coldfire/cache.c
- create mode 100644 arch/m68k/coldfire/config.c
- create mode 100644 arch/m68k/coldfire/entry.S
- create mode 100644 arch/m68k/coldfire/head.S
- create mode 100644 arch/m68k/coldfire/ints.c
- create mode 100644 arch/m68k/coldfire/iomap.c
- create mode 100644 arch/m68k/coldfire/mcf5445x-pci.c
- create mode 100644 arch/m68k/coldfire/muldi3.S
- create mode 100644 arch/m68k/coldfire/pci.c
- create mode 100644 arch/m68k/coldfire/signal.c
- create mode 100644 arch/m68k/coldfire/traps.c
- create mode 100644 arch/m68k/coldfire/vmlinux-cf.lds
- --- /dev/null
- +++ b/arch/m68k/coldfire/Makefile
- @@ -0,0 +1,11 @@
- +#
- +# Makefile for Linux arch/m68k/coldfire source directory
- +#
- +
- +obj-y:= entry.o config.o cache.o signal.o muldi3.o traps.o ints.o
- +
- +ifneq ($(strip $(CONFIG_USB) $(CONFIG_USB_GADGET_MCF5445X)),)
- + obj-y += usb.o usb/
- +endif
- +
- +obj-$(CONFIG_PCI) += pci.o mcf5445x-pci.o iomap.o
- --- /dev/null
- +++ b/arch/m68k/coldfire/cache.c
- @@ -0,0 +1,215 @@
- +/*
- + * linux/arch/m68k/coldifre/cache.c
- + *
- + * Matt Waddel [email protected]
- + * Copyright Freescale Semiconductor, Inc. 2007
- + *
- + * 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/interrupt.h>
- +#include <asm/cfcache.h>
- +#include <asm/coldfire.h>
- +#include <asm/system.h>
- +
- +#define _DCACHE_SIZE (2*16384)
- +#define _ICACHE_SIZE (2*16384)
- +
- +#define _SET_SHIFT 4
- +
- +/*
- + * Masks for cache sizes. Programming note: because the set size is a
- + * power of two, the mask is also the last address in the set.
- + */
- +
- +#define _DCACHE_SET_MASK ((_DCACHE_SIZE/64-1)<<_SET_SHIFT)
- +#define _ICACHE_SET_MASK ((_ICACHE_SIZE/64-1)<<_SET_SHIFT)
- +#define LAST_DCACHE_ADDR _DCACHE_SET_MASK
- +#define LAST_ICACHE_ADDR _ICACHE_SET_MASK
- +
- +/************************************************************
- + * Routine to cleanly flush the cache, pushing all lines and
- + * invalidating them.
- + *
- + * The is the flash-resident version, used after copying the .text
- + * segment from flash to ram.
- + *************************************************************/
- +void FLASHDcacheFlushInvalidate(void)
- + __attribute__ ((section (".text_loader")));
- +
- +void FLASHDcacheFlushInvalidate()
- +{
- + unsigned long set;
- + unsigned long start_set;
- + unsigned long end_set;
- +
- + start_set = 0;
- + end_set = (unsigned long)LAST_DCACHE_ADDR;
- +
- + for (set = start_set; set < end_set; set += (0x10 - 3))
- + asm volatile("cpushl %%dc,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%dc,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%dc,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%dc,(%0)" : : "a" (set));
- +}
- +
- +/************************************************************
- + * Routine to cleanly flush the cache, pushing all lines and
- + * invalidating them.
- + *
- + *************************************************************/
- +void DcacheFlushInvalidate()
- +{
- + unsigned long set;
- + unsigned long start_set;
- + unsigned long end_set;
- +
- + start_set = 0;
- + end_set = (unsigned long)LAST_DCACHE_ADDR;
- +
- + for (set = start_set; set < end_set; set += (0x10 - 3))
- + asm volatile("cpushl %%dc,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%dc,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%dc,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%dc,(%0)" : : "a" (set));
- +}
- +
- +
- +
- +/******************************************************************************
- + * Routine to cleanly flush the a block of cache, pushing all relevant lines
- + * and invalidating them.
- + *
- + ******************************************************************************/
- +void DcacheFlushInvalidateCacheBlock(void *start, unsigned long size)
- +{
- + unsigned long set;
- + unsigned long start_set;
- + unsigned long end_set;
- +
- + /* if size is bigger than the cache can store
- + * set the size to the maximum amount
- + */
- +
- + if (size > LAST_DCACHE_ADDR)
- + size = LAST_DCACHE_ADDR;
- +
- + start_set = ((unsigned long)start) & _DCACHE_SET_MASK;
- + end_set = ((unsigned long)(start+size-1)) & _DCACHE_SET_MASK;
- +
- + if (start_set > end_set) {
- + /* from the begining to the lowest address */
- + for (set = 0; set <= end_set; set += (0x10 - 3))
- + asm volatile("cpushl %%dc,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%dc,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%dc,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%dc,(%0)" : : "a" (set));
- +
- + /* next loop will finish the cache ie pass the hole */
- + end_set = LAST_DCACHE_ADDR;
- + }
- + for (set = start_set; set <= end_set; set += (0x10 - 3))
- + asm volatile("cpushl %%dc,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%dc,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%dc,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%dc,(%0)" : : "a" (set));
- +}
- +
- +
- +void IcacheInvalidateCacheBlock(void *start, unsigned long size)
- +{
- + unsigned long set;
- + unsigned long start_set;
- + unsigned long end_set;
- +
- + /* if size is bigger than the cache can store
- + * set the size to the maximum ammount
- + */
- +
- + if (size > LAST_ICACHE_ADDR)
- + size = LAST_ICACHE_ADDR;
- +
- + start_set = ((unsigned long)start) & _ICACHE_SET_MASK;
- + end_set = ((unsigned long)(start+size-1)) & _ICACHE_SET_MASK;
- +
- + if (start_set > end_set) {
- + /* from the begining to the lowest address */
- + for (set = 0; set <= end_set; set += (0x10 - 3))
- + asm volatile("cpushl %%ic,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%ic,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%ic,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%ic,(%0)" : : "a" (set));
- +
- + /* next loop will finish the cache ie pass the hole */
- + end_set = LAST_ICACHE_ADDR;
- + }
- + for (set = start_set; set <= end_set; set += (0x10 - 3))
- + asm volatile("cpushl %%ic,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%ic,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%ic,(%0)\n"
- + "\taddq%.l #1,%0\n"
- + "\tcpushl %%ic,(%0)" : : "a" (set));
- +}
- +
- +
- +/********************************************************************
- + * Disable the data cache completely
- + ********************************************************************/
- +void DcacheDisable(void)
- +{
- + int newValue;
- + unsigned long flags;
- +
- + local_save_flags(flags);
- + local_irq_disable();
- +
- + DcacheFlushInvalidate(); /* begin by flushing the cache */
- + newValue = CACHE_DISABLE_MODE; /* disable it */
- + cacr_set(newValue);
- + local_irq_restore(flags);
- +}
- +
- +/********************************************************************
- + * Unconditionally enable the data cache
- + ********************************************************************/
- +void DcacheEnable(void)
- +{
- + cacr_set(CACHE_INITIAL_MODE);
- +}
- +
- +
- +unsigned long shadow_cacr;
- +
- +void cacr_set(unsigned long x)
- +{
- + shadow_cacr = x;
- +
- + __asm__ __volatile__ ("movec %0, %%cacr"
- + : /* no outputs */
- + : "r" (shadow_cacr));
- +}
- +
- +unsigned long cacr_get(void)
- +{
- + return shadow_cacr;
- +}
- --- /dev/null
- +++ b/arch/m68k/coldfire/config.c
- @@ -0,0 +1,420 @@
- +/*
- + * linux/arch/m68k/coldifre/config.c
- + *
- + * Matt Waddel [email protected]
- + * Copyright Freescale Semiconductor, Inc. 2007
- + *
- + * 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/init.h>
- +#include <linux/string.h>
- +#include <linux/kernel.h>
- +#include <linux/console.h>
- +#include <linux/bootmem.h>
- +#include <linux/mm.h>
- +#include <asm/bootinfo.h>
- +#include <asm/machdep.h>
- +#include <asm/coldfire.h>
- +#include <asm/cfcache.h>
- +#include <asm/bootinfo.h>
- +#include <asm/io.h>
- +#include <asm/cfmmu.h>
- +#include <asm/setup.h>
- +#include <asm/irq.h>
- +#include <asm/traps.h>
- +#include <asm/movs.h>
- +#include <asm/movs.h>
- +#include <asm/page.h>
- +#include <asm/pgalloc.h>
- +#include <asm/mcf5445x_intc.h>
- +#include <asm/mcf5445x_sdramc.h>
- +#include <asm/mcf5445x_fbcs.h>
- +#include <asm/mcf5445x_dtim.h>
- +
- +/* JKM -- testing */
- +#include <linux/pfn.h>
- +/* JKM */
- +
- +extern int get_irq_list(struct seq_file *p, void *v);
- +extern char _text, _end;
- +extern char _etext, _edata, __init_begin, __init_end;
- +extern struct console mcfrs_console;
- +extern char m68k_command_line[CL_SIZE];
- +extern unsigned long availmem;
- +
- +static int irq_enable[NR_IRQS];
- +unsigned long num_pages;
- +
- +void coldfire_sort_memrec(void)
- +{
- + int i, j;
- +
- + /* Sort the m68k_memory records by address */
- + for (i = 0; i < m68k_num_memory; ++i) {
- + for (j = i + 1; j < m68k_num_memory; ++j) {
- + if (m68k_memory[i].addr > m68k_memory[j].addr) {
- + struct mem_info tmp;
- + tmp = m68k_memory[i];
- + m68k_memory[i] = m68k_memory[j];
- + m68k_memory[j] = tmp;
- + }
- + }
- + }
- + /* Trim off discontiguous bits */
- + for (i = 1; i < m68k_num_memory; ++i) {
- + if ((m68k_memory[i-1].addr + m68k_memory[i-1].size) !=
- + m68k_memory[i].addr) {
- + printk(KERN_DEBUG "m68k_parse_bootinfo: addr gap between \
- + 0x%lx & 0x%lx\n",
- + m68k_memory[i-1].addr+m68k_memory[i-1].size,
- + m68k_memory[i].addr);
- + m68k_num_memory = i;
- + break;
- + }
- + }
- +}
- +
- +int __init uboot_commandline(char *bootargs)
- +{
- + int len = 0, cmd_line_len;
- + static struct uboot_record uboot_info;
- +
- + extern unsigned long uboot_info_stk;
- +
- + /* Add 0x80000000 to get post-remapped kernel memory location */
- + uboot_info.bd_info = (*(u32 *)(uboot_info_stk)) + 0x80000000;
- + uboot_info.initrd_start = (*(u32 *)(uboot_info_stk+4)) + 0x80000000;
- + uboot_info.initrd_end = (*(u32 *)(uboot_info_stk+8)) + 0x80000000;
- + uboot_info.cmd_line_start = (*(u32 *)(uboot_info_stk+12)) + 0x80000000;
- + uboot_info.cmd_line_stop = (*(u32 *)(uboot_info_stk+16)) + 0x80000000;
- +
- + cmd_line_len = uboot_info.cmd_line_stop - uboot_info.cmd_line_start;
- + if ((cmd_line_len > 0) && (cmd_line_len < CL_SIZE-1))
- + len = (int)strncpy(bootargs, (char *)uboot_info.cmd_line_start,\
- + cmd_line_len);
- +
- + return len;
- +}
- +
- +/*
- + * This routine does things not done in the bootloader.
- + */
- +#define DEFAULT_COMMAND_LINE "root=/dev/mtdblock1 rw rootfstype=jffs2 ip=none mtdparts=physmap-flash.0:5M(kernel)ro,-(jffs2)"
- +asmlinkage void __init cf_early_init(void)
- +{
- + struct bi_record *record = (struct bi_record *) &_end;
- +
- + extern char _end;
- +
- + SET_VBR((void *)MCF_RAMBAR1);
- +
- + /* Mask all interrupts */
- + MCF_INTC0_IMRL = 0xFFFFFFFF;
- + MCF_INTC0_IMRH = 0xFFFFFFFF;
- + MCF_INTC1_IMRL = 0xFFFFFFFF;
- + MCF_INTC1_IMRH = 0xFFFFFFFF;
- +
- +#if defined(CONFIG_NOR_FLASH_BASE)
- + MCF_FBCS_CSAR(1) = CONFIG_NOR_FLASH_BASE;
- +#else
- + MCF_FBCS_CSAR(1) = 0x00000000;
- +#endif
- +
- +#if CONFIG_SDRAM_SIZE > (256*1024*1024)
- + /* Init optional SDRAM chip select */
- + MCF_SDRAMC_SDCS(1) = (256*1024*1024) | 0x1B;
- +#endif
- +
- + m68k_machtype = MACH_CFMMU;
- + m68k_fputype = FPU_CFV4E;
- + m68k_mmutype = MMU_CFV4E;
- + m68k_cputype = CPU_CFV4E;
- +
- + m68k_num_memory = 0;
- + m68k_memory[m68k_num_memory].addr = CONFIG_SDRAM_BASE;
- + m68k_memory[m68k_num_memory++].size = CONFIG_SDRAM_SIZE;
- +
- + if (!uboot_commandline(m68k_command_line)) {
- +#if defined(CONFIG_BOOTPARAM)
- + strncpy(m68k_command_line, CONFIG_BOOTPARAM_STRING, CL_SIZE-1);
- +#else
- + strcpy(m68k_command_line, DEFAULT_COMMAND_LINE);
- +#endif
- + }
- +
- +
- +#if defined(CONFIG_BLK_DEV_INITRD)
- + /* add initrd image */
- + record = (struct bi_record *) ((void *)record + record->size);
- + record->tag = BI_RAMDISK;
- + record->size = sizeof(record->tag) + sizeof(record->size)
- + + sizeof(record->data[0]) + sizeof(record->data[1]);
- +#endif
- +
- + /* Mark end of tags. */
- + record = (struct bi_record *) ((void *) record + record->size);
- + record->tag = 0;
- + record->data[0] = 0;
- + record->data[1] = 0;
- + record->size = sizeof(record->tag) + sizeof(record->size)
- + + sizeof(record->data[0]) + sizeof(record->data[1]);
- +
- + /* Invalidate caches via CACR */
- + cacr_set(CACHE_DISABLE_MODE);
- +
- + /* Turn on caches via CACR, enable EUSP */
- + cacr_set(CACHE_INITIAL_MODE);
- +}
- +
- +void settimericr(unsigned int timer, unsigned int level)
- +{
- + volatile unsigned char *icrp;
- + unsigned int icr;
- + unsigned char irq;
- +
- + if (timer <= 2) {
- + switch (timer) {
- + case 2: irq = 33; icr = MCFSIM_ICR_TIMER2; break;
- + default: irq = 32; icr = MCFSIM_ICR_TIMER1; break;
- + }
- +
- + icrp = (volatile unsigned char *) (icr);
- + *icrp = level;
- + coldfire_enable_irq0(irq);
- + }
- +}
- +
- +/* Assembler routines */
- +asmlinkage void buserr(void);
- +asmlinkage void trap(void);
- +asmlinkage void system_call(void);
- +asmlinkage void inthandler(void);
- +
- +void __init coldfire_trap_init(void)
- +{
- + int i = 0;
- + e_vector *vectors;
- +
- + vectors = (e_vector *)MCF_RAMBAR1;
- + /*
- + * There is a common trap handler and common interrupt
- + * handler that handle almost every vector. We treat
- + * the system call and bus error special, they get their
- + * own first level handlers.
- + */
- + for (i = 3; (i <= 23); i++)
- + vectors[i] = trap;
- + for (i = 33; (i <= 63); i++)
- + vectors[i] = trap;
- + for (i = 24; (i <= 31); i++)
- + vectors[i] = inthandler;
- + for (i = 64; (i < 255); i++)
- + vectors[i] = inthandler;
- +
- + vectors[255] = 0;
- + vectors[2] = buserr;
- + vectors[32] = system_call;
- +}
- +
- +void coldfire_tick(void)
- +{
- + /* Reset the ColdFire timer */
- + __raw_writeb(MCF_DTIM_DTER_CAP | MCF_DTIM_DTER_REF, MCF_DTIM0_DTER);
- +}
- +
- +void __init coldfire_sched_init(irq_handler_t handler)
- +{
- + unsigned int mcf_timerlevel = 5;
- + unsigned int mcf_timervector = 64+32;
- +
- + __raw_writew(MCF_DTIM_DTMR_RST_RST, MCF_DTIM0_DTMR);
- + __raw_writel(((MCF_BUSCLK / 16) / HZ), MCF_DTIM0_DTRR);
- + __raw_writew(MCF_DTIM_DTMR_ORRI | MCF_DTIM_DTMR_CLK_DIV16 |
- + MCF_DTIM_DTMR_FRR | MCF_DTIM_DTMR_RST_EN, \
- + MCF_DTIM0_DTMR);
- +
- + request_irq(mcf_timervector, handler, SA_INTERRUPT, \
- + "timer", (void *)MCF_DTIM0_DTMR);
- +
- + settimericr(1, mcf_timerlevel);
- +}
- +
- +int timerirqpending(int timer)
- +{
- + unsigned int imr = 0;
- +
- + switch (timer) {
- + case 1: imr = 0x1; break;
- + case 2: imr = 0x2; break;
- + default: break;
- + }
- +
- + return (getiprh() & imr);
- +}
- +
- +unsigned long coldfire_gettimeoffset(void)
- +{
- + volatile unsigned long trr, tcn, offset;
- +
- + tcn = __raw_readw(MCF_DTIM0_DTCN);
- + trr = __raw_readl(MCF_DTIM0_DTRR);
- + offset = (tcn * (1000000 / HZ)) / trr;
- +
- + /* Check if we just wrapped the counters and maybe missed a tick */
- + if ((offset < (1000000 / HZ / 2)) && timerirqpending(1))
- + offset += 1000000 / HZ;
- + return offset;
- +}
- +
- +void coldfire_reboot(void)
- +{
- + /* disable interrupts and do a software reset */
- + asm("movew #0x2700, %%sr\n\t"
- + "moveb #0x80, %%d0\n\t"
- + "moveb %%d0, 0xfc0a0000\n\t"
- + : : : "%d0");
- +}
- +
- +/* int coldfire_hwclk(int i, struct rtc_time *t)
- +{
- + printk ("Real time clock needs porting.\n");
- + return 0;
- +}*/
- +
- +static void coldfire_get_model(char *model)
- +{
- + sprintf(model, "Version 4 ColdFire");
- +}
- +
- +void coldfire_enable_irq(unsigned int vec)
- +{
- + unsigned long flags;
- +
- + vec -= 64;
- +
- + if (((int)vec < 0) || (vec > 63)) {
- + printk(KERN_WARNING "enable_irq %d failed\n", vec);
- + return;
- + }
- +
- + local_irq_save(flags);
- + irq_enable[vec]++;
- + if (vec < 32)
- + MCF_INTC0_IMRL &= ~(1 << vec);
- + else
- + MCF_INTC0_IMRH &= ~(1 << (vec - 32));
- + local_irq_restore(flags);
- +}
- +
- +void coldfire_disable_irq(unsigned int vec)
- +{
- + unsigned long flags;
- +
- + vec -= 64;
- +
- + if (((int)vec < 0) || (vec > 63)) {
- + printk(KERN_WARNING "disable_irq %d failed\n", vec);
- + return;
- + }
- +
- + local_irq_save(flags);
- + if (--irq_enable[vec] == 0) {
- + if (vec < 32)
- + MCF_INTC0_IMRL |= (1 << vec);
- + else
- + MCF_INTC0_IMRH |= (1 << (vec - 32));
- +
- + }
- + local_irq_restore(flags);
- +}
- +
- +static void __init
- +coldfire_bootmem_alloc(unsigned long memory_start, unsigned long memory_end)
- +{
- + unsigned long base_pfn;
- +
- + /* compute total pages in system */
- + num_pages = PAGE_ALIGN(memory_end - PAGE_OFFSET) >> PAGE_SHIFT;
- +
- + /* align start/end to page boundries */
- + memory_start = PAGE_ALIGN(memory_start);
- + memory_end = memory_end & PAGE_MASK;
- +
- + /* page numbers */
- + base_pfn = __pa(PAGE_OFFSET) >> PAGE_SHIFT;
- + min_low_pfn = __pa(memory_start) >> PAGE_SHIFT;
- + max_low_pfn = __pa(memory_end) >> PAGE_SHIFT;
- +
- + high_memory = (void *)memory_end;
- + availmem = memory_start;
- +
- + /* setup bootmem data */
- + m68k_setup_node(0);
- + availmem += init_bootmem_node(NODE_DATA(0), min_low_pfn,
- + base_pfn, max_low_pfn);
- + availmem = PAGE_ALIGN(availmem);
- + free_bootmem(__pa(availmem), memory_end - (availmem));
- +}
- +
- +void __init config_coldfire(void)
- +{
- + unsigned long endmem, startmem;
- + int i;
- +
- + /*
- + * Calculate endmem from m68k_memory, assume all are contiguous
- + */
- + startmem = ((((int) &_end) + (PAGE_SIZE - 1)) & PAGE_MASK);
- + endmem = PAGE_OFFSET;
- + for (i = 0; i < m68k_num_memory; ++i)
- + endmem += m68k_memory[i].size;
- +
- + printk(KERN_INFO "starting up linux startmem 0x%lx, endmem 0x%lx, \
- + size %luMB\n", startmem, endmem, (endmem - startmem) >> 20);
- +
- + memset(irq_enable, 0, sizeof(irq_enable));
- +
- + /*
- + * Setup coldfire mach-specific handlers
- + */
- + mach_max_dma_address = 0xffffffff;
- + mach_sched_init = coldfire_sched_init;
- + mach_tick = coldfire_tick;
- + mach_gettimeoffset = coldfire_gettimeoffset;
- + mach_reset = coldfire_reboot;
- +/* mach_hwclk = coldfire_hwclk; to be done */
- + mach_get_model = coldfire_get_model;
- +
- + coldfire_bootmem_alloc(startmem, endmem);
- +
- + /*
- + * initrd setup
- + */
- +/* #ifdef CONFIG_BLK_DEV_INITRD
- + if (m68k_ramdisk.size) {
- + reserve_bootmem (__pa(m68k_ramdisk.addr), m68k_ramdisk.size);
- + initrd_start = (unsigned long) m68k_ramdisk.addr;
- + initrd_end = initrd_start + m68k_ramdisk.size;
- + printk (KERN_DEBUG "initrd: %08lx - %08lx\n", initrd_start,
- + initrd_end);
- + }
- +#endif */
- +
- +#if defined(CONFIG_DUMMY_CONSOLE) || defined(CONFIG_FRAMEBUFFER_CONSOLE)
- + conswitchp = &dummy_con;
- +#endif
- +
- +#if defined(CONFIG_SERIAL_COLDFIRE)
- + /*
- + * This causes trouble when it is re-registered later.
- + * Currently this is fixed by conditionally commenting
- + * out the register_console in mcf_serial.c
- + */
- + register_console(&mcfrs_console);
- +#endif
- +}
- --- /dev/null
- +++ b/arch/m68k/coldfire/entry.S
- @@ -0,0 +1,701 @@
- +/*
- + * arch/m68k/coldfire/entry.S
- + *
- + * Copyright (C) 1999-2002, Greg Ungerer ([email protected])
- + * Copyright (C) 1998 D. Jeff Dionne <[email protected]>,
- + * Kenneth Albanowski <[email protected]>,
- + * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
- + * Copyright (C) 2004-2006 Macq Electronique SA. (www.macqel.com)
- + * Matt Waddel [email protected]
- + * Kurt Mahan [email protected]
- + * Copyright Freescale Semiconductor, Inc. 2007
- + *
- + * Based on:
- + *
- + * arch/m68knommu/platform/5307/entry.S &
- + * arch/m68k/kernel/entry.S
- + *
- + * Copyright (C) 1991, 1992 Linus Torvalds
- + *
- + * This file is subject to the terms and conditions of the GNU General Public
- + * License. See the file README.legal in the main directory of this archive
- + * for more details.
- + *
- + * Linux/m68k support by Hamish Macdonald
- + *
- + * ColdFire support by Greg Ungerer ([email protected])
- + * 5307 fixes by David W. Miller
- + * linux 2.4 support David McCullough <[email protected]>
- + * Bug, speed and maintainability fixes by Philippe De Muyter <[email protected]>
- + * Ported to mmu Coldfire by Matt Waddel
- + */
- +
- +#include <linux/sys.h>
- +#include <linux/linkage.h>
- +#include <asm/cf_entry.h>
- +#include <asm/errno.h>
- +#include <asm/setup.h>
- +#include <asm/segment.h>
- +#include <asm/traps.h>
- +#include <asm/unistd.h>
- +
- +/*
- + * TASK_INFO:
- + *
- + * - TINFO_PREEMPT (struct thread_info / preempt_count)
- + * Used to keep track of preemptability
- + * - TINFO_FLAGS (struct thread_info / flags - include/asm-m68k/thread_info.h)
- + * Various bit flags that are checked for scheduling/tracing
- + * Bits 0-7 are checked every exception exit
- + * 8-15 are checked every syscall exit
- + *
- + * TIF_SIGPENDING 6
- + * TIF_NEED_RESCHED 7
- + * TIF_DELAYED_TRACE 14
- + * TIF_SYSCALL_TRACE 15
- + * TIF_MEMDIE 16 (never checked here)
- + */
- +
- +.bss
- +
- +sw_ksp:
- +.long 0
- +
- +sw_usp:
- +.long 0
- +
- +.text
- +
- +.globl system_call
- +.globl buserr
- +.globl trap
- +.globl resume
- +.globl ret_from_exception
- +.globl ret_from_signal
- +.globl sys_call_table
- +.globl ret_from_interrupt
- +.globl inthandler
- +
- +ENTRY(buserr)
- + SAVE_ALL_INT
- + GET_CURRENT(%d0)
- + movel %sp,%sp@- /* stack frame pointer argument */
- + jsr buserr_c
- + addql #4,%sp
- + jra .Lret_from_exception
- +
- +ENTRY(trap)
- + SAVE_ALL_INT
- + GET_CURRENT(%d0)
- + movel %sp,%sp@- /* stack frame pointer argument */
- + jsr trap_c
- + addql #4,%sp
- + jra .Lret_from_exception
- +
- + /* After a fork we jump here directly from resume,
- + %d1 contains the previous task schedule_tail */
- +ENTRY(ret_from_fork)
- + movel %d1,%sp@-
- + jsr schedule_tail
- + addql #4,%sp
- + jra .Lret_from_exception
- +
- +do_trace_entry:
- + movel #-ENOSYS,%d1 /* needed for strace */
- + movel %d1,%sp@(PT_D0)
- + subql #4,%sp
- + SAVE_SWITCH_STACK
- + jbsr syscall_trace
- + RESTORE_SWITCH_STACK
- + addql #4,%sp
- + movel %sp@(PT_ORIG_D0),%d0
- + cmpl #NR_syscalls,%d0
- + jcs syscall
- +badsys:
- + movel #-ENOSYS,%d1
- + movel %d1,%sp@(PT_D0)
- + jra ret_from_exception
- +
- +do_trace_exit:
- + subql #4,%sp
- + SAVE_SWITCH_STACK
- + jbsr syscall_trace
- + RESTORE_SWITCH_STACK
- + addql #4,%sp
- + jra .Lret_from_exception
- +
- +ENTRY(ret_from_signal)
- + RESTORE_SWITCH_STACK
- + addql #4,%sp
- + jra .Lret_from_exception
- +
- +ENTRY(system_call)
- + SAVE_ALL_SYS
- +
- + GET_CURRENT(%d1)
- + /* save top of frame */
- + movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
- +
- + /* syscall trace */
- + tstb %curptr@(TASK_INFO+TINFO_FLAGS+2)
- + jmi do_trace_entry /* SYSCALL_TRACE is set */
- + cmpl #NR_syscalls,%d0
- + jcc badsys
- +syscall:
- + movel #sys_call_table,%a0
- + asll #2,%d0
- + addl %d0,%a0
- + movel %a0@,%a0
- + jsr %a0@
- + movel %d0,%sp@(PT_D0) /* save the return value */
- +ret_from_syscall:
- + movew %curptr@(TASK_INFO+TINFO_FLAGS+2),%d0
- + jne syscall_exit_work /* flags set so process */
- +1: RESTORE_ALL
- +
- +syscall_exit_work:
- + btst #5,%sp@(PT_SR) /* check if returning to kernel */
- + bnes 1b /* if so, skip resched, signals */
- +
- + btstl #15,%d0 /* check if SYSCALL_TRACE */
- + jne do_trace_exit
- + btstl #14,%d0 /* check if DELAYED_TRACE */
- + jne do_delayed_trace
- + btstl #6,%d0 /* check if SIGPENDING */
- + jne do_signal_return
- + pea resume_userspace
- + jra schedule
- +
- +ENTRY(ret_from_exception)
- +.Lret_from_exception:
- + btst #5,%sp@(PT_SR) /* check if returning to kernel */
- + bnes 1f /* if so, skip resched, signals */
- + movel %d0,%sp@- /* Only allow interrupts when we are */
- + move %sr,%d0 /* last one on the kernel stack, */
- + andl #ALLOWINT,%d0 /* otherwise stack overflow can occur */
- + move %d0,%sr /* during heavy interrupt load. */
- + movel %sp@+,%d0
- +
- +resume_userspace:
- + moveb %curptr@(TASK_INFO+TINFO_FLAGS+3),%d0
- + jne exit_work /* SIGPENDING and/or NEED_RESCHED set */
- +1: RESTORE_ALL
- +
- +exit_work:
- + /* save top of frame */
- + movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
- + btstl #6,%d0 /* check for SIGPENDING in flags */
- + jne do_signal_return
- + pea resume_userspace
- + jra schedule
- +
- +do_signal_return:
- + subql #4,%sp /* dummy return address */
- + SAVE_SWITCH_STACK
- + pea %sp@(SWITCH_STACK_SIZE)
- + clrl %sp@-
- + bsrl do_signal
- + addql #8,%sp
- + RESTORE_SWITCH_STACK
- + addql #4,%sp
- + jbra resume_userspace
- +
- +do_delayed_trace:
- + bclr #7,%sp@(PT_SR) /* clear trace bit in SR */
- + pea 1 /* send SIGTRAP */
- + movel %curptr,%sp@-
- + pea LSIGTRAP
- + jbsr send_sig
- + addql #8,%sp
- + addql #4,%sp
- + jbra resume_userspace
- +
- +/*
- + * This is the interrupt handler (for all hardware interrupt
- + * sources). It figures out the vector number and calls the appropriate
- + * interrupt service routine directly.
- + */
- +ENTRY(inthandler)
- + SAVE_ALL_INT
- + GET_CURRENT(%d0)
- + addql #1,%curptr@(TASK_INFO+TINFO_PREEMPT)
- + /* put exception # in d0 */
- + movel %sp@(PT_VECTOR),%d0
- + swap %d0 /* extract bits 25:18 */
- + lsrl #2,%d0
- + andl #0x0ff,%d0
- +
- + movel %sp,%sp@-
- + movel %d0,%sp@- /* put vector # on stack */
- +auto_irqhandler_fixup = . + 2
- + jbsr process_int /* process the IRQ */
- + addql #8,%sp /* pop parameters off stack */
- +
- +ENTRY(ret_from_interrupt)
- +ret_from_interrupt:
- +
- + subql #1,%curptr@(TASK_INFO+TINFO_PREEMPT)
- + jeq ret_from_last_interrupt
- +2: RESTORE_ALL
- +
- + ALIGN
- +ret_from_last_interrupt:
- + moveb %sp@(PT_SR),%d0
- + andl #(~ALLOWINT>>8)&0xff,%d0
- + jne 2b
- +
- + /* check if we need to do software interrupts */
- + tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING
- + jeq .Lret_from_exception
- + pea ret_from_exception
- + jra do_softirq
- +
- +ENTRY(user_inthandler)
- + SAVE_ALL_INT
- + GET_CURRENT(%d0)
- + addql #1,%curptr@(TASK_INFO+TINFO_PREEMPT)
- + /* put exception # in d0 */
- + movel %sp@(PT_VECTOR),%d0
- +user_irqvec_fixup = . + 2
- + swap %d0 /* extract bits 25:18 */
- + lsrl #2,%d0
- + andl #0x0ff,%d0
- +
- + movel %sp,%sp@-
- + movel %d0,%sp@- /* put vector # on stack */
- +user_irqhandler_fixup = . + 2
- + jbsr process_int /* process the IRQ */
- + addql #8,%sp /* pop parameters off stack */
- +
- + subql #1,%curptr@(TASK_INFO+TINFO_PREEMPT)
- + jeq ret_from_last_interrupt
- + RESTORE_ALL
- +
- +/* Handler for uninitialized and spurious interrupts */
- +
- +ENTRY(bad_inthandler)
- + SAVE_ALL_INT
- + GET_CURRENT(%d0)
- + addql #1,%curptr@(TASK_INFO+TINFO_PREEMPT)
- +
- + movel %sp,%sp@-
- + jsr handle_badint
- + addql #4,%sp
- +
- + subql #1,%curptr@(TASK_INFO+TINFO_PREEMPT)
- + jeq ret_from_last_interrupt
- + RESTORE_ALL
- +
- +ENTRY(sys_fork)
- + SAVE_SWITCH_STACK
- + pea %sp@(SWITCH_STACK_SIZE)
- + jbsr m68k_fork
- + addql #4,%sp
- + RESTORE_SWITCH_STACK
- + rts
- +
- +ENTRY(sys_clone)
- + SAVE_SWITCH_STACK
- + pea %sp@(SWITCH_STACK_SIZE)
- + jbsr m68k_clone
- + addql #4,%sp
- + RESTORE_SWITCH_STACK
- + rts
- +
- +ENTRY(sys_vfork)
- + SAVE_SWITCH_STACK
- + pea %sp@(SWITCH_STACK_SIZE)
- + jbsr m68k_vfork
- + addql #4,%sp
- + RESTORE_SWITCH_STACK
- + rts
- +
- +ENTRY(sys_sigsuspend)
- + SAVE_SWITCH_STACK
- + pea %sp@(SWITCH_STACK_SIZE)
- + jbsr do_sigsuspend
- + addql #4,%sp
- + RESTORE_SWITCH_STACK
- + rts
- +
- +ENTRY(sys_rt_sigsuspend)
- + SAVE_SWITCH_STACK
- + pea %sp@(SWITCH_STACK_SIZE)
- + jbsr do_rt_sigsuspend
- + addql #4,%sp
- + RESTORE_SWITCH_STACK
- + rts
- +
- +ENTRY(sys_sigreturn)
- + SAVE_SWITCH_STACK
- + jbsr do_sigreturn
- + RESTORE_SWITCH_STACK
- + rts
- +
- +ENTRY(sys_rt_sigreturn)
- + SAVE_SWITCH_STACK
- + jbsr do_rt_sigreturn
- + RESTORE_SWITCH_STACK
- + rts
- +
- +resume:
- + /*
- + * Beware - when entering resume, prev (the current task) is
- + * in a0, next (the new task) is in a1,so don't change these
- + * registers until their contents are no longer needed.
- + */
- +
- + /* save sr */
- + movew %sr,%d0
- + movew %d0,%a0@(TASK_THREAD+THREAD_SR)
- +
- + /* save usp */
- + /* Save USP via %a1 (which is saved/restored from %d0) */
- + movel %a1,%d0
- + movel %usp,%a1
- + movel %a1,%a0@(TASK_THREAD+THREAD_USP)
- + movel %d0,%a1
- +
- + /* save non-scratch registers on stack */
- + SAVE_SWITCH_STACK
- +
- + /* save current kernel stack pointer */
- + movel %sp,%a0@(TASK_THREAD+THREAD_KSP)
- +
- + /* Return previous task in %d1 */
- + movel %curptr,%d1
- +
- + /* switch to new task (a1 contains new task) */
- + movel %a1,%curptr
- +
- + /* restore the kernel stack pointer */
- + movel %a1@(TASK_THREAD+THREAD_KSP),%sp
- +
- + /* restore non-scratch registers */
- + RESTORE_SWITCH_STACK
- +
- + /* restore user stack pointer */
- + movel %a1@(TASK_THREAD+THREAD_USP),%a0
- + movel %a0,%usp
- +
- + /* restore status register */
- + movew %a1@(TASK_THREAD+THREAD_SR),%d0
- + movew %d0,%sr
- +
- + rts
- +
- +.data
- +ALIGN
- +sys_call_table:
- + .long sys_ni_syscall /* 0 - old "setup()" system call*/
- + .long sys_exit
- + .long sys_fork
- + .long sys_read
- + .long sys_write
- + .long sys_open /* 5 */
- + .long sys_close
- + .long sys_waitpid
- + .long sys_creat
- + .long sys_link
- + .long sys_unlink /* 10 */
- + .long sys_execve
- + .long sys_chdir
- + .long sys_time
- + .long sys_mknod
- + .long sys_chmod /* 15 */
- + .long sys_chown16
- + .long sys_ni_syscall /* old break syscall holder */
- + .long sys_stat
- + .long sys_lseek
- + .long sys_getpid /* 20 */
- + .long sys_mount
- + .long sys_oldumount
- + .long sys_setuid16
- + .long sys_getuid16
- + .long sys_stime /* 25 */
- + .long sys_ptrace
- + .long sys_alarm
- + .long sys_fstat
- + .long sys_pause
- + .long sys_utime /* 30 */
- + .long sys_ni_syscall /* old stty syscall holder */
- + .long sys_ni_syscall /* old gtty syscall holder */
- + .long sys_access
- + .long sys_nice
- + .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
- + .long sys_sync
- + .long sys_kill
- + .long sys_rename
- + .long sys_mkdir
- + .long sys_rmdir /* 40 */
- + .long sys_dup
- + .long sys_pipe
- + .long sys_times
- + .long sys_ni_syscall /* old prof syscall holder */
- + .long sys_brk /* 45 */
- + .long sys_setgid16
- + .long sys_getgid16
- + .long sys_signal
- + .long sys_geteuid16
- + .long sys_getegid16 /* 50 */
- + .long sys_acct
- + .long sys_umount /* recycled never used phys() */
- + .long sys_ni_syscall /* old lock syscall holder */
- + .long sys_ioctl
- + .long sys_fcntl /* 55 */
- + .long sys_ni_syscall /* old mpx syscall holder */
- + .long sys_setpgid
- + .long sys_ni_syscall /* old ulimit syscall holder */
- + .long sys_ni_syscall
- + .long sys_umask /* 60 */
- + .long sys_chroot
- + .long sys_ustat
- + .long sys_dup2
- + .long sys_getppid
- + .long sys_getpgrp /* 65 */
- + .long sys_setsid
- + .long sys_sigaction
- + .long sys_sgetmask
- + .long sys_ssetmask
- + .long sys_setreuid16 /* 70 */
- + .long sys_setregid16
- + .long sys_sigsuspend
- + .long sys_sigpending
- + .long sys_sethostname
- + .long sys_setrlimit /* 75 */
- + .long sys_old_getrlimit
- + .long sys_getrusage
- + .long sys_gettimeofday
- + .long sys_settimeofday
- + .long sys_getgroups16 /* 80 */
- + .long sys_setgroups16
- + .long old_select
- + .long sys_symlink
- + .long sys_lstat
- + .long sys_readlink /* 85 */
- + .long sys_uselib
- + .long sys_swapon
- + .long sys_reboot
- + .long old_readdir
- + .long old_mmap /* 90 */
- + .long sys_munmap
- + .long sys_truncate
- + .long sys_ftruncate
- + .long sys_fchmod
- + .long sys_fchown16 /* 95 */
- + .long sys_getpriority
- + .long sys_setpriority
- + .long sys_ni_syscall /* old profil syscall holder */
- + .long sys_statfs
- + .long sys_fstatfs /* 100 */
- + .long sys_ni_syscall /* ioperm for i386 */
- + .long sys_socketcall
- + .long sys_syslog
- + .long sys_setitimer
- + .long sys_getitimer /* 105 */
- + .long sys_newstat
- + .long sys_newlstat
- + .long sys_newfstat
- + .long sys_ni_syscall
- + .long sys_ni_syscall /* 110 */ /* iopl for i386 */
- + .long sys_vhangup
- + .long sys_ni_syscall /* obsolete idle() syscall */
- + .long sys_ni_syscall /* vm86old for i386 */
- + .long sys_wait4
- + .long sys_swapoff /* 115 */
- + .long sys_sysinfo
- + .long sys_ipc
- + .long sys_fsync
- + .long sys_sigreturn
- + .long sys_clone /* 120 */
- + .long sys_setdomainname
- + .long sys_newuname
- + .long sys_cacheflush /* modify_ldt for i386 */
- + .long sys_adjtimex
- + .long sys_mprotect /* 125 */
- + .long sys_sigprocmask
- + .long sys_ni_syscall /* old "create_module" */
- + .long sys_init_module
- + .long sys_delete_module
- + .long sys_ni_syscall /* 130 - old "get_kernel_syms" */
- + .long sys_quotactl
- + .long sys_getpgid
- + .long sys_fchdir
- + .long sys_bdflush
- + .long sys_sysfs /* 135 */
- + .long sys_personality
- + .long sys_ni_syscall /* for afs_syscall */
- + .long sys_setfsuid16
- + .long sys_setfsgid16
- + .long sys_llseek /* 140 */
- + .long sys_getdents
- + .long sys_select
- + .long sys_flock
- + .long sys_msync
- + .long sys_readv /* 145 */
- + .long sys_writev
- + .long sys_getsid
- + .long sys_fdatasync
- + .long sys_sysctl
- + .long sys_mlock /* 150 */
- + .long sys_munlock
- + .long sys_mlockall
- + .long sys_munlockall
- + .long sys_sched_setparam
- + .long sys_sched_getparam /* 155 */
- + .long sys_sched_setscheduler
- + .long sys_sched_getscheduler
- + .long sys_sched_yield
- + .long sys_sched_get_priority_max
- + .long sys_sched_get_priority_min /* 160 */
- + .long sys_sched_rr_get_interval
- + .long sys_nanosleep
- + .long sys_mremap
- + .long sys_setresuid16
- + .long sys_getresuid16 /* 165 */
- + .long sys_getpagesize
- + .long sys_ni_syscall /* old sys_query_module */
- + .long sys_poll
- + .long sys_nfsservctl
- + .long sys_setresgid16 /* 170 */
- + .long sys_getresgid16
- + .long sys_prctl
- + .long sys_rt_sigreturn
- + .long sys_rt_sigaction
- + .long sys_rt_sigprocmask /* 175 */
- + .long sys_rt_sigpending
- + .long sys_rt_sigtimedwait
- + .long sys_rt_sigqueueinfo
- + .long sys_rt_sigsuspend
- + .long sys_pread64 /* 180 */
- + .long sys_pwrite64
- + .long sys_lchown16;
- + .long sys_getcwd
- + .long sys_capget
- + .long sys_capset /* 185 */
- + .long sys_sigaltstack
- + .long sys_sendfile
- + .long sys_ni_syscall /* streams1 */
- + .long sys_ni_syscall /* streams2 */
- + .long sys_vfork /* 190 */
- + .long sys_getrlimit
- + .long sys_mmap2
- + .long sys_truncate64
- + .long sys_ftruncate64
- + .long sys_stat64 /* 195 */
- + .long sys_lstat64
- + .long sys_fstat64
- + .long sys_chown
- + .long sys_getuid
- + .long sys_getgid /* 200 */
- + .long sys_geteuid
- + .long sys_getegid
- + .long sys_setreuid
- + .long sys_setregid
- + .long sys_getgroups /* 205 */
- + .long sys_setgroups
- + .long sys_fchown
- + .long sys_setresuid
- + .long sys_getresuid
- + .long sys_setresgid /* 210 */
- + .long sys_getresgid
- + .long sys_lchown
- + .long sys_setuid
- + .long sys_setgid
- + .long sys_setfsuid /* 215 */
- + .long sys_setfsgid
- + .long sys_pivot_root
- + .long sys_ni_syscall
- + .long sys_ni_syscall
- + .long sys_getdents64 /* 220 */
- + .long sys_gettid
- + .long sys_tkill
- + .long sys_setxattr
- + .long sys_lsetxattr
- + .long sys_fsetxattr /* 225 */
- + .long sys_getxattr
- + .long sys_lgetxattr
- + .long sys_fgetxattr
- + .long sys_listxattr
- + .long sys_llistxattr /* 230 */
- + .long sys_flistxattr
- + .long sys_removexattr
- + .long sys_lremovexattr
- + .long sys_fremovexattr
- + .long sys_futex /* 235 */
- + .long sys_sendfile64
- + .long sys_mincore
- + .long sys_madvise
- + .long sys_fcntl64
- + .long sys_readahead /* 240 */
- + .long sys_io_setup
- + .long sys_io_destroy
- + .long sys_io_getevents
- + .long sys_io_submit
- + .long sys_io_cancel /* 245 */
- + .long sys_fadvise64
- + .long sys_exit_group
- + .long sys_lookup_dcookie
- + .long sys_epoll_create
- + .long sys_epoll_ctl /* 250 */
- + .long sys_epoll_wait
- + .long sys_remap_file_pages
- + .long sys_set_tid_address
- + .long sys_timer_create
- + .long sys_timer_settime /* 255 */
- + .long sys_timer_gettime
- + .long sys_timer_getoverrun
- + .long sys_timer_delete
- + .long sys_clock_settime
- + .long sys_clock_gettime /* 260 */
- + .long sys_clock_getres
- + .long sys_clock_nanosleep
- + .long sys_statfs64
- + .long sys_fstatfs64
- + .long sys_tgkill /* 265 */
- + .long sys_utimes
- + .long sys_fadvise64_64
- + .long sys_mbind
- + .long sys_get_mempolicy
- + .long sys_set_mempolicy /* 270 */
- + .long sys_mq_open
- + .long sys_mq_unlink
- + .long sys_mq_timedsend
- + .long sys_mq_timedreceive
- + .long sys_mq_notify /* 275 */
- + .long sys_mq_getsetattr
- + .long sys_waitid
- + .long sys_ni_syscall /* for sys_vserver */
- + .long sys_add_key
- + .long sys_request_key /* 280 */
- + .long sys_keyctl
- + .long sys_ioprio_set
- + .long sys_ioprio_get
- + .long sys_inotify_init
- + .long sys_inotify_add_watch /* 285 */
- + .long sys_inotify_rm_watch
- + .long sys_migrate_pages
- + .long sys_openat
- + .long sys_mkdirat
- + .long sys_mknodat /* 290 */
- + .long sys_fchownat
- + .long sys_futimesat
- + .long sys_fstatat64
- + .long sys_unlinkat
- + .long sys_renameat /* 295 */
- + .long sys_linkat
- + .long sys_symlinkat
- + .long sys_readlinkat
- + .long sys_fchmodat
- + .long sys_faccessat /* 300 */
- + .long sys_ni_syscall /* Reserved for pselect6 */
- + .long sys_ni_syscall /* Reserved for ppoll */
- + .long sys_unshare
- + .long sys_set_robust_list
- + .long sys_get_robust_list /* 305 */
- + .long sys_splice
- + .long sys_sync_file_range
- + .long sys_tee
- + .long sys_vmsplice
- + .long sys_move_pages /* 310 */
- +
- --- /dev/null
- +++ b/arch/m68k/coldfire/head.S
- @@ -0,0 +1,474 @@
- +/*
- + * head.S is the MMU enabled ColdFire specific initial boot code
- + *
- + * Ported to ColdFire by
- + * Matt Waddel [email protected]
- + * Kurt Mahan [email protected]
- + * Copyright Freescale Semiconductor, Inc. 2007
- + *
- + * 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.
- + *
- + * Parts of this code came from arch/m68k/kernel/head.S
- + */
- +#include <linux/linkage.h>
- +#include <linux/init.h>
- +#include <asm/bootinfo.h>
- +#include <asm/setup.h>
- +#include <asm/entry.h>
- +#include <asm/pgtable.h>
- +#include <asm/page.h>
- +#include <asm/coldfire.h>
- +#include <asm/mcfuart.h>
- +#include <asm/cfcache.h>
- +
- +#define DEBUG
- +
- +.globl kernel_pg_dir
- +.globl availmem
- +.globl set_context
- +.globl set_fpga
- +
- +#ifdef DEBUG
- +/* When debugging use readable names for labels */
- +#ifdef __STDC__
- +#define L(name) .head.S.##name
- +#else
- +#define L(name) .head.S./**/name
- +#endif
- +#else
- +#ifdef __STDC__
- +#define L(name) .L##name
- +#else
- +#define L(name) .L/**/name
- +#endif
- +#endif
- +
- +/* The __INITDATA stuff is a no-op when ftrace or kgdb are turned on */
- +#ifndef __INITDATA
- +#define __INITDATA .data
- +#define __FINIT .previous
- +#endif
- +
- +/*
- + * Setup ACR mappings to provide the following memory map:
- + * Data
- + * 0xA0000000 -> 0xAFFFFFFF [0] NO CACHE / PRECISE / SUPER ONLY
- + * 0xFC000000 -> 0xFCFFFFFF [1] NO CACHE / PRECISE / SUPER ONLY
- + * Code
- + * None currently (mapped via TLBs)
- + */
- +
- +#define ACR0_DEFAULT #0xA00FA048 /* ACR0 default value */
- +#define ACR1_DEFAULT #0xFC00A040 /* ACR1 default value */
- +#define ACR2_DEFAULT #0x00000000 /* ACR2 default value */
- +#define ACR3_DEFAULT #0x00000000 /* ACR3 default value */
- +
- +/* ACR mapping for FPGA (maps 0) */
- +#define ACR0_FPGA #0x000FA048 /* ACR0 enable FPGA */
- +
- +/* Several macros to make the writing of subroutines easier:
- + * - func_start marks the beginning of the routine which setups the frame
- + * register and saves the registers, it also defines another macro
- + * to automatically restore the registers again.
- + * - func_return marks the end of the routine and simply calls the prepared
- + * macro to restore registers and jump back to the caller.
- + * - func_define generates another macro to automatically put arguments
- + * onto the stack call the subroutine and cleanup the stack again.
- + */
- +
- +.macro load_symbol_address symbol,register
- + movel #\symbol,\register
- +.endm
- +
- +.macro func_start name,saveregs,savesize,stack=0
- +L(\name):
- + linkw %a6,#-\stack
- + subal #(\savesize),%sp
- + moveml \saveregs,%sp@
- +.set stackstart,-\stack
- +
- +.macro func_return_\name
- + moveml %sp@,\saveregs
- + addal #(\savesize),%sp
- + unlk %a6
- + rts
- +.endm
- +.endm
- +
- +.macro func_return name
- + func_return_\name
- +.endm
- +
- +.macro func_call name
- + jbsr L(\name)
- +.endm
- +
- +.macro move_stack nr,arg1,arg2,arg3,arg4
- +.if \nr
- + move_stack "(\nr-1)",\arg2,\arg3,\arg4
- + movel \arg1,%sp@-
- +.endif
- +.endm
- +
- +.macro func_define name,nr=0
- +.macro \name arg1,arg2,arg3,arg4
- + move_stack \nr,\arg1,\arg2,\arg3,\arg4
- + func_call \name
- +.if \nr
- + lea %sp@(\nr*4),%sp
- +.endif
- +.endm
- +.endm
- +
- +func_define serial_putc,1
- +
- +.macro putc ch
- + pea \ch
- + func_call serial_putc
- + addql #4,%sp
- +.endm
- +
- +.macro dputc ch
- +#ifdef DEBUG
- + putc \ch
- +#endif
- +.endm
- +
- +func_define putn,1
- +
- +.macro dputn nr
- +#ifdef DEBUG
- + putn \nr
- +#endif
- +.endm
- +
- +/*
- + mmu_map - creates a new TLB entry
- +
- + virt_addr Must be on proper boundary
- + phys_addr Must be on proper boundary
- + itlb MMUOR_ITLB if instruction TLB or 0
- + asid address space ID
- + shared_global MMUTR_SG if shared between different ASIDs or 0
- + size_code MMUDR_SZ1M 1 MB
- + MMUDR_SZ4K 4 KB
- + MMUDR_SZ8K 8 KB
- + MMUDR_SZ16M 16 MB
- + cache_mode MMUDR_INC instruction non-cacheable
- + MMUDR_IC instruction cacheable
- + MMUDR_DWT data writethrough
- + MMUDR_DCB data copyback
- + MMUDR_DNCP data non-cacheable, precise
- + MMUDR_DNCIP data non-cacheable, imprecise
- + super_prot MMUDR_SP if user mode generates exception or 0
- + readable MMUDR_R if permits read access (data TLB) or 0
- + writable MMUDR_W if permits write access (data TLB) or 0
- + executable MMUDR_X if permits execute access (instruction TLB) or 0
- + locked MMUDR_LK prevents TLB entry from being replaced or 0
- + temp_data_reg a data register to use for temporary values
- +*/
- +.macro mmu_map virt_addr,phys_addr,itlb,asid,shared_global,size_code,cache_mode,super_prot,readable,writable,executable,locked,temp_data_reg
- + /* Set up search of TLB. */
- + movel #(\virt_addr+1), \temp_data_reg
- + movel \temp_data_reg, MMUAR
- + /* Search. */
- + movel #(MMUOR_STLB + MMUOR_ADR +\itlb), \temp_data_reg
- + movew \temp_data_reg, (MMUOR)
- + /* Set up tag value. */
- + movel #(\virt_addr + \asid + \shared_global + MMUTR_V), \temp_data_reg
- + movel \temp_data_reg, MMUTR
- + /* Set up data value. */
- + movel #(\phys_addr + \size_code + \cache_mode + \super_prot + \readable + \writable + \executable + \locked), \temp_data_reg
- + movel \temp_data_reg, MMUDR
- + /* Save it. */
- + movel #(MMUOR_ACC + MMUOR_UAA + \itlb), \temp_data_reg
- + movew \temp_data_reg, (MMUOR)
- +.endm /* mmu_map */
- +
- +.macro mmu_unmap virt_addr,itlb,temp_data_reg
- + /* Set up search of TLB. */
- + movel #(\virt_addr+1), \temp_data_reg
- + movel \temp_data_reg, MMUAR
- + /* Search. */
- + movel #(MMUOR_STLB + MMUOR_ADR +\itlb), \temp_data_reg
- + movew \temp_data_reg, (MMUOR)
- + /* Test for hit. */
- + movel MMUSR,\temp_data_reg
- + btst #MMUSR_HITN,\temp_data_reg
- + beq 1f
- + /* Read the TLB. */
- + movel #(MMUOR_RW + MMUOR_ACC +\itlb), \temp_data_reg
- + movew \temp_data_reg, (MMUOR)
- + movel MMUSR,\temp_data_reg
- + /* Set up tag value. */
- + movel #0, \temp_data_reg
- + movel \temp_data_reg, MMUTR
- + /* Set up data value. */
- + movel #0, \temp_data_reg
- + movel \temp_data_reg, MMUDR
- + /* Save it. */
- + movel #(MMUOR_ACC + MMUOR_UAA + \itlb), \temp_data_reg
- + movew \temp_data_reg, (MMUOR)
- +1:
- +.endm /* mmu_unmap */
- +
- +/* .text */
- +.section ".text.head","ax"
- +ENTRY(_stext)
- +/* Version numbers of the bootinfo interface -- if we later pass info
- + * from boot ROM we might want to put something real here.
- + *
- + * The area from _stext to _start will later be used as kernel pointer table
- + */
- + bras 1f /* Jump over bootinfo version numbers */
- +
- + .long BOOTINFOV_MAGIC
- + .long 0
- +1: jmp __start-0x80000000
- +
- +.equ kernel_pg_dir,_stext
- +.equ .,_stext+0x1000
- +
- +ENTRY(_start)
- + jra __start
- +__INIT
- +ENTRY(__start)
- +
- +/* Save the location of u-boot info - cmd line, bd_info, etc. */
- + movel %a7,%a4 /* Don't use %a4 before cf_early_init */
- + addl #0x80000004,%a4 /* 0x80000004= 1 stack push + high mem offset */
- +
- +/* Setup initial stack pointer */
- + movel #0x40001000,%sp
- +
- +/* Clear usp */
- + subl %a0,%a0
- + movel %a0,%usp
- +
- + movel #(MCF_RAMBAR1 + 0x221), %d0
- + movec %d0, %rambar1
- + movew #0x2700,%sr
- +
- + movel #(MMU_BASE+1),%d0
- + movecl %d0,%mmubar
- + movel #MMUOR_CA,%a0 /* Clear tlb entries */
- + movew %a0,(MMUOR)
- + movel #(MMUOR_CA + MMUOR_ITLB),%a0 /* Use ITLB for searches */
- + movew %a0,(MMUOR)
- + movel #0,%a0 /* Clear Addr Space User ID */
- + movecl %a0,%asid
- +
- +/* setup ACRs */
- + movel ACR0_DEFAULT, %d0 /* ACR0 (DATA) setup */
- + movec %d0, %acr0
- + movel ACR1_DEFAULT, %d0 /* ACR1 (DATA) setup */
- + movec %d0, %acr1
- + movel ACR2_DEFAULT, %d0 /* ACR2 (CODE) setup */
- + movec %d0, %acr2
- + movel ACR3_DEFAULT, %d0 /* ACR3 (CODE) setup */
- + movec %d0, %acr3
- +
- + /* If you change the memory size to another value make a matching
- + change in paging_init(cf-mmu.c) to zones_size[]. */
- +
- + /* Map 256MB as code */
- + mmu_map (PAGE_OFFSET+0*0x1000000), (PHYS_OFFSET+0*0x1000000), \
- + MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \
- + 0, 0, MMUDR_X, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+1*0x1000000), (PHYS_OFFSET+1*0x1000000), \
- + MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \
- + 0, 0, MMUDR_X, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+2*0x1000000), (PHYS_OFFSET+2*0x1000000), \
- + MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \
- + 0, 0, MMUDR_X, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+3*0x1000000), (PHYS_OFFSET+3*0x1000000), \
- + MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \
- + 0, 0, MMUDR_X, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+4*0x1000000), (PHYS_OFFSET+4*0x1000000), \
- + MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \
- + 0, 0, MMUDR_X, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+5*0x1000000), (PHYS_OFFSET+5*0x1000000), \
- + MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \
- + 0, 0, MMUDR_X, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+6*0x1000000), (PHYS_OFFSET+6*0x1000000), \
- + MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \
- + 0, 0, MMUDR_X, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+7*0x1000000), (PHYS_OFFSET+7*0x1000000), \
- + MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \
- + 0, 0, MMUDR_X, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+8*0x1000000), (PHYS_OFFSET+8*0x1000000), \
- + MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \
- + 0, 0, MMUDR_X, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+9*0x1000000), (PHYS_OFFSET+9*0x1000000), \
- + MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \
- + 0, 0, MMUDR_X, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+10*0x1000000), (PHYS_OFFSET+10*0x1000000), \
- + MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \
- + 0, 0, MMUDR_X, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+11*0x1000000), (PHYS_OFFSET+11*0x1000000), \
- + MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \
- + 0, 0, MMUDR_X, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+12*0x1000000), (PHYS_OFFSET+12*0x1000000), \
- + MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \
- + 0, 0, MMUDR_X, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+13*0x1000000), (PHYS_OFFSET+13*0x1000000), \
- + MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \
- + 0, 0, MMUDR_X, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+14*0x1000000), (PHYS_OFFSET+14*0x1000000), \
- + MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \
- + 0, 0, MMUDR_X, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+15*0x1000000), (PHYS_OFFSET+15*0x1000000), \
- + MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \
- + 0, 0, MMUDR_X, MMUDR_LK, %d0
- +
- + /* Map 256MB as data also */
- + mmu_map (PAGE_OFFSET+0*0x1000000), (PHYS_OFFSET+0*0x1000000), 0, 0, \
- + MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
- + 0, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+1*0x1000000), (PHYS_OFFSET+1*0x1000000), 0, 0, \
- + MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
- + 0, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+2*0x1000000), (PHYS_OFFSET+2*0x1000000), 0, 0, \
- + MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
- + 0, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+3*0x1000000), (PHYS_OFFSET+3*0x1000000), 0, 0, \
- + MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
- + 0, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+4*0x1000000), (PHYS_OFFSET+4*0x1000000), 0, 0, \
- + MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
- + 0, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+5*0x1000000), (PHYS_OFFSET+5*0x1000000), 0, 0, \
- + MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
- + 0, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+6*0x1000000), (PHYS_OFFSET+6*0x1000000), 0, 0, \
- + MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
- + 0, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+7*0x1000000), (PHYS_OFFSET+7*0x1000000), 0, 0, \
- + MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
- + 0, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+8*0x1000000), (PHYS_OFFSET+8*0x1000000), 0, 0, \
- + MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
- + 0, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+9*0x1000000), (PHYS_OFFSET+9*0x1000000), 0, 0, \
- + MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
- + 0, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+10*0x1000000), (PHYS_OFFSET+10*0x1000000), 0, 0, \
- + MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
- + 0, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+11*0x1000000), (PHYS_OFFSET+11*0x1000000), 0, 0, \
- + MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
- + 0, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+12*0x1000000), (PHYS_OFFSET+12*0x1000000), 0, 0, \
- + MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
- + 0, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+13*0x1000000), (PHYS_OFFSET+13*0x1000000), 0, 0, \
- + MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
- + 0, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+14*0x1000000), (PHYS_OFFSET+14*0x1000000), 0, 0, \
- + MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
- + 0, MMUDR_LK, %d0
- + mmu_map (PAGE_OFFSET+15*0x1000000), (PHYS_OFFSET+15*0x1000000), 0, 0, \
- + MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
- + 0, MMUDR_LK, %d0
- +
- + /* Do unity mapping to enable the MMU. Map first 16 MB in place as
- + code (delete TLBs after MMU is enabled and we are executing in high
- + memory). */
- + mmu_map (PHYS_OFFSET+0*0x1000000), (PHYS_OFFSET+0*0x1000000), \
- + MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_INC, MMUDR_SP, 0, \
- + 0, MMUDR_X, 0, %d0
- + /* Map first 16 MB as data too. */
- + mmu_map (PHYS_OFFSET+0*0x1000000), (PHYS_OFFSET+0*0x1000000), 0, 0, \
- + MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
- + 0, 0, %d0
- +
- + /* Turn on MMU */
- + movel #(MMUCR_EN),%a0
- + movel %a0,MMUCR
- + nop /* This synchs the pipeline after a write to MMUCR */
- +
- + movel #__running_high,%a0 /* Get around PC-relative addressing. */
- + jmp %a0@
- +
- +ENTRY(__running_high)
- + load_symbol_address _stext,%sp
- + movel L(memory_start),%a0
- + movel %a0,availmem
- + load_symbol_address L(phys_kernel_start),%a0
- + load_symbol_address _stext,%a1
- + subl #_stext,%a1
- + addl #PAGE_OFFSET,%a1
- + movel %a1,%a0@
- +
- + /* Unmap first 16 MB, code and data. */
- + mmu_unmap (PHYS_OFFSET+0*0x1000000), MMUOR_ITLB, %d0
- + mmu_unmap (PHYS_OFFSET+0*0x1000000), 0, %d0
- +
- +/* Setup initial stack pointer */
- + lea init_task,%a2
- + lea init_thread_union+THREAD_SIZE,%sp
- + subl %a6,%a6 /* clear a6 for gdb */
- +
- +#ifdef CONFIG_MCF_USER_HALT
- +/* Setup debug control reg to allow halts from user space */
- + lea wdbg_uhe,%a0
- + wdebug (%a0)
- +#endif
- +
- + movel %a4,uboot_info_stk /* save uboot info to variable */
- + jsr cf_early_init
- + jmp start_kernel
- +
- +.section ".text.head","ax"
- +set_context:
- +func_start set_context,%d0,(1*4)
- + movel 12(%sp),%d0
- + movec %d0,%asid
- +func_return set_context
- +
- +/*
- + * set_fpga(addr,val)
- + *
- + * Map in 0x00000000 -> 0x0fffffff and then do the write.
- + */
- +set_fpga:
- + movew %sr,%d1
- + movew #0x2700,%sr
- + movel ACR0_FPGA, %d0
- + movec %d0, %acr0
- + nop
- + moveal 4(%sp),%a0
- + movel 8(%sp),%a0@
- + movel ACR0_DEFAULT, %d0
- + movec %d0, %acr0
- + nop
- + movew %d1,%sr
- + rts
- +
- + .data
- + .align 4
- +
- +availmem:
- + .long 0
- +L(phys_kernel_start):
- + .long PAGE_OFFSET
- +L(kernel_end):
- + .long 0
- +L(memory_start):
- + .long PAGE_OFFSET_RAW
- +
- +#ifdef CONFIG_MCF_USER_HALT
- +/*
- + * Enable User Halt Enable in the debug control register.
- + */
- +wdbg_uhe:
- + .word 0x2c80 /* DR0 */
- + .word 0x00b0 /* 31:16 */
- + .word 0x0400 /* 15:0 -- enable UHE */
- + .word 0x0000 /* unused */
- +#endif
- +
- +
- --- /dev/null
- +++ b/arch/m68k/coldfire/ints.c
- @@ -0,0 +1,384 @@
- +/*
- + * linux/arch/m68k/coldfire/ints.c -- General interrupt handling code
- + *
- + * Copyright (C) 1999-2002 Greg Ungerer ([email protected])
- + * Copyright (C) 1998 D. Jeff Dionne <[email protected]>,
- + * Kenneth Albanowski <[email protected]>,
- + * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
- + * Matt Waddel [email protected]
- + * Copyright Freescale Semiconductor, Inc. 2007
- + * Kurt Mahan [email protected]
- + *
- + * Based on:
- + * linux/arch/m68k/kernel/ints.c &
- + * linux/arch/m68knommu/5307/ints.c
- + *
- + * 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/types.h>
- +#include <linux/init.h>
- +#include <linux/sched.h>
- +#include <linux/kernel_stat.h>
- +#include <linux/errno.h>
- +#include <linux/seq_file.h>
- +#include <linux/interrupt.h>
- +
- +#include <asm/system.h>
- +#include <asm/irq.h>
- +#include <asm/traps.h>
- +#include <asm/page.h>
- +#include <asm/machdep.h>
- +#include <asm/irq_regs.h>
- +
- +#include <asm/mcfsim.h>
- +
- +/*
- + * IRQ Handler lists.
- + */
- +static struct irq_node *irq_list[SYS_IRQS];
- +static struct irq_controller *irq_controller[SYS_IRQS];
- +static int irq_depth[SYS_IRQS];
- +
- +/*
- + * IRQ Controller
- + */
- +#ifdef CONFIG_M54455
- +void m5445x_irq_enable(unsigned int irq);
- +void m5445x_irq_disable(unsigned int irq);
- +static struct irq_controller m5445x_irq_controller = {
- + .name = "M5445X",
- + .lock = SPIN_LOCK_UNLOCKED,
- + .enable = m5445x_irq_enable,
- + .disable = m5445x_irq_disable,
- +};
- +#endif
- +
- +#define POOL_SIZE SYS_IRQS
- +static struct irq_node pool[POOL_SIZE];
- +static struct irq_node *get_irq_node(void);
- +
- +/* The number of spurious interrupts */
- +unsigned int num_spurious;
- +asmlinkage void handle_badint(struct pt_regs *regs);
- +
- +/*
- + * void init_IRQ(void)
- + *
- + * This function should be called during kernel startup to initialize
- + * the IRQ handling routines.
- + */
- +void __init init_IRQ(void)
- +{
- + int i;
- +
- +#ifdef CONFIG_M54455
- + for (i = 0; i < SYS_IRQS; i++)
- + irq_controller[i] = &m5445x_irq_controller;
- +#endif
- +}
- +
- +/*
- + * process_int(unsigned long vec, struct pt_regs *fp)
- + *
- + * Process an interrupt. Called from entry.S.
- + */
- +asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
- +{
- + struct pt_regs *old_regs;
- + struct irq_node *node;
- + old_regs = set_irq_regs(fp);
- + kstat_cpu(0).irqs[vec]++;
- +
- + node = irq_list[vec];
- + if (!node)
- + handle_badint(fp);
- + else {
- + do {
- + node->handler(vec, node->dev_id);
- + node = node->next;
- + } while (node);
- + }
- +
- + set_irq_regs(old_regs);
- +}
- +
- +/*
- + * show_interrupts( struct seq_file *p, void *v)
- + *
- + * Called to show all the current interrupt information.
- + */
- +int show_interrupts(struct seq_file *p, void *v)
- +{
- + struct irq_controller *contr;
- + struct irq_node *node;
- + int i = *(loff_t *) v;
- +
- + if ((i < NR_IRQS) && (irq_list[i])) {
- + contr = irq_controller[i];
- + node = irq_list[i];
- + seq_printf(p, "%-8s %3u: %10u %s", contr->name, i,
- + kstat_cpu(0).irqs[i], node->devname);
- + while ((node = node->next))
- + seq_printf(p, ", %s", node->devname);
- +
- + seq_printf(p, "\n");
- + }
- +
- + return 0;
- +}
- +
- +/*
- + * get_irq_node(void)
- + *
- + * Get an irq node from the pool.
- + */
- +struct irq_node *get_irq_node(void)
- +{
- + struct irq_node *p = pool;
- + int i;
- +
- + for (i = 0; i < POOL_SIZE; i++, p++) {
- + if (!p->handler) {
- + memset(p, 0, sizeof(struct irq_node));
- + return p;
- + }
- + }
- + printk(KERN_INFO "%s(%s:%d): No more irq nodes, I suggest you \
- + increase POOL_SIZE", __FUNCTION__, __FILE__, __LINE__);
- + return NULL;
- +}
- +
- +void init_irq_proc(void)
- +{
- + /* Insert /proc/irq driver here */
- +}
- +
- +int setup_irq(unsigned int irq, struct irq_node *node)
- +{
- + struct irq_controller *contr;
- + struct irq_node **prev;
- + unsigned long flags;
- +
- + if (irq >= NR_IRQS || !irq_controller[irq]) {
- + printk("%s: Incorrect IRQ %d from %s\n",
- + __FUNCTION__, irq, node->devname);
- + return -ENXIO;
- + }
- +
- + contr = irq_controller[irq];
- + spin_lock_irqsave(&contr->lock, flags);
- +
- + prev = irq_list + irq;
- + if (*prev) {
- + /* Can't share interrupts unless both agree to */
- + if (!((*prev)->flags & node->flags & IRQF_SHARED)) {
- + spin_unlock_irqrestore(&contr->lock, flags);
- + return -EBUSY;
- + }
- + while (*prev)
- + prev = &(*prev)->next;
- + }
- +
- + if (!irq_list[irq]) {
- + if (contr->startup)
- + contr->startup(irq);
- + else
- + contr->enable(irq);
- + }
- + node->next = NULL;
- + *prev = node;
- +
- + spin_unlock_irqrestore(&contr->lock, flags);
- +
- + return 0;
- +}
- +
- +int request_irq(unsigned int irq,
- + irq_handler_t handler,
- + unsigned long flags, const char *devname, void *dev_id)
- +{
- + struct irq_node *node = get_irq_node();
- + int res;
- +
- + if (!node)
- + return -ENOMEM;
- +
- + node->handler = handler;
- + node->flags = flags;
- + node->dev_id = dev_id;
- + node->devname = devname;
- +
- + res = setup_irq(irq, node);
- + if (res)
- + node->handler = NULL;
- +
- + return res;
- +}
- +EXPORT_SYMBOL(request_irq);
- +
- +void free_irq(unsigned int irq, void *dev_id)
- +{
- + struct irq_controller *contr;
- + struct irq_node **p, *node;
- + unsigned long flags;
- +
- + if (irq >= NR_IRQS || !irq_controller[irq]) {
- + printk(KERN_DEBUG "%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
- + return;
- + }
- +
- + contr = irq_controller[irq];
- + spin_lock_irqsave(&contr->lock, flags);
- +
- + p = irq_list + irq;
- + while ((node = *p)) {
- + if (node->dev_id == dev_id)
- + break;
- + p = &node->next;
- + }
- +
- + if (node) {
- + *p = node->next;
- + node->handler = NULL;
- + } else
- + printk(KERN_DEBUG "%s: Removing probably wrong IRQ %d\n",
- + __FUNCTION__, irq);
- +
- + if (!irq_list[irq]) {
- + if (contr->shutdown)
- + contr->shutdown(irq);
- + else
- + contr->disable(irq);
- + }
- +
- + spin_unlock_irqrestore(&contr->lock, flags);
- +}
- +EXPORT_SYMBOL(free_irq);
- +
- +void enable_irq(unsigned int irq)
- +{
- + struct irq_controller *contr;
- + unsigned long flags;
- +
- + if (irq >= NR_IRQS || !irq_controller[irq]) {
- + printk(KERN_DEBUG "%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
- + return;
- + }
- +
- + contr = irq_controller[irq];
- + spin_lock_irqsave(&contr->lock, flags);
- + if (irq_depth[irq]) {
- + if (!--irq_depth[irq]) {
- + if (contr->enable)
- + contr->enable(irq);
- + }
- + } else
- + WARN_ON(1);
- + spin_unlock_irqrestore(&contr->lock, flags);
- +}
- +EXPORT_SYMBOL(enable_irq);
- +
- +void disable_irq(unsigned int irq)
- +{
- + struct irq_controller *contr;
- + unsigned long flags;
- +
- + if (irq >= NR_IRQS || !irq_controller[irq]) {
- + printk(KERN_DEBUG "%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
- + return;
- + }
- +
- + contr = irq_controller[irq];
- + spin_lock_irqsave(&contr->lock, flags);
- + if (!irq_depth[irq]++) {
- + if (contr->disable)
- + contr->disable(irq);
- + }
- + spin_unlock_irqrestore(&contr->lock, flags);
- +}
- +EXPORT_SYMBOL(disable_irq);
- +
- +unsigned long probe_irq_on(void)
- +{
- + return 0;
- +}
- +EXPORT_SYMBOL(probe_irq_on);
- +
- +int probe_irq_off(unsigned long irqs)
- +{
- + return 0;
- +}
- +EXPORT_SYMBOL(probe_irq_off);
- +
- +asmlinkage void handle_badint(struct pt_regs *regs)
- +{
- + kstat_cpu(0).irqs[0]++;
- + num_spurious++;
- + printk(KERN_DEBUG "unexpected interrupt from %u\n", regs->vector);
- +}
- +EXPORT_SYMBOL(handle_badint);
- +
- +#ifdef CONFIG_M54455
- +/*
- + * M5445X Implementation
- + */
- +void m5445x_irq_enable(unsigned int irq)
- +{
- + /* enable the interrupt hardware */
- + if (irq < 64)
- + return;
- +
- + /* adjust past non-hardware ints */
- + irq -= 64;
- +
- + /* check for eport */
- + if ((irq > 0) && (irq < 8)) {
- + /* enable eport */
- + MCF_EPORT_EPPAR &= ~(3 << (irq*2)); /* level */
- + MCF_EPORT_EPDDR &= ~(1 << irq); /* input */
- + MCF_EPORT_EPIER |= 1 << irq; /* irq enabled */
- + }
- +
- + if (irq < 64) {
- + /* controller 0 */
- + MCF_INTC0_ICR(irq) = 0x02;
- + MCF_INTC0_CIMR = irq;
- + } else {
- + /* controller 1 */
- + irq -= 64;
- + MCF_INTC1_ICR(irq) = 0x02;
- + MCF_INTC1_CIMR = irq;
- + }
- +}
- +
- +void m5445x_irq_disable(unsigned int irq)
- +{
- + /* disable the interrupt hardware */
- + if (irq < 64)
- + return;
- +
- + /* adjust past non-hardware ints */
- + irq -= 64;
- +
- + /* check for eport */
- + if ((irq > 0) && (irq < 8)) {
- + /* disable eport */
- + MCF_EPORT_EPIER &= ~(1 << irq);
- + }
- +
- + if (irq < 64) {
- + /* controller 0 */
- + MCF_INTC0_ICR(irq) = 0x00;
- + MCF_INTC0_SIMR = irq;
- + } else {
- + /* controller 1 */
- + irq -= 64;
- + MCF_INTC1_ICR(irq) = 0x00;
- + MCF_INTC1_SIMR = irq;
- + }
- +}
- +#endif
- --- /dev/null
- +++ b/arch/m68k/coldfire/iomap.c
- @@ -0,0 +1,54 @@
- +/*
- + * arch/m68k/coldfire/iomap.c
- + *
- + * Generic coldfire iomap interface
- + *
- + * Based on the sh64 iomap.c by Paul Mundt.
- + *
- + * 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/pci.h>
- +#include <asm/io.h>
- +
- +void __iomem *__attribute__ ((weak))
- +ioport_map(unsigned long port, unsigned int len)
- +{
- + return (void __iomem *)port;
- +}
- +EXPORT_SYMBOL(pci_iomap);
- +
- +void ioport_unmap(void __iomem *addr)
- +{
- + /* Nothing .. */
- +}
- +EXPORT_SYMBOL(pci_iounmap);
- +
- +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
- +{
- + unsigned long start = pci_resource_start(dev, bar);
- + unsigned long len = pci_resource_len(dev, bar);
- + unsigned long flags = pci_resource_flags(dev, bar);
- +printk(KERN_INFO "PCI_IOMAP: BAR=%d START=0x%lx LEN=0x%lx FLAGS=0x%lx\n",
- + bar, start, len, flags);
- +
- + if (!len)
- + return NULL;
- + if (max && len > max)
- + len = max;
- + if (flags & IORESOURCE_IO)
- + return ioport_map(start, len);
- + if (flags & IORESOURCE_MEM)
- + return (void __iomem *)start;
- +
- + /* What? */
- + return NULL;
- +}
- +EXPORT_SYMBOL(ioport_map);
- +
- +void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
- +{
- + /* Nothing .. */
- +}
- +EXPORT_SYMBOL(ioport_unmap);
- --- /dev/null
- +++ b/arch/m68k/coldfire/mcf5445x-pci.c
- @@ -0,0 +1,427 @@
- +/*
- + * arch/m68k/coldfire/mcf5445x-pci.c
- + *
- + * Coldfire M5445x specific PCI implementation.
- + *
- + * Copyright (c) 2007 Freescale Semiconductor, Inc.
- + * Kurt Mahan <[email protected]>
- + */
- +
- +#include <linux/delay.h>
- +#include <linux/pci.h>
- +
- +#include <asm/mcfsim.h>
- +#include <asm/pci.h>
- +#include <asm/irq.h>
- +
- +/*
- + * Layout MCF5445x to PCI memory mappings:
- + *
- + * WIN MCF5445x PCI TYPE
- + * --- -------- --- ----
- + * [0] 0xA0000000 -> 0xA7FFFFFF 0xA0000000 -> 0xA7FFFFFF MEM
- + * [1] 0xA8000000 -> 0xABFFFFFF 0xA8000000 -> 0xABFFFFFF MEM
- + * [2] 0xAC000000 -> 0xAFFFFFFF 0xAC000000 -> 0xAFFFFFFF IO
- + */
- +
- +#define MCF5445X_PCI_MEM_BASE 0xA0000000
- +#define MCF5445X_PCI_MEM_SIZE 0x0C000000
- +
- +#define MCF5445X_PCI_CONFIG_BASE 0xAC000000
- +#define MCF5445X_PCI_CONFIG_SIZE 0x04000000
- +
- +#define MCF5445X_PCI_IO_BASE 0xAC000000
- +#define MCF5445X_PCI_IO_SIZE 0x04000000
- +
- +/* PCI Bus memory resource block */
- +struct resource pci_iomem_resource = {
- + .name = "PCI memory space",
- + .start = MCF5445X_PCI_MEM_BASE,
- + .flags = IORESOURCE_MEM,
- + .end = MCF5445X_PCI_MEM_BASE + MCF5445X_PCI_MEM_SIZE - 1
- +};
- +
- +/* PCI Bus ioport resource block */
- +struct resource pci_ioport_resource = {
- + .name = "PCI I/O space",
- + .start = MCF5445X_PCI_IO_BASE,
- + .flags = IORESOURCE_IO,
- + .end = MCF5445X_PCI_IO_BASE + MCF5445X_PCI_IO_SIZE - 1
- +};
- +
- +/*
- + * The M54455EVB multiplexes all the PCI interrupts via
- + * the FPGA and routes them to a single interrupt. The
- + * PCI spec requires all PCI interrupt routines be smart
- + * enough to sort out their own interrupts.
- + * The interrupt source from the FPGA is configured
- + * to EPORT 3.
- + */
- +#define MCF5445X_PCI_IRQ 0x43
- +
- +#define PCI_SLOTS 4
- +
- +/*
- + * FPGA Info
- + */
- +#define FPGA_PCI_IRQ_ENABLE (u32 *)0x09000000
- +#define FPGA_PCI_IRQ_STATUS (u32 *)0x09000004
- +#define FPGA_PCI_IRQ_ROUTE (u32 *)0x0900000c
- +#define FPGA_SEVEN_LED (u32 *)0x09000014
- +
- +extern void set_fpga(u32 *addr, u32 val);
- +
- +#ifdef DEBUG
- +void mcf5445x_pci_dumpregs(void);
- +#endif
- +
- +/*
- + * static void mcf5445x_conf_device(struct pci_dev *dev)
- + *
- + * Machine dependent Configure the given device.
- + *
- + * Parameters:
- + *
- + * dev - the pci device.
- + */
- +void __init
- +mcf5445x_conf_device(struct pci_dev *dev)
- +{
- + set_fpga(FPGA_PCI_IRQ_ENABLE, 0x0f);
- +}
- +
- +/*
- + * int mcf5445x_pci_config_read(unsigned int seg, unsigned int bus,
- + * unsigned int devfn, int reg,
- + * u32 *value)
- + *
- + * Read from PCI configuration space.
- + *
- + */
- +int mcf5445x_pci_config_read(unsigned int seg, unsigned int bus,
- + unsigned int devfn, int reg, int len, u32 *value)
- +{
- + u32 addr = MCF_PCI_PCICAR_BUSNUM(bus) |
- + MCF_PCI_PCICAR_DEVNUM(PCI_SLOT(devfn)) |
- + MCF_PCI_PCICAR_FUNCNUM(PCI_FUNC(devfn)) |
- + MCF_PCI_PCICAR_DWORD(reg) |
- + MCF_PCI_PCICAR_E;
- +
- + if ((bus > 255) || (devfn > 255) || (reg > 255)) {
- + *value = -1;
- + return -EINVAL;
- + }
- +
- + /* setup for config mode */
- + MCF_PCI_PCICAR = addr;
- + __asm__ __volatile__("nop");
- +
- + switch (len) {
- + case 1:
- + *value = *(volatile u8 *)(MCF5445X_PCI_CONFIG_BASE+(reg&3));
- + break;
- + case 2:
- + *value = le16_to_cpu(*(volatile u16 *)
- + (MCF5445X_PCI_CONFIG_BASE + (reg&2)));
- + break;
- + case 4:
- + *value = le32_to_cpu(*(volatile u32 *)
- + (MCF5445X_PCI_CONFIG_BASE));
- + break;
- + }
- +
- + /* clear config mode */
- + MCF_PCI_PCICAR = ~MCF_PCI_PCICAR_E;
- + __asm__ __volatile__("nop");
- +
- + return 0;
- +}
- +
- +/*
- + * int mcf5445x_pci_config_write(unsigned int seg, unsigned int bus,
- + * unsigned int devfn, int reg,
- + * u32 *value)
- + *
- + * Write to PCI configuration space
- + */
- +int mcf5445x_pci_config_write(unsigned int seg, unsigned int bus,
- + unsigned int devfn, int reg, int len, u32 value)
- +{
- + u32 addr = MCF_PCI_PCICAR_BUSNUM(bus) |
- + MCF_PCI_PCICAR_DEVNUM(PCI_SLOT(devfn)) |
- + MCF_PCI_PCICAR_FUNCNUM(PCI_FUNC(devfn)) |
- + MCF_PCI_PCICAR_DWORD(reg) |
- + MCF_PCI_PCICAR_E;
- +
- + if ((bus > 255) || (devfn > 255) || (reg > 255))
- + return -EINVAL;
- +
- + /* setup for config mode */
- + MCF_PCI_PCICAR = addr;
- + __asm__ __volatile__("nop");
- +
- + switch (len) {
- + case 1:
- + *(volatile u8 *)(MCF5445X_PCI_CONFIG_BASE+(reg&3)) = (u8)value;
- + break;
- + case 2:
- + *(volatile u16 *)(MCF5445X_PCI_CONFIG_BASE+(reg&2)) =
- + cpu_to_le16((u16)value);
- + break;
- + case 4:
- + *(volatile u32 *)(MCF5445X_PCI_CONFIG_BASE) =
- + cpu_to_le32(value);
- + break;
- + }
- +
- + /* clear config mode */
- + MCF_PCI_PCICAR = ~MCF_PCI_PCICAR_E;
- + __asm__ __volatile__("nop");
- +
- + return 0;
- +}
- +
- +/* hardware operations */
- +static struct pci_raw_ops mcf5445x_pci_ops = {
- + .read = mcf5445x_pci_config_read,
- + .write = mcf5445x_pci_config_write,
- +};
- +
- +/*
- + * irqreturn_t mcf5445x_pci_interrupt( int irq, void *dev)
- + *
- + * PCI controller interrupt handler.
- + */
- +static irqreturn_t
- +mcf5445x_pci_interrupt(int irq, void *dev)
- +{
- + u32 status = MCF_PCI_PCIGSCR;
- +#ifdef DEBUG
- + printk(KERN_INFO "PCI: Controller irq status=0x%08x\n", status);
- +#endif
- + /* clear */
- + MCF_PCI_PCIGSCR = status;
- +
- + return IRQ_HANDLED;
- +}
- +
- +/*
- + * irqreturn_t mcf5445x_pci_arb_interrupt( int irq, void *dev)
- + *
- + * PCI Arbiter interrupt handler.
- + */
- +static irqreturn_t
- +mcf5445x_pci_arb_interrupt(int irq, void *dev)
- +{
- + u32 status = MCF_PCIARB_PASR;
- +#ifdef DEBUG
- + printk(KERN_INFO "PCI: Arbiter irq status=0x%08x\n", status);
- +#endif
- + /* clear */
- + MCF_PCIARB_PASR = status;
- + return IRQ_HANDLED;
- +}
- +
- +/*
- + * struct pci_bus_info *init_mcf5445x_pci(void)
- + *
- + * Machine specific initialisation:
- + *
- + * - Allocate and initialise a 'pci_bus_info' structure
- + * - Initialize hardware
- + *
- + * Result: pointer to 'pci_bus_info' structure.
- + */
- +int __init
- +init_mcf5445x_pci(void)
- +{
- + /*
- + * Initialize the PCI core
- + */
- +
- + /* arbitration controller */
- + MCF_PCIARB_PACR = MCF_PCIARB_PACR_INTMPRI |
- + MCF_PCIARB_PACR_EXTMPRI(0x0f) |
- + MCF_PCIARB_PACR_INTMINTEN |
- + MCF_PCIARB_PACR_EXTMINTEN(0x0f);
- +
- + /* pci pin assignment regs */
- + MCF_GPIO_PAR_PCI = MCF_GPIO_PAR_PCI_GNT0 |
- + MCF_GPIO_PAR_PCI_GNT1 |
- + MCF_GPIO_PAR_PCI_GNT2 |
- + MCF_GPIO_PAR_PCI_GNT3_GNT3 |
- + MCF_GPIO_PAR_PCI_REQ0 |
- + MCF_GPIO_PAR_PCI_REQ1 |
- + MCF_GPIO_PAR_PCI_REQ2 |
- + MCF_GPIO_PAR_PCI_REQ3_REQ3;
- +
- + /* target control reg */
- + MCF_PCI_PCITCR = MCF_PCI_PCITCR_P |
- + MCF_PCI_PCITCR_WCT(8);
- +
- + /* PCI MEM address */
- + MCF_PCI_PCIIW0BTAR = 0xA007A000;
- +
- + /* PCI MEM address */
- + MCF_PCI_PCIIW1BTAR = 0xA803A800;
- +
- + /* PCI IO address */
- + MCF_PCI_PCIIW2BTAR = 0xAC03AC00;
- +
- + /* window control */
- + MCF_PCI_PCIIWCR = MCF_PCI_PCIIWCR_WINCTRL0_ENABLE |
- + MCF_PCI_PCIIWCR_WINCTRL0_MEMREAD |
- + MCF_PCI_PCIIWCR_WINCTRL1_ENABLE |
- + MCF_PCI_PCIIWCR_WINCTRL1_MEMREAD |
- + MCF_PCI_PCIIWCR_WINCTRL2_ENABLE |
- + MCF_PCI_PCIIWCR_WINCTRL2_IO;
- +
- + /* initiator control reg */
- + MCF_PCI_PCIICR = 0x00ff;
- +
- + /* type 0 - command */
- + MCF_PCI_PCISCR = MCF_PCI_PCISCR_MW | /* mem write/inval */
- + MCF_PCI_PCISCR_B | /* bus master enable */
- + MCF_PCI_PCISCR_M; /* mem access enable */
- +
- + /* type 0 - config reg */
- + MCF_PCI_PCICR1 = MCF_PCI_PCICR1_CACHELINESIZE(8) |
- + MCF_PCI_PCICR1_LATTIMER(0xff);
- +
- + /* type 0 - config 2 reg */
- + MCF_PCI_PCICR2 = 0;
- +
- + /* target control reg */
- + MCF_PCI_PCITCR2 = MCF_PCI_PCITCR2_B0E |
- + MCF_PCI_PCITCR2_B4E;
- +
- + /* translate addresses from PCI[0] to CF[SDRAM] */
- + MCF_PCI_PCITBATR0 = MCF_RAMBAR1 | MCF_PCI_PCITBATR0_EN;
- + MCF_PCI_PCITBATR4 = MCF_RAMBAR1 | MCF_PCI_PCITBATR4_EN;
- +
- + /* setup controller interrupt handlers */
- + if (request_irq(55+128, mcf5445x_pci_interrupt, IRQF_SHARED,
- + "PCI Controller", NULL))
- + printk(KERN_ERR "PCI: Unable to register controller irq\n");
- +
- + if (request_irq (56+128, mcf5445x_pci_arb_interrupt, IRQF_SHARED, "PCI Arbiter", NULL))
- + printk(KERN_ERR "PCI: Unable to register arbiter irq\n");
- +
- + /* global control - clear reset bit */
- + MCF_PCI_PCIGSCR = MCF_PCI_PCIGSCR_SEE |
- + MCF_PCI_PCIGSCR_PEE;
- +
- + /* let everything settle */
- + udelay(1000);
- +
- + /* allocate bus ioport resource */
- + if (request_resource(&ioport_resource, &pci_ioport_resource) < 0)
- + printk(KERN_ERR "PCI: Unable to alloc ioport resource\n");
- +
- + /* allocate bus iomem resource */
- + if (request_resource(&iomem_resource, &pci_iomem_resource) < 0)
- + printk(KERN_ERR "PCI: Unable to alloc iomem resource\n");
- +
- + /* setup FPGA to route PCI to IRQ3(67), SW7 to IRQ7, SW6 to IRQ4 */
- + set_fpga(FPGA_PCI_IRQ_ENABLE, 0x00000000);
- + set_fpga(FPGA_PCI_IRQ_ROUTE, 0x00000039);
- + set_fpga(FPGA_SEVEN_LED, 0x000000FF);
- +
- + raw_pci_ops = &mcf5445x_pci_ops;
- +
- + return 0;
- +}
- +
- +/*
- + * DEBUGGING
- + */
- +
- +#ifdef DEBUG
- +struct regdump {
- + u32 addr;
- + char regname[16];
- +};
- +
- +struct regdump type0regs[] = {
- + { 0xfc0a8000, "PCIIDR" },
- + { 0xfc0a8004, "PCISCR" },
- + { 0xfc0a8008, "PCICCRIR" },
- + { 0xfc0a800c, "PCICR1" },
- + { 0xfc0a8010, "PCIBAR0" },
- + { 0xfc0a8014, "PCIBAR1" },
- + { 0xfc0a8018, "PCIBAR2" },
- + { 0xfc0a801c, "PCIBAR3" },
- + { 0xfc0a8020, "PCIBAR4" },
- + { 0xfc0a8024, "PCIBAR5" },
- + { 0xfc0a8028, "PCICCPR" },
- + { 0xfc0a802c, "PCISID" },
- + { 0xfc0a8030, "PCIERBAR" },
- + { 0xfc0a8034, "PCICPR" },
- + { 0xfc0a803c, "PCICR2" },
- + { 0, "" }
- +};
- +
- +struct regdump genregs[] = {
- + { 0xfc0a8060, "PCIGSCR" },
- + { 0xfc0a8064, "PCITBATR0" },
- + { 0xfc0a8068, "PCITBATR1" },
- + { 0xfc0a806c, "PCITCR1" },
- + { 0xfc0a8070, "PCIIW0BTAR" },
- + { 0xfc0a8074, "PCIIW1BTAR" },
- + { 0xfc0a8078, "PCIIW2BTAR" },
- + { 0xfc0a8080, "PCIIWCR" },
- + { 0xfc0a8084, "PCIICR" },
- + { 0xfc0a8088, "PCIISR" },
- + { 0xfc0a808c, "PCITCR2" },
- + { 0xfc0a8090, "PCITBATR0" },
- + { 0xfc0a8094, "PCITBATR1" },
- + { 0xfc0a8098, "PCITBATR2" },
- + { 0xfc0a809c, "PCITBATR3" },
- + { 0xfc0a80a0, "PCITBATR4" },
- + { 0xfc0a80a4, "PCITBATR5" },
- + { 0xfc0a80a8, "PCIINTR" },
- + { 0xfc0a80f8, "PCICAR" },
- + { 0, "" }
- +};
- +
- +struct regdump arbregs[] = {
- + { 0xfc0ac000, "PACR" },
- + { 0xfc0ac004, "PASR" }, /* documentation error */
- + { 0, "" }
- +};
- +
- +/*
- + * void mcf5445x_pci_dumpregs()
- + *
- + * Dump out all the PCI registers
- + */
- +void
- +mcf5445x_pci_dumpregs(void)
- +{
- + struct regdump *reg;
- +
- + printk(KERN_INFO "*** MCF5445x PCI TARGET 0 REGISTERS ***\n");
- +
- + reg = type0regs;
- + while (reg->addr) {
- + printk(KERN_INFO "0x%08x 0x%08x %s\n", reg->addr,
- + *((u32 *)reg->addr), reg->regname);
- + reg++;
- + }
- +
- + printk(KERN_INFO "\n*** MCF5445x PCI GENERAL REGISTERS ***\n");
- + reg = genregs;
- + while (reg->addr) {
- + printk(KERN_INFO "0x%08x 0x%08x %s\n", reg->addr,
- + *((u32 *)reg->addr), reg->regname);
- + reg++;
- + }
- + printk(KERN_INFO "\n*** MCF5445x PCI ARBITER REGISTERS ***\n");
- + reg = arbregs;
- + while (reg->addr) {
- + printk(KERN_INFO "0x%08x 0x%08x %s\n", reg->addr,
- + *((u32 *)reg->addr), reg->regname);
- + reg++;
- + }
- +}
- +#endif /* DEBUG */
- --- /dev/null
- +++ b/arch/m68k/coldfire/muldi3.S
- @@ -0,0 +1,64 @@
- +/*
- + * Coldfire muldi3 assembly verion
- + */
- +
- +#include <linux/linkage.h>
- +.globl __muldi3
- +
- +ENTRY(__muldi3)
- + linkw %fp,#0
- + lea %sp@(-32),%sp
- + moveml %d2-%d7/%a2-%a3,%sp@
- + moveal %fp@(8), %a2
- + moveal %fp@(12), %a3
- + moveal %fp@(16), %a0
- + moveal %fp@(20),%a1
- + movel %a3,%d2
- + andil #65535,%d2
- + movel %a3,%d3
- + clrw %d3
- + swap %d3
- + movel %a1,%d0
- + andil #65535,%d0
- + movel %a1,%d1
- + clrw %d1
- + swap %d1
- + movel %d2,%d7
- + mulsl %d0,%d7
- + movel %d2,%d4
- + mulsl %d1,%d4
- + movel %d3,%d2
- + mulsl %d0,%d2
- + mulsl %d1,%d3
- + movel %d7,%d0
- + clrw %d0
- + swap %d0
- + addl %d0,%d4
- + addl %d2,%d4
- + cmpl %d4,%d2
- + blss 1f
- + addil #65536,%d3
- +1:
- + movel %d4,%d0
- + clrw %d0
- + swap %d0
- + movel %d3,%d5
- + addl %d0,%d5
- + movew %d4,%d6
- + swap %d6
- + movew %d7,%d6
- + movel %d5,%d0
- + movel %d6,%d1
- + movel %a3,%d2
- + movel %a0,%d3
- + mulsl %d3,%d2
- + movel %a2,%d3
- + movel %a1,%d4
- + mulsl %d4,%d3
- + addl %d3,%d2
- + movel %d2,%d0
- + addl %d5,%d0
- + moveml %sp@, %d2-%d7/%a2-%a3
- + lea %sp@(32),%sp
- + unlk %fp
- + rts
- --- /dev/null
- +++ b/arch/m68k/coldfire/pci.c
- @@ -0,0 +1,245 @@
- +/*
- + * linux/arch/m68k/coldfire/pci.c
- + *
- + * PCI initialization for Coldfire architectures.
- + *
- + * Currently Supported:
- + * M5445x
- + *
- + * Copyright (c) 2007 Freescale Semiconductor, Inc.
- + * Kurt Mahan <[email protected]>
- + */
- +
- +#include <linux/kernel.h>
- +#include <linux/init.h>
- +#include <linux/pci.h>
- +
- +#include <asm/mcfsim.h>
- +#include <asm/pci.h>
- +
- +/* pci ops for reading/writing config */
- +struct pci_raw_ops *raw_pci_ops;
- +
- +/* pci debug flag */
- +static int debug_pci;
- +
- +#ifdef CONFIG_M54455
- +extern int init_mcf5445x_pci(void);
- +extern void mcf5445x_conf_device(struct pci_dev *dev);
- +extern void mcf5445x_pci_dumpregs(void);
- +
- +extern struct resource pci_ioport_resource;
- +extern struct resource pci_iomem_resource;
- +#endif
- +
- +static int
- +pci_read(struct pci_bus *bus, unsigned int devfn, int where,
- + int size, u32 *value)
- +{
- + return raw_pci_ops->read(0, bus->number, devfn, where, size, value);
- +}
- +
- +static int
- +pci_write(struct pci_bus *bus, unsigned int devfn, int where,
- + int size, u32 value)
- +{
- + return raw_pci_ops->write(0, bus->number, devfn, where, size, value);
- +}
- +
- +struct pci_ops pci_root_ops = {
- + .read = pci_read,
- + .write = pci_write,
- +};
- +
- +/*
- + * pcibios_setup(char *)
- + *
- + * Initialize the pcibios based on cmd line params.
- + */
- +char * __init
- +pcibios_setup(char *str)
- +{
- + if (!strcmp(str, "debug")) {
- + debug_pci = 1;
- + return NULL;
- + }
- + return str;
- +}
- +
- +/*
- + * 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 have be mirrored at 0x0100-0x03ff..
- + */
- +void
- +pcibios_align_resource(void *data, struct resource *res, resource_size_t size,
- + resource_size_t align)
- +{
- + struct pci_dev *dev = data;
- +
- + if (res->flags & IORESOURCE_IO) {
- + resource_size_t start = res->start;
- +
- + if (size > 0x100)
- + printk(KERN_ERR "PCI: I/O Region %s/%d too large"
- + " (%ld bytes)\n", pci_name(dev),
- + dev->resource - res, (long int)size);
- +
- + if (start & 0x300) {
- + start = (start + 0x3ff) & ~0x3ff;
- + res->start = start;
- + }
- + }
- +}
- +
- +/*
- + * Swizzle the device pin each time we cross a bridge
- + * and return the slot number.
- + */
- +static u8 __devinit
- +pcibios_swizzle(struct pci_dev *dev, u8 *pin)
- +{
- + return 0;
- +}
- +
- +/*
- + * Map a slot/pin to an IRQ.
- + */
- +static int
- +pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
- +{
- + return 0x43;
- +}
- +
- +/*
- + * pcibios_update_irq(struct pci_dev *dev, int irq)
- + *
- + * Update a PCI interrupt.
- + */
- +void __init
- +pcibios_update_irq(struct pci_dev *dev, int irq)
- +{
- + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
- +}
- +
- +/*
- + * pcibios_enable_device(struct pci_dev *dev, int mask)
- + *
- + * Enable a device on the PCI bus.
- + */
- +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++) {
- + 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;
- + }
- + 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);
- +#ifdef CONFIG_M54455
- + mcf5445x_conf_device(dev);
- +#endif
- + }
- +
- + return 0;
- +}
- +
- +/*
- + * pcibios_fixup_bus(struct pci_bus *bus)
- + */
- +void __init
- +pcibios_fixup_bus(struct pci_bus *bus)
- +{
- + struct pci_dev *dev = bus->self;
- +
- + if (!dev) {
- + /* Root bus. */
- +#ifdef CONFIG_M54455
- + bus->resource[0] = &pci_ioport_resource;
- + bus->resource[1] = &pci_iomem_resource;
- +#endif
- + }
- +}
- +
- +/*
- + * pcibios_init(void)
- + *
- + * Allocate/initialize low level pci bus/devices.
- + */
- +static int __init
- +pcibios_init(void)
- +{
- + struct pci_bus *bus;
- +
- + if (!raw_pci_ops) {
- + printk(KERN_WARNING "PCIBIOS: FATAL: NO PCI Hardware found\n");
- + return 0;
- + }
- +
- + /* allocate and scan the (only) bus */
- + bus = pci_scan_bus_parented(NULL, 0, &pci_root_ops, NULL);
- +
- + /* setup everything */
- + if (bus) {
- + /* compute the bridge window sizes */
- + pci_bus_size_bridges(bus);
- +
- + /* (re)assign device resources */
- + pci_bus_assign_resources(bus);
- +
- + /* add the bus to the system */
- + pci_bus_add_devices(bus);
- +
- + /* fixup irqs */
- + pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
- + }
- +
- + return 0;
- +}
- +
- +/*
- + * pci_init(void)
- + *
- + * Initialize the PCI Hardware.
- + */
- +static int __init
- +pci_init(void)
- +{
- +#if defined(CONFIG_M54455)
- + init_mcf5445x_pci();
- +#endif
- + if (!raw_pci_ops)
- + printk(KERN_ERR "PCI: FATAL: NO PCI Detected\n");
- +
- + return 0;
- +}
- +
- +/* low level hardware (first) */
- +arch_initcall(pci_init);
- +
- +/* basic bios init (second) */
- +subsys_initcall(pcibios_init);
- --- /dev/null
- +++ b/arch/m68k/coldfire/signal.c
- @@ -0,0 +1,868 @@
- +/*
- + * linux/arch/m68k/kernel/signal.c
- + *
- + * Copyright (C) 1991, 1992 Linus Torvalds
- + *
- + * 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.
- + */
- +
- +/*
- + * Derived from m68k/kernel/signal.c and the original authors are credited
- + * there.
- + *
- + * Coldfire support by:
- + * Matt Waddel [email protected]
- + * Copyright Freescale Semiconductor, Inc 2007
- + */
- +
- +#include <linux/sched.h>
- +#include <linux/mm.h>
- +#include <linux/kernel.h>
- +#include <linux/signal.h>
- +#include <linux/syscalls.h>
- +#include <linux/errno.h>
- +#include <linux/wait.h>
- +#include <linux/ptrace.h>
- +#include <linux/unistd.h>
- +#include <linux/stddef.h>
- +#include <linux/highuid.h>
- +#include <linux/personality.h>
- +#include <linux/tty.h>
- +#include <linux/binfmts.h>
- +
- +#include <asm/setup.h>
- +#include <asm/cf_uaccess.h>
- +#include <asm/cf_pgtable.h>
- +#include <asm/traps.h>
- +#include <asm/ucontext.h>
- +
- +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
- +
- +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
- +
- +const int frame_extra_sizes[16] = {
- + [1] = -1,
- + [2] = sizeof(((struct frame *)0)->un.fmt2),
- + [3] = sizeof(((struct frame *)0)->un.fmt3),
- + [4] = 0,
- + [5] = -1,
- + [6] = -1,
- + [7] = sizeof(((struct frame *)0)->un.fmt7),
- + [8] = -1,
- + [9] = sizeof(((struct frame *)0)->un.fmt9),
- + [10] = sizeof(((struct frame *)0)->un.fmta),
- + [11] = sizeof(((struct frame *)0)->un.fmtb),
- + [12] = -1,
- + [13] = -1,
- + [14] = -1,
- + [15] = -1,
- +};
- +
- +/*
- + * Atomically swap in the new signal mask, and wait for a signal.
- + */
- +asmlinkage int do_sigsuspend(struct pt_regs *regs)
- +{
- + old_sigset_t mask = regs->d3;
- + sigset_t saveset;
- +
- + mask &= _BLOCKABLE;
- + spin_lock_irq(¤t->sighand->siglock);
- + saveset = current->blocked;
- + siginitset(¤t->blocked, mask);
- + recalc_sigpending();
- + spin_unlock_irq(¤t->sighand->siglock);
- +
- + regs->d0 = -EINTR;
- + while (1) {
- + current->state = TASK_INTERRUPTIBLE;
- + schedule();
- + if (do_signal(&saveset, regs))
- + return -EINTR;
- + }
- +}
- +
- +asmlinkage int
- +do_rt_sigsuspend(struct pt_regs *regs)
- +{
- + sigset_t __user *unewset = (sigset_t __user *)regs->d1;
- + size_t sigsetsize = (size_t)regs->d2;
- + sigset_t saveset, 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);
- +
- + spin_lock_irq(¤t->sighand->siglock);
- + saveset = current->blocked;
- + current->blocked = newset;
- + recalc_sigpending();
- + spin_unlock_irq(¤t->sighand->siglock);
- +
- + regs->d0 = -EINTR;
- + while (1) {
- + current->state = TASK_INTERRUPTIBLE;
- + schedule();
- + if (do_signal(&saveset, regs))
- + return -EINTR;
- + }
- +}
- +
- +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;
- +}
- +
- +asmlinkage int
- +sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
- +{
- + return do_sigaltstack(uss, uoss, rdusp());
- +}
- +
- +
- +/*
- + * Do a signal return; undo the signal stack.
- + *
- + * Keep the return code on the stack quadword aligned!
- + * That makes the cache flush below easier.
- + */
- +
- +struct sigframe
- +{
- + char __user *pretcode;
- + int sig;
- + int code;
- + struct sigcontext __user *psc;
- + char retcode[16];
- + unsigned long extramask[_NSIG_WORDS-1];
- + struct sigcontext sc;
- +};
- +
- +struct rt_sigframe
- +{
- + char __user *pretcode;
- + int sig;
- + struct siginfo __user *pinfo;
- + void __user *puc;
- + char retcode[16];
- + struct siginfo info;
- + struct ucontext uc;
- +};
- +
- +#define FPCONTEXT_SIZE 216
- +#define uc_fpstate uc_filler[0]
- +#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
- +#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
- +
- +#ifdef CONFIG_FPU
- +static unsigned char fpu_version; /* version num of fpu, set by setup_frame */
- +
- +static inline int restore_fpu_state(struct sigcontext *sc)
- +{
- + int err = 1;
- +
- + if (FPU_IS_EMU) {
- + /* restore registers */
- + memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
- + memcpy(current->thread.fp, sc->sc_fpregs, 24);
- + return 0;
- + }
- +
- + if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
- + /* Verify the frame format. */
- + if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version))
- + goto out;
- + if (CPU_IS_020_OR_030) {
- + if (m68k_fputype & FPU_68881 &&
- + !(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4))
- + goto out;
- + if (m68k_fputype & FPU_68882 &&
- + !(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4))
- + goto out;
- + } else if (CPU_IS_040) {
- + if (!(sc->sc_fpstate[1] == 0x00 ||
- + sc->sc_fpstate[1] == 0x28 ||
- + sc->sc_fpstate[1] == 0x60))
- + goto out;
- + } else if (CPU_IS_060) {
- + if (!(sc->sc_fpstate[3] == 0x00 ||
- + sc->sc_fpstate[3] == 0x60 ||
- + sc->sc_fpstate[3] == 0xe0))
- + goto out;
- + } else
- + goto out;
- +
- + }
- + err = 0;
- +
- +out:
- + return err;
- +}
- +
- +static inline int rt_restore_fpu_state(struct ucontext __user *uc)
- +{
- + unsigned char fpstate[FPCONTEXT_SIZE];
- + int context_size = CPU_IS_060 ? 8 : 0;
- + fpregset_t fpregs;
- + int err = 1;
- +
- + if (FPU_IS_EMU) {
- + /* restore fpu control register */
- + if (__copy_from_user(current->thread.fpcntl,
- + uc->uc_mcontext.fpregs.f_fpcntl, 12))
- + goto out;
- + /* restore all other fpu register */
- + if (__copy_from_user(current->thread.fp,
- + uc->uc_mcontext.fpregs.f_fpregs, 96))
- + goto out;
- + return 0;
- + }
- +
- + if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
- + goto out;
- + if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
- + if (!CPU_IS_060)
- + context_size = fpstate[1];
- + /* Verify the frame format. */
- + if (!CPU_IS_060 && (fpstate[0] != fpu_version))
- + goto out;
- + if (CPU_IS_020_OR_030) {
- + if (m68k_fputype & FPU_68881 &&
- + !(context_size == 0x18 || context_size == 0xb4))
- + goto out;
- + if (m68k_fputype & FPU_68882 &&
- + !(context_size == 0x38 || context_size == 0xd4))
- + goto out;
- + } else if (CPU_IS_040) {
- + if (!(context_size == 0x00 ||
- + context_size == 0x28 ||
- + context_size == 0x60))
- + goto out;
- + } else if (CPU_IS_060) {
- + if (!(fpstate[3] == 0x00 ||
- + fpstate[3] == 0x60 ||
- + fpstate[3] == 0xe0))
- + goto out;
- + } else
- + goto out;
- + if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
- + sizeof(fpregs)))
- + goto out;
- + }
- + if (context_size &&
- + __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,
- + context_size))
- + goto out;
- + err = 0;
- +
- +out:
- + return err;
- +}
- +#endif
- +
- +static inline int
- +restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc,
- + void __user *fp, int *pd0)
- +{
- + int fsize, formatvec;
- + struct sigcontext context;
- + int err = 0;
- +
- + /* get previous context */
- + if (copy_from_user(&context, usc, sizeof(context)))
- + goto badframe;
- +
- + /* restore passed registers */
- + regs->d1 = context.sc_d1;
- + regs->a0 = context.sc_a0;
- + regs->a1 = context.sc_a1;
- + regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
- + regs->pc = context.sc_pc;
- + regs->orig_d0 = -1; /* disable syscall checks */
- + wrusp(context.sc_usp);
- + formatvec = context.sc_formatvec;
- + regs->format = formatvec >> 12;
- + regs->vector = formatvec & 0xfff;
- +
- +#ifdef CONFIG_FPU
- + err = restore_fpu_state(&context);
- +#endif
- +
- + fsize = frame_extra_sizes[regs->format];
- + if (fsize < 0) {
- + /*
- + * user process trying to return with weird frame format
- + */
- +#ifdef DEBUG
- + printk(KERN_DEBUG "user process returning with weird \
- + frame format\n");
- +#endif
- + goto badframe;
- + }
- +
- + /* OK. Make room on the supervisor stack for the extra junk,
- + * if necessary.
- + */
- +
- + {
- + struct switch_stack *sw = (struct switch_stack *)regs - 1;
- + regs->d0 = context.sc_d0;
- +#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
- + __asm__ __volatile__
- + (" movel %0,%/sp\n\t"
- + " bra ret_from_signal\n"
- + "4:\n"
- + ".section __ex_table,\"a\"\n"
- + " .align 4\n"
- + " .long 2b,4b\n"
- + ".previous"
- + : /* no outputs, it doesn't ever return */
- + : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
- + "n" (frame_offset), "a" (fp)
- + : "a0");
- +#undef frame_offset
- + /*
- + * If we ever get here an exception occurred while
- + * building the above stack-frame.
- + */
- + goto badframe;
- + }
- +
- + *pd0 = context.sc_d0;
- + return err;
- +
- +badframe:
- + return 1;
- +}
- +
- +static inline int
- +rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
- + struct ucontext __user *uc, int *pd0)
- +{
- + int fsize, temp;
- + greg_t __user *gregs = uc->uc_mcontext.gregs;
- + unsigned long usp;
- + int err;
- +
- + err = __get_user(temp, &uc->uc_mcontext.version);
- + if (temp != MCONTEXT_VERSION)
- + goto badframe;
- + /* restore passed registers */
- + err |= __get_user(regs->d0, &gregs[0]);
- + err |= __get_user(regs->d1, &gregs[1]);
- + err |= __get_user(regs->d2, &gregs[2]);
- + err |= __get_user(regs->d3, &gregs[3]);
- + err |= __get_user(regs->d4, &gregs[4]);
- + err |= __get_user(regs->d5, &gregs[5]);
- + err |= __get_user(sw->d6, &gregs[6]);
- + err |= __get_user(sw->d7, &gregs[7]);
- + err |= __get_user(regs->a0, &gregs[8]);
- + err |= __get_user(regs->a1, &gregs[9]);
- + err |= __get_user(regs->a2, &gregs[10]);
- + err |= __get_user(sw->a3, &gregs[11]);
- + err |= __get_user(sw->a4, &gregs[12]);
- + err |= __get_user(sw->a5, &gregs[13]);
- + err |= __get_user(sw->a6, &gregs[14]);
- + err |= __get_user(usp, &gregs[15]);
- + wrusp(usp);
- + err |= __get_user(regs->pc, &gregs[16]);
- + err |= __get_user(temp, &gregs[17]);
- + regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
- + regs->orig_d0 = -1; /* disable syscall checks */
- + err |= __get_user(temp, &uc->uc_formatvec);
- + regs->format = temp >> 12;
- + regs->vector = temp & 0xfff;
- +
- +#ifdef CONFIG_FPU
- + err |= rt_restore_fpu_state(uc);
- +#endif
- +
- + if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
- + goto badframe;
- +
- + fsize = frame_extra_sizes[regs->format];
- + if (fsize < 0) {
- + /*
- + * user process trying to return with weird frame format
- + */
- +#ifdef DEBUG
- + printk(KERN_DEBUG "user process returning with weird \
- + frame format\n");
- +#endif
- + goto badframe;
- + }
- +
- + /* OK. Make room on the supervisor stack for the extra junk,
- + * if necessary.
- + */
- +
- + {
- +#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
- + __asm__ __volatile__
- + (" movel %0,%/sp\n\t"
- + " bra ret_from_signal\n"
- + "4:\n"
- + ".section __ex_table,\"a\"\n"
- + " .align 4\n"
- + " .long 2b,4b\n"
- + ".previous"
- + : /* no outputs, it doesn't ever return */
- + : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
- + "n" (frame_offset), "a" (&uc->uc_extra)
- + : "a0");
- +#undef frame_offset
- + /*
- + * If we ever get here an exception occurred while
- + * building the above stack-frame.
- + */
- + goto badframe;
- + }
- +
- + *pd0 = regs->d0;
- + return err;
- +
- +badframe:
- + return 1;
- +}
- +
- +asmlinkage int do_sigreturn(unsigned long __unused)
- +{
- + struct switch_stack *sw = (struct switch_stack *) &__unused;
- + struct pt_regs *regs = (struct pt_regs *) (sw + 1);
- + unsigned long usp = rdusp();
- + struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
- + sigset_t set;
- + int d0;
- +
- + if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
- + goto badframe;
- + if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
- + (_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 + 1, &d0))
- + goto badframe;
- + return d0;
- +
- +badframe:
- + force_sig(SIGSEGV, current);
- + return 0;
- +}
- +
- +asmlinkage int do_rt_sigreturn(unsigned long __unused)
- +{
- + struct switch_stack *sw = (struct switch_stack *) &__unused;
- + struct pt_regs *regs = (struct pt_regs *) (sw + 1);
- + unsigned long usp = rdusp();
- + struct rt_sigframe __user *frame =
- + (struct rt_sigframe __user *)(usp - 4);
- + sigset_t set;
- + int d0;
- +
- + 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 (rt_restore_ucontext(regs, sw, &frame->uc, &d0))
- + goto badframe;
- + return d0;
- +
- +badframe:
- + force_sig(SIGSEGV, current);
- + return 0;
- +}
- +
- +#ifdef CONFIG_FPU
- +/*
- + * Set up a signal frame.
- + */
- +
- +static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
- +{
- + if (FPU_IS_EMU) {
- + /* save registers */
- + memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
- + memcpy(sc->sc_fpregs, current->thread.fp, 24);
- + return;
- + }
- +}
- +
- +static inline int rt_save_fpu_state(struct ucontext __user *uc,
- + struct pt_regs *regs)
- +{
- + int err = 0;
- +
- + if (FPU_IS_EMU) {
- + /* save fpu control register */
- + err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl,
- + current->thread.fpcntl, 12);
- + /* save all other fpu register */
- + err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
- + current->thread.fp, 96);
- + return err;
- + }
- +
- + return err;
- +}
- +#endif
- +
- +static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
- + unsigned long mask)
- +{
- + sc->sc_mask = mask;
- + sc->sc_usp = rdusp();
- + sc->sc_d0 = regs->d0;
- + sc->sc_d1 = regs->d1;
- + sc->sc_a0 = regs->a0;
- + sc->sc_a1 = regs->a1;
- + sc->sc_sr = regs->sr;
- + sc->sc_pc = regs->pc;
- + sc->sc_formatvec = regs->format << 12 | regs->vector;
- +#ifdef CONFIG_FPU
- + save_fpu_state(sc, regs);
- +#endif
- +}
- +
- +static inline int rt_setup_ucontext(struct ucontext __user *uc,
- + struct pt_regs *regs)
- +{
- + struct switch_stack *sw = (struct switch_stack *)regs - 1;
- + greg_t __user *gregs = uc->uc_mcontext.gregs;
- + int err = 0;
- +
- + err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
- + err |= __put_user(regs->d0, &gregs[0]);
- + err |= __put_user(regs->d1, &gregs[1]);
- + err |= __put_user(regs->d2, &gregs[2]);
- + err |= __put_user(regs->d3, &gregs[3]);
- + err |= __put_user(regs->d4, &gregs[4]);
- + err |= __put_user(regs->d5, &gregs[5]);
- + err |= __put_user(sw->d6, &gregs[6]);
- + err |= __put_user(sw->d7, &gregs[7]);
- + err |= __put_user(regs->a0, &gregs[8]);
- + err |= __put_user(regs->a1, &gregs[9]);
- + err |= __put_user(regs->a2, &gregs[10]);
- + err |= __put_user(sw->a3, &gregs[11]);
- + err |= __put_user(sw->a4, &gregs[12]);
- + err |= __put_user(sw->a5, &gregs[13]);
- + err |= __put_user(sw->a6, &gregs[14]);
- + err |= __put_user(rdusp(), &gregs[15]);
- + err |= __put_user(regs->pc, &gregs[16]);
- + err |= __put_user(regs->sr, &gregs[17]);
- + err |= __put_user((regs->format << 12) | regs->vector,
- + &uc->uc_formatvec);
- +#ifdef CONFIG_FPU
- + err |= rt_save_fpu_state(uc, regs);
- +#endif
- + return err;
- +}
- +
- +extern void IcacheInvalidateCacheBlock(void *, unsigned long);
- +static inline void push_cache(unsigned long vaddr)
- +{
- + IcacheInvalidateCacheBlock((void *)vaddr, 8);
- +}
- +
- +static inline void __user *
- +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
- +{
- + unsigned long usp;
- +
- + /* Default to using normal stack. */
- + usp = rdusp();
- +
- + /* This is the X/Open sanctioned signal stack switching. */
- + if (ka->sa.sa_flags & SA_ONSTACK) {
- + if (!sas_ss_flags(usp))
- + usp = current->sas_ss_sp + current->sas_ss_size;
- + }
- + return (void __user *)((usp - frame_size) & -8UL);
- +}
- +
- +static void setup_frame(int sig, struct k_sigaction *ka,
- + sigset_t *set, struct pt_regs *regs)
- +{
- + struct sigframe __user *frame;
- + int fsize = frame_extra_sizes[regs->format];
- + struct sigcontext context;
- + int err = 0;
- +
- + if (fsize < 0) {
- +#ifdef DEBUG
- + printk(KERN_DEBUG "setup_frame: Unknown frame format %#x\n",
- + regs->format);
- +#endif
- + goto give_sigsegv;
- + }
- +
- + frame = get_sigframe(ka, regs, sizeof(*frame));
- +
- + err |= __put_user((current_thread_info()->exec_domain
- + && current_thread_info()->exec_domain->signal_invmap
- + && sig < 32
- + ? current_thread_info()->exec_domain->signal_invmap[sig]
- + : sig),
- + &frame->sig);
- +
- + err |= __put_user(regs->vector, &frame->code);
- + err |= __put_user(&frame->sc, &frame->psc);
- +
- + if (_NSIG_WORDS > 1)
- + err |= copy_to_user(frame->extramask, &set->sig[1],
- + sizeof(frame->extramask));
- +
- + setup_sigcontext(&context, regs, set->sig[0]);
- + err |= copy_to_user(&frame->sc, &context, sizeof(context));
- +
- + /* Set up to return from userspace. */
- + err |= __put_user(frame->retcode, &frame->pretcode);
- + /* moveq #,d0; trap #0 */
- + err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
- + (long __user *)(frame->retcode));
- +
- + if (err)
- + goto give_sigsegv;
- +
- + push_cache((unsigned long) &frame->retcode);
- +
- + /* Set up registers for signal handler */
- + wrusp((unsigned long) frame);
- + regs->pc = (unsigned long) ka->sa.sa_handler;
- +
- +adjust_stack:
- + /* Prepare to skip over the extra stuff in the exception frame. */
- + if (regs->stkadj) {
- + struct pt_regs *tregs =
- + (struct pt_regs *)((ulong)regs + regs->stkadj);
- +#ifdef DEBUG
- + printk(KERN_DEBUG "Performing stackadjust=%04x\n",
- + regs->stkadj);
- +#endif
- + /* This must be copied with decreasing addresses to
- + handle overlaps. */
- + tregs->vector = 0;
- + tregs->format = 0;
- + tregs->pc = regs->pc;
- + tregs->sr = regs->sr;
- + }
- + return;
- +
- +give_sigsegv:
- + force_sigsegv(sig, current);
- + goto adjust_stack;
- +}
- +
- +static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- + sigset_t *set, struct pt_regs *regs)
- +{
- + struct rt_sigframe __user *frame;
- + int fsize = frame_extra_sizes[regs->format];
- + int err = 0;
- +
- + if (fsize < 0) {
- +#ifdef DEBUG
- + printk(KERN_DEBUG "setup_frame: Unknown frame format %#x\n",
- + regs->format);
- +#endif
- + goto give_sigsegv;
- + }
- +
- + frame = get_sigframe(ka, regs, sizeof(*frame));
- +
- + if (fsize) {
- + err |= copy_to_user(&frame->uc.uc_extra, regs + 1, fsize);
- + regs->stkadj = fsize;
- + }
- +
- + err |= __put_user((current_thread_info()->exec_domain
- + && current_thread_info()->exec_domain->signal_invmap
- + && sig < 32
- + ? current_thread_info()->exec_domain->signal_invmap[sig]
- + : sig),
- + &frame->sig);
- + err |= __put_user(&frame->info, &frame->pinfo);
- + err |= __put_user(&frame->uc, &frame->puc);
- + err |= copy_siginfo_to_user(&frame->info, info);
- +
- + /* Create the ucontext. */
- + err |= __put_user(0, &frame->uc.uc_flags);
- + err |= __put_user(NULL, &frame->uc.uc_link);
- + err |= __put_user((void __user *)current->sas_ss_sp,
- + &frame->uc.uc_stack.ss_sp);
- + err |= __put_user(sas_ss_flags(rdusp()),
- + &frame->uc.uc_stack.ss_flags);
- + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
- + err |= rt_setup_ucontext(&frame->uc, regs);
- + err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
- +
- + /* Set up to return from userspace. */
- + err |= __put_user(frame->retcode, &frame->pretcode);
- +
- + /* moveq #,d0; andi.l #,D0; trap #0 */
- + err |= __put_user(0x70AD0280, (long *)(frame->retcode + 0));
- + err |= __put_user(0x000000ff, (long *)(frame->retcode + 4));
- + err |= __put_user(0x4e400000, (long *)(frame->retcode + 8));
- +
- + if (err)
- + goto give_sigsegv;
- +
- + push_cache((unsigned long) &frame->retcode);
- +
- + /* Set up registers for signal handler */
- + wrusp((unsigned long) frame);
- + regs->pc = (unsigned long) ka->sa.sa_handler;
- +
- +adjust_stack:
- + /* Prepare to skip over the extra stuff in the exception frame. */
- + if (regs->stkadj) {
- + struct pt_regs *tregs =
- + (struct pt_regs *)((ulong)regs + regs->stkadj);
- +#ifdef DEBUG
- + printk(KERN_DEBUG "Performing stackadjust=%04x\n",
- + regs->stkadj);
- +#endif
- + /* This must be copied with decreasing addresses to
- + handle overlaps. */
- + tregs->vector = 0;
- + tregs->format = 0;
- + tregs->pc = regs->pc;
- + tregs->sr = regs->sr;
- + }
- + return;
- +
- +give_sigsegv:
- + force_sigsegv(sig, current);
- + goto adjust_stack;
- +}
- +
- +static inline void
- +handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
- +{
- + switch (regs->d0) {
- + case -ERESTARTNOHAND:
- + if (!has_handler)
- + goto do_restart;
- + regs->d0 = -EINTR;
- + break;
- +
- + case -ERESTARTSYS:
- + if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
- + regs->d0 = -EINTR;
- + break;
- + }
- + /* fallthrough */
- + case -ERESTARTNOINTR:
- +do_restart:
- + regs->d0 = regs->orig_d0;
- + regs->pc -= 2;
- + break;
- + }
- +}
- +
- +/*
- + * OK, we're invoking a handler
- + */
- +static void
- +handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
- + sigset_t *oldset, struct pt_regs *regs)
- +{
- + /* are we from a system call? */
- + if (regs->orig_d0 >= 0)
- + /* If so, check system call restarting.. */
- + handle_restart(regs, ka, 1);
- +
- + /* set up the stack frame */
- + if (ka->sa.sa_flags & SA_SIGINFO)
- + setup_rt_frame(sig, ka, info, oldset, regs);
- + else
- + setup_frame(sig, ka, oldset, regs);
- +
- + if (ka->sa.sa_flags & SA_ONESHOT)
- + ka->sa.sa_handler = SIG_DFL;
- +
- + spin_lock_irq(¤t->sighand->siglock);
- + sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
- + if (!(ka->sa.sa_flags & SA_NODEFER))
- + sigaddset(¤t->blocked, sig);
- + recalc_sigpending();
- + spin_unlock_irq(¤t->sighand->siglock);
- +}
- +
- +/*
- + * 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.
- + */
- +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
- +{
- + siginfo_t info;
- + struct k_sigaction ka;
- + int signr;
- +
- + current->thread.esp0 = (unsigned long) regs;
- +
- + if (!oldset)
- + oldset = ¤t->blocked;
- +
- + signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- + if (signr > 0) {
- + /* Whee! Actually deliver the signal. */
- + handle_signal(signr, &ka, &info, oldset, regs);
- + return 1;
- + }
- +
- + /* Did we come from a system call? */
- + if (regs->orig_d0 >= 0)
- + /* Restart the system call - no handlers present */
- + handle_restart(regs, NULL, 0);
- +
- + return 0;
- +}
- --- /dev/null
- +++ b/arch/m68k/coldfire/traps.c
- @@ -0,0 +1,454 @@
- +/*
- + * linux/arch/m68knommu/kernel/traps.c
- + *
- + * Copyright (C) 1993, 1994 by Hamish Macdonald
- + *
- + * 68040 fixes by Michael Rausch
- + * 68040 fixes by Martin Apel
- + * 68060 fixes by Roman Hodek
- + * 68060 fixes by Jesper Skov
- + *
- + * 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.
- + */
- +
- +/*
- + * Sets up all exception vectors
- + */
- +#include <linux/sched.h>
- +#include <linux/signal.h>
- +#include <linux/kernel.h>
- +#include <linux/mm.h>
- +#include <linux/module.h>
- +#include <linux/types.h>
- +#include <linux/a.out.h>
- +#include <linux/user.h>
- +#include <linux/string.h>
- +#include <linux/linkage.h>
- +#include <linux/init.h>
- +#include <linux/ptrace.h>
- +#include <linux/kallsyms.h>
- +
- +#include <asm/setup.h>
- +#include <asm/fpu.h>
- +#include <asm/system.h>
- +#include <asm/uaccess.h>
- +#include <asm/traps.h>
- +#include <asm/pgtable.h>
- +#include <asm/machdep.h>
- +#include <asm/siginfo.h>
- +
- +static char const * const vec_names[] = {
- + "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
- + "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
- + "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
- + "UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION",
- + "FORMAT ERROR", "UNINITIALIZED INTERRUPT",
- + "UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17",
- + "UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19",
- + "UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21",
- + "UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23",
- + "SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT",
- + "LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT",
- + "SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3",
- + "TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7",
- + "TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11",
- + "TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15",
- + "FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW",
- + "FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN",
- + "FPCP UNSUPPORTED OPERATION",
- + "MMU CONFIGURATION ERROR"
- +};
- +
- +asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
- + unsigned long error_code);
- +asmlinkage void trap_c(struct frame *fp);
- +extern void __init coldfire_trap_init(void);
- +
- +void __init trap_init(void)
- +{
- + coldfire_trap_init();
- +}
- +
- +/* The following table converts the FS encoding of a ColdFire
- + exception stack frame into the error_code value needed by
- + do_fault. */
- +
- +static const unsigned char fs_err_code[] = {
- + 0, /* 0000 */
- + 0, /* 0001 */
- + 0, /* 0010 */
- + 0, /* 0011 */
- + 1, /* 0100 */
- + 0, /* 0101 */
- + 0, /* 0110 */
- + 0, /* 0111 */
- + 2, /* 1000 */
- + 3, /* 1001 */
- + 2, /* 1010 */
- + 0, /* 1011 */
- + 1, /* 1100 */
- + 1, /* 1101 */
- + 0, /* 1110 */
- + 0 /* 1111 */
- +};
- +
- +#ifdef DEBUG
- +static const char *fs_err_msg[16] = {
- + "Normal",
- + "Reserved",
- + "Interrupt during debug service routine",
- + "Reserved",
- + "X Protection",
- + "TLB X miss (opword)",
- + "TLB X miss (ext. word)",
- + "IFP in emulator mode",
- + "W Protection",
- + "Write error",
- + "TLB W miss",
- + "Reserved",
- + "R Protection",
- + "R/RMW Protection",
- + "TLB R miss",
- + "OEP in emulator mode",
- +};
- +#endif
- +
- +static inline void access_errorCF(struct frame *fp)
- +{
- + unsigned long int mmusr, complainingAddress;
- + unsigned int err_code, fs;
- + int need_page_fault;
- +
- + mmusr = fp->ptregs.mmusr;
- + complainingAddress = fp->ptregs.mmuar;
- +#ifdef DEBUG
- + printk(KERN_DEBUG "pc %#lx, mmusr %#lx, complainingAddress %#lx\n", \
- + fp->ptregs.pc, mmusr, complainingAddress);
- +#endif
- +
- + /*
- + * error_code:
- + * bit 0 == 0 means no page found, 1 means protection fault
- + * bit 1 == 0 means read, 1 means write
- + */
- +
- + fs = (fp->ptregs.fs2 << 2) | fp->ptregs.fs1;
- + switch (fs) {
- + case 5: /* 0101 TLB opword X miss */
- + need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 0, 0);
- + complainingAddress = fp->ptregs.pc;
- + break;
- + case 6: /* 0110 TLB extension word X miss */
- + need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 0, 1);
- + complainingAddress = fp->ptregs.pc + sizeof(long);
- + break;
- + case 10: /* 1010 TLB W miss */
- + need_page_fault = cf_tlb_miss(&fp->ptregs, 1, 1, 0);
- + break;
- + case 14: /* 1110 TLB R miss */
- + need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 1, 0);
- + break;
- + default:
- + /* 0000 Normal */
- + /* 0001 Reserved */
- + /* 0010 Interrupt during debug service routine */
- + /* 0011 Reserved */
- + /* 0100 X Protection */
- + /* 0111 IFP in emulator mode */
- + /* 1000 W Protection*/
- + /* 1001 Write error*/
- + /* 1011 Reserved*/
- + /* 1100 R Protection*/
- + /* 1101 R Protection*/
- + /* 1111 OEP in emulator mode*/
- + need_page_fault = 1;
- + break;
- + }
- +
- + if (need_page_fault) {
- + err_code = fs_err_code[fs];
- + if ((fs == 13) && (mmusr & MMUSR_WF)) /* rd-mod-wr access */
- + err_code |= 2; /* bit1 - write, bit0 - protection */
- + do_page_fault(&fp->ptregs, complainingAddress, err_code);
- + }
- +}
- +
- +void die_if_kernel(char *str, struct pt_regs *fp, int nr)
- +{
- + if (!(fp->sr & PS_S))
- + return;
- +
- + console_verbose();
- + printk(KERN_EMERG "%s: %08x\n", str, nr);
- + printk(KERN_EMERG "PC: [<%08lx>]", fp->pc);
- + print_symbol(" %s", fp->pc);
- + printk(KERN_EMERG "\nSR: %04x SP: %p a2: %08lx\n",
- + fp->sr, fp, fp->a2);
- + printk(KERN_EMERG "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
- + fp->d0, fp->d1, fp->d2, fp->d3);
- + printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
- + fp->d4, fp->d5, fp->a0, fp->a1);
- +
- + printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n",
- + current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
- + show_stack(NULL, (unsigned long *)fp);
- + do_exit(SIGSEGV);
- +}
- +
- +asmlinkage void buserr_c(struct frame *fp)
- +{
- + unsigned int fs;
- +
- + /* Only set esp0 if coming from user mode */
- + if (user_mode(&fp->ptregs))
- + current->thread.esp0 = (unsigned long) fp;
- +
- + fs = (fp->ptregs.fs2 << 2) | fp->ptregs.fs1;
- +#if defined(DEBUG)
- + printk(KERN_DEBUG "*** Bus Error *** (%x)%s\n", fs,
- + fs_err_msg[fs & 0xf]);
- +#endif
- + switch (fs) {
- + case 0x5:
- + case 0x6:
- + case 0x7:
- + case 0x9:
- + case 0xa:
- + case 0xd:
- + case 0xe:
- + case 0xf:
- + access_errorCF(fp);
- + break;
- + default:
- + die_if_kernel("bad frame format", &fp->ptregs, 0);
- +#if defined(DEBUG)
- + printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
- +#endif
- + force_sig(SIGSEGV, current);
- + }
- +}
- +
- +
- +int kstack_depth_to_print = 48;
- +
- +void show_stack(struct task_struct *task, unsigned long *stack)
- +{
- + unsigned long *endstack, addr, symaddr;
- + extern char _start, _etext;
- + int i;
- +
- + if (!stack) {
- + if (task)
- + stack = (unsigned long *)task->thread.ksp;
- + else
- + stack = (unsigned long *)&stack;
- + }
- +
- + addr = (unsigned long) stack;
- + endstack = (unsigned long *) PAGE_ALIGN(addr);
- +
- + printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
- + for (i = 0; i < kstack_depth_to_print; i++) {
- + if (stack + 1 > endstack)
- + break;
- + if (i % 8 == 0)
- + printk("\n" KERN_EMERG " ");
- + symaddr = *stack;
- + printk(KERN_EMERG " %08lx", *stack++);
- + if ((symaddr >= 0xc0000000) && (symaddr < 0xc1000000))
- + print_symbol("(%s)", symaddr);
- + }
- + printk("\n");
- +
- + printk(KERN_EMERG "Call Trace:");
- + i = 0;
- + while (stack + 1 <= endstack) {
- + addr = *stack++;
- + /*
- + * If the address is either in the text segment of the
- + * kernel, or in the region which contains vmalloc'ed
- + * memory, it *may* be the address of a calling
- + * routine; if so, print it so that someone tracing
- + * down the cause of the crash will be able to figure
- + * out the call path that was taken.
- + */
- + if (((addr >= (unsigned long) &_start) &&
- + (addr <= (unsigned long) &_etext))) {
- + if (i % 4 == 0)
- + printk("\n" KERN_EMERG " ");
- + printk(KERN_EMERG " [<%08lx>]", addr);
- + i++;
- + }
- + }
- + printk("\n");
- +}
- +
- +void bad_super_trap(struct frame *fp)
- +{
- + console_verbose();
- + if (fp->ptregs.vector < 4*sizeof(vec_names)/sizeof(vec_names[0]))
- + printk(KERN_WARNING "*** %s *** FORMAT=%X\n",
- + vec_names[(fp->ptregs.vector) >> 2],
- + fp->ptregs.format);
- + else
- + printk(KERN_WARNING "*** Exception %d *** FORMAT=%X\n",
- + (fp->ptregs.vector) >> 2,
- + fp->ptregs.format);
- + printk(KERN_WARNING "Current process id is %d\n", current->pid);
- + die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
- +}
- +
- +asmlinkage void trap_c(struct frame *fp)
- +{
- + int sig;
- + siginfo_t info;
- +
- + if (fp->ptregs.sr & PS_S) {
- + if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
- + /* traced a trapping instruction */
- + current->ptrace |= PT_DTRACE;
- + } else
- + bad_super_trap(fp);
- + return;
- + }
- +
- + /* send the appropriate signal to the user program */
- + switch ((fp->ptregs.vector) >> 2) {
- + case VEC_ADDRERR:
- + info.si_code = BUS_ADRALN;
- + sig = SIGBUS;
- + break;
- + case VEC_ILLEGAL:
- + case VEC_LINE10:
- + case VEC_LINE11:
- + info.si_code = ILL_ILLOPC;
- + sig = SIGILL;
- + break;
- + case VEC_PRIV:
- + info.si_code = ILL_PRVOPC;
- + sig = SIGILL;
- + break;
- + case VEC_COPROC:
- + info.si_code = ILL_COPROC;
- + sig = SIGILL;
- + break;
- + case VEC_TRAP1: /* gdbserver breakpoint */
- + fp->ptregs.pc -= 2;
- + info.si_code = TRAP_TRACE;
- + sig = SIGTRAP;
- + break;
- + case VEC_TRAP2:
- + case VEC_TRAP3:
- + case VEC_TRAP4:
- + case VEC_TRAP5:
- + case VEC_TRAP6:
- + case VEC_TRAP7:
- + case VEC_TRAP8:
- + case VEC_TRAP9:
- + case VEC_TRAP10:
- + case VEC_TRAP11:
- + case VEC_TRAP12:
- + case VEC_TRAP13:
- + case VEC_TRAP14:
- + info.si_code = ILL_ILLTRP;
- + sig = SIGILL;
- + break;
- + case VEC_FPBRUC:
- + case VEC_FPOE:
- + case VEC_FPNAN:
- + info.si_code = FPE_FLTINV;
- + sig = SIGFPE;
- + break;
- + case VEC_FPIR:
- + info.si_code = FPE_FLTRES;
- + sig = SIGFPE;
- + break;
- + case VEC_FPDIVZ:
- + info.si_code = FPE_FLTDIV;
- + sig = SIGFPE;
- + break;
- + case VEC_FPUNDER:
- + info.si_code = FPE_FLTUND;
- + sig = SIGFPE;
- + break;
- + case VEC_FPOVER:
- + info.si_code = FPE_FLTOVF;
- + sig = SIGFPE;
- + break;
- + case VEC_ZERODIV:
- + info.si_code = FPE_INTDIV;
- + sig = SIGFPE;
- + break;
- + case VEC_CHK:
- + case VEC_TRAP:
- + info.si_code = FPE_INTOVF;
- + sig = SIGFPE;
- + break;
- + case VEC_TRACE: /* ptrace single step */
- + info.si_code = TRAP_TRACE;
- + sig = SIGTRAP;
- + break;
- + case VEC_TRAP15: /* breakpoint */
- + info.si_code = TRAP_BRKPT;
- + sig = SIGTRAP;
- + break;
- + default:
- + info.si_code = ILL_ILLOPC;
- + sig = SIGILL;
- + break;
- + }
- + info.si_signo = sig;
- + info.si_errno = 0;
- + switch (fp->ptregs.format) {
- + default:
- + info.si_addr = (void *) fp->ptregs.pc;
- + break;
- + case 2:
- + info.si_addr = (void *) fp->un.fmt2.iaddr;
- + break;
- + case 7:
- + info.si_addr = (void *) fp->un.fmt7.effaddr;
- + break;
- + case 9:
- + info.si_addr = (void *) fp->un.fmt9.iaddr;
- + break;
- + case 10:
- + info.si_addr = (void *) fp->un.fmta.daddr;
- + break;
- + case 11:
- + info.si_addr = (void *) fp->un.fmtb.daddr;
- + break;
- + }
- + force_sig_info(sig, &info, current);
- +}
- +
- +asmlinkage void set_esp0(unsigned long ssp)
- +{
- + current->thread.esp0 = ssp;
- +}
- +
- +/*
- + * The architecture-independent backtrace generator
- + */
- +void dump_stack(void)
- +{
- + unsigned long stack;
- +
- + show_stack(current, &stack);
- +}
- +EXPORT_SYMBOL(dump_stack);
- +
- +#ifdef CONFIG_M68KFPU_EMU
- +asmlinkage void fpemu_signal(int signal, int code, void *addr)
- +{
- + siginfo_t info;
- +
- + info.si_signo = signal;
- + info.si_errno = 0;
- + info.si_code = code;
- + info.si_addr = addr;
- + force_sig_info(signal, &info, current);
- +}
- +#endif
- --- /dev/null
- +++ b/arch/m68k/coldfire/vmlinux-cf.lds
- @@ -0,0 +1,92 @@
- +/* ld script to make m68k Coldfire Linux kernel */
- +
- +#include <asm-generic/vmlinux.lds.h>
- +
- +OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k")
- +OUTPUT_ARCH(m68k)
- +ENTRY(_start)
- +jiffies = jiffies_64 + 4;
- +SECTIONS
- +{
- + . = 0xC0020000;
- + _text = .; /* Text and read-only data */
- + .text : {
- + *(.text.head)
- + TEXT_TEXT
- + SCHED_TEXT
- + LOCK_TEXT
- + *(.fixup)
- + *(.gnu.warning)
- + } :text = 0x4e75
- +
- + _etext = .; /* End of text section */
- +
- + . = ALIGN(16);
- + __start___ex_table = .;
- + __ex_table : { *(__ex_table) }
- + __stop___ex_table = .;
- +
- + RODATA
- +
- + .data : { /* Data */
- + DATA_DATA
- + CONSTRUCTORS
- + }
- +
- + .bss : { *(.bss) } /* BSS */
- +
- + . = ALIGN(16);
- + .data.cacheline_aligned : { *(.data.cacheline_aligned) } :data
- +
- + _edata = .; /* End of data section */
- +
- + . = ALIGN(8192); /* Initrd */
- + __init_begin = .;
- + .init.text : {
- + _sinittext = .;
- + *(.init.text)
- + _einittext = .;
- + }
- + .init.data : { *(.init.data) }
- + . = ALIGN(16);
- + __setup_start = .;
- + .init.setup : { *(.init.setup) }
- + __setup_end = .;
- + __initcall_start = .;
- + .initcall.init : {
- + INITCALLS
- + }
- + __initcall_end = .;
- + __con_initcall_start = .;
- + .con_initcall.init : { *(.con_initcall.init) }
- + __con_initcall_end = .;
- + SECURITY_INIT
- +#ifdef CONFIG_BLK_DEV_INITRD
- + . = ALIGN(8192);
- + __initramfs_start = .;
- + .init.ramfs : { *(.init.ramfs) }
- + __initramfs_end = .;
- +#endif
- + . = ALIGN(8192);
- + __init_end = .;
- +
- + .data.init_task : { *(.data.init_task) } /* The initial task and kernel stack */
- +
- + _end = . ;
- +
- + /* Sections to be discarded */
- + /DISCARD/ : {
- + *(.exit.text)
- + *(.exit.data)
- + *(.exitcall.exit)
- + }
- +
- + /* Stabs debugging sections. */
- + .stab 0 : { *(.stab) }
- + .stabstr 0 : { *(.stabstr) }
- + .stab.excl 0 : { *(.stab.excl) }
- + .stab.exclstr 0 : { *(.stab.exclstr) }
- + .stab.index 0 : { *(.stab.index) }
- + .stab.indexstr 0 : { *(.stab.indexstr) }
- + .comment 0 : { *(.comment) }
- +}
|