1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367 |
- From 11553b0de8992ded6240d034bd49f561d17bea53 Mon Sep 17 00:00:00 2001
- From: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
- Date: Thu, 13 Jun 2013 01:18:02 +0200
- Subject: MIPS: add support for Lantiq XWAY SoCs
- Signed-off-by: Luka Perkov <luka@openwrt.org>
- Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
- --- a/.gitignore
- +++ b/.gitignore
- @@ -49,6 +49,13 @@
- /u-boot.sb
- /u-boot.bd
- /u-boot.geany
- +/u-boot.bin.lzma
- +/u-boot.bin.lzo
- +/u-boot.ltq.lzma.norspl
- +/u-boot.ltq.lzo.norspl
- +/u-boot.ltq.norspl
- +/u-boot.lzma.img
- +/u-boot.lzo.img
-
- #
- # Generated files
- --- a/Makefile
- +++ b/Makefile
- @@ -435,6 +435,12 @@ $(obj)u-boot.bin: $(obj)u-boot
- $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
- $(BOARD_SIZE_CHECK)
-
- +$(obj)u-boot.bin.lzma: $(obj)u-boot.bin
- + cat $< | lzma -9 -f - > $@
- +
- +$(obj)u-boot.bin.lzo: $(obj)u-boot.bin
- + cat $< | lzop -9 -f - > $@
- +
- $(obj)u-boot.ldr: $(obj)u-boot
- $(CREATE_LDR_ENV)
- $(LDR) -T $(CONFIG_BFIN_CPU) -c $@ $< $(LDR_FLAGS)
- @@ -454,13 +460,23 @@ ifndef CONFIG_SYS_UBOOT_START
- CONFIG_SYS_UBOOT_START := 0
- endif
-
- -$(obj)u-boot.img: $(obj)u-boot.bin
- - $(obj)tools/mkimage -A $(ARCH) -T firmware -C none \
- +define GEN_UBOOT_IMAGE
- + $(obj)tools/mkimage -A $(ARCH) -T firmware -C $(1) \
- -O u-boot -a $(CONFIG_SYS_TEXT_BASE) \
- -e $(CONFIG_SYS_UBOOT_START) \
- -n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \
- sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \
- -d $< $@
- +endef
- +
- +$(obj)u-boot.img: $(obj)u-boot.bin
- + $(call GEN_UBOOT_IMAGE,none)
- +
- +$(obj)u-boot.lzma.img: $(obj)u-boot.bin.lzma
- + $(call GEN_UBOOT_IMAGE,lzma)
- +
- +$(obj)u-boot.lzo.img: $(obj)u-boot.bin.lzo
- + $(call GEN_UBOOT_IMAGE,lzo)
-
- $(obj)u-boot.imx: $(obj)u-boot.bin depend
- $(MAKE) -C $(SRCTREE)/arch/arm/imx-common $(OBJTREE)/u-boot.imx
- @@ -571,6 +587,27 @@ $(obj)u-boot-img-spl-at-end.bin: $(obj)s
- conv=notrunc 2>/dev/null
- cat $(obj)u-boot-pad.img $(obj)spl/u-boot-spl.bin > $@
-
- +$(obj)u-boot.ltq.sfspl: $(obj)u-boot.img $(obj)spl/u-boot-spl.bin
- + $(obj)tools/ltq-boot-image -t sfspl -e $(CONFIG_SPL_TEXT_BASE) \
- + -s $(obj)spl/u-boot-spl.bin -u $< -o $@
- +
- +$(obj)u-boot.ltq.lzo.sfspl: $(obj)u-boot.lzo.img $(obj)spl/u-boot-spl.bin
- + $(obj)tools/ltq-boot-image -t sfspl -e $(CONFIG_SPL_TEXT_BASE) \
- + -s $(obj)spl/u-boot-spl.bin -u $< -o $@
- +
- +$(obj)u-boot.ltq.lzma.sfspl: $(obj)u-boot.lzma.img $(obj)spl/u-boot-spl.bin
- + $(obj)tools/ltq-boot-image -t sfspl -e $(CONFIG_SPL_TEXT_BASE) \
- + -s $(obj)spl/u-boot-spl.bin -u $< -o $@
- +
- +$(obj)u-boot.ltq.norspl: $(obj)u-boot.img $(obj)spl/u-boot-spl.bin
- + cat $(obj)spl/u-boot-spl.bin $< > $@
- +
- +$(obj)u-boot.ltq.lzo.norspl: $(obj)u-boot.lzo.img $(obj)spl/u-boot-spl.bin
- + cat $(obj)spl/u-boot-spl.bin $< > $@
- +
- +$(obj)u-boot.ltq.lzma.norspl: $(obj)u-boot.lzma.img $(obj)spl/u-boot-spl.bin
- + cat $(obj)spl/u-boot-spl.bin $< > $@
- +
- ifeq ($(CONFIG_SANDBOX),y)
- GEN_UBOOT = \
- cd $(LNDIR) && $(CC) $(SYMS) -T $(obj)u-boot.lds \
- --- a/README
- +++ b/README
- @@ -468,6 +468,11 @@ The following options need to be configu
- CONF_CM_CACHABLE_CUW
- CONF_CM_CACHABLE_ACCELERATED
-
- + CONFIG_SYS_MIPS_CACHE_EXT_INIT
- +
- + Enable this to use extended cache initialization for recent
- + MIPS CPU cores.
- +
- CONFIG_SYS_XWAY_EBU_BOOTCFG
-
- Special option for Lantiq XWAY SoCs for booting from NOR flash.
- --- a/arch/mips/config.mk
- +++ b/arch/mips/config.mk
- @@ -45,9 +45,13 @@ PLATFORM_CPPFLAGS += -DCONFIG_MIPS -D__M
- # On the other hand, we want PIC in the U-Boot code to relocate it from ROM
- # to RAM. $28 is always used as gp.
- #
- -PLATFORM_CPPFLAGS += -G 0 -mabicalls -fpic $(ENDIANNESS)
- +PF_ABICALLS ?= -mabicalls
- +PF_PIC ?= -fpic
- +PF_PIE ?= -pie
- +
- +PLATFORM_CPPFLAGS += -G 0 $(PF_ABICALLS) $(PF_PIC) $(ENDIANNESS)
- PLATFORM_CPPFLAGS += -msoft-float
- PLATFORM_LDFLAGS += -G 0 -static -n -nostdlib $(ENDIANNESS)
- PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections
- -LDFLAGS_FINAL += --gc-sections -pie
- +LDFLAGS_FINAL += --gc-sections $(PF_PIE)
- OBJCFLAGS += --remove-section=.dynsym
- --- a/arch/mips/cpu/mips32/cache.S
- +++ b/arch/mips/cpu/mips32/cache.S
- @@ -29,7 +29,11 @@
- */
- #define MIPS_MAX_CACHE_SIZE 0x10000
-
- +#ifdef CONFIG_SYS_MIPS_CACHE_EXT_INIT
- +#define INDEX_BASE 0x9fc00000
- +#else
- #define INDEX_BASE CKSEG0
- +#endif
-
- .macro cache_op op addr
- .set push
- @@ -65,7 +69,11 @@
- */
- LEAF(mips_init_icache)
- blez a1, 9f
- +#ifdef CONFIG_SYS_MIPS_CACHE_EXT_INIT
- + mtc0 zero, CP0_ITAGLO
- +#else
- mtc0 zero, CP0_TAGLO
- +#endif
- /* clear tag to invalidate */
- PTR_LI t0, INDEX_BASE
- PTR_ADDU t1, t0, a1
- @@ -90,7 +98,11 @@ LEAF(mips_init_icache)
- */
- LEAF(mips_init_dcache)
- blez a1, 9f
- +#ifdef CONFIG_SYS_MIPS_CACHE_EXT_INIT
- + mtc0 zero, CP0_DTAGLO
- +#else
- mtc0 zero, CP0_TAGLO
- +#endif
- /* clear all tags */
- PTR_LI t0, INDEX_BASE
- PTR_ADDU t1, t0, a1
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/danube/Makefile
- @@ -0,0 +1,31 @@
- +#
- +# Copyright (C) 2000-2011 Wolfgang Denk, DENX Software Engineering, wd@denx.de
- +#
- +# SPDX-License-Identifier: GPL-2.0+
- +#
- +
- +include $(TOPDIR)/config.mk
- +
- +LIB = $(obj)lib$(SOC).o
- +
- +COBJS-y += cgu.o chipid.o ebu.o mem.o pmu.o rcu.o
- +SOBJS-y += cgu_init.o mem_init.o
- +
- +COBJS := $(COBJS-y)
- +SOBJS := $(SOBJS-y)
- +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
- +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
- +
- +all: $(LIB)
- +
- +$(LIB): $(obj).depend $(OBJS)
- + $(call cmd_link_o_target, $(OBJS))
- +
- +#########################################################################
- +
- +# defines $(obj).depend target
- +include $(SRCTREE)/rules.mk
- +
- +sinclude $(obj).depend
- +
- +#########################################################################
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/danube/cgu.c
- @@ -0,0 +1,117 @@
- +/*
- + * Copyright (C) 2007-2010 Lantiq Deutschland GmbH
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <asm/arch/soc.h>
- +#include <asm/lantiq/clk.h>
- +#include <asm/lantiq/io.h>
- +
- +#define LTQ_CGU_SYS_DDR_MASK 0x0003
- +#define LTQ_CGU_SYS_DDR_SHIFT 0
- +#define LTQ_CGU_SYS_CPU0_MASK 0x000C
- +#define LTQ_CGU_SYS_CPU0_SHIFT 2
- +#define LTQ_CGU_SYS_FPI_MASK 0x0040
- +#define LTQ_CGU_SYS_FPI_SHIFT 6
- +
- +struct ltq_cgu_regs {
- + u32 rsvd0;
- + u32 pll0_cfg; /* PLL0 config */
- + u32 pll1_cfg; /* PLL1 config */
- + u32 pll2_cfg; /* PLL2 config */
- + u32 sys; /* System clock */
- + u32 update; /* CGU update control */
- + u32 if_clk; /* Interface clock */
- + u32 osc_con; /* Update OSC Control */
- + u32 smd; /* SDRAM Memory Control */
- + u32 rsvd1[3];
- + u32 pcm_cr; /* PCM control */
- + u32 pci_cr; /* PCI clock control */
- +};
- +
- +static struct ltq_cgu_regs *ltq_cgu_regs =
- + (struct ltq_cgu_regs *) CKSEG1ADDR(LTQ_CGU_BASE);
- +
- +static inline u32 ltq_cgu_sys_readl(u32 mask, u32 shift)
- +{
- + return (ltq_readl(<q_cgu_regs->sys) & mask) >> shift;
- +}
- +
- +unsigned long ltq_get_io_region_clock(void)
- +{
- + u32 ddr_sel;
- + unsigned long clk;
- +
- + ddr_sel = ltq_cgu_sys_readl(LTQ_CGU_SYS_DDR_MASK,
- + LTQ_CGU_SYS_DDR_SHIFT);
- +
- + switch (ddr_sel) {
- + case 0:
- + clk = CLOCK_166_MHZ;
- + break;
- + case 1:
- + clk = CLOCK_133_MHZ;
- + break;
- + case 2:
- + clk = CLOCK_111_MHZ;
- + break;
- + case 3:
- + clk = CLOCK_83_MHZ;
- + break;
- + default:
- + clk = 0;
- + break;
- + }
- +
- + return clk;
- +}
- +
- +unsigned long ltq_get_cpu_clock(void)
- +{
- + u32 cpu0_sel;
- + unsigned long clk;
- +
- + cpu0_sel = ltq_cgu_sys_readl(LTQ_CGU_SYS_CPU0_MASK,
- + LTQ_CGU_SYS_CPU0_SHIFT);
- +
- + switch (cpu0_sel) {
- + /* Same as PLL0 output (333,33 MHz) */
- + case 0:
- + clk = CLOCK_333_MHZ;
- + break;
- + /* 1/1 fixed ratio to DDR clock */
- + case 1:
- + clk = ltq_get_io_region_clock();
- + break;
- + /* 1/2 fixed ratio to DDR clock */
- + case 2:
- + clk = ltq_get_io_region_clock() << 1;
- + break;
- + default:
- + clk = 0;
- + break;
- + }
- +
- + return clk;
- +}
- +
- +unsigned long ltq_get_bus_clock(void)
- +{
- + u32 fpi_sel;
- + unsigned long clk;
- +
- + fpi_sel = ltq_cgu_sys_readl(LTQ_CGU_SYS_FPI_MASK,
- + LTQ_CGU_SYS_FPI_SHIFT);
- +
- + if (fpi_sel)
- + /* Half the DDR clock */
- + clk = ltq_get_io_region_clock() >> 1;
- + else
- + /* Same as DDR clock */
- + clk = ltq_get_io_region_clock();
- +
- + return clk;
- +}
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/danube/cgu_init.S
- @@ -0,0 +1,142 @@
- +/*
- + * Copyright (C) 2007-2010 Lantiq Deutschland GmbH
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <config.h>
- +#include <asm/asm.h>
- +#include <asm/regdef.h>
- +#include <asm/addrspace.h>
- +#include <asm/arch/soc.h>
- +
- +/* RCU module register */
- +#define LTQ_RCU_RST_REQ 0x0010
- +#define LTQ_RCU_RST_STAT 0x0014
- +#define LTQ_RCU_RST_REQ_VALUE 0x40000008
- +#define LTQ_RCU_RST_STAT_XTAL_F 0x20000
- +
- +/* CGU module register */
- +#define LTQ_CGU_PLL0_CFG 0x0004 /* PLL0 config */
- +#define LTQ_CGU_PLL1_CFG 0x0008 /* PLL1 config */
- +#define LTQ_CGU_PLL2_CFG 0x000C /* PLL2 config */
- +#define LTQ_CGU_SYS 0x0010 /* System clock */
- +
- +/* Valid SYS.CPU0/1 values */
- +#define LTQ_CGU_SYS_CPU0_SHIFT 2
- +#define LTQ_CGU_SYS_CPU1_SHIFT 4
- +#define LTQ_CGU_SYS_CPU_PLL0 0x0
- +#define LTQ_CGU_SYS_CPU_DDR_EQUAL 0x1
- +#define LTQ_CGU_SYS_CPU_DDR_TWICE 0x2
- +
- +/* Valid SYS.DDR values */
- +#define LTQ_CGU_SYS_DDR_SHIFT 0
- +#define LTQ_CGU_SYS_DDR_167_MHZ 0x0
- +#define LTQ_CGU_SYS_DDR_133_MHZ 0x1
- +#define LTQ_CGU_SYS_DDR_111_MHZ 0x2
- +#define LTQ_CGU_SYS_DDR_83_MHZ 0x3
- +
- +/* Valid SYS.FPI values */
- +#define LTQ_CGU_SYS_FPI_SHIFT 6
- +#define LTQ_CGU_SYS_FPI_DDR_EQUAL 0x0
- +#define LTQ_CGU_SYS_FPI_DDR_HALF 0x1
- +
- +/* Valid SYS.PPE values */
- +#define LTQ_CGU_SYS_PPE_SHIFT 7
- +#define LTQ_CGU_SYS_PPE_266_MHZ 0x0
- +#define LTQ_CGU_SYS_PPE_240_MHZ 0x1
- +#define LTQ_CGU_SYS_PPE_222_MHZ 0x2
- +#define LTQ_CGU_SYS_PPE_133_MHZ 0x3
- +
- +#if (CONFIG_SYS_CLOCK_MODE == LTQ_CLK_CPU_333_DDR_167)
- +#define LTQ_CGU_SYS_CPU_CONFIG LTQ_CGU_SYS_CPU_DDR_TWICE
- +#define LTQ_CGU_SYS_DDR_CONFIG LTQ_CGU_SYS_DDR_167_MHZ
- +#define LTQ_CGU_SYS_FPI_CONFIG LTQ_CGU_SYS_FPI_DDR_HALF
- +#define LTQ_CGU_SYS_PPE_CONFIG LTQ_CGU_SYS_PPE_266_MHZ
- +#elif (CONFIG_SYS_CLOCK_MODE == LTQ_CLK_CPU_111_DDR_111)
- +#define LTQ_CGU_SYS_CPU_CONFIG LTQ_CGU_SYS_CPU_DDR_EQUAL
- +#define LTQ_CGU_SYS_DDR_CONFIG LTQ_CGU_SYS_DDR_111_MHZ
- +#define LTQ_CGU_SYS_FPI_CONFIG LTQ_CGU_SYS_FPI_DDR_HALF
- +#define LTQ_CGU_SYS_PPE_CONFIG LTQ_CGU_SYS_PPE_133_MHZ
- +#else
- +#error "Invalid system clock configuration!"
- +#endif
- +
- +/* Build register values */
- +#define LTQ_CGU_SYS_VALUE ((LTQ_CGU_SYS_PPE_CONFIG << \
- + LTQ_CGU_SYS_PPE_SHIFT) | \
- + (LTQ_CGU_SYS_FPI_CONFIG << \
- + LTQ_CGU_SYS_FPI_SHIFT) | \
- + (LTQ_CGU_SYS_CPU_CONFIG << \
- + LTQ_CGU_SYS_CPU1_SHIFT) | \
- + (LTQ_CGU_SYS_CPU_CONFIG << \
- + LTQ_CGU_SYS_CPU0_SHIFT) | \
- + LTQ_CGU_SYS_DDR_CONFIG)
- +
- +/* Reset values for PLL registers for usage with 35.328 MHz crystal */
- +#define PLL0_35MHZ_CONFIG 0x9D861059
- +#define PLL1_35MHZ_CONFIG 0x1A260CD9
- +#define PLL2_35MHZ_CONFIG 0x8000f1e5
- +
- +/* Reset values for PLL registers for usage with 36 MHz crystal */
- +#define PLL0_36MHZ_CONFIG 0x1000125D
- +#define PLL1_36MHZ_CONFIG 0x1B1E0C99
- +#define PLL2_36MHZ_CONFIG 0x8002f2a1
- +
- +LEAF(ltq_cgu_init)
- + /* Load current CGU register value */
- + li t0, (LTQ_CGU_BASE | KSEG1)
- + lw t1, LTQ_CGU_SYS(t0)
- +
- + /* Load target CGU register values */
- + li t3, LTQ_CGU_SYS_VALUE
- +
- + /* Only update registers if values differ */
- + beq t1, t3, finished
- +
- + /*
- + * Check whether the XTAL_F bit in RST_STAT register is set or not.
- + * This bit is latched in via pin strapping. If bit is set then
- + * clock source is a 36 MHz crystal. Otherwise a 35.328 MHz crystal.
- + */
- + li t1, (LTQ_RCU_BASE | KSEG1)
- + lw t2, LTQ_RCU_RST_STAT(t1)
- + and t2, t2, LTQ_RCU_RST_STAT_XTAL_F
- + beq t2, LTQ_RCU_RST_STAT_XTAL_F, boot_36mhz
- +
- +boot_35mhz:
- + /* Configure PLL for 35.328 MHz */
- + li t2, PLL0_35MHZ_CONFIG
- + sw t2, LTQ_CGU_PLL0_CFG(t0)
- + li t2, PLL1_35MHZ_CONFIG
- + sw t2, LTQ_CGU_PLL1_CFG(t0)
- + li t2, PLL2_35MHZ_CONFIG
- + sw t2, LTQ_CGU_PLL2_CFG(t0)
- +
- + b do_reset
- +
- +boot_36mhz:
- + /* Configure PLL for 36 MHz */
- + li t2, PLL0_36MHZ_CONFIG
- + sw t2, LTQ_CGU_PLL0_CFG(t0)
- + li t2, PLL1_36MHZ_CONFIG
- + sw t2, LTQ_CGU_PLL1_CFG(t0)
- + li t2, PLL2_36MHZ_CONFIG
- + sw t2, LTQ_CGU_PLL2_CFG(t0)
- +
- +do_reset:
- + /* Store new clock config */
- + sw t3, LTQ_CGU_SYS(t0)
- +
- + /* Perform software reset to activate new clock config */
- + li t2, LTQ_RCU_RST_REQ_VALUE
- + sw t2, LTQ_RCU_RST_REQ(t1)
- +
- +wait_reset:
- + b wait_reset
- +
- +finished:
- + jr ra
- +
- + END(ltq_cgu_init)
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/danube/chipid.c
- @@ -0,0 +1,59 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <asm/lantiq/io.h>
- +#include <asm/lantiq/chipid.h>
- +#include <asm/arch/soc.h>
- +
- +#define LTQ_CHIPID_VERSION_SHIFT 28
- +#define LTQ_CHIPID_VERSION_MASK (0xF << LTQ_CHIPID_VERSION_SHIFT)
- +#define LTQ_CHIPID_PNUM_SHIFT 12
- +#define LTQ_CHIPID_PNUM_MASK (0xFFFF << LTQ_CHIPID_PNUM_SHIFT)
- +
- +struct ltq_chipid_regs {
- + u32 manid; /* Manufacturer identification */
- + u32 chipid; /* Chip identification */
- +};
- +
- +static struct ltq_chipid_regs *ltq_chipid_regs =
- + (struct ltq_chipid_regs *) CKSEG1ADDR(LTQ_CHIPID_BASE);
- +
- +unsigned int ltq_chip_version_get(void)
- +{
- + u32 chipid;
- +
- + chipid = ltq_readl(<q_chipid_regs->chipid);
- +
- + return (chipid & LTQ_CHIPID_VERSION_MASK) >> LTQ_CHIPID_VERSION_SHIFT;
- +}
- +
- +unsigned int ltq_chip_partnum_get(void)
- +{
- + u32 chipid;
- +
- + chipid = ltq_readl(<q_chipid_regs->chipid);
- +
- + return (chipid & LTQ_CHIPID_PNUM_MASK) >> LTQ_CHIPID_PNUM_SHIFT;
- +}
- +
- +const char *ltq_chip_partnum_str(void)
- +{
- + enum ltq_chip_partnum partnum = ltq_chip_partnum_get();
- +
- + switch (partnum) {
- + case LTQ_SOC_DANUBE:
- + return "Danube";
- + case LTQ_SOC_DANUBE_S:
- + return "Danube-S";
- + case LTQ_SOC_TWINPASS:
- + return "Twinpass";
- + default:
- + printf("Unknown partnum: %x\n", partnum);
- + }
- +
- + return "";
- +}
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/danube/config.mk
- @@ -0,0 +1,25 @@
- +#
- +# Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- +#
- +# SPDX-License-Identifier: GPL-2.0+
- +#
- +
- +PF_CPPFLAGS_DANUBE := $(call cc-option,-mtune=24kec,)
- +PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_DANUBE)
- +
- +ifdef CONFIG_SPL_BUILD
- +PF_ABICALLS := -mno-abicalls
- +PF_PIC := -fno-pic
- +PF_PIE :=
- +USE_PRIVATE_LIBGCC := yes
- +endif
- +
- +LIBS-y += $(CPUDIR)/lantiq-common/liblantiq-common.o
- +
- +ifndef CONFIG_SPL_BUILD
- +ifdef CONFIG_SYS_BOOT_NORSPL
- +ALL-y += $(obj)u-boot.ltq.norspl
- +ALL-$(CONFIG_SPL_LZO_SUPPORT) += $(obj)u-boot.ltq.lzo.norspl
- +ALL-$(CONFIG_SPL_LZMA_SUPPORT) += $(obj)u-boot.ltq.lzma.norspl
- +endif
- +endif
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/danube/ebu.c
- @@ -0,0 +1,105 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <asm/arch/soc.h>
- +#include <asm/lantiq/io.h>
- +
- +#define EBU_ADDRSEL_MASK(mask) ((mask & 0xf) << 4)
- +#define EBU_ADDRSEL_REGEN (1 << 0)
- +
- +#define EBU_CON_WRDIS (1 << 31)
- +#define EBU_CON_AGEN_DEMUX (0x0 << 24)
- +#define EBU_CON_AGEN_MUX (0x2 << 24)
- +#define EBU_CON_SETUP (1 << 22)
- +#define EBU_CON_WAIT_DIS (0x0 << 20)
- +#define EBU_CON_WAIT_ASYNC (0x1 << 20)
- +#define EBU_CON_WAIT_SYNC (0x2 << 20)
- +#define EBU_CON_WINV (1 << 19)
- +#define EBU_CON_PW_8BIT (0x0 << 16)
- +#define EBU_CON_PW_16BIT (0x1 << 16)
- +#define EBU_CON_ALEC(cycles) ((cycles & 0x3) << 14)
- +#define EBU_CON_BCGEN_CS (0x0 << 12)
- +#define EBU_CON_BCGEN_INTEL (0x1 << 12)
- +#define EBU_CON_BCGEN_MOTOROLA (0x2 << 12)
- +#define EBU_CON_WAITWRC(cycles) ((cycles & 0x7) << 8)
- +#define EBU_CON_WAITRDC(cycles) ((cycles & 0x3) << 6)
- +#define EBU_CON_HOLDC(cycles) ((cycles & 0x3) << 4)
- +#define EBU_CON_RECOVC(cycles) ((cycles & 0x3) << 2)
- +#define EBU_CON_CMULT_1 0x0
- +#define EBU_CON_CMULT_4 0x1
- +#define EBU_CON_CMULT_8 0x2
- +#define EBU_CON_CMULT_16 0x3
- +
- +#if defined(CONFIG_LTQ_SUPPORT_NOR_FLASH)
- +#define ebu_region0_enable 1
- +#else
- +#define ebu_region0_enable 0
- +#endif
- +
- +#if defined(CONFIG_LTQ_SUPPORT_NAND_FLASH)
- +#define ebu_region1_enable 1
- +#else
- +#define ebu_region1_enable 0
- +#endif
- +
- +struct ltq_ebu_regs {
- + u32 clc;
- + u32 rsvd0[3];
- + u32 con;
- + u32 rsvd1[3];
- + u32 addr_sel_0;
- + u32 addr_sel_1;
- + u32 rsvd2[14];
- + u32 con_0;
- + u32 con_1;
- +};
- +
- +static struct ltq_ebu_regs *ltq_ebu_regs =
- + (struct ltq_ebu_regs *) CKSEG1ADDR(LTQ_EBU_BASE);
- +
- +void ltq_ebu_init(void)
- +{
- + if (ebu_region0_enable) {
- + /*
- + * Map EBU region 0 to range 0x10000000-0x13ffffff and enable
- + * region control. This supports up to 32 MiB NOR flash in
- + * bank 0.
- + */
- + ltq_writel(<q_ebu_regs->addr_sel_0, LTQ_EBU_REGION0_BASE |
- + EBU_ADDRSEL_MASK(1) | EBU_ADDRSEL_REGEN);
- +
- + ltq_writel(<q_ebu_regs->con_0, EBU_CON_AGEN_DEMUX |
- + EBU_CON_WAIT_DIS | EBU_CON_PW_16BIT |
- + EBU_CON_ALEC(3) | EBU_CON_BCGEN_INTEL |
- + EBU_CON_WAITWRC(7) | EBU_CON_WAITRDC(3) |
- + EBU_CON_HOLDC(3) | EBU_CON_RECOVC(3) |
- + EBU_CON_CMULT_16);
- + } else
- + ltq_clrbits(<q_ebu_regs->addr_sel_0, EBU_ADDRSEL_REGEN);
- +
- + if (ebu_region1_enable) {
- + /*
- + * Map EBU region 1 to range 0x14000000-0x13ffffff and enable
- + * region control. This supports NAND flash in bank 1.
- + */
- + ltq_writel(<q_ebu_regs->addr_sel_1, LTQ_EBU_REGION1_BASE |
- + EBU_ADDRSEL_MASK(3) | EBU_ADDRSEL_REGEN);
- +
- + ltq_writel(<q_ebu_regs->con_1, EBU_CON_AGEN_DEMUX |
- + EBU_CON_SETUP | EBU_CON_WAIT_DIS | EBU_CON_PW_8BIT |
- + EBU_CON_ALEC(3) | EBU_CON_BCGEN_INTEL |
- + EBU_CON_WAITWRC(2) | EBU_CON_WAITRDC(2) |
- + EBU_CON_HOLDC(1) | EBU_CON_RECOVC(1) |
- + EBU_CON_CMULT_4);
- + } else
- + ltq_clrbits(<q_ebu_regs->addr_sel_1, EBU_ADDRSEL_REGEN);
- +}
- +
- +void *flash_swap_addr(unsigned long addr)
- +{
- + return (void *)(addr ^ 2);
- +}
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/danube/mem.c
- @@ -0,0 +1,30 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <asm/arch/soc.h>
- +#include <asm/lantiq/io.h>
- +
- +static void *ltq_mc_ddr_base = (void *) CKSEG1ADDR(LTQ_MC_DDR_BASE);
- +
- +static inline u32 ltq_mc_dc_read(u32 index)
- +{
- + return ltq_readl(ltq_mc_ddr_base + LTQ_MC_DDR_DC_OFFSET(index));
- +}
- +
- +phys_size_t initdram(int board_type)
- +{
- + u32 col, row, dc04, dc19, dc20;
- +
- + dc04 = ltq_mc_dc_read(4);
- + dc19 = ltq_mc_dc_read(19);
- + dc20 = ltq_mc_dc_read(20);
- +
- + row = (dc04 & 0xF) - ((dc19 & 0x700) >> 8);
- + col = ((dc04 & 0xF00) >> 8) - (dc20 & 0x7);
- +
- + return (1 << (row + col)) * 4 * 2;
- +}
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/danube/mem_init.S
- @@ -0,0 +1,114 @@
- +/*
- + * Copyright (C) 2007-2010 Lantiq Deutschland GmbH
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <config.h>
- +#include <asm/asm.h>
- +#include <asm/regdef.h>
- +#include <asm/addrspace.h>
- +#include <asm/arch/soc.h>
- +
- +/* Must be configured in BOARDDIR */
- +#include <ddr_settings.h>
- +
- +#define LTQ_MC_GEN_ERRCAUSE 0x0010
- +#define LTQ_MC_GEN_ERRADDR 0x0020
- +#define LTQ_MC_GEN_CON 0x0060
- +#define LTQ_MC_GEN_STAT 0x0070
- +#define LTQ_MC_GEN_CON_SRAM_DDR_ENABLE 0x5
- +#define LTQ_MC_GEN_STAT_DLCK_PWRON 0xC
- +
- +#define LTQ_MC_DDR_DC03_MC_START 0x100
- +
- + /* Store given value in MC DDR CCRx register */
- + .macro dc_sw num, val
- + li t2, \val
- + sw t2, LTQ_MC_DDR_DC_OFFSET(\num)(t1)
- + .endm
- +
- +LEAF(ltq_mem_init)
- + /* Load MC General and MC DDR module base */
- + li t0, (LTQ_MC_GEN_BASE | KSEG1)
- + li t1, (LTQ_MC_DDR_BASE | KSEG1)
- +
- + /* Clear access error log registers */
- + sw zero, LTQ_MC_GEN_ERRCAUSE(t0)
- + sw zero, LTQ_MC_GEN_ERRADDR(t0)
- +
- + /* Enable DDR and SRAM module in memory controller */
- + li t2, LTQ_MC_GEN_CON_SRAM_DDR_ENABLE
- + sw t2, LTQ_MC_GEN_CON(t0)
- +
- + /* Clear start bit of DDR memory controller */
- + sw zero, LTQ_MC_DDR_DC_OFFSET(3)(t1)
- +
- + /* Init memory controller registers with values ddr_settings.h */
- + dc_sw 0, MC_DC00_VALUE
- + dc_sw 1, MC_DC01_VALUE
- + dc_sw 2, MC_DC02_VALUE
- + dc_sw 4, MC_DC04_VALUE
- + dc_sw 5, MC_DC05_VALUE
- + dc_sw 6, MC_DC06_VALUE
- + dc_sw 7, MC_DC07_VALUE
- + dc_sw 8, MC_DC08_VALUE
- + dc_sw 9, MC_DC09_VALUE
- +
- + dc_sw 10, MC_DC10_VALUE
- + dc_sw 11, MC_DC11_VALUE
- + dc_sw 12, MC_DC12_VALUE
- + dc_sw 13, MC_DC13_VALUE
- + dc_sw 14, MC_DC14_VALUE
- + dc_sw 15, MC_DC15_VALUE
- + dc_sw 16, MC_DC16_VALUE
- + dc_sw 17, MC_DC17_VALUE
- + dc_sw 18, MC_DC18_VALUE
- + dc_sw 19, MC_DC19_VALUE
- +
- + dc_sw 20, MC_DC20_VALUE
- + dc_sw 21, MC_DC21_VALUE
- + dc_sw 22, MC_DC22_VALUE
- + dc_sw 23, MC_DC23_VALUE
- + dc_sw 24, MC_DC24_VALUE
- + dc_sw 25, MC_DC25_VALUE
- + dc_sw 26, MC_DC26_VALUE
- + dc_sw 27, MC_DC27_VALUE
- + dc_sw 28, MC_DC28_VALUE
- + dc_sw 29, MC_DC29_VALUE
- +
- + dc_sw 30, MC_DC30_VALUE
- + dc_sw 31, MC_DC31_VALUE
- + dc_sw 32, MC_DC32_VALUE
- + dc_sw 33, MC_DC33_VALUE
- + dc_sw 34, MC_DC34_VALUE
- + dc_sw 35, MC_DC35_VALUE
- + dc_sw 36, MC_DC36_VALUE
- + dc_sw 37, MC_DC37_VALUE
- + dc_sw 38, MC_DC38_VALUE
- + dc_sw 39, MC_DC39_VALUE
- +
- + dc_sw 40, MC_DC40_VALUE
- + dc_sw 41, MC_DC41_VALUE
- + dc_sw 42, MC_DC42_VALUE
- + dc_sw 43, MC_DC43_VALUE
- + dc_sw 44, MC_DC44_VALUE
- + dc_sw 45, MC_DC45_VALUE
- + dc_sw 46, MC_DC46_VALUE
- +
- + /* Set start bit of DDR memory controller */
- + li t2, LTQ_MC_DDR_DC03_MC_START
- + sw t2, LTQ_MC_DDR_DC_OFFSET(3)(t1)
- +
- + /* Wait until DLL has locked and core is ready for data transfers */
- +wait_ready:
- + lw t2, LTQ_MC_GEN_STAT(t0)
- + li t3, LTQ_MC_GEN_STAT_DLCK_PWRON
- + and t2, t3
- + bne t2, t3, wait_ready
- +
- +finished:
- + jr ra
- +
- + END(ltq_mem_init)
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/danube/pmu.c
- @@ -0,0 +1,117 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <asm/lantiq/io.h>
- +#include <asm/lantiq/pm.h>
- +#include <asm/arch/soc.h>
- +
- +#define LTQ_PMU_PWDCR_RESERVED 0xFD0C001C
- +
- +#define LTQ_PMU_PWDCR_TDM (1 << 25)
- +#define LTQ_PMU_PWDCR_PPE_ENET0 (1 << 23)
- +#define LTQ_PMU_PWDCR_PPE_ENET1 (1 << 22)
- +#define LTQ_PMU_PWDCR_PPE_TC (1 << 21)
- +#define LTQ_PMU_PWDCR_DEU (1 << 20)
- +#define LTQ_PMU_PWDCR_UART1 (1 << 17)
- +#define LTQ_PMU_PWDCR_SDIO (1 << 16)
- +#define LTQ_PMU_PWDCR_AHB (1 << 15)
- +#define LTQ_PMU_PWDCR_FPI0 (1 << 14)
- +#define LTQ_PMU_PWDCR_PPE (1 << 13)
- +#define LTQ_PMU_PWDCR_GPTC (1 << 12)
- +#define LTQ_PMU_PWDCR_LEDC (1 << 11)
- +#define LTQ_PMU_PWDCR_EBU (1 << 10)
- +#define LTQ_PMU_PWDCR_DSL (1 << 9)
- +#define LTQ_PMU_PWDCR_SPI (1 << 8)
- +#define LTQ_PMU_PWDCR_UART0 (1 << 7)
- +#define LTQ_PMU_PWDCR_USB (1 << 6)
- +#define LTQ_PMU_PWDCR_DMA (1 << 5)
- +#define LTQ_PMU_PWDCR_FPI1 (1 << 1)
- +#define LTQ_PMU_PWDCR_USB_PHY (1 << 0)
- +
- +struct ltq_pmu_regs {
- + u32 rsvd0[7];
- + u32 pwdcr;
- + u32 sr;
- + u32 pwdcr1;
- + u32 sr1;
- +};
- +
- +static struct ltq_pmu_regs *ltq_pmu_regs =
- + (struct ltq_pmu_regs *) CKSEG1ADDR(LTQ_PMU_BASE);
- +
- +u32 ltq_pm_map(enum ltq_pm_modules module)
- +{
- + u32 val;
- +
- + switch (module) {
- + case LTQ_PM_CORE:
- + val = LTQ_PMU_PWDCR_UART1 | LTQ_PMU_PWDCR_FPI0 |
- + LTQ_PMU_PWDCR_LEDC | LTQ_PMU_PWDCR_EBU;
- + break;
- + case LTQ_PM_DMA:
- + val = LTQ_PMU_PWDCR_DMA;
- + break;
- + case LTQ_PM_ETH:
- + val = LTQ_PMU_PWDCR_PPE_ENET0 | LTQ_PMU_PWDCR_PPE_TC |
- + LTQ_PMU_PWDCR_PPE;
- + break;
- + case LTQ_PM_SPI:
- + val = LTQ_PMU_PWDCR_SPI;
- + break;
- + default:
- + val = 0;
- + break;
- + }
- +
- + return val;
- +}
- +
- +int ltq_pm_enable(enum ltq_pm_modules module)
- +{
- + const unsigned long timeout = 1000;
- + unsigned long timebase;
- + u32 sr, val;
- +
- + val = ltq_pm_map(module);
- + if (unlikely(!val))
- + return 1;
- +
- + ltq_clrbits(<q_pmu_regs->pwdcr, val);
- +
- + timebase = get_timer(0);
- +
- + do {
- + sr = ltq_readl(<q_pmu_regs->sr);
- + if (~sr & val)
- + return 0;
- + } while (get_timer(timebase) < timeout);
- +
- + return 1;
- +}
- +
- +int ltq_pm_disable(enum ltq_pm_modules module)
- +{
- + u32 val;
- +
- + val = ltq_pm_map(module);
- + if (unlikely(!val))
- + return 1;
- +
- + ltq_setbits(<q_pmu_regs->pwdcr, val);
- +
- + return 0;
- +}
- +
- +void ltq_pmu_init(void)
- +{
- + u32 set, clr;
- +
- + clr = ltq_pm_map(LTQ_PM_CORE);
- + set = ~(LTQ_PMU_PWDCR_RESERVED | clr);
- +
- + ltq_clrsetbits(<q_pmu_regs->pwdcr, clr, set);
- +}
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/danube/rcu.c
- @@ -0,0 +1,125 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <asm/lantiq/io.h>
- +#include <asm/lantiq/reset.h>
- +#include <asm/lantiq/cpu.h>
- +#include <asm/arch/soc.h>
- +
- +#define LTQ_RCU_RD_SRST (1 << 30) /* Global SW Reset */
- +#define LTQ_RCU_RD_MC (1 << 14) /* Memory Controller */
- +#define LTQ_RCU_RD_PCI (1 << 13) /* PCI core */
- +#define LTQ_RCU_RD_DFE_AFE (1 << 12) /* Voice DFE/AFE */
- +#define LTQ_RCU_RD_DSL_AFE (1 << 11) /* DSL AFE */
- +#define LTQ_RCU_RD_SDIO (1 << 10) /* SDIO core */
- +#define LTQ_RCU_RD_DMA (1 << 9) /* DMA core */
- +#define LTQ_RCU_RD_PPE (1 << 8) /* PPE core */
- +#define LTQ_RCU_RD_ARC_DFE (1 << 7) /* ARC/DFE core */
- +#define LTQ_RCU_RD_AHB (1 << 6) /* AHB bus */
- +#define LTQ_RCU_RD_ENET_MAC1 (1 << 5) /* Ethernet MAC1 */
- +#define LTQ_RCU_RD_USB (1 << 4) /* USB and Phy core */
- +#define LTQ_RCU_RD_CPU1 (1 << 3) /* CPU1 subsystem */
- +#define LTQ_RCU_RD_FPI (1 << 2) /* FPI bus */
- +#define LTQ_RCU_RD_CPU0 (1 << 1) /* CPU0 subsystem */
- +#define LTQ_RCU_RD_HRST (1 << 0) /* HW reset via HRST pin */
- +
- +#define LTQ_RCU_STAT_BOOT_SHIFT 18
- +#define LTQ_RCU_STAT_BOOT_MASK (0x7 << LTQ_RCU_STAT_BOOT_SHIFT)
- +
- +struct ltq_rcu_regs {
- + u32 rsvd0[4];
- + u32 req; /* Reset request */
- + u32 stat; /* Reset status */
- + u32 usb_cfg; /* USB configure */
- + u32 rsvd1[2];
- + u32 pci_rdy; /* PCI boot ready */
- +};
- +
- +static struct ltq_rcu_regs *ltq_rcu_regs =
- + (struct ltq_rcu_regs *) CKSEG1ADDR(LTQ_RCU_BASE);
- +
- +u32 ltq_reset_map(enum ltq_reset_modules module)
- +{
- + u32 val;
- +
- + switch (module) {
- + case LTQ_RESET_CORE:
- + case LTQ_RESET_SOFT:
- + val = LTQ_RCU_RD_SRST | LTQ_RCU_RD_CPU1;
- + break;
- + case LTQ_RESET_DMA:
- + val = LTQ_RCU_RD_DMA;
- + break;
- + case LTQ_RESET_ETH:
- + val = LTQ_RCU_RD_PPE;
- + break;
- + case LTQ_RESET_HARD:
- + val = LTQ_RCU_RD_HRST;
- + break;
- + default:
- + val = 0;
- + break;
- + }
- +
- + return val;
- +}
- +
- +int ltq_reset_activate(enum ltq_reset_modules module)
- +{
- + u32 val;
- +
- + val = ltq_reset_map(module);
- + if (unlikely(!val))
- + return 1;
- +
- + ltq_setbits(<q_rcu_regs->req, val);
- +
- + return 0;
- +}
- +
- +int ltq_reset_deactivate(enum ltq_reset_modules module)
- +{
- + u32 val;
- +
- + val = ltq_reset_map(module);
- + if (unlikely(!val))
- + return 1;
- +
- + ltq_clrbits(<q_rcu_regs->req, val);
- +
- + return 0;
- +}
- +
- +enum ltq_boot_select ltq_boot_select(void)
- +{
- + u32 stat;
- + unsigned int bootstrap;
- +
- + stat = ltq_readl(<q_rcu_regs->stat);
- + bootstrap = (stat & LTQ_RCU_STAT_BOOT_MASK) >> LTQ_RCU_STAT_BOOT_SHIFT;
- +
- + switch (bootstrap) {
- + case 0:
- + return BOOT_NOR_NO_BOOTROM;
- + case 1:
- + return BOOT_NOR;
- + case 2:
- + return BOOT_MII0;
- + case 3:
- + return BOOT_PCI;
- + case 4:
- + return BOOT_UART;
- + case 5:
- + return BOOT_SPI;
- + case 6:
- + return BOOT_NAND;
- + case 7:
- + return BOOT_RMII0;
- + default:
- + return BOOT_UNKNOWN;
- + }
- +}
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/lantiq-common/Makefile
- @@ -0,0 +1,34 @@
- +#
- +# Copyright (C) 2000-2011 Wolfgang Denk, DENX Software Engineering, wd@denx.de
- +#
- +# SPDX-License-Identifier: GPL-2.0+
- +#
- +
- +include $(TOPDIR)/config.mk
- +
- +LIB = $(obj)liblantiq-common.o
- +
- +START = start.o
- +COBJS-y = cpu.o pmu.o
- +COBJS-$(CONFIG_SPL_BUILD) += spl.o
- +SOBJS-y = lowlevel_init.o
- +
- +COBJS := $(COBJS-y)
- +SOBJS := $(SOBJS-y)
- +SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
- +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
- +START := $(addprefix $(obj),$(START))
- +
- +all: $(LIB)
- +
- +$(LIB): $(obj).depend $(OBJS)
- + $(call cmd_link_o_target, $(OBJS))
- +
- +#########################################################################
- +
- +# defines $(obj).depend target
- +include $(SRCTREE)/rules.mk
- +
- +sinclude $(obj).depend
- +
- +#########################################################################
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/lantiq-common/cpu.c
- @@ -0,0 +1,59 @@
- +/*
- + * Copyright (C) 2012-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <asm/lantiq/chipid.h>
- +#include <asm/lantiq/clk.h>
- +#include <asm/lantiq/reset.h>
- +#include <asm/lantiq/cpu.h>
- +
- +static const char ltq_bootsel_strings[][16] = {
- + "NOR",
- + "NOR w/o BootROM",
- + "UART",
- + "UART w/o EEPROM",
- + "SPI",
- + "NAND",
- + "PCI",
- + "MII0",
- + "RMII0",
- + "RGMII1",
- + "unknown",
- +};
- +
- +const char *ltq_boot_select_str(void)
- +{ enum ltq_boot_select bootsel = ltq_boot_select();
- +
- + if (bootsel > BOOT_UNKNOWN)
- + bootsel = BOOT_UNKNOWN;
- +
- + return ltq_bootsel_strings[bootsel];
- +}
- +
- +void ltq_chip_print_info(void)
- +{
- + char buf[32];
- +
- + printf("SoC: Lantiq %s v1.%u\n", ltq_chip_partnum_str(),
- + ltq_chip_version_get());
- + printf("CPU: %s MHz\n", strmhz(buf, ltq_get_cpu_clock()));
- + printf("IO: %s MHz\n", strmhz(buf, ltq_get_io_region_clock()));
- + printf("BUS: %s MHz\n", strmhz(buf, ltq_get_bus_clock()));
- + printf("BOOT: %s\n", ltq_boot_select_str());
- +}
- +
- +int arch_cpu_init(void)
- +{
- + ltq_pmu_init();
- + ltq_ebu_init();
- +
- + return 0;
- +}
- +
- +void _machine_restart(void)
- +{
- + ltq_reset_activate(LTQ_RESET_CORE);
- +}
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/lantiq-common/lowlevel_init.S
- @@ -0,0 +1,20 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <asm/asm.h>
- +#include <asm/regdef.h>
- +
- +NESTED(lowlevel_init, 0, ra)
- + move t8, ra
- +
- + la t7, ltq_cgu_init
- + jalr t7
- +
- + la t7, ltq_mem_init
- + jalr t7
- +
- + jr t8
- + END(lowlevel_init)
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/lantiq-common/pmu.c
- @@ -0,0 +1,9 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <asm/lantiq/pm.h>
- +
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/lantiq-common/spl.c
- @@ -0,0 +1,403 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <image.h>
- +#include <version.h>
- +#include <spi_flash.h>
- +#include <linux/compiler.h>
- +#include <lzma/LzmaDec.h>
- +#include <linux/lzo.h>
- +#include <asm/mipsregs.h>
- +
- +#if defined(CONFIG_LTQ_SPL_CONSOLE)
- +#define spl_has_console 1
- +
- +#if defined(CONFIG_LTQ_SPL_DEBUG)
- +#define spl_has_debug 1
- +#else
- +#define spl_has_debug 0
- +#endif
- +
- +#else
- +#define spl_has_console 0
- +#define spl_has_debug 0
- +#endif
- +
- +#define spl_debug(fmt, args...) \
- + do { \
- + if (spl_has_debug) \
- + printf(fmt, ##args); \
- + } while (0)
- +
- +#define spl_puts(msg) \
- + do { \
- + if (spl_has_console) \
- + puts(msg); \
- + } while (0)
- +
- +#if defined(CONFIG_LTQ_SUPPORT_SPL_SPI_FLASH) && defined(CONFIG_SYS_BOOT_SFSPL)
- +#define spl_boot_spi_flash 1
- +#else
- +#define spl_boot_spi_flash 0
- +#ifndef CONFIG_SPL_SPI_BUS
- +#define CONFIG_SPL_SPI_BUS 0
- +#endif
- +#ifndef CONFIG_SPL_SPI_CS
- +#define CONFIG_SPL_SPI_CS 0
- +#endif
- +#ifndef CONFIG_SPL_SPI_MAX_HZ
- +#define CONFIG_SPL_SPI_MAX_HZ 0
- +#endif
- +#ifndef CONFIG_SPL_SPI_MODE
- +#define CONFIG_SPL_SPI_MODE 0
- +#endif
- +#endif
- +
- +#if defined(CONFIG_LTQ_SUPPORT_SPL_NOR_FLASH) && defined(CONFIG_SYS_BOOT_NORSPL)
- +#define spl_boot_nor_flash 1
- +#else
- +#define spl_boot_nor_flash 0
- +#endif
- +
- +#define spl_sync() __asm__ __volatile__("sync");
- +
- +struct spl_image {
- + ulong data_addr;
- + ulong entry_addr;
- + ulong data_size;
- + ulong entry_size;
- + ulong data_crc;
- + u8 comp;
- +};
- +
- +DECLARE_GLOBAL_DATA_PTR;
- +
- +/* Emulated malloc area needed for LZMA allocator in BSS */
- +static u8 *spl_mem_ptr __maybe_unused;
- +static size_t spl_mem_size __maybe_unused;
- +
- +static int spl_is_comp_lzma(const struct spl_image *spl)
- +{
- +#if defined(CONFIG_LTQ_SPL_COMP_LZMA)
- + return spl->comp == IH_COMP_LZMA;
- +#else
- + return 0;
- +#endif
- +}
- +
- +static int spl_is_comp_lzo(const struct spl_image *spl)
- +{
- +#if defined(CONFIG_LTQ_SPL_COMP_LZO)
- + return spl->comp == IH_COMP_LZO;
- +#else
- + return 0;
- +#endif
- +}
- +
- +static int spl_is_compressed(const struct spl_image *spl)
- +{
- + if (spl_is_comp_lzma(spl))
- + return 1;
- +
- + if (spl_is_comp_lzo(spl))
- + return 1;
- +
- + return 0;
- +}
- +
- +static void spl_console_init(void)
- +{
- + if (!spl_has_console)
- + return;
- +
- + gd->flags |= GD_FLG_RELOC;
- + gd->baudrate = CONFIG_BAUDRATE;
- +
- + serial_init();
- +
- + gd->have_console = 1;
- +
- + spl_puts("\nU-Boot SPL " PLAIN_VERSION " (" U_BOOT_DATE " - " \
- + U_BOOT_TIME ")\n");
- +}
- +
- +static int spl_parse_image(const image_header_t *hdr, struct spl_image *spl)
- +{
- + spl_puts("SPL: checking U-Boot image\n");
- +
- + if (!image_check_magic(hdr)) {
- + spl_puts("SPL: invalid magic\n");
- + return -1;
- + }
- +
- + if (!image_check_hcrc(hdr)) {
- + spl_puts("SPL: invalid header CRC\n");
- + return -1;
- + }
- +
- + spl->data_addr += image_get_header_size();
- + spl->entry_addr = image_get_load(hdr);
- + spl->data_size = image_get_data_size(hdr);
- + spl->data_crc = image_get_dcrc(hdr);
- + spl->comp = image_get_comp(hdr);
- +
- + spl_debug("SPL: data %08lx, size %lu, entry %08lx, comp %u\n",
- + spl->data_addr, spl->data_size, spl->entry_addr, spl->comp);
- +
- + return 0;
- +}
- +
- +static int spl_check_data(const struct spl_image *spl, ulong loadaddr)
- +{
- + ulong dcrc = crc32(0, (unsigned char *)loadaddr, spl->data_size);
- +
- + if (dcrc != spl->data_crc) {
- + spl_puts("SPL: invalid data CRC\n");
- + return 0;
- + }
- +
- + return 1;
- +}
- +
- +static void *spl_lzma_alloc(void *p, size_t size)
- +{
- + u8 *ret;
- +
- + if (size > spl_mem_size)
- + return NULL;
- +
- + ret = spl_mem_ptr;
- + spl_mem_ptr += size;
- + spl_mem_size -= size;
- +
- + return ret;
- +}
- +
- +static void spl_lzma_free(void *p, void *addr)
- +{
- +}
- +
- +static int spl_copy_image(struct spl_image *spl)
- +{
- + spl_puts("SPL: copying U-Boot to RAM\n");
- +
- + memcpy((void *) spl->entry_addr, (const void *) spl->data_addr,
- + spl->data_size);
- +
- + spl->entry_size = spl->data_size;
- +
- + return 0;
- +}
- +
- +static int spl_uncompress_lzma(struct spl_image *spl, unsigned long loadaddr)
- +{
- + SRes res;
- + const Byte *prop = (const Byte *) loadaddr;
- + const Byte *src = (const Byte *) loadaddr + LZMA_PROPS_SIZE +
- + sizeof(uint64_t);
- + Byte *dest = (Byte *) spl->entry_addr;
- + SizeT dest_len = 0xFFFFFFFF;
- + SizeT src_len = spl->data_size - LZMA_PROPS_SIZE;
- + ELzmaStatus status = 0;
- + ISzAlloc alloc;
- +
- + spl_puts("SPL: decompressing U-Boot with LZMA\n");
- +
- + alloc.Alloc = spl_lzma_alloc;
- + alloc.Free = spl_lzma_free;
- + spl_mem_ptr = (u8 *) CONFIG_SPL_MALLOC_BASE;
- + spl_mem_size = CONFIG_SPL_MALLOC_MAX_SIZE;
- +
- + res = LzmaDecode(dest, &dest_len, src, &src_len, prop, LZMA_PROPS_SIZE,
- + LZMA_FINISH_ANY, &status, &alloc);
- + if (res != SZ_OK)
- + return 1;
- +
- + spl->entry_size = dest_len;
- +
- + return 0;
- +}
- +
- +static int spl_uncompress_lzo(struct spl_image *spl, unsigned long loadaddr)
- +{
- + size_t len;
- + int ret;
- +
- + spl_puts("SPL: decompressing U-Boot with LZO\n");
- +
- + ret = lzop_decompress(
- + (const unsigned char*) loadaddr, spl->data_size,
- + (unsigned char *) spl->entry_addr, &len);
- +
- + spl->entry_size = len;
- +
- + return ret;
- +}
- +
- +static int spl_uncompress(struct spl_image *spl, unsigned long loadaddr)
- +{
- + int ret;
- +
- + if (spl_is_comp_lzma(spl))
- + ret = spl_uncompress_lzma(spl, loadaddr);
- + else if (spl_is_comp_lzo(spl))
- + ret = spl_uncompress_lzo(spl, loadaddr);
- + else
- + ret = 1;
- +
- + return ret;
- +}
- +
- +static int spl_load_spi_flash(struct spl_image *spl)
- +{
- + struct spi_flash sf = { 0 };
- + image_header_t hdr;
- + int ret;
- + unsigned long loadaddr;
- +
- + /*
- + * Image format:
- + *
- + * - 12 byte non-volatile bootstrap header
- + * - SPL binary
- + * - 12 byte non-volatile bootstrap header
- + * - 64 byte U-Boot mkimage header
- + * - U-Boot binary
- + */
- + spl->data_addr = image_copy_end() - CONFIG_SPL_TEXT_BASE + 24;
- +
- + spl_puts("SPL: probing SPI flash\n");
- +
- + spi_init();
- + ret = spl_spi_flash_probe(&sf);
- + if (ret)
- + return ret;
- +
- + spl_debug("SPL: reading image header at offset %lx\n", spl->data_addr);
- +
- + ret = spi_flash_read(&sf, spl->data_addr, sizeof(hdr), &hdr);
- + if (ret)
- + return ret;
- +
- + spl_debug("SPL: checking image header at offset %lx\n", spl->data_addr);
- +
- + ret = spl_parse_image(&hdr, spl);
- + if (ret)
- + return ret;
- +
- + if (spl_is_compressed(spl))
- + loadaddr = CONFIG_LOADADDR;
- + else
- + loadaddr = spl->entry_addr;
- +
- + spl_puts("SPL: loading U-Boot to RAM\n");
- +
- + ret = spi_flash_read(&sf, spl->data_addr, spl->data_size,
- + (void *) loadaddr);
- +
- + if (!spl_check_data(spl, loadaddr))
- + return -1;
- +
- + if (spl_is_compressed(spl))
- + ret = spl_uncompress(spl, loadaddr);
- +
- + return ret;
- +}
- +
- +static int spl_load_nor_flash(struct spl_image *spl)
- +{
- + const image_header_t *hdr;
- + int ret;
- +
- + /*
- + * Image format:
- + *
- + * - SPL binary
- + * - 64 byte U-Boot mkimage header
- + * - U-Boot binary
- + */
- + spl->data_addr = image_copy_end();
- + hdr = (const image_header_t *) image_copy_end();
- +
- + spl_debug("SPL: checking image header at address %p\n", hdr);
- +
- + ret = spl_parse_image(hdr, spl);
- + if (ret)
- + return ret;
- +
- + if (spl_is_compressed(spl))
- + ret = spl_uncompress(spl, spl->data_addr);
- + else
- + ret = spl_copy_image(spl);
- +
- + return ret;
- +}
- +
- +static int spl_load(struct spl_image *spl)
- +{
- + int ret;
- +
- + if (spl_boot_spi_flash)
- + ret = spl_load_spi_flash(spl);
- + else if (spl_boot_nor_flash)
- + ret = spl_load_nor_flash(spl);
- + else
- + ret = 1;
- +
- + return ret;
- +}
- +
- +void __noreturn spl_lantiq_init(void)
- +{
- + void (*uboot)(void) __noreturn;
- + struct spl_image spl;
- + gd_t gd_data;
- + int ret;
- +
- + gd = &gd_data;
- + barrier();
- + memset((void *)gd, 0, sizeof(gd_t));
- +
- + spl_console_init();
- +
- + spl_debug("SPL: initializing\n");
- +
- +#if 0
- + spl_debug("CP0_CONFIG: %08x\n", read_c0_config());
- + spl_debug("CP0_CONFIG1: %08x\n", read_c0_config1());
- + spl_debug("CP0_CONFIG2: %08x\n", read_c0_config2());
- + spl_debug("CP0_CONFIG3: %08x\n", read_c0_config3());
- + spl_debug("CP0_CONFIG6: %08x\n", read_c0_config6());
- + spl_debug("CP0_CONFIG7: %08x\n", read_c0_config7());
- + spl_debug("CP0_STATUS: %08x\n", read_c0_status());
- + spl_debug("CP0_PRID: %08x\n", read_c0_prid());
- +#endif
- +
- + board_early_init_f();
- + timer_init();
- +
- + memset(&spl, 0, sizeof(spl));
- +
- + ret = spl_load(&spl);
- + if (ret)
- + goto hang;
- +
- + spl_debug("SPL: U-Boot entry %08lx\n", spl.entry_addr);
- + spl_puts("SPL: jumping to U-Boot\n");
- +
- + flush_cache(spl.entry_addr, spl.entry_size);
- + spl_sync();
- +
- + uboot = (void *) spl.entry_addr;
- + uboot();
- +
- +hang:
- + spl_puts("SPL: cannot start U-Boot\n");
- +
- + for (;;)
- + ;
- +}
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/lantiq-common/start.S
- @@ -0,0 +1,143 @@
- +/*
- + * Copyright (C) 2010 Lantiq Deutschland GmbH
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <config.h>
- +#include <asm/regdef.h>
- +#include <asm/mipsregs.h>
- +
- +#define S_PRIdCoID 16 /* Company ID (R) */
- +#define M_PRIdCoID (0xff << S_PRIdCoID)
- +#define S_PRIdImp 8 /* Implementation ID (R) */
- +#define M_PRIdImp (0xff << S_PRIdImp)
- +
- +#define K_CacheAttrCWTnWA 0 /* Cacheable, write-thru, no write allocate */
- +#define K_CacheAttrCWTWA 1 /* Cacheable, write-thru, write allocate */
- +#define K_CacheAttrU 2 /* Uncached */
- +#define K_CacheAttrC 3 /* Cacheable */
- +#define K_CacheAttrCN 3 /* Cacheable, non-coherent */
- +#define K_CacheAttrCCE 4 /* Cacheable, coherent, exclusive */
- +#define K_CacheAttrCCS 5 /* Cacheable, coherent, shared */
- +#define K_CacheAttrCCU 6 /* Cacheable, coherent, update */
- +#define K_CacheAttrUA 7 /* Uncached accelerated */
- +
- +#define S_ConfigK23 28 /* Kseg2/3 coherency algorithm (FM MMU only) (R/W) */
- +#define M_ConfigK23 (0x7 << S_ConfigK23)
- +#define W_ConfigK23 3
- +#define S_ConfigKU 25 /* Kuseg coherency algorithm (FM MMU only) (R/W) */
- +#define M_ConfigKU (0x7 << S_ConfigKU)
- +#define W_ConfigKU 3
- +
- +#define S_ConfigMM 18 /* Merge mode (implementation specific) */
- +#define M_ConfigMM (0x1 << S_ConfigMM)
- +
- +#define S_StatusBEV 22 /* Enable Boot Exception Vectors (R/W) */
- +#define M_StatusBEV (0x1 << S_StatusBEV)
- +
- +#define S_StatusFR 26 /* Enable 64-bit FPRs (R/W) */
- +#define M_StatusFR (0x1 << S_StatusFR)
- +
- +#define S_ConfigK0 0 /* Kseg0 coherency algorithm (R/W) */
- +#define M_ConfigK0 (0x7 << S_ConfigK0)
- +
- +#define CONFIG0_MIPS32_64_MSK 0x8000ffff
- +#define STATUS_MIPS32_64_MSK 0xfffcffff
- +
- +#define STATUS_MIPS24K 0
- +#define CONFIG0_MIPS24K ((K_CacheAttrCN << S_ConfigK23) |\
- + (K_CacheAttrCN << S_ConfigKU) |\
- + (M_ConfigMM))
- +
- +#define STATUS_MIPS34K 0
- +#define CONFIG0_MIPS34K ((K_CacheAttrCN << S_ConfigK23) |\
- + (K_CacheAttrCN << S_ConfigKU) |\
- + (M_ConfigMM))
- +
- +#define STATUS_MIPS32_64 (M_StatusBEV | M_StatusFR)
- +#define CONFIG0_MIPS32_64 (K_CacheAttrCN << S_ConfigK0)
- +
- +#ifdef CONFIG_SOC_XWAY_DANUBE
- +#define CONFIG0_LANTIQ (CONFIG0_MIPS24K | CONFIG0_MIPS32_64)
- +#define STATUS_LANTIQ (STATUS_MIPS24K | STATUS_MIPS32_64)
- +#endif
- +
- +#ifdef CONFIG_SOC_XWAY_VRX200
- +#define CONFIG0_LANTIQ (CONFIG0_MIPS34K | CONFIG0_MIPS32_64)
- +#define STATUS_LANTIQ (STATUS_MIPS34K | STATUS_MIPS32_64)
- +#endif
- +
- +
- + .set noreorder
- +
- + .globl _start
- + .text
- +_start:
- + /* Entry point */
- + b main
- + nop
- +
- + /* Lantiq SoC Boot config word */
- + .org 0x10
- +#ifdef CONFIG_SYS_XWAY_EBU_BOOTCFG
- + .word CONFIG_SYS_XWAY_EBU_BOOTCFG
- +#else
- + .word 0
- +#endif
- + .word 0
- +
- + .align 4
- +main:
- +
- + /* Init Timer */
- + mtc0 zero, CP0_COUNT
- + mtc0 zero, CP0_COMPARE
- +
- + /* Setup MIPS24K/MIPS34K specifics (implementation dependent fields) */
- + mfc0 t0, CP0_CONFIG
- + li t1, CONFIG0_MIPS32_64_MSK
- + and t0, t1
- + li t1, CONFIG0_LANTIQ
- + or t0, t1
- + mtc0 t0, CP0_CONFIG
- +
- + mfc0 t0, CP0_STATUS
- + li t1, STATUS_MIPS32_64_MSK
- + and t0, t1
- + li t1, STATUS_LANTIQ
- + or t0, t1
- + mtc0 t0, CP0_STATUS
- +
- + /* Initialize CGU */
- + la t9, ltq_cgu_init
- + jalr t9
- + nop
- +
- + /* Initialize memory controller */
- + la t9, ltq_mem_init
- + jalr t9
- + nop
- +
- + /* Initialize caches... */
- + la t9, mips_cache_reset
- + jalr t9
- + nop
- +
- + /* Clear BSS */
- + la t1, __bss_start
- + la t2, __bss_end
- + sub t1, 4
- +1:
- + addi t1, 4
- + bltl t1, t2, 1b
- + sw zero, 0(t1)
- +
- + /* Setup stack pointer and force alignment on a 16 byte boundary */
- + li t0, (CONFIG_SPL_STACK_BASE & ~0xF)
- + la sp, 0(t0)
- +
- + la t9, spl_lantiq_init
- + jr t9
- + nop
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/lantiq-common/u-boot-spl.lds
- @@ -0,0 +1,48 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +MEMORY { .spl_mem : ORIGIN = CONFIG_SPL_TEXT_BASE, \
- + LENGTH = CONFIG_SPL_MAX_SIZE }
- +MEMORY { .bss_mem : ORIGIN = CONFIG_SPL_BSS_BASE, \
- + LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
- +
- +OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradlittlemips")
- +OUTPUT_ARCH(mips)
- +ENTRY(_start)
- +SECTIONS
- +{
- + . = ALIGN(4);
- + .text : {
- + *(.text*)
- + } > .spl_mem
- +
- + . = ALIGN(4);
- + .rodata : {
- + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
- + } > .spl_mem
- +
- + . = ALIGN(4);
- + .data : {
- + *(SORT_BY_ALIGNMENT(.data*))
- + *(SORT_BY_ALIGNMENT(.sdata*))
- + } > .spl_mem
- +
- + . = ALIGN(4);
- + __image_copy_end = .;
- + uboot_end_data = .;
- +
- + .bss : {
- + __bss_start = .;
- + *(.bss*)
- + *(.sbss*)
- + . = ALIGN(4);
- + __bss_end = .;
- + } > .bss_mem
- +
- + . = ALIGN(4);
- + __end = .;
- + uboot_end = .;
- +}
- --- a/arch/mips/cpu/mips32/start.S
- +++ b/arch/mips/cpu/mips32/start.S
- @@ -105,7 +105,7 @@ reset:
- mtc0 zero, CP0_COUNT
- mtc0 zero, CP0_COMPARE
-
- -#ifndef CONFIG_SKIP_LOWLEVEL_INIT
- +#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) || defined(CONFIG_SYS_DISABLE_CACHE)
- /* CONFIG0 register */
- li t0, CONF_CM_UNCACHED
- mtc0 t0, CP0_CONFIG
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/vrx200/Makefile
- @@ -0,0 +1,32 @@
- +#
- +# Copyright (C) 2000-2011 Wolfgang Denk, DENX Software Engineering, wd@denx.de
- +#
- +# SPDX-License-Identifier: GPL-2.0+
- +#
- +
- +include $(TOPDIR)/config.mk
- +
- +LIB = $(obj)lib$(SOC).o
- +
- +COBJS-y += cgu.o chipid.o dcdc.o ebu.o gphy.o mem.o pmu.o rcu.o
- +SOBJS-y += cgu_init.o mem_init.o
- +SOBJS-y += gphy_fw.o
- +
- +COBJS := $(COBJS-y)
- +SOBJS := $(SOBJS-y)
- +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
- +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
- +
- +all: $(LIB)
- +
- +$(LIB): $(obj).depend $(OBJS)
- + $(call cmd_link_o_target, $(OBJS))
- +
- +#########################################################################
- +
- +# defines $(obj).depend target
- +include $(SRCTREE)/rules.mk
- +
- +sinclude $(obj).depend
- +
- +#########################################################################
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/vrx200/cgu.c
- @@ -0,0 +1,208 @@
- +/*
- + * Copyright (C) 2010 Lantiq Deutschland GmbH
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <asm/arch/soc.h>
- +#include <asm/arch/gphy.h>
- +#include <asm/lantiq/clk.h>
- +#include <asm/lantiq/io.h>
- +
- +#define LTQ_CGU_PLL1_PLLN_SHIFT 6
- +#define LTQ_CGU_PLL1_PLLN_MASK (0x3F << LTQ_CGU_PLL1_PLLN_SHIFT)
- +#define LTQ_CGU_PLL1_PLLM_SHIFT 2
- +#define LTQ_CGU_PLL1_PLLM_MASK (0xF << LTQ_CGU_PLL1_PLLM_SHIFT)
- +#define LTQ_CGU_PLL1_PLLL (1 << 1)
- +#define LTQ_CGU_PLL1_PLL_EN 1
- +
- +#define LTQ_CGU_SYS_OCP_SHIFT 0
- +#define LTQ_CGU_SYS_OCP_MASK (0x3 << LTQ_CGU_SYS_OCP_SHIFT)
- +#define LTQ_CGU_SYS_CPU_SHIFT 4
- +#define LTQ_CGU_SYS_CPU_MASK (0xF << LTQ_CGU_SYS_CPU_SHIFT)
- +
- +#define LTQ_CGU_UPDATE 1
- +
- +#define LTQ_CGU_IFCLK_GPHY_SEL_SHIFT 2
- +#define LTQ_CGU_IFCLK_GPHY_SEL_MASK (0x7 << LTQ_CGU_IFCLK_GPHY_SEL_SHIFT)
- +
- +struct ltq_cgu_regs {
- + u32 rsvd0;
- + u32 pll0_cfg; /* PLL0 config */
- + u32 pll1_cfg; /* PLL1 config */
- + u32 sys; /* System clock */
- + u32 clk_fsr; /* Clock frequency select */
- + u32 clk_gsr; /* Clock gating status */
- + u32 clk_gcr0; /* Clock gating control 0 */
- + u32 clk_gcr1; /* Clock gating control 1 */
- + u32 update; /* CGU update control */
- + u32 if_clk; /* Interface clock */
- + u32 ddr; /* DDR memory control */
- + u32 ct1_sr; /* CT status 1 */
- + u32 ct_kval; /* CT K value */
- + u32 pcm_cr; /* PCM control */
- + u32 pci_cr; /* PCI clock control */
- + u32 rsvd1;
- + u32 gphy1_cfg; /* GPHY1 config */
- + u32 gphy0_cfg; /* GPHY0 config */
- + u32 rsvd2[6];
- + u32 pll2_cfg; /* PLL2 config */
- +};
- +
- +static struct ltq_cgu_regs *ltq_cgu_regs =
- + (struct ltq_cgu_regs *) CKSEG1ADDR(LTQ_CGU_BASE);
- +
- +static inline u32 ltq_cgu_sys_readl(u32 mask, u32 shift)
- +{
- + return (ltq_readl(<q_cgu_regs->sys) & mask) >> shift;
- +}
- +
- +unsigned long ltq_get_io_region_clock(void)
- +{
- + unsigned int ocp_sel;
- + unsigned long clk, cpu_clk;
- +
- + cpu_clk = ltq_get_cpu_clock();
- +
- + ocp_sel = ltq_cgu_sys_readl(LTQ_CGU_SYS_OCP_MASK,
- + LTQ_CGU_SYS_OCP_SHIFT);
- +
- + switch (ocp_sel) {
- + case 0:
- + /* OCP ratio 1 */
- + clk = cpu_clk;
- + break;
- + case 2:
- + /* OCP ratio 2 */
- + clk = cpu_clk / 2;
- + break;
- + case 3:
- + /* OCP ratio 2.5 */
- + clk = (cpu_clk * 2) / 5;
- + break;
- + case 4:
- + /* OCP ratio 3 */
- + clk = cpu_clk / 3;
- + break;
- + default:
- + clk = 0;
- + break;
- + }
- +
- + return clk;
- +}
- +
- +unsigned long ltq_get_cpu_clock(void)
- +{
- + unsigned int cpu_sel;
- + unsigned long clk;
- +
- + cpu_sel = ltq_cgu_sys_readl(LTQ_CGU_SYS_CPU_MASK,
- + LTQ_CGU_SYS_CPU_SHIFT);
- +
- + switch (cpu_sel) {
- + case 0:
- + clk = CLOCK_600_MHZ;
- + break;
- + case 1:
- + clk = CLOCK_500_MHZ;
- + break;
- + case 2:
- + clk = CLOCK_393_MHZ;
- + break;
- + case 3:
- + clk = CLOCK_333_MHZ;
- + break;
- + case 5:
- + case 6:
- + clk = CLOCK_197_MHZ;
- + break;
- + case 7:
- + clk = CLOCK_166_MHZ;
- + break;
- + case 4:
- + case 8:
- + case 9:
- + clk = CLOCK_125_MHZ;
- + break;
- + default:
- + clk = 0;
- + break;
- + }
- +
- + return clk;
- +}
- +
- +unsigned long ltq_get_bus_clock(void)
- +{
- + return ltq_get_io_region_clock();
- +}
- +
- +void ltq_cgu_gphy_clk_src(enum ltq_gphy_clk clk)
- +{
- + ltq_clrbits(<q_cgu_regs->if_clk, LTQ_CGU_IFCLK_GPHY_SEL_MASK);
- + ltq_setbits(<q_cgu_regs->if_clk, clk << LTQ_CGU_IFCLK_GPHY_SEL_SHIFT);
- +}
- +
- +static inline int ltq_cgu_pll1_locked(void)
- +{
- + u32 pll1_cfg = ltq_readl(<q_cgu_regs->pll1_cfg);
- +
- + return pll1_cfg & LTQ_CGU_PLL1_PLLL;
- +}
- +
- +static inline void ltq_cgu_pll1_restart(unsigned m, unsigned n)
- +{
- + u32 pll1_cfg;
- +
- + ltq_clrbits(<q_cgu_regs->pll1_cfg, LTQ_CGU_PLL1_PLL_EN);
- + ltq_setbits(<q_cgu_regs->update, LTQ_CGU_UPDATE);
- +
- + pll1_cfg = ltq_readl(<q_cgu_regs->pll1_cfg);
- + pll1_cfg &= ~(LTQ_CGU_PLL1_PLLN_MASK | LTQ_CGU_PLL1_PLLM_MASK);
- + pll1_cfg |= n << LTQ_CGU_PLL1_PLLN_SHIFT;
- + pll1_cfg |= m << LTQ_CGU_PLL1_PLLM_SHIFT;
- + pll1_cfg |= LTQ_CGU_PLL1_PLL_EN;
- + ltq_writel(<q_cgu_regs->pll1_cfg, pll1_cfg);
- + ltq_setbits(<q_cgu_regs->update, LTQ_CGU_UPDATE);
- +
- + __udelay(1000);
- +}
- +
- +/*
- + * From chapter 9 in errata sheet:
- + *
- + * Under certain condition, the PLL1 may failed to enter into lock
- + * status by hardware default N, M setting.
- + *
- + * Since system always starts from PLL0, the system software can run
- + * and re-program the PLL1 settings.
- + */
- +static void ltq_cgu_pll1_init(void)
- +{
- + unsigned i;
- + const unsigned pll1_m[] = { 1, 2, 3, 4 };
- + const unsigned pll1_n[] = { 21, 32, 43, 54 };
- +
- + /* Check if PLL1 has locked with hardware default settings */
- + if (ltq_cgu_pll1_locked())
- + return;
- +
- + for (i = 0; i < 4; i++) {
- + ltq_cgu_pll1_restart(pll1_m[i], pll1_n[i]);
- +
- + if (ltq_cgu_pll1_locked())
- + goto done;
- + }
- +
- +done:
- + /* Restart with hardware default values M=5, N=64 */
- + ltq_cgu_pll1_restart(5, 64);
- +}
- +
- +void ltq_pll_init(void)
- +{
- + ltq_cgu_pll1_init();
- +}
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/vrx200/cgu_init.S
- @@ -0,0 +1,119 @@
- +/*
- + * Copyright (C) 2010 Lantiq Deutschland GmbH
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <config.h>
- +#include <asm/asm.h>
- +#include <asm/regdef.h>
- +#include <asm/addrspace.h>
- +#include <asm/arch/soc.h>
- +
- +/* RCU module register */
- +#define LTQ_RCU_RST_REQ 0x0010 /* Reset request */
- +#define LTQ_RCU_RST_REQ_VALUE ((1 << 14) | (1 << 1))
- +
- +/* CGU module register */
- +#define LTQ_CGU_PLL0_CFG 0x0004 /* PLL0 config */
- +#define LTQ_CGU_PLL1_CFG 0x0008 /* PLL1 config */
- +#define LTQ_CGU_PLL2_CFG 0x0060 /* PLL2 config */
- +#define LTQ_CGU_SYS 0x000C /* System clock */
- +#define LTQ_CGU_CLK_FSR 0x0010 /* Clock frequency select */
- +#define LTQ_CGU_UPDATE 0x0020 /* Clock update control */
- +
- +/* Valid SYS.CPU values */
- +#define LTQ_CGU_SYS_CPU_SHIFT 4
- +#define LTQ_CGU_SYS_CPU_600_MHZ 0x0
- +#define LTQ_CGU_SYS_CPU_500_MHZ 0x1
- +#define LTQ_CGU_SYS_CPU_393_MHZ 0x2
- +#define LTQ_CGU_SYS_CPU_333_MHZ 0x3
- +#define LTQ_CGU_SYS_CPU_197_MHZ 0x5
- +#define LTQ_CGU_SYS_CPU_166_MHZ 0x7
- +#define LTQ_CGU_SYS_CPU_125_MHZ 0x9
- +
- +/* Valid SYS.OCP values */
- +#define LTQ_CGU_SYS_OCP_SHIFT 0
- +#define LTQ_CGU_SYS_OCP_1 0x0
- +#define LTQ_CGU_SYS_OCP_2 0x2
- +#define LTQ_CGU_SYS_OCP_2_5 0x3
- +#define LTQ_CGU_SYS_OCP_3 0x4
- +
- +/* Valid CLK_FSR.ETH values */
- +#define LTQ_CGU_CLK_FSR_ETH_SHIFT 24
- +#define LTQ_CGU_CLK_FSR_ETH_50_MHZ 0x0
- +#define LTQ_CGU_CLK_FSR_ETH_25_MHZ 0x1
- +#define LTQ_CGU_CLK_FSR_ETH_2_5_MHZ 0x2
- +#define LTQ_CGU_CLK_FSR_ETH_125_MHZ 0x3
- +
- +/* Valid CLK_FSR.PPE values */
- +#define LTQ_CGU_CLK_FSR_PPE_SHIFT 16
- +#define LTQ_CGU_CLK_FSR_PPE_500_MHZ 0x0 /* Overclock frequency */
- +#define LTQ_CGU_CLK_FSR_PPE_450_MHZ 0x1 /* High frequency */
- +#define LTQ_CGU_CLK_FSR_PPE_400_MHZ 0x2 /* Low frequency */
- +
- +#if (CONFIG_SYS_CLOCK_MODE == LTQ_CLK_CPU_500_DDR_250)
- +#define LTQ_CGU_SYS_CPU_CONFIG LTQ_CGU_SYS_CPU_500_MHZ
- +#define LTQ_CGU_SYS_OCP_CONFIG LTQ_CGU_SYS_OCP_2
- +#define LTQ_CGU_CLK_FSR_ETH_CONFIG LTQ_CGU_CLK_FSR_ETH_125_MHZ
- +#define LTQ_CGU_CLK_FSR_PPE_CONFIG LTQ_CGU_CLK_FSR_PPE_450_MHZ
- +#else
- +#error "Invalid system clock configuration!"
- +#endif
- +
- +/* Build register values */
- +#define LTQ_CGU_SYS_VALUE ((LTQ_CGU_SYS_CPU_CONFIG << \
- + LTQ_CGU_SYS_CPU_SHIFT) | \
- + LTQ_CGU_SYS_OCP_CONFIG)
- +
- +#define LTQ_CGU_CLK_FSR_VALUE ((LTQ_CGU_CLK_FSR_ETH_CONFIG << \
- + LTQ_CGU_CLK_FSR_ETH_SHIFT) | \
- + (LTQ_CGU_CLK_FSR_PPE_CONFIG << \
- + LTQ_CGU_CLK_FSR_PPE_SHIFT))
- +
- + .set noreorder
- +
- +LEAF(ltq_cgu_init)
- + /* Load current CGU register values */
- + li t0, (LTQ_CGU_BASE | KSEG1)
- + lw t1, LTQ_CGU_SYS(t0)
- + lw t2, LTQ_CGU_CLK_FSR(t0)
- +
- + /* Load target CGU register values */
- + li t3, LTQ_CGU_SYS_VALUE
- + li t4, LTQ_CGU_CLK_FSR_VALUE
- +
- + /* Only update registers if values differ */
- + bne t1, t3, update
- + nop
- + beq t2, t4, finished
- + nop
- +
- +update:
- + /* Store target register values */
- + sw t3, LTQ_CGU_SYS(t0)
- + sw t4, LTQ_CGU_CLK_FSR(t0)
- +
- + /* Perform software reset to activate new clock config */
- +#if 0
- + li t0, (LTQ_RCU_BASE | KSEG1)
- + lw t1, LTQ_RCU_RST_REQ(t0)
- + or t1, LTQ_RCU_RST_REQ_VALUE
- + sw t1, LTQ_RCU_RST_REQ(t0)
- +#else
- + li t1, 1
- + sw t1, LTQ_CGU_UPDATE(t0)
- +#endif
- +
- +#if 0
- +wait_reset:
- + b wait_reset
- + nop
- +#endif
- +
- +finished:
- + jr ra
- + nop
- +
- + END(ltq_cgu_init)
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/vrx200/chipid.c
- @@ -0,0 +1,62 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <asm/lantiq/io.h>
- +#include <asm/lantiq/chipid.h>
- +#include <asm/arch/soc.h>
- +
- +#define LTQ_CHIPID_VERSION_SHIFT 28
- +#define LTQ_CHIPID_VERSION_MASK (0x7 << LTQ_CHIPID_VERSION_SHIFT)
- +#define LTQ_CHIPID_PNUM_SHIFT 12
- +#define LTQ_CHIPID_PNUM_MASK (0xFFFF << LTQ_CHIPID_PNUM_SHIFT)
- +
- +struct ltq_chipid_regs {
- + u32 manid; /* Manufacturer identification */
- + u32 chipid; /* Chip identification */
- +};
- +
- +static struct ltq_chipid_regs *ltq_chipid_regs =
- + (struct ltq_chipid_regs *) CKSEG1ADDR(LTQ_CHIPID_BASE);
- +
- +unsigned int ltq_chip_version_get(void)
- +{
- + u32 chipid;
- +
- + chipid = ltq_readl(<q_chipid_regs->chipid);
- +
- + return (chipid & LTQ_CHIPID_VERSION_MASK) >> LTQ_CHIPID_VERSION_SHIFT;
- +}
- +
- +unsigned int ltq_chip_partnum_get(void)
- +{
- + u32 chipid;
- +
- + chipid = ltq_readl(<q_chipid_regs->chipid);
- +
- + return (chipid & LTQ_CHIPID_PNUM_MASK) >> LTQ_CHIPID_PNUM_SHIFT;
- +}
- +
- +const char *ltq_chip_partnum_str(void)
- +{
- + enum ltq_chip_partnum partnum = ltq_chip_partnum_get();
- +
- + switch (partnum) {
- + case LTQ_SOC_VRX268:
- + case LTQ_SOC_VRX268_2:
- + return "VRX268";
- + case LTQ_SOC_VRX288:
- + case LTQ_SOC_VRX288_2:
- + return "VRX288";
- + case LTQ_SOC_GRX288:
- + case LTQ_SOC_GRX288_2:
- + return "GRX288";
- + default:
- + printf("Unknown partnum: %x\n", partnum);
- + }
- +
- + return "";
- +}
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/vrx200/config.mk
- @@ -0,0 +1,30 @@
- +#
- +# Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- +#
- +# SPDX-License-Identifier: GPL-2.0+
- +#
- +
- +PF_CPPFLAGS_XRX := $(call cc-option,-mtune=34kc,)
- +PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_XRX)
- +
- +ifdef CONFIG_SPL_BUILD
- +PF_ABICALLS := -mno-abicalls
- +PF_PIC := -fno-pic
- +PF_PIE :=
- +USE_PRIVATE_LIBGCC := yes
- +endif
- +
- +LIBS-y += $(CPUDIR)/lantiq-common/liblantiq-common.o
- +
- +ifndef CONFIG_SPL_BUILD
- +ifdef CONFIG_SYS_BOOT_SFSPL
- +ALL-y += $(obj)u-boot.ltq.sfspl
- +ALL-$(CONFIG_SPL_LZO_SUPPORT) += $(obj)u-boot.ltq.lzo.sfspl
- +ALL-$(CONFIG_SPL_LZMA_SUPPORT) += $(obj)u-boot.ltq.lzma.sfspl
- +endif
- +ifdef CONFIG_SYS_BOOT_NORSPL
- +ALL-y += $(obj)u-boot.ltq.norspl
- +ALL-$(CONFIG_SPL_LZO_SUPPORT) += $(obj)u-boot.ltq.lzo.norspl
- +ALL-$(CONFIG_SPL_LZMA_SUPPORT) += $(obj)u-boot.ltq.lzma.norspl
- +endif
- +endif
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/vrx200/dcdc.c
- @@ -0,0 +1,106 @@
- +/*
- + * Copyright (C) 2010 Lantiq Deutschland GmbH
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <asm/arch/soc.h>
- +#include <asm/lantiq/io.h>
- +
- +#define LTQ_DCDC_CLK_SET0_CLK_SEL_P (1 << 6)
- +#define LTQ_DCDC_CLK_SET1_SEL_DIV25 (1 << 5)
- +#define LTQ_DCDC_CONF_TEST_DIG_PID_FREEZE (1 << 5)
- +
- +struct ltq_dcdc_regs {
- + u8 b0_coeh; /* Coefficient b0 */
- + u8 b0_coel; /* Coefficient b0 */
- + u8 b1_coeh; /* Coefficient b1 */
- + u8 b1_coel; /* Coefficient b1 */
- + u8 b2_coeh; /* Coefficient b2 */
- + u8 b2_coel; /* Coefficient b2 */
- + u8 clk_set0; /* Clock setup */
- + u8 clk_set1; /* Clock setup */
- + u8 pwm_confh; /* Configure PWM */
- + u8 pwm_confl; /* Configure PWM */
- + u8 bias_vreg0; /* Bias and regulator setup */
- + u8 bias_vreg1; /* Bias and regulator setup */
- + u8 adc_gen0; /* ADC and general control */
- + u8 adc_gen1; /* ADC and general control */
- + u8 adc_con0; /* ADC and general config */
- + u8 adc_con1; /* ADC and general config */
- + u8 conf_test_ana; /* not documented */
- + u8 conf_test_dig; /* not documented */
- + u8 dcdc_status; /* not documented */
- + u8 pid_status; /* not documented */
- + u8 duty_cycle; /* not documented */
- + u8 non_ov_delay; /* not documented */
- + u8 analog_gain; /* not documented */
- + u8 duty_cycle_max_sat; /* not documented */
- + u8 duty_cycle_min_sat; /* not documented */
- + u8 duty_cycle_max; /* not documented */
- + u8 duty_cycle_min; /* not documented */
- + u8 error_max; /* not documented */
- + u8 error_read; /* not documented */
- + u8 delay_deglitch; /* not documented */
- + u8 latch_control; /* not documented */
- + u8 rsvd[240];
- + u8 osc_conf; /* OSC general config */
- + u8 osc_stat; /* OSC general status */
- +};
- +
- +static struct ltq_dcdc_regs *ltq_dcdc_regs =
- + (struct ltq_dcdc_regs *) CKSEG1ADDR(LTQ_DCDC_BASE);
- +
- +void ltq_dcdc_init(unsigned int dig_ref)
- +{
- + u8 dig_ref_cur, val;
- +
- + /* Set duty cycle max sat. to 70/90, enable PID freeze */
- + ltq_writeb(<q_dcdc_regs->duty_cycle_max_sat, 0x5A);
- + ltq_writeb(<q_dcdc_regs->duty_cycle_min_sat, 0x46);
- + val = ltq_readb(<q_dcdc_regs->conf_test_dig);
- + val |= LTQ_DCDC_CONF_TEST_DIG_PID_FREEZE;
- + ltq_writeb(<q_dcdc_regs->conf_test_dig, val);
- +
- + /* Program new coefficients */
- + ltq_writeb(<q_dcdc_regs->b0_coeh, 0x00);
- + ltq_writeb(<q_dcdc_regs->b0_coel, 0x00);
- + ltq_writeb(<q_dcdc_regs->b1_coeh, 0xFF);
- + ltq_writeb(<q_dcdc_regs->b1_coel, 0xE6);
- + ltq_writeb(<q_dcdc_regs->b2_coeh, 0x00);
- + ltq_writeb(<q_dcdc_regs->b2_coel, 0x1B);
- + ltq_writeb(<q_dcdc_regs->non_ov_delay, 0x8B);
- +
- + /* Set duty cycle max sat. to 60/108, disable PID freeze */
- + ltq_writeb(<q_dcdc_regs->duty_cycle_max_sat, 0x6C);
- + ltq_writeb(<q_dcdc_regs->duty_cycle_min_sat, 0x3C);
- + val = ltq_readb(<q_dcdc_regs->conf_test_dig);
- + val &= ~LTQ_DCDC_CONF_TEST_DIG_PID_FREEZE;
- + ltq_writeb(<q_dcdc_regs->conf_test_dig, val);
- +
- + /* Init clock and DLL settings */
- + val = ltq_readb(<q_dcdc_regs->clk_set0);
- + val |= LTQ_DCDC_CLK_SET0_CLK_SEL_P;
- + ltq_writeb(<q_dcdc_regs->clk_set0, val);
- + val = ltq_readb(<q_dcdc_regs->clk_set1);
- + val |= LTQ_DCDC_CLK_SET1_SEL_DIV25;
- + ltq_writeb(<q_dcdc_regs->clk_set1, val);
- + ltq_writeb(<q_dcdc_regs->pwm_confh, 0xF9);
- +
- + wmb();
- +
- + /* Adapt value of digital reference of DCDC converter */
- + dig_ref_cur = ltq_readb(<q_dcdc_regs->bias_vreg1);
- +
- + while (dig_ref_cur != dig_ref) {
- + if (dig_ref >= dig_ref_cur)
- + dig_ref_cur++;
- + else if (dig_ref < dig_ref_cur)
- + dig_ref_cur--;
- +
- + ltq_writeb(<q_dcdc_regs->bias_vreg1, dig_ref_cur);
- + __udelay(1000);
- + }
- +}
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/vrx200/ebu.c
- @@ -0,0 +1,126 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <asm/arch/soc.h>
- +#include <asm/lantiq/io.h>
- +
- +#define EBU_ADDRSEL_MASK(mask) ((mask & 0xf) << 4)
- +#define EBU_ADDRSEL_REGEN (1 << 0)
- +
- +#define EBU_CON_WRDIS (1 << 31)
- +#define EBU_CON_AGEN_DEMUX (0x0 << 24)
- +#define EBU_CON_AGEN_MUX (0x2 << 24)
- +#define EBU_CON_SETUP (1 << 22)
- +#define EBU_CON_WAIT_DIS (0x0 << 20)
- +#define EBU_CON_WAIT_ASYNC (0x1 << 20)
- +#define EBU_CON_WAIT_SYNC (0x2 << 20)
- +#define EBU_CON_WINV (1 << 19)
- +#define EBU_CON_PW_8BIT (0x0 << 16)
- +#define EBU_CON_PW_16BIT (0x1 << 16)
- +#define EBU_CON_ALEC(cycles) ((cycles & 0x3) << 14)
- +#define EBU_CON_BCGEN_CS (0x0 << 12)
- +#define EBU_CON_BCGEN_INTEL (0x1 << 12)
- +#define EBU_CON_BCGEN_MOTOROLA (0x2 << 12)
- +#define EBU_CON_WAITWRC(cycles) ((cycles & 0x7) << 8)
- +#define EBU_CON_WAITRDC(cycles) ((cycles & 0x3) << 6)
- +#define EBU_CON_HOLDC(cycles) ((cycles & 0x3) << 4)
- +#define EBU_CON_RECOVC(cycles) ((cycles & 0x3) << 2)
- +#define EBU_CON_CMULT_1 0x0
- +#define EBU_CON_CMULT_4 0x1
- +#define EBU_CON_CMULT_8 0x2
- +#define EBU_CON_CMULT_16 0x3
- +
- +#if defined(CONFIG_LTQ_SUPPORT_NOR_FLASH)
- +#define ebu_region0_enable 1
- +#else
- +#define ebu_region0_enable 0
- +#endif
- +
- +#if ((CONFIG_SYS_MAX_FLASH_BANKS == 2) && defined(CONFIG_LTQ_SUPPORT_NOR_FLASH) )
- +#define ebu_region0_addrsel_mask 3
- +#else
- +#define ebu_region0_addrsel_mask 1
- +#endif
- +
- +#if defined(CONFIG_LTQ_SUPPORT_NAND_FLASH) || ((CONFIG_SYS_MAX_FLASH_BANKS == 2) && defined(CONFIG_LTQ_SUPPORT_NOR_FLASH) )
- +#define ebu_region1_enable 1
- +#else
- +#define ebu_region1_enable 0
- +#endif
- +
- +struct ltq_ebu_regs {
- + u32 clc;
- + u32 rsvd0;
- + u32 id;
- + u32 rsvd1;
- + u32 con;
- + u32 rsvd2[3];
- + u32 addr_sel_0;
- + u32 addr_sel_1;
- + u32 addr_sel_2;
- + u32 addr_sel_3;
- + u32 rsvd3[12];
- + u32 con_0;
- + u32 con_1;
- + u32 con_2;
- + u32 con_3;
- +};
- +
- +static struct ltq_ebu_regs *ltq_ebu_regs =
- + (struct ltq_ebu_regs *) CKSEG1ADDR(LTQ_EBU_BASE);
- +
- +void ltq_ebu_init(void)
- +{
- + if (ebu_region0_enable) {
- + /*
- + * Map EBU region 0 to range 0x10000000-0x13ffffff and enable
- + * region control. This supports up to 32 MiB NOR flash in
- + * bank 0.
- + */
- + ltq_writel(<q_ebu_regs->addr_sel_0, LTQ_EBU_REGION0_BASE |
- + EBU_ADDRSEL_MASK(ebu_region0_addrsel_mask) | EBU_ADDRSEL_REGEN);
- +
- + ltq_writel(<q_ebu_regs->con_0, EBU_CON_AGEN_DEMUX |
- + EBU_CON_WAIT_DIS | EBU_CON_PW_16BIT |
- + EBU_CON_ALEC(3) | EBU_CON_BCGEN_INTEL |
- + EBU_CON_WAITWRC(7) | EBU_CON_WAITRDC(3) |
- + EBU_CON_HOLDC(3) | EBU_CON_RECOVC(3) |
- + EBU_CON_CMULT_16);
- + } else
- + ltq_clrbits(<q_ebu_regs->addr_sel_0, EBU_ADDRSEL_REGEN);
- +
- + if (ebu_region1_enable) {
- + /*
- + * Map EBU region 1 to range 0x14000000-0x13ffffff and enable
- + * region control. This supports NAND flash in bank 1. (and NOR flash in bank 2)
- + */
- + ltq_writel(<q_ebu_regs->addr_sel_1, LTQ_EBU_REGION1_BASE |
- + EBU_ADDRSEL_MASK(3) | EBU_ADDRSEL_REGEN);
- +
- + if (ebu_region0_addrsel_mask == 1)
- + ltq_writel(<q_ebu_regs->con_1, EBU_CON_AGEN_DEMUX |
- + EBU_CON_SETUP | EBU_CON_WAIT_DIS | EBU_CON_PW_8BIT |
- + EBU_CON_ALEC(3) | EBU_CON_BCGEN_INTEL |
- + EBU_CON_WAITWRC(2) | EBU_CON_WAITRDC(2) |
- + EBU_CON_HOLDC(1) | EBU_CON_RECOVC(1) |
- + EBU_CON_CMULT_4);
- +
- + if (ebu_region0_addrsel_mask == 3)
- + ltq_writel(<q_ebu_regs->con_1, EBU_CON_AGEN_DEMUX |
- + EBU_CON_WAIT_DIS | EBU_CON_PW_16BIT |
- + EBU_CON_ALEC(3) | EBU_CON_BCGEN_INTEL |
- + EBU_CON_WAITWRC(7) | EBU_CON_WAITRDC(3) |
- + EBU_CON_HOLDC(3) | EBU_CON_RECOVC(3) |
- + EBU_CON_CMULT_16);
- + } else
- + ltq_clrbits(<q_ebu_regs->addr_sel_1, EBU_ADDRSEL_REGEN);
- +}
- +
- +void *flash_swap_addr(unsigned long addr)
- +{
- + return (void *)(addr ^ 2);
- +}
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/vrx200/gphy.c
- @@ -0,0 +1,68 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <asm/lantiq/io.h>
- +#include <asm/arch/soc.h>
- +#include <asm/arch/gphy.h>
- +#include <lzma/LzmaTypes.h>
- +#include <lzma/LzmaDec.h>
- +#include <lzma/LzmaTools.h>
- +
- +static inline void ltq_gphy_decompress(const void *fw_start, const void *fw_end,
- + ulong dst_addr)
- +{
- + const ulong fw_len = (ulong) fw_end - (ulong) fw_start;
- + const ulong addr = CKSEG1ADDR(dst_addr);
- +
- + debug("ltq_gphy_decompress: addr %08lx, fw_start %p, fw_end %p\n",
- + addr, fw_start, fw_end);
- +
- + SizeT lzma_len = 65536;
- + int ret = lzmaBuffToBuffDecompress(
- + (unsigned char *)addr, &lzma_len,
- + (unsigned char *)fw_start, fw_len);
- +}
- +
- +void ltq_gphy_phy11g_a1x_load(ulong addr)
- +{
- + extern ulong __ltq_fw_phy11g_a1x_start;
- + extern ulong __ltq_fw_phy11g_a1x_end;
- +
- + ltq_gphy_decompress(&__ltq_fw_phy11g_a1x_start,
- + &__ltq_fw_phy11g_a1x_end,
- + addr);
- +}
- +
- +void ltq_gphy_phy11g_a2x_load(ulong addr)
- +{
- + extern ulong __ltq_fw_phy11g_a2x_start;
- + extern ulong __ltq_fw_phy11g_a2x_end;
- +
- + ltq_gphy_decompress(&__ltq_fw_phy11g_a2x_start,
- + &__ltq_fw_phy11g_a2x_end,
- + addr);
- +}
- +
- +void ltq_gphy_phy22f_a1x_load(ulong addr)
- +{
- + extern ulong __ltq_fw_phy22f_a1x_start;
- + extern ulong __ltq_fw_phy22f_a1x_end;
- +
- + ltq_gphy_decompress(&__ltq_fw_phy22f_a1x_start,
- + &__ltq_fw_phy22f_a1x_end,
- + addr);
- +}
- +
- +void ltq_gphy_phy22f_a2x_load(ulong addr)
- +{
- + extern ulong __ltq_fw_phy22f_a2x_start;
- + extern ulong __ltq_fw_phy22f_a2x_end;
- +
- + ltq_gphy_decompress(&__ltq_fw_phy22f_a2x_start,
- + &__ltq_fw_phy22f_a2x_end,
- + addr);
- +}
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/vrx200/gphy_fw.S
- @@ -0,0 +1,27 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <asm/asm.h>
- +
- + .section .rodata.__ltq_fw_phy11g_a1x
- +EXPORT(__ltq_fw_phy11g_a1x_start)
- + .incbin "fw_phy11g_a1x.blob"
- +EXPORT(__ltq_fw_phy11g_a1x_end)
- +
- + .section .rodata.__ltq_fw_phy11g_a2x
- +EXPORT(__ltq_fw_phy11g_a2x_start)
- + .incbin "fw_phy11g_a2x.blob"
- +EXPORT(__ltq_fw_phy11g_a2x_end)
- +
- + .section .rodata.__ltq_fw_phy22f_a1x
- +EXPORT(__ltq_fw_phy22f_a1x_start)
- + .incbin "fw_phy22f_a1x.blob"
- +EXPORT(__ltq_fw_phy22f_a1x_end)
- +
- + .section .rodata.__ltq_fw_phy22f_a2x
- +EXPORT(__ltq_fw_phy22f_a2x_start)
- + .incbin "fw_phy22f_a2x.blob"
- +EXPORT(__ltq_fw_phy22f_a2x_end)
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/vrx200/mem.c
- @@ -0,0 +1,57 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <asm/arch/soc.h>
- +#include <asm/lantiq/io.h>
- +
- +#define LTQ_CCR03_EIGHT_BANK_MODE (1 << 0)
- +#define LTQ_CCR08_CS_MAP_SHIFT 24
- +#define LTQ_CCR08_CS_MAP_MASK (0x3 << LTQ_CCR08_CS_MAP_SHIFT)
- +#define LTQ_CCR11_COLUMN_SIZE_SHIFT 24
- +#define LTQ_CCR11_COLUMN_SIZE_MASK (0x7 << LTQ_CCR11_COLUMN_SIZE_SHIFT)
- +#define LTQ_CCR11_ADDR_PINS_MASK 0x7
- +#define LTQ_CCR15_MAX_COL_REG_SHIFT 24
- +#define LTQ_CCR15_MAX_COL_REG_MASK (0xF << LTQ_CCR15_MAX_COL_REG_SHIFT)
- +#define LTQ_CCR16_MAX_ROW_REG_MASK 0xF
- +
- +static void *ltq_mc_ddr_base = (void *) CKSEG1ADDR(LTQ_MC_DDR_BASE);
- +
- +static inline u32 ltq_mc_ccr_read(u32 index)
- +{
- + return ltq_readl(ltq_mc_ddr_base + LTQ_MC_DDR_CCR_OFFSET(index));
- +}
- +
- +phys_size_t initdram(int board_type)
- +{
- + u32 max_col_reg, max_row_reg, column_size, addr_pins;
- + u32 banks, cs_map;
- + phys_size_t size;
- +
- + banks = (ltq_mc_ccr_read(3) & LTQ_CCR03_EIGHT_BANK_MODE) ? 8 : 4;
- +
- + cs_map = (ltq_mc_ccr_read(8) & LTQ_CCR08_CS_MAP_MASK) >>
- + LTQ_CCR08_CS_MAP_SHIFT;
- +
- + column_size = (ltq_mc_ccr_read(11) & LTQ_CCR11_COLUMN_SIZE_MASK) >>
- + LTQ_CCR11_COLUMN_SIZE_SHIFT;
- +
- + addr_pins = ltq_mc_ccr_read(11) & LTQ_CCR11_ADDR_PINS_MASK;
- +
- + max_col_reg = (ltq_mc_ccr_read(15) & LTQ_CCR15_MAX_COL_REG_MASK) >>
- + LTQ_CCR15_MAX_COL_REG_SHIFT;
- +
- + max_row_reg = ltq_mc_ccr_read(16) & LTQ_CCR16_MAX_ROW_REG_MASK;
- +
- + /*
- + * size (bytes) = 2 ^ rowsize * 2 ^ colsize * banks * chipselects
- + * * datawidth (bytes)
- + */
- + size = (2 << (max_col_reg - column_size - 1)) *
- + (2 << (max_row_reg - addr_pins - 1)) * banks * cs_map * 2;
- +
- + return size;
- +}
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/vrx200/mem_init.S
- @@ -0,0 +1,233 @@
- +/*
- + * Copyright (C) 2010 Lantiq Deutschland GmbH
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <config.h>
- +#include <asm/asm.h>
- +#include <asm/regdef.h>
- +#include <asm/addrspace.h>
- +#include <asm/arch/soc.h>
- +
- +/* Must be configured in BOARDDIR */
- +#include <ddr_settings.h>
- +
- +#define LTQ_MC_DDR_START (1 << 8)
- +#define LTQ_MC_DDR_DLL_LOCK_IND 1
- +
- +#define CCS_ALWAYS_LAST 0x0430
- +#define CCS_AHBM_CR_BURST_EN (1 << 2)
- +#define CCS_FPIM_CR_BURST_EN (1 << 1)
- +
- +#define CCR03_EIGHT_BANK_MODE (1 << 0)
- +
- + /* Store given value in MC DDR CCRx register */
- + .macro ccr_sw num, val
- + li t1, \val
- + sw t1, LTQ_MC_DDR_CCR_OFFSET(\num)(t0)
- + .endm
- +
- +LEAF(ltq_mem_init)
- + /* Load MC DDR module base */
- + li t0, (LTQ_MC_DDR_BASE | KSEG1)
- +
- + /* Put memory controller in inactive mode */
- + sw zero, LTQ_MC_DDR_CCR_OFFSET(7)(t0)
- +
- + /* Init MC DDR CCR registers with values from ddr_settings.h */
- + ccr_sw 0, MC_CCR00_VALUE
- + ccr_sw 1, MC_CCR01_VALUE
- + ccr_sw 2, MC_CCR02_VALUE
- + ccr_sw 3, MC_CCR03_VALUE
- + ccr_sw 4, MC_CCR04_VALUE
- + ccr_sw 5, MC_CCR05_VALUE
- + ccr_sw 6, MC_CCR06_VALUE
- + ccr_sw 7, MC_CCR07_VALUE
- + ccr_sw 8, MC_CCR08_VALUE
- + ccr_sw 9, MC_CCR09_VALUE
- +
- + ccr_sw 10, MC_CCR10_VALUE
- + ccr_sw 11, MC_CCR11_VALUE
- + ccr_sw 12, MC_CCR12_VALUE
- + ccr_sw 13, MC_CCR13_VALUE
- + ccr_sw 14, MC_CCR14_VALUE
- + ccr_sw 15, MC_CCR15_VALUE
- + ccr_sw 16, MC_CCR16_VALUE
- + ccr_sw 17, MC_CCR17_VALUE
- + ccr_sw 18, MC_CCR18_VALUE
- + ccr_sw 19, MC_CCR19_VALUE
- +
- + ccr_sw 20, MC_CCR20_VALUE
- + ccr_sw 21, MC_CCR21_VALUE
- + ccr_sw 22, MC_CCR22_VALUE
- + ccr_sw 23, MC_CCR23_VALUE
- + ccr_sw 24, MC_CCR24_VALUE
- + ccr_sw 25, MC_CCR25_VALUE
- + ccr_sw 26, MC_CCR26_VALUE
- + ccr_sw 27, MC_CCR27_VALUE
- + ccr_sw 28, MC_CCR28_VALUE
- + ccr_sw 29, MC_CCR29_VALUE
- +
- + ccr_sw 30, MC_CCR30_VALUE
- + ccr_sw 31, MC_CCR31_VALUE
- + ccr_sw 32, MC_CCR32_VALUE
- + ccr_sw 33, MC_CCR33_VALUE
- + ccr_sw 34, MC_CCR34_VALUE
- + ccr_sw 35, MC_CCR35_VALUE
- + ccr_sw 36, MC_CCR36_VALUE
- + ccr_sw 37, MC_CCR37_VALUE
- + ccr_sw 38, MC_CCR38_VALUE
- + ccr_sw 39, MC_CCR39_VALUE
- +
- + ccr_sw 40, MC_CCR40_VALUE
- + ccr_sw 41, MC_CCR41_VALUE
- + ccr_sw 42, MC_CCR42_VALUE
- + ccr_sw 43, MC_CCR43_VALUE
- + ccr_sw 44, MC_CCR44_VALUE
- + ccr_sw 45, MC_CCR45_VALUE
- + ccr_sw 46, MC_CCR46_VALUE
- +
- + ccr_sw 52, MC_CCR52_VALUE
- + ccr_sw 53, MC_CCR53_VALUE
- + ccr_sw 54, MC_CCR54_VALUE
- + ccr_sw 55, MC_CCR55_VALUE
- + ccr_sw 56, MC_CCR56_VALUE
- + ccr_sw 57, MC_CCR57_VALUE
- + ccr_sw 58, MC_CCR58_VALUE
- + ccr_sw 59, MC_CCR59_VALUE
- +
- + ccr_sw 60, MC_CCR60_VALUE
- + ccr_sw 61, MC_CCR61_VALUE
- +
- + /* Disable bursts between FPI Master bus and XBAR bus */
- + li t4, (LTQ_MC_GLOBAL_BASE | KSEG1)
- + li t5, CCS_AHBM_CR_BURST_EN
- + sw t5, CCS_ALWAYS_LAST(t4)
- +
- + /* Init abort condition for DRAM probe */
- + move t4, zero
- +
- + /*
- + * Put memory controller in active mode and start initialitation
- + * sequence for connected DDR-SDRAM device
- + */
- +mc_start:
- + lw t1, LTQ_MC_DDR_CCR_OFFSET(7)(t0)
- + li t2, LTQ_MC_DDR_START
- + or t1, t1, t2
- + sw t1, LTQ_MC_DDR_CCR_OFFSET(7)(t0)
- +
- + /*
- + * Wait until DLL has locked and core is ready for data transfers.
- + * DLL lock indication is in register CCR47 and CCR48
- + */
- +wait_ready:
- + li t1, LTQ_MC_DDR_DLL_LOCK_IND
- + lw t2, LTQ_MC_DDR_CCR_OFFSET(47)(t0)
- + and t2, t2, t1
- + bne t1, t2, wait_ready
- +
- + lw t2, LTQ_MC_DDR_CCR_OFFSET(48)(t0)
- + and t2, t2, t1
- + bne t1, t2, wait_ready
- +
- +#ifdef CONFIG_SYS_DRAM_PROBE
- +dram_probe:
- + /* Initialization is finished after the second MC start */
- + bnez t4, mc_finished
- +
- + /*
- + * Preload register values for CCR03 and CCR11. Initial settings
- + * are 8-bank mode enabled, 14 use address row bits, 10 used
- + * column address bits.
- + */
- + li t1, CONFIG_SYS_SDRAM_BASE_UC
- + li t5, MC_CCR03_VALUE
- + li t6, MC_CCR11_VALUE
- + addi t4, t4, 1
- +
- + /*
- + * Store test values to DRAM at offsets 0 and 2^13 (bit 2 in bank select
- + * address BA[3]) and read back the value at offset 0. If the resulting
- + * value is equal to 1 we can skip to the next test. Otherwise
- + * the 8-bank mode does not work with the current DRAM device,
- + * thus we need to clear the according bit in register CCR03.
- + */
- + li t2, 1
- + sw t2, 0x0(t1)
- + li t3, (1 << 13)
- + add t3, t3, t1
- + sw zero, 0(t3)
- + lw t3, 0(t1)
- + bnez t3, row_col_test
- +
- + /* Clear CCR03.EIGHT_BANK_MODE */
- + li t3, ~CCR03_EIGHT_BANK_MODE
- + and t5, t5, t3
- +
- +row_col_test:
- + /*
- + * Store test values to DRAM at offsets 0, 2^27 (bit 13 of row address
- + * RA[14]) and 2^26 (bit 12 of RA[14]). The chosen test values
- + * represent the difference between max. row address bits (14) and used
- + * row address bits. Then the read back value at offset 0 indicates
- + * the useable row address bits with the current DRAM device. This
- + * value must be set in the CCR11 register.
- + */
- + sw zero, 0(t1)
- +
- + li t2, 1
- + li t3, (1 << 27)
- + add t3, t3, t1
- + sw t2, 0(t3)
- +
- + li t2, 2
- + li t3, (1 << 26)
- + add t3, t3, t1
- + sw t2, 0(t3)
- +
- + /* Update CCR11.ADDR_PINS */
- + lw t3, 0(t1)
- + add t6, t6, t3
- +
- + /*
- + * Store test values to DRAM at offsets 0, 2^10 (bit 9 of column address
- + * CA[10]) and 2^9 (bit 8 of CA[10]). The chosen test values represent
- + * the difference between max. column address bits (12) and used
- + * column address bits. Then the read back value at offset 0 indicates
- + * the useable column address bits with the current DRAM device. This
- + * value must be set in the CCR11 register.
- + */
- + sw zero, 0(t1)
- +
- + li t2, 1
- + li t3, (1 << 10)
- + add t3, t3, t1
- + sw t2, 0(t3)
- +
- + li t2, 2
- + li t3, (1 << 9)
- + add t3, t3, t1
- + sw t2, 0(t3)
- +
- + /* Update CCR11.COLUMN_SIZE */
- + lw t3, 0(t1)
- + sll t3, t3, 24
- + add t6, t6, t3
- +
- + /* Put memory controller in inactive mode */
- + sw zero, LTQ_MC_DDR_CCR_OFFSET(7)(t0)
- +
- + /* Update CCR03 and CCR11 and restart memory controller initialiation */
- + sw t5, LTQ_MC_DDR_CCR_OFFSET(3)(t0)
- + sw t6, LTQ_MC_DDR_CCR_OFFSET(11)(t0)
- + b mc_start
- +
- +mc_finished:
- +#endif /* CONFIG_SYS_DRAM_PROBE */
- +
- + jr ra
- +
- + END(ltq_mem_init)
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/vrx200/pmu.c
- @@ -0,0 +1,130 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <asm/lantiq/io.h>
- +#include <asm/lantiq/pm.h>
- +#include <asm/arch/soc.h>
- +
- +#define LTQ_PMU_PWDCR_RESERVED ((1 << 13) | (1 << 4))
- +
- +#define LTQ_PMU_PWDCR_PCIELOC_EN (1 << 31)
- +#define LTQ_PMU_PWDCR_GPHY (1 << 30)
- +#define LTQ_PMU_PWDCR_PPE_TOP (1 << 29)
- +#define LTQ_PMU_PWDCR_SWITCH (1 << 28)
- +#define LTQ_PMU_PWDCR_USB1 (1 << 27)
- +#define LTQ_PMU_PWDCR_USB1_PHY (1 << 26)
- +#define LTQ_PMU_PWDCR_TDM (1 << 25)
- +#define LTQ_PMU_PWDCR_PPE_DPLUS (1 << 24)
- +#define LTQ_PMU_PWDCR_PPE_DPLUM (1 << 23)
- +#define LTQ_PMU_PWDCR_PPE_EMA (1 << 22)
- +#define LTQ_PMU_PWDCR_PPE_TC (1 << 21)
- +#define LTQ_PMU_PWDCR_DEU (1 << 20)
- +#define LTQ_PMU_PWDCR_PPE_SLL01 (1 << 19)
- +#define LTQ_PMU_PWDCR_PPE_QSB (1 << 18)
- +#define LTQ_PMU_PWDCR_UART1 (1 << 17)
- +#define LTQ_PMU_PWDCR_SDIO (1 << 16)
- +#define LTQ_PMU_PWDCR_AHBM (1 << 15)
- +#define LTQ_PMU_PWDCR_FPIM (1 << 14)
- +#define LTQ_PMU_PWDCR_GPTC (1 << 12)
- +#define LTQ_PMU_PWDCR_LEDC (1 << 11)
- +#define LTQ_PMU_PWDCR_EBU (1 << 10)
- +#define LTQ_PMU_PWDCR_DSL (1 << 9)
- +#define LTQ_PMU_PWDCR_SPI (1 << 8)
- +#define LTQ_PMU_PWDCR_USIF (1 << 7)
- +#define LTQ_PMU_PWDCR_USB0 (1 << 6)
- +#define LTQ_PMU_PWDCR_DMA (1 << 5)
- +#define LTQ_PMU_PWDCR_DFEV1 (1 << 3)
- +#define LTQ_PMU_PWDCR_DFEV0 (1 << 2)
- +#define LTQ_PMU_PWDCR_FPIS (1 << 1)
- +#define LTQ_PMU_PWDCR_USB0_PHY (1 << 0)
- +
- +struct ltq_pmu_regs {
- + u32 rsvd0[7];
- + u32 pwdcr; /* Power down control */
- + u32 sr; /* Power down status */
- + u32 pwdcr1; /* Power down control 1 */
- + u32 sr1; /* Power down status 1 */
- +};
- +
- +static struct ltq_pmu_regs *ltq_pmu_regs =
- + (struct ltq_pmu_regs *) CKSEG1ADDR(LTQ_PMU_BASE);
- +
- +u32 ltq_pm_map(enum ltq_pm_modules module)
- +{
- + u32 val;
- +
- + switch (module) {
- + case LTQ_PM_CORE:
- + val = LTQ_PMU_PWDCR_UART1 | LTQ_PMU_PWDCR_FPIM |
- + LTQ_PMU_PWDCR_LEDC | LTQ_PMU_PWDCR_EBU;
- + break;
- + case LTQ_PM_DMA:
- + val = LTQ_PMU_PWDCR_DMA;
- + break;
- + case LTQ_PM_ETH:
- + val = LTQ_PMU_PWDCR_GPHY | LTQ_PMU_PWDCR_PPE_TOP |
- + LTQ_PMU_PWDCR_SWITCH | LTQ_PMU_PWDCR_PPE_DPLUS |
- + LTQ_PMU_PWDCR_PPE_DPLUM | LTQ_PMU_PWDCR_PPE_EMA |
- + LTQ_PMU_PWDCR_PPE_TC | LTQ_PMU_PWDCR_PPE_SLL01 |
- + LTQ_PMU_PWDCR_PPE_QSB;
- + break;
- + case LTQ_PM_SPI:
- + val = LTQ_PMU_PWDCR_SPI;
- + break;
- + default:
- + val = 0;
- + break;
- + }
- +
- + return val;
- +}
- +
- +int ltq_pm_enable(enum ltq_pm_modules module)
- +{
- + const unsigned long timeout = 1000;
- + unsigned long timebase;
- + u32 sr, val;
- +
- + val = ltq_pm_map(module);
- + if (unlikely(!val))
- + return 1;
- +
- + ltq_clrbits(<q_pmu_regs->pwdcr, val);
- +
- + timebase = get_timer(0);
- +
- + do {
- + sr = ltq_readl(<q_pmu_regs->sr);
- + if (~sr & val)
- + return 0;
- + } while (get_timer(timebase) < timeout);
- +
- + return 1;
- +}
- +
- +int ltq_pm_disable(enum ltq_pm_modules module)
- +{
- + u32 val;
- +
- + val = ltq_pm_map(module);
- + if (unlikely(!val))
- + return 1;
- +
- + ltq_setbits(<q_pmu_regs->pwdcr, val);
- +
- + return 0;
- +}
- +
- +void ltq_pmu_init(void)
- +{
- + u32 set, clr;
- +
- + clr = ltq_pm_map(LTQ_PM_CORE);
- + set = ~(LTQ_PMU_PWDCR_RESERVED | clr);
- +
- + ltq_clrsetbits(<q_pmu_regs->pwdcr, clr, set);
- +}
- --- /dev/null
- +++ b/arch/mips/cpu/mips32/vrx200/rcu.c
- @@ -0,0 +1,194 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <asm/lantiq/io.h>
- +#include <asm/lantiq/reset.h>
- +#include <asm/lantiq/cpu.h>
- +#include <asm/arch/soc.h>
- +
- +#define LTQ_RCU_RD_GPHY0 (1 << 31) /* GPHY0 */
- +#define LTQ_RCU_RD_SRST (1 << 30) /* Global SW Reset */
- +#define LTQ_RCU_RD_GPHY1 (1 << 29) /* GPHY1 */
- +#define LTQ_RCU_RD_ENMIP2 (1 << 28) /* Enable NMI of PLL2 */
- +#define LTQ_RCU_RD_REG25_PD (1 << 26) /* Power down 2.5V regulator */
- +#define LTQ_RCU_RD_ENDINIT (1 << 25) /* FPI slave bus access */
- +#define LTQ_RCU_RD_PPE_ATM_TC (1 << 23) /* PPE ATM TC */
- +#define LTQ_RCU_RD_PCIE (1 << 22) /* PCI-E core */
- +#define LTQ_RCU_RD_ETHSW (1 << 21) /* Ethernet switch */
- +#define LTQ_RCU_RD_DSP_DEN (1 << 20) /* Enable DSP JTAG */
- +#define LTQ_RCU_RD_TDM (1 << 19) /* TDM module interface */
- +#define LTQ_RCU_RD_ENMIP1 (1 << 18) /* Enable NMI of PLL1 */
- +#define LTQ_RCU_RD_SWBCK (1 << 17) /* Switch backward compat */
- +#define LTQ_RCU_RD_HSNAND (1 << 16) /* HSNAND controller */
- +#define LTQ_RCU_RD_ENMIP0 (1 << 15) /* Enable NMI of PLL0 */
- +#define LTQ_RCU_RD_MC (1 << 14) /* Memory Controller */
- +#define LTQ_RCU_RD_PCI (1 << 13) /* PCI core */
- +#define LTQ_RCU_RD_PCIE_PHY (1 << 12) /* PCI-E Phy */
- +#define LTQ_RCU_RD_DFE_CORE (1 << 11) /* DFE core */
- +#define LTQ_RCU_RD_SDIO (1 << 10) /* SDIO core */
- +#define LTQ_RCU_RD_DMA (1 << 9) /* DMA core */
- +#define LTQ_RCU_RD_PPE (1 << 8) /* PPE core */
- +#define LTQ_RCU_RD_DFE (1 << 7) /* DFE core */
- +#define LTQ_RCU_RD_AHB (1 << 6) /* AHB bus */
- +#define LTQ_RCU_RD_HRST_CFG (1 << 5) /* HW reset configuration */
- +#define LTQ_RCU_RD_USB (1 << 4) /* USB and Phy core */
- +#define LTQ_RCU_RD_PPE_DSP (1 << 3) /* PPE DSP interface */
- +#define LTQ_RCU_RD_FPI (1 << 2) /* FPI bus */
- +#define LTQ_RCU_RD_CPU (1 << 1) /* CPU subsystem */
- +#define LTQ_RCU_RD_HRST (1 << 0) /* HW reset via HRST pin */
- +
- +#define LTQ_RCU_STAT_BOOT_SHIFT 17
- +#define LTQ_RCU_STAT_BOOT_MASK (0xF << LTQ_RCU_STAT_BOOT_SHIFT)
- +#define LTQ_RCU_STAT_BOOT_H (1 << 12)
- +
- +#define LTQ_RCU_GP_STRAP_CLOCKSOURCE (1 << 15)
- +
- +struct ltq_rcu_regs {
- + u32 rsvd0[4];
- + u32 req; /* Reset request */
- + u32 stat; /* Reset status */
- + u32 usb0_cfg; /* USB0 configure */
- + u32 gp_strap; /* GPIO strapping */
- + u32 gfs_add0; /* GPHY0 firmware base addr */
- + u32 stat2; /* SLIC and USB reset status */
- + u32 pci_rdy; /* PCI boot ready */
- + u32 ppe_conf; /* PPE ethernet config */
- + u32 pcie_phy_con; /* PCIE PHY config/status */
- + u32 usb1_cfg; /* USB1 configure */
- + u32 usb_ana_cfg1a; /* USB analog config 1a */
- + u32 usb_ana_cfg1b; /* USB analog config 1b */
- + u32 rsvd1;
- + u32 gf_mdio_add; /* GPHY0/1 MDIO address */
- + u32 req2; /* SLIC and USB reset request */
- + u32 ahb_endian; /* AHB bus endianess */
- + u32 rsvd2[4];
- + u32 gcc; /* General CPU config */
- + u32 rsvd3;
- + u32 gfs_add1; /* GPHY1 firmware base addr */
- +};
- +
- +static struct ltq_rcu_regs *ltq_rcu_regs =
- + (struct ltq_rcu_regs *) CKSEG1ADDR(LTQ_RCU_BASE);
- +
- +u32 ltq_reset_map(enum ltq_reset_modules module)
- +{
- + u32 val;
- +
- + switch (module) {
- + case LTQ_RESET_CORE:
- + case LTQ_RESET_SOFT:
- + val = LTQ_RCU_RD_SRST | LTQ_RCU_RD_CPU | LTQ_RCU_RD_ENMIP2 |
- + LTQ_RCU_RD_GPHY1 | LTQ_RCU_RD_GPHY0;
- + break;
- + case LTQ_RESET_DMA:
- + val = LTQ_RCU_RD_DMA;
- + break;
- + case LTQ_RESET_ETH:
- + val = LTQ_RCU_RD_PPE | LTQ_RCU_RD_ETHSW;
- + break;
- + case LTQ_RESET_PHY:
- + val = LTQ_RCU_RD_GPHY1 | LTQ_RCU_RD_GPHY0;
- + break;
- + case LTQ_RESET_HARD:
- + val = LTQ_RCU_RD_HRST;
- + break;
- + default:
- + val = 0;
- + break;
- + }
- +
- + return val;
- +}
- +
- +int ltq_reset_activate(enum ltq_reset_modules module)
- +{
- + u32 val;
- +
- + val = ltq_reset_map(module);
- + if (unlikely(!val))
- + return 1;
- +
- + ltq_setbits(<q_rcu_regs->req, val);
- +
- + return 0;
- +}
- +
- +int ltq_reset_deactivate(enum ltq_reset_modules module)
- +{
- + u32 val;
- +
- + val = ltq_reset_map(module);
- + if (unlikely(!val))
- + return 1;
- +
- + ltq_clrbits(<q_rcu_regs->req, val);
- +
- + return 0;
- +}
- +
- +enum ltq_boot_select ltq_boot_select(void)
- +{
- + u32 stat;
- + unsigned int bootstrap;
- +
- + /*
- + * Boot select value is built from bits 20-17 and bit 12.
- + * The bit sequence is read as 4-2-1-0-3.
- + */
- + stat = ltq_readl(<q_rcu_regs->stat);
- + bootstrap = ((stat & LTQ_RCU_STAT_BOOT_H) << 4) |
- + ((stat & LTQ_RCU_STAT_BOOT_MASK) >> LTQ_RCU_STAT_BOOT_SHIFT);
- +
- + switch (bootstrap) {
- + case 0:
- + return BOOT_NOR_NO_BOOTROM;
- + case 1:
- + return BOOT_RGMII1;
- + case 2:
- + return BOOT_NOR;
- + case 4:
- + return BOOT_UART_NO_EEPROM;
- + case 6:
- + return BOOT_PCI;
- + case 8:
- + return BOOT_UART;
- + case 10:
- + return BOOT_SPI;
- + case 12:
- + return BOOT_NAND;
- + default:
- + return BOOT_UNKNOWN;
- + }
- +}
- +
- +void ltq_rcu_gphy_boot(unsigned int id, ulong addr)
- +{
- + u32 module;
- + void *gfs_add;
- +
- + switch (id) {
- + case 0:
- + module = LTQ_RCU_RD_GPHY0;
- + gfs_add = <q_rcu_regs->gfs_add0;
- + break;
- + case 1:
- + module = LTQ_RCU_RD_GPHY1;
- + gfs_add = <q_rcu_regs->gfs_add1;
- + break;
- + default:
- + BUG();
- + }
- +
- + /* Stop and reset GPHY */
- + ltq_setbits(<q_rcu_regs->req, module);
- +
- + /* Configure firmware and boot address */
- + ltq_writel(gfs_add, CPHYSADDR(addr & 0xFFFFC000));
- +
- + /* Start GPHY by releasing reset */
- + ltq_clrbits(<q_rcu_regs->req, module);
- +}
- --- /dev/null
- +++ b/arch/mips/include/asm/arch-danube/config.h
- @@ -0,0 +1,163 @@
- +/*
- + * Copyright (C) 2007-2010 Lantiq Deutschland GmbH
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + *
- + * Common board configuration for Lantiq XWAY Danube family
- + *
- + * Use following defines in your board config to enable specific features
- + * and drivers for this SoC:
- + *
- + * CONFIG_LTQ_SUPPORT_UART
- + * - support the Danube ASC/UART interface and console
- + *
- + * CONFIG_LTQ_SUPPORT_NOR_FLASH
- + * - support a parallel NOR flash via the CFI interface in flash bank 0
- + *
- + * CONFIG_LTQ_SUPPORT_ETHERNET
- + * - support the Danube ETOP and MAC interface
- + *
- + * CONFIG_LTQ_SUPPORT_SPI_FLASH
- + * - support the Danube SPI interface and serial flash drivers
- + * - specific SPI flash drivers must be configured separately
- + */
- +
- +#ifndef __DANUBE_CONFIG_H__
- +#define __DANUBE_CONFIG_H__
- +
- +/* CPU and SoC type */
- +#define CONFIG_SOC_LANTIQ
- +#define CONFIG_SOC_XWAY_DANUBE
- +
- +/* Cache configuration */
- +#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
- +#define CONFIG_SYS_DCACHE_SIZE (16 * 1024)
- +#define CONFIG_SYS_ICACHE_SIZE (16 * 1024)
- +#define CONFIG_SYS_CACHELINE_SIZE 32
- +#define CONFIG_SYS_MIPS_CACHE_EXT_INIT
- +
- +/*
- + * Supported clock modes
- + * PLL0 clock output is 333 MHz
- + * PLL1 clock output is 262.144 MHz
- + */
- +#define LTQ_CLK_CPU_333_DDR_167 0 /* Base PLL0, OCP 2 */
- +#define LTQ_CLK_CPU_111_DDR_111 1 /* Base PLL0, OCP 1 */
- +
- +/* CPU speed */
- +#define CONFIG_SYS_CLOCK_MODE LTQ_CLK_CPU_333_DDR_167
- +#define CONFIG_SYS_MIPS_TIMER_FREQ 166666667
- +#define CONFIG_SYS_HZ 1000
- +
- +/* RAM */
- +#define CONFIG_NR_DRAM_BANKS 1
- +#define CONFIG_SYS_SDRAM_BASE 0x80000000
- +#define CONFIG_SYS_MEMTEST_START 0x81000000
- +#define CONFIG_SYS_MEMTEST_END 0x82000000
- +#define CONFIG_SYS_LOAD_ADDR 0x81000000
- +#define CONFIG_SYS_INIT_SP_OFFSET 0x4000
- +
- +/* SRAM */
- +#define CONFIG_SYS_SRAM_BASE 0xBE1A0000
- +#define CONFIG_SYS_SRAM_SIZE 0x10000
- +
- +/* ASC/UART driver and console */
- +#define CONFIG_LANTIQ_SERIAL
- +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
- +
- +/* GPIO */
- +#define CONFIG_LANTIQ_GPIO
- +#define CONFIG_LTQ_GPIO_MAX_BANKS 2
- +
- +/* FLASH driver */
- +#if defined(CONFIG_LTQ_SUPPORT_NOR_FLASH)
- +#define CONFIG_SYS_MAX_FLASH_BANKS 1
- +#define CONFIG_SYS_MAX_FLASH_SECT 256
- +#define CONFIG_SYS_FLASH_BASE 0xB0000000
- +#define CONFIG_FLASH_16BIT
- +#define CONFIG_SYS_FLASH_CFI
- +#define CONFIG_FLASH_CFI_DRIVER
- +#define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_16BIT
- +#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
- +#define CONFIG_FLASH_SHOW_PROGRESS 50
- +#define CONFIG_SYS_FLASH_PROTECTION
- +#define CONFIG_CFI_FLASH_USE_WEAK_ADDR_SWAP
- +
- +#define CONFIG_CMD_FLASH
- +#else
- +#define CONFIG_SYS_NO_FLASH
- +#endif /* CONFIG_NOR_FLASH */
- +
- +#if defined(CONFIG_LTQ_SUPPORT_SPI_FLASH)
- +#define CONFIG_LANTIQ_SPI
- +#define CONFIG_SPI_FLASH
- +
- +#define CONFIG_CMD_SF
- +#define CONFIG_CMD_SPI
- +#endif
- +
- +#if defined(CONFIG_LTQ_SUPPORT_NAND_FLASH)
- +#define CONFIG_NAND_LANTIQ
- +#define CONFIG_SYS_MAX_NAND_DEVICE 1
- +#define CONFIG_SYS_NAND_BASE 0xB4000000
- +
- +#define CONFIG_CMD_NAND
- +#endif
- +
- +#if defined(CONFIG_LTQ_SUPPORT_ETHERNET)
- +#define CONFIG_LANTIQ_DMA
- +#define CONFIG_LANTIQ_DANUBE_ETOP
- +
- +#define CONFIG_PHYLIB
- +#define CONFIG_MII
- +
- +#define CONFIG_CMD_MII
- +#define CONFIG_CMD_NET
- +#endif
- +
- +#define CONFIG_SPL_MAX_SIZE (32 * 1024)
- +#define CONFIG_SPL_BSS_MAX_SIZE (8 * 1024)
- +#define CONFIG_SPL_STACK_MAX_SIZE (8 * 1024)
- +#define CONFIG_SPL_MALLOC_MAX_SIZE (32 * 1024)
- +/*#define CONFIG_SPL_STACK_BSS_IN_SRAM*/
- +
- +#if defined(CONFIG_SPL_STACK_BSS_IN_SRAM)
- +#define CONFIG_SPL_STACK_BASE (CONFIG_SYS_SRAM_BASE + \
- + CONFIG_SPL_MAX_SIZE + \
- + CONFIG_SPL_STACK_MAX_SIZE - 1)
- +#define CONFIG_SPL_BSS_BASE (CONFIG_SPL_STACK_BASE + 1)
- +#define CONFIG_SPL_MALLOC_BASE (CONFIG_SYS_SDRAM_BASE + \
- + CONFIG_SYS_INIT_SP_OFFSET)
- +#else
- +#define CONFIG_SPL_STACK_BASE (CONFIG_SYS_SDRAM_BASE + \
- + CONFIG_SYS_INIT_SP_OFFSET + \
- + CONFIG_SPL_STACK_MAX_SIZE - 1)
- +#define CONFIG_SPL_BSS_BASE (CONFIG_SPL_STACK_BASE + 1)
- +#define CONFIG_SPL_MALLOC_BASE (CONFIG_SPL_BSS_BASE + \
- + CONFIG_SPL_BSS_MAX_SIZE)
- +#endif
- +
- +#if defined(CONFIG_SYS_BOOT_RAM)
- +#define CONFIG_SYS_TEXT_BASE 0xa0100000
- +#define CONFIG_SKIP_LOWLEVEL_INIT
- +#define CONFIG_SYS_DISABLE_CACHE
- +#endif
- +
- +#if defined(CONFIG_SYS_BOOT_NOR)
- +#define CONFIG_SYS_TEXT_BASE 0xB0000000
- +#endif
- +
- +#if defined(CONFIG_SYS_BOOT_NORSPL)
- +#define CONFIG_SYS_TEXT_BASE 0x80100000
- +#define CONFIG_SPL_TEXT_BASE 0xB0000000
- +#endif
- +
- +#if defined(CONFIG_SYS_BOOT_NOR) || defined(CONFIG_SYS_BOOT_NORSPL)
- +#define CONFIG_SYS_XWAY_EBU_BOOTCFG 0x688C688C
- +#define CONFIG_XWAY_SWAP_BYTES
- +#endif
- +
- +#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
- +
- +#endif /* __DANUBE_CONFIG_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/arch-danube/gpio.h
- @@ -0,0 +1,12 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __DANUBE_GPIO_H__
- +#define __DANUBE_GPIO_H__
- +
- +#include <asm/lantiq/gpio.h>
- +
- +#endif /* __DANUBE_GPIO_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/arch-danube/nand.h
- @@ -0,0 +1,13 @@
- +/*
- + * Copyright (C) 2012-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __DANUBE_NAND_H__
- +#define __DANUBE_NAND_H__
- +
- +struct nand_chip;
- +int ltq_nand_init(struct nand_chip *nand);
- +
- +#endif /* __DANUBE_NAND_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/arch-danube/soc.h
- @@ -0,0 +1,38 @@
- +/*
- + * Copyright (C) 2007-2010 Lantiq Deutschland GmbH
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __DANUBE_SOC_H__
- +#define __DANUBE_SOC_H__
- +
- +#define LTQ_ASC0_BASE 0x1E100400
- +#define LTQ_SPI_BASE 0x1E100800
- +#define LTQ_GPIO_BASE 0x1E100B00
- +#define LTQ_SSIO_BASE 0x1E100BB0
- +#define LTQ_ASC1_BASE 0x1E100C00
- +#define LTQ_DMA_BASE 0x1E104100
- +
- +#define LTQ_EBU_BASE 0x1E105300
- +#define LTQ_EBU_REGION0_BASE 0x10000000
- +#define LTQ_EBU_REGION1_BASE 0x14000000
- +#define LTQ_EBU_NAND_BASE (LTQ_EBU_BASE + 0xB0)
- +
- +#define LTQ_PPE_BASE 0x1E180000
- +#define LTQ_PPE_ETOP_BASE (LTQ_PPE_BASE + 0x11800)
- +#define LTQ_PPE_ENET0_BASE (LTQ_PPE_BASE + 0x11840)
- +
- +#define LTQ_PMU_BASE 0x1F102000
- +#define LTQ_CGU_BASE 0x1F103000
- +#define LTQ_MPS_BASE 0x1F107000
- +#define LTQ_CHIPID_BASE (LTQ_MPS_BASE + 0x340)
- +#define LTQ_RCU_BASE 0x1F203000
- +
- +#define LTQ_MC_GEN_BASE 0x1F800000
- +#define LTQ_MC_SDR_BASE 0x1F800200
- +#define LTQ_MC_DDR_BASE 0x1F801000
- +#define LTQ_MC_DDR_DC_OFFSET(x) (x * 0x10)
- +
- +#endif /* __DANUBE_SOC_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/arch-vrx200/config.h
- @@ -0,0 +1,187 @@
- +/*
- + * Copyright (C) 2010 Lantiq Deutschland GmbH
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + *
- + * Common board configuration for Lantiq XWAY VRX200 family
- + *
- + * Use following defines in your board config to enable specific features
- + * and drivers for this SoC:
- + *
- + * CONFIG_LTQ_SUPPORT_UART
- + * - support the VRX200 ASC/UART interface and console
- + *
- + * CONFIG_LTQ_SUPPORT_NOR_FLASH
- + * - support a parallel NOR flash via the CFI interface in flash bank 0
- + *
- + * CONFIG_LTQ_SUPPORT_ETHERNET
- + * - support the VRX200 internal switch
- + *
- + * CONFIG_LTQ_SUPPORT_SPI_FLASH
- + * - support the VRX200 SPI interface and serial flash drivers
- + * - specific SPI flash drivers must be configured separately
- + *
- + * CONFIG_LTQ_SUPPORT_SPL_SPI_FLASH
- + * - build a preloader that runs in the internal SRAM and loads
- + * the U-Boot from SPI flash into RAM
- + */
- +
- +#ifndef __VRX200_CONFIG_H__
- +#define __VRX200_CONFIG_H__
- +
- +/* CPU and SoC type */
- +#define CONFIG_SOC_LANTIQ
- +#define CONFIG_SOC_XWAY_VRX200
- +
- +/* Cache configuration */
- +#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
- +#define CONFIG_SYS_DCACHE_SIZE (32 * 1024)
- +#define CONFIG_SYS_ICACHE_SIZE (32 * 1024)
- +#define CONFIG_SYS_CACHELINE_SIZE 32
- +#define CONFIG_SYS_MIPS_CACHE_EXT_INIT
- +
- +/*
- + * Supported clock modes
- + * PLL0 clock output is 1000 MHz
- + * PLL1 clock output is 393.219 MHz
- + */
- +#define LTQ_CLK_CPU_600_DDR_300 0 /* Base PLL0, OCP 2 */
- +#define LTQ_CLK_CPU_600_DDR_200 1 /* Base PLL0, OCP 3 */
- +#define LTQ_CLK_CPU_500_DDR_250 2 /* Base PLL0, OCP 2 */
- +#define LTQ_CLK_CPU_500_DDR_200 3 /* Base PLL0, OCP 2.5 */
- +#define LTQ_CLK_CPU_333_DDR_167 4 /* Base PLL0, OCP 2 */
- +#define LTQ_CLK_CPU_167_DDR_167 5 /* Base PLL0, OCP 1 */
- +#define LTQ_CLK_CPU_125_DDR_125 6 /* Base PLL0, OCP 1 */
- +#define LTQ_CLK_CPU_393_DDR_197 7 /* Base PLL1, OCP 2 */
- +#define LTQ_CLK_CPU_197_DDR_197 8 /* Base PLL1, OCP 1 */
- +
- +/* CPU speed */
- +#define CONFIG_SYS_CLOCK_MODE LTQ_CLK_CPU_500_DDR_250
- +#define CONFIG_SYS_MIPS_TIMER_FREQ 250000000
- +#define CONFIG_SYS_HZ 1000
- +
- +/* RAM */
- +#define CONFIG_NR_DRAM_BANKS 1
- +#define CONFIG_SYS_SDRAM_BASE 0x80000000
- +#define CONFIG_SYS_SDRAM_BASE_UC 0xa0000000
- +#define CONFIG_SYS_MEMTEST_START 0x81000000
- +#define CONFIG_SYS_MEMTEST_END 0x82000000
- +#define CONFIG_SYS_LOAD_ADDR 0x81000000
- +#define CONFIG_SYS_INIT_SP_OFFSET (32 * 1024)
- +
- +/* SRAM */
- +#define CONFIG_SYS_SRAM_BASE 0xBE220000
- +#define CONFIG_SYS_SRAM_SIZE 0x10000
- +
- +/* ASC/UART driver and console */
- +#define CONFIG_LANTIQ_SERIAL
- +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
- +
- +/* GPIO */
- +#define CONFIG_LANTIQ_GPIO
- +#define CONFIG_LTQ_GPIO_MAX_BANKS 3
- +#define CONFIG_LTQ_HAS_GPIO_BANK3
- +
- +/* FLASH driver */
- +#if defined(CONFIG_LTQ_SUPPORT_NOR_FLASH)
- +#ifndef CONFIG_SYS_MAX_FLASH_BANKS
- +#define CONFIG_SYS_MAX_FLASH_BANKS 1
- +#endif
- +#define CONFIG_SYS_MAX_FLASH_SECT 256
- +#define CONFIG_SYS_FLASH_BASE 0xB0000000
- +#define CONFIG_SYS_FLASH2_BASE 0xB4000000
- +#define CONFIG_FLASH_16BIT
- +#define CONFIG_SYS_FLASH_CFI
- +#define CONFIG_FLASH_CFI_DRIVER
- +#define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_16BIT
- +#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
- +#define CONFIG_FLASH_SHOW_PROGRESS 50
- +#define CONFIG_SYS_FLASH_PROTECTION
- +#define CONFIG_CFI_FLASH_USE_WEAK_ADDR_SWAP
- +
- +#define CONFIG_CMD_FLASH
- +#else
- +#define CONFIG_SYS_NO_FLASH
- +#endif /* CONFIG_NOR_FLASH */
- +
- +#if defined(CONFIG_LTQ_SUPPORT_SPI_FLASH)
- +#define CONFIG_LANTIQ_SPI
- +#define CONFIG_SPI_FLASH
- +
- +#define CONFIG_CMD_SF
- +#define CONFIG_CMD_SPI
- +#endif
- +
- +#if defined(CONFIG_LTQ_SUPPORT_NAND_FLASH)
- +#define CONFIG_NAND_LANTIQ
- +#define CONFIG_SYS_MAX_NAND_DEVICE 1
- +#define CONFIG_SYS_NAND_BASE 0xB4000000
- +
- +#define CONFIG_CMD_NAND
- +#endif
- +
- +#if defined(CONFIG_LTQ_SUPPORT_ETHERNET)
- +#define CONFIG_LANTIQ_DMA
- +#define CONFIG_LANTIQ_VRX200_SWITCH
- +#define CONFIG_PHY_LANTIQ
- +
- +#define CONFIG_SYS_RX_ETH_BUFFER 8
- +#define CONFIG_PHYLIB
- +#define CONFIG_MII
- +#define CONFIG_UDP_CHECKSUM
- +
- +#define CONFIG_CMD_MII
- +#define CONFIG_CMD_NET
- +#endif
- +
- +#define CONFIG_SPL_MAX_SIZE (32 * 1024)
- +#define CONFIG_SPL_BSS_MAX_SIZE (8 * 1024)
- +#define CONFIG_SPL_STACK_MAX_SIZE (8 * 1024)
- +#define CONFIG_SPL_MALLOC_MAX_SIZE (32 * 1024)
- +#define CONFIG_SPL_STACK_BSS_IN_SRAM
- +
- +#if defined(CONFIG_SPL_STACK_BSS_IN_SRAM)
- +#define CONFIG_SPL_STACK_BASE (CONFIG_SYS_SRAM_BASE + \
- + CONFIG_SPL_MAX_SIZE + \
- + CONFIG_SPL_STACK_MAX_SIZE - 1)
- +#define CONFIG_SPL_BSS_BASE (CONFIG_SPL_STACK_BASE + 1)
- +#define CONFIG_SPL_MALLOC_BASE (CONFIG_SYS_SDRAM_BASE + \
- + CONFIG_SYS_INIT_SP_OFFSET)
- +#else
- +#define CONFIG_SPL_STACK_BASE (CONFIG_SYS_SDRAM_BASE + \
- + CONFIG_SYS_INIT_SP_OFFSET + \
- + CONFIG_SPL_STACK_MAX_SIZE - 1)
- +#define CONFIG_SPL_BSS_BASE (CONFIG_SPL_STACK_BASE + 1)
- +#define CONFIG_SPL_MALLOC_BASE (CONFIG_SPL_BSS_BASE + \
- + CONFIG_SPL_BSS_MAX_SIZE)
- +#endif
- +
- +#if defined(CONFIG_SYS_BOOT_RAM)
- +#define CONFIG_SYS_TEXT_BASE 0xA0100000
- +#define CONFIG_SKIP_LOWLEVEL_INIT
- +#define CONFIG_SYS_DISABLE_CACHE
- +#endif
- +
- +#if defined(CONFIG_SYS_BOOT_NOR)
- +#define CONFIG_SYS_TEXT_BASE 0xB0000000
- +#endif
- +
- +#if defined(CONFIG_SYS_BOOT_SFSPL)
- +#define CONFIG_SYS_TEXT_BASE 0x80100000
- +#define CONFIG_SPL_TEXT_BASE 0xBE220000
- +#endif
- +
- +#if defined(CONFIG_SYS_BOOT_NORSPL)
- +#define CONFIG_SYS_TEXT_BASE 0x80100000
- +#define CONFIG_SPL_TEXT_BASE 0xB0000000
- +#endif
- +
- +#if defined(CONFIG_SYS_BOOT_NOR) || defined(CONFIG_SYS_BOOT_NORSPL)
- +#define CONFIG_SYS_XWAY_EBU_BOOTCFG 0x688C688C
- +#define CONFIG_XWAY_SWAP_BYTES
- +#endif
- +
- +#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
- +
- +#endif /* __VRX200_CONFIG_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/arch-vrx200/gphy.h
- @@ -0,0 +1,65 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __VRX200_GPHY_H__
- +#define __VRX200_GPHY_H__
- +
- +enum ltq_gphy_clk {
- + /* XTAL 36 MHz input */
- + LTQ_GPHY_CLK_36MHZ_XTAL = 1,
- + /* 25 MHz from PLL0 with divider */
- + LTQ_GPHY_CLK_25MHZ_PLL0 = 2,
- + /* derived from PLL2 output (XTAL is 36 MHz) */
- + LTQ_GPHY_CLK_24MHZ_PLL2 = 3,
- + /* 25 MHz Clock from Pin GPIO3 */
- + LTQ_GPHY_CLK_25MHZ_GPIO3 = 4,
- +};
- +
- +/*
- + * Load PHY11G firmware for VRX200 v1.1 to given RAM address
- + *
- + * Address must be 16k aligned!
- + */
- +extern void ltq_gphy_phy11g_a1x_load(ulong addr);
- +
- +/*
- + * Load PHY11G firmware for VRX200 v1.2 to given RAM address
- + *
- + * Address must be 16k aligned!
- + */
- +extern void ltq_gphy_phy11g_a2x_load(ulong addr);
- +
- +/*
- + * Load PHY22F firmware for VRX200 v1.1 to given RAM address
- + *
- + * Address must be 16k aligned!
- + */
- +extern void ltq_gphy_phy22f_a1x_load(ulong addr);
- +
- +/*
- + * Load PHY22F firmware for VRX200 v1.2 to given RAM address
- + *
- + * Address must be 16k aligned!
- + */
- +extern void ltq_gphy_phy22f_a2x_load(ulong addr);
- +
- +/*
- + * Set clock source of internal GPHYs
- + *
- + * According registers resides in CGU address space. Thus this function
- + * is implemented by the CGU driver.
- + */
- +extern void ltq_cgu_gphy_clk_src(enum ltq_gphy_clk clk);
- +
- +/*
- + * Boot internal GPHY with id from given RAM address
- + *
- + * According registers resides in RCU address space. Thus this function
- + * is implemented by the RCU driver.
- + */
- +extern void ltq_rcu_gphy_boot(unsigned int id, ulong addr);
- +
- +#endif /* __VRX200_GPHY_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/arch-vrx200/gpio.h
- @@ -0,0 +1,12 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __VRX200_GPIO_H__
- +#define __VRX200_GPIO_H__
- +
- +#include <asm/lantiq/gpio.h>
- +
- +#endif /* __VRX200_GPIO_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/arch-vrx200/nand.h
- @@ -0,0 +1,13 @@
- +/*
- + * Copyright (C) 2012-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __VRX200_NAND_H__
- +#define __VRX200_NAND_H__
- +
- +struct nand_chip;
- +int ltq_nand_init(struct nand_chip *nand);
- +
- +#endif /* __VRX200_NAND_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/arch-vrx200/soc.h
- @@ -0,0 +1,45 @@
- +/*
- + * Copyright (C) 2010 Lantiq Deutschland GmbH
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __VRX200_SOC_H__
- +#define __VRX200_SOC_H__
- +
- +#define LTQ_ASC0_BASE 0x1E100400
- +#define LTQ_SPI_BASE 0x1E100800
- +#define LTQ_GPIO_BASE 0x1E100B00
- +#define LTQ_SSIO_BASE 0x1E100BB0
- +#define LTQ_ASC1_BASE 0x1E100C00
- +#define LTQ_DMA_BASE 0x1E104100
- +
- +#define LTQ_EBU_BASE 0x1E105300
- +#define LTQ_EBU_REGION0_BASE 0x10000000
- +#define LTQ_EBU_REGION1_BASE 0x14000000
- +#define LTQ_EBU_NAND_BASE (LTQ_EBU_BASE + 0xB0)
- +
- +#define LTQ_SWITCH_BASE 0x1E108000
- +#define LTQ_SWITCH_CORE_BASE LTQ_SWITCH_BASE
- +#define LTQ_SWITCH_TOP_PDI_BASE LTQ_SWITCH_CORE_BASE
- +#define LTQ_SWITCH_BM_PDI_BASE (LTQ_SWITCH_CORE_BASE + 4 * 0x40)
- +#define LTQ_SWITCH_MAC_PDI_0_BASE (LTQ_SWITCH_CORE_BASE + 4 * 0x900)
- +#define LTQ_SWITCH_MAC_PDI_X_BASE(x) (LTQ_SWITCH_MAC_PDI_0_BASE + x * 0x30)
- +#define LTQ_SWITCH_TOPLEVEL_BASE (LTQ_SWITCH_BASE + 4 * 0xC40)
- +#define LTQ_SWITCH_MDIO_PDI_BASE (LTQ_SWITCH_TOPLEVEL_BASE)
- +#define LTQ_SWITCH_MII_PDI_BASE (LTQ_SWITCH_TOPLEVEL_BASE + 4 * 0x36)
- +#define LTQ_SWITCH_PMAC_PDI_BASE (LTQ_SWITCH_TOPLEVEL_BASE + 4 * 0x82)
- +
- +#define LTQ_PMU_BASE 0x1F102000
- +#define LTQ_CGU_BASE 0x1F103000
- +#define LTQ_DCDC_BASE 0x1F106A00
- +#define LTQ_MPS_BASE 0x1F107000
- +#define LTQ_CHIPID_BASE (LTQ_MPS_BASE + 0x340)
- +#define LTQ_RCU_BASE 0x1F203000
- +
- +#define LTQ_MC_GLOBAL_BASE 0x1F400000
- +#define LTQ_MC_DDR_BASE 0x1F401000
- +#define LTQ_MC_DDR_CCR_OFFSET(x) (x * 0x10)
- +
- +#endif /* __VRX200_SOC_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/arch-vrx200/switch.h
- @@ -0,0 +1,502 @@
- +/*
- + * Copyright (C) 2012-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __VRX200_SWITCH_H__
- +#define __VRX200_SWITCH_H__
- +
- +/* Switch core registers */
- +struct vr9_switch_core_regs {
- + __be32 swres;
- + /* TODO: implement registers */
- + __be32 rsvd0[0x3f];
- +};
- +
- +/* Switch buffer management registers */
- +struct vr9_switch_bm_regs {
- + struct bm_core {
- + __be32 ram_val3; /* RAM value 3 */
- + __be32 ram_val2; /* RAM value 2 */
- + __be32 ram_val1; /* RAM value 1 */
- + __be32 ram_val0; /* RAM value 0 */
- + __be32 ram_addr; /* RAM address */
- + __be32 ram_ctrl; /* RAM access control */
- + __be32 fsqm_gctrl; /* Free segment queue global control */
- + __be32 cons_sel; /* Number of consumed segments */
- + __be32 cons_pkt; /* Number of consumed packet pointers */
- + __be32 gctrl; /* Global control */
- + __be32 queue_gctrl; /* Queue manager global control */
- + /* TODO: implement registers */
- + __be32 rsvd0[0x35];
- + } core;
- +
- + struct bm_port {
- + __be32 pcfg; /* Port config */
- + __be32 rmon_ctrl; /* RMON control */
- + } port[13];
- +
- + __be32 rsvd0[0x66];
- +
- + struct bm_queue {
- + __be32 rsvd0;
- + __be32 pqm_rs; /* Packet queue manager rate shape assignment */
- + } queue[32];
- +
- + struct bm_shaper {
- + __be32 ctrl; /* Rate shaper control */
- + __be32 cbs; /* Rate shaper committed burst size */
- + __be32 ibs; /* Rate shaper instantaneous burst size */
- + __be32 cir_ext; /* Rate shaper rate exponent */
- + __be32 cir_mant; /* Rate shaper rate mantissa */
- + } shaper[16];
- +
- + __be32 rsvd1[0x2a8];
- +};
- +
- +/* Switch parser and classification engine registers */
- +struct vr9_switch_pce_regs {
- + struct pce_core {
- + __be32 tbl_key[16]; /* Table key data */
- + __be32 tbl_mask; /* Table mask */
- + __be32 tbl_val[5]; /* Table value */
- + __be32 tbl_addr; /* Table entry address */
- + __be32 tbl_ctrl; /* Table access control */
- + __be32 tbl_stat; /* Table general status */
- + __be32 age_0; /* Aging counter config 0 */
- + __be32 age_1; /* Aging counter config 1 */
- + __be32 pmap_1; /* Port map (monitoring) */
- + __be32 pmap_2; /* Port map (multicast) */
- + __be32 pmap_3; /* Port map (unknown unicast) */
- + __be32 gctrl_0; /* Global control 0 */
- + __be32 gctrl_1; /* Global control 1 */
- + __be32 tcm_gctrl; /* Three-color marker global control */
- + __be32 igmp_ctrl; /* IGMP control */
- + __be32 igmp_drpm; /* IGMP default router port map */
- + __be32 igmp_age_0; /* IGMP aging 0 */
- + __be32 igmp_age_1; /* IGMP aging 1 */
- + __be32 igmp_stat; /* IGMP status */
- + __be32 wol_gctrl; /* Wake-on-LAN control */
- + __be32 wol_da_0; /* Wake-on-LAN destination address 0 */
- + __be32 wol_da_1; /* Wake-on-LAN destination address 1 */
- + __be32 wol_da_2; /* Wake-on-LAN destination address 2 */
- + __be32 wol_pw_0; /* Wake-on-LAN password 0 */
- + __be32 wol_pw_1; /* Wake-on-LAN password 1 */
- + __be32 wol_pw_2; /* Wake-on-LAN password 2 */
- + __be32 ier_0; /* PCE global interrupt enable 0 */
- + __be32 ier_1; /* PCE global interrupt enable 1 */
- + __be32 isr_0; /* PCE global interrupt status 0 */
- + __be32 isr_1; /* PCE global interrupt status 1 */
- + __be32 parser_stat; /* Parser status */
- + __be32 rsvd0[0x6];
- + } core;
- +
- + __be32 rsvd0[0x10];
- +
- + struct pce_port {
- + __be32 pctrl_0; /* Port control 0 */
- + __be32 pctrl_1; /* Port control 1 */
- + __be32 pctrl_2; /* Port control 2 */
- + __be32 pctrl_3; /* Port control 3 */
- + __be32 wol_ctrl; /* Wake-on-LAN control */
- + __be32 vlan_ctrl; /* VLAN control */
- + __be32 def_pvid; /* Default port VID */
- + __be32 pstat; /* Port status */
- + __be32 pier; /* Interrupt enable */
- + __be32 pisr; /* Interrupt status */
- + } port[13];
- +
- + __be32 rsvd1[0x7e];
- +
- + struct pce_meter {
- + /* TODO: implement registers */
- + __be32 rsvd0[0x7];
- + } meter[8];
- +
- + __be32 rsvd2[0x308];
- +};
- +
- +static inline unsigned int to_pce_tbl_key_id(unsigned int id)
- +{
- + BUG_ON(id > 15);
- +
- + return 15 - id;
- +}
- +
- +static inline unsigned int to_pce_tbl_value_id(unsigned int id)
- +{
- + BUG_ON(id > 4);
- +
- + return 4 - id;
- +}
- +
- +/* Switch ethernet MAC registers */
- +struct vr9_switch_mac_regs {
- + struct mac_core {
- + __be32 test; /* MAC test */
- + __be32 pfad_cfg; /* Pause frame source address config */
- + __be32 pfsa_0; /* Pause frame source address 0 */
- + __be32 pfsa_1; /* Pause frame source address 1 */
- + __be32 pfsa_2; /* Pause frame source address 2 */
- + __be32 flen; /* Frame length */
- + __be32 vlan_etype_0; /* VLAN ethertype 0 */
- + __be32 vlan_etype_1; /* VLAN ethertype 1 */
- + __be32 ier; /* Interrupt enable */
- + __be32 isr; /* Interrupt status */
- + __be32 rsvd0[0x36];
- + } core;
- +
- + struct mac_port {
- + __be32 pstat; /* Port status */
- + __be32 pisr; /* Interrupt status */
- + __be32 pier; /* Interrupt enable */
- + __be32 ctrl_0; /* Control 0 */
- + __be32 ctrl_1; /* Control 1 */
- + __be32 ctrl_2; /* Control 2 */
- + __be32 ctrl_3; /* Control 3 */
- + __be32 ctrl_4; /* Control 4 */
- + __be32 ctrl_5; /* Control 5 */
- + __be32 rsvd0[0x2];
- + __be32 testen; /* Test enable */
- + } port[13];
- +
- + __be32 rsvd0[0xa4];
- +};
- +
- +/* Switch Fetch DMA registers */
- +struct vr9_switch_fdma_regs {
- + struct fdma_core {
- + __be32 ctrl; /* FDMA control */
- + __be32 stetype; /* Special tag ethertype control */
- + __be32 vtetype; /* VLAN tag ethertype control */
- + __be32 stat; /* FDMA status */
- + __be32 ier; /* FDMA interrupt enable */
- + __be32 isr; /* FDMA interrupt status */
- + } core;
- +
- + __be32 rsvd0[0x3a];
- +
- + struct fdma_port {
- + __be32 pctrl; /* Port control */
- + __be32 prio; /* Port priority */
- + __be32 pstat_0; /* Port status 0 */
- + __be32 pstat_1; /* Port status 1 */
- + __be32 tstamp_0; /* Egress time stamp 0 */
- + __be32 tstamp_1; /* Egress time stamp 1 */
- + } port[13];
- +
- + __be32 rsvd1[0x72];
- +};
- +
- +/* Switch Store DMA registers */
- +struct vr9_switch_sdma_regs {
- + struct sdma_core {
- + __be32 ctrl; /* SDMA Control */
- + __be32 fcthr_1; /* Flow control threshold 1 */
- + __be32 rsvd0;
- + __be32 fcthr_3; /* Flow control threshold 3 */
- + __be32 fcthr_4; /* Flow control threshold 4 */
- + __be32 fcthr_5; /* Flow control threshold 5 */
- + __be32 fcthr_6; /* Flow control threshold 6 */
- + __be32 fcthr_7; /* Flow control threshold 7 */
- + __be32 stat_0; /* SDMA status 0 */
- + __be32 stat_1; /* SDMA status 1 */
- + __be32 stat_2; /* SDMA status 2 */
- + __be32 ier; /* SDMA interrupt enable */
- + __be32 isr; /* SDMA interrupt status */
- + } core;
- +
- + __be32 rsvd0[0x73];
- +
- + struct sdma_port {
- + __be32 pctrl; /* Port control */
- + __be32 prio; /* Port priority */
- + __be32 pstat_0; /* Port status 0 */
- + __be32 pstat_1; /* Port status 1 */
- + __be32 tstamp_0; /* Ingress time stamp 0 */
- + __be32 tstamp_1; /* Ingress time stamp 1 */
- + } port[13];
- +
- + __be32 rsvd1[0x32];
- +};
- +
- +/* Switch MDIO control and status registers */
- +struct vr9_switch_mdio_regs {
- + __be32 glob_ctrl; /* Global control 0 */
- + __be32 rsvd0[7];
- + __be32 mdio_ctrl; /* MDIO control */
- + __be32 mdio_read; /* MDIO read data */
- + __be32 mdio_write; /* MDIO write data */
- + __be32 mdc_cfg_0; /* MDC clock configuration 0 */
- + __be32 mdc_cfg_1; /* MDC clock configuration 1 */
- + __be32 rsvd1[0x3];
- + __be32 phy_addr[6]; /* PHY address port 5..0 */
- + __be32 mdio_stat[6]; /* MDIO PHY polling status port 0..5 */
- + __be32 aneg_eee[6]; /* EEE auto-neg overrides port 0..5 */
- + __be32 rsvd2[0x14];
- +};
- +
- +static inline unsigned int to_mdio_phyaddr_id(unsigned int id)
- +{
- + BUG_ON(id > 5);
- +
- + return 5 - id;
- +}
- +
- +/* Switch xMII control registers */
- +struct vr9_switch_mii_regs {
- + __be32 mii_cfg0; /* xMII port 0 configuration */
- + __be32 pcdu0; /* Port 0 clock delay configuration */
- + __be32 mii_cfg1; /* xMII port 1 configuration */
- + __be32 pcdu1; /* Port 1 clock delay configuration */
- + __be32 rsvd0[0x6];
- + __be32 mii_cfg5; /* xMII port 5 configuration */
- + __be32 pcdu5; /* Port 5 clock delay configuration */
- + __be32 rsvd1[0x14];
- + __be32 rxb_ctl_0; /* Port 0 receive buffer control */
- + __be32 rxb_ctl_1; /* Port 1 receive buffer control */
- + __be32 rxb_ctl_5; /* Port 5 receive buffer control */
- + __be32 rsvd2[0x28];
- + __be32 dbg_ctl; /* Debug control */
- +};
- +
- +/* Switch Pseudo-MAC registers */
- +struct vr9_switch_pmac_regs {
- + __be32 hd_ctl; /* PMAC header control */
- + __be32 tl; /* PMAC type/length */
- + __be32 sa1; /* PMAC source address 1 */
- + __be32 sa2; /* PMAC source address 2 */
- + __be32 sa3; /* PMAC source address 3 */
- + __be32 da1; /* PMAC destination address 1 */
- + __be32 da2; /* PMAC destination address 2 */
- + __be32 da3; /* PMAC destination address 3 */
- + __be32 vlan; /* PMAC VLAN */
- + __be32 rx_ipg; /* PMAC interpacket gap in RX direction */
- + __be32 st_etype; /* PMAC special tag ethertype */
- + __be32 ewan; /* PMAC ethernet WAN group */
- + __be32 ctl; /* PMAC control */
- + __be32 rsvd0[0x2];
- +};
- +
- +struct vr9_switch_regs {
- + struct vr9_switch_core_regs core;
- + struct vr9_switch_bm_regs bm;
- + struct vr9_switch_pce_regs pce;
- + struct vr9_switch_mac_regs mac;
- + struct vr9_switch_fdma_regs fdma;
- + struct vr9_switch_sdma_regs sdma;
- + struct vr9_switch_mdio_regs mdio;
- + struct vr9_switch_mii_regs mii;
- + struct vr9_switch_pmac_regs pmac;
- +};
- +
- +static inline void *to_pce_tbl_key(struct vr9_switch_regs *regs,
- + unsigned int id)
- +{
- + return ®s->pce.core.tbl_key[to_pce_tbl_key_id(id)];
- +}
- +
- +static inline void *to_pce_tbl_value(struct vr9_switch_regs *regs,
- + unsigned int id)
- +{
- + return ®s->pce.core.tbl_val[to_pce_tbl_value_id(id)];
- +}
- +
- +static inline void *to_mac_ctrl(struct vr9_switch_regs *regs,
- + unsigned int id, unsigned int ctrl)
- +{
- + struct mac_port *mac = ®s->mac.port[id];
- +
- + switch (ctrl) {
- + case 0:
- + return &mac->ctrl_0;
- + case 1:
- + return &mac->ctrl_1;
- + case 2:
- + return &mac->ctrl_2;
- + case 3:
- + return &mac->ctrl_3;
- + case 4:
- + return &mac->ctrl_4;
- + case 5:
- + return &mac->ctrl_5;
- + default:
- + return NULL;
- + }
- +}
- +
- +static inline void *to_mdio_phyaddr(struct vr9_switch_regs *regs,
- + unsigned int id)
- +{
- + return ®s->mdio.phy_addr[to_mdio_phyaddr_id(id)];
- +}
- +
- +static inline void *to_mii_miicfg(struct vr9_switch_regs *regs,
- + unsigned int id)
- +{
- + switch (id) {
- + case 0:
- + return ®s->mii.mii_cfg0;
- + case 1:
- + return ®s->mii.mii_cfg1;
- + case 5:
- + return ®s->mii.mii_cfg5;
- + default:
- + return NULL;
- + }
- +}
- +
- +static inline void *to_mii_pcdu(struct vr9_switch_regs *regs,
- + unsigned int id)
- +{
- + switch (id) {
- + case 0:
- + return ®s->mii.pcdu0;
- + case 1:
- + return ®s->mii.pcdu1;
- + case 5:
- + return ®s->mii.pcdu5;
- + default:
- + return NULL;
- + }
- +}
- +
- +#define VR9_SWITCH_REG_OFFSET(reg) (4 * (reg))
- +
- +#define BUILD_CHECK_VR9_REG(name, offset) \
- + BUILD_BUG_ON(offsetof(struct vr9_switch_regs, name) != (4 * offset))
- +
- +static inline void build_check_vr9_registers(void)
- +{
- + BUILD_CHECK_VR9_REG(core, 0x0);
- + BUILD_CHECK_VR9_REG(bm.core, 0x40);
- + BUILD_CHECK_VR9_REG(bm.core.queue_gctrl, 0x4a);
- + BUILD_CHECK_VR9_REG(bm.port[0], 0x80);
- + BUILD_CHECK_VR9_REG(bm.queue, 0x100);
- + BUILD_CHECK_VR9_REG(bm.shaper, 0x140);
- + BUILD_CHECK_VR9_REG(pce.core, 0x438);
- + BUILD_CHECK_VR9_REG(pce.core.tbl_ctrl, 0x44f);
- + BUILD_CHECK_VR9_REG(pce.core.parser_stat, 0x469);
- + BUILD_CHECK_VR9_REG(pce.port[0], 0x480);
- + BUILD_CHECK_VR9_REG(pce.meter[0], 0x580);
- + BUILD_CHECK_VR9_REG(mac.core, 0x8c0);
- + BUILD_CHECK_VR9_REG(mac.port[0].pstat, 0x900);
- + BUILD_CHECK_VR9_REG(mac.port[0].ctrl_0, 0x903);
- + BUILD_CHECK_VR9_REG(mac.port[1].pstat, 0x90c);
- + BUILD_CHECK_VR9_REG(mac.port[1].ctrl_0, 0x90f);
- + BUILD_CHECK_VR9_REG(mac.port[2].pstat, 0x918);
- + BUILD_CHECK_VR9_REG(mac.port[2].ctrl_0, 0x91b);
- + BUILD_CHECK_VR9_REG(fdma.core, 0xa40);
- + BUILD_CHECK_VR9_REG(fdma.port[0], 0xa80);
- + BUILD_CHECK_VR9_REG(sdma.core, 0xb40);
- + BUILD_CHECK_VR9_REG(sdma.port[0], 0xbc0);
- + BUILD_CHECK_VR9_REG(mdio, 0xc40);
- + BUILD_CHECK_VR9_REG(mii, (0xc40 + 0x36));
- + BUILD_CHECK_VR9_REG(pmac, (0xc40 + 0x82));
- +}
- +
- +#define BM_GCTRL_F_SRES 1
- +
- +#define MAC_CTRL0_BM (1 << 12)
- +#define MAC_CTRL0_APADEN (1 << 11)
- +#define MAC_CTRL0_VPAD2EN (1 << 10)
- +#define MAC_CTRL0_VPADEN (1 << 9)
- +#define MAC_CTRL0_PADEN (1 << 8)
- +#define MAC_CTRL0_FCS (1 << 7)
- +#define MAC_CTRL0_FCON_SHIFT 4
- +#define MAC_CTRL0_FCON_AUTO (0x0 << MAC_CTRL0_FCON_SHIFT)
- +#define MAC_CTRL0_FCON_RX (0x1 << MAC_CTRL0_FCON_SHIFT)
- +#define MAC_CTRL0_FCON_TX (0x2 << MAC_CTRL0_FCON_SHIFT)
- +#define MAC_CTRL0_FCON_RXTX (0x3 << MAC_CTRL0_FCON_SHIFT)
- +#define MAC_CTRL0_FCON_NONE (0x4 << MAC_CTRL0_FCON_SHIFT)
- +#define MAC_CTRL0_FDUP_SHIFT 2
- +#define MAC_CTRL0_FDUP_AUTO (0x0 << MAC_CTRL0_FDUP_SHIFT)
- +#define MAC_CTRL0_FDUP_EN (0x1 << MAC_CTRL0_FDUP_SHIFT)
- +#define MAC_CTRL0_FDUP_DIS (0x3 << MAC_CTRL0_FDUP_SHIFT)
- +#define MAC_CTRL0_GMII_AUTO 0x0
- +#define MAC_CTRL0_GMII_MII 0x1
- +#define MAC_CTRL0_GMII_GMII 0x2
- +#define MAC_CTRL0_GMII_GMII_2G 0x3
- +
- +#define MAC_CTRL1_DEFERMODE (1 << 15)
- +#define MAC_CTRL1_SHORTPRE (1 << 8)
- +
- +#define MAC_CTRL2_MLEN (1 << 3)
- +#define MAC_CTRL2_LCHKL (1 << 2)
- +#define MAC_CTRL2_LCHKS_DIS 0x0
- +#define MAC_CTRL2_LCHKS_UNTAG 0x1
- +#define MAC_CTRL2_LCHKS_TAG 0x2
- +
- +#define PHY_ADDR_LNKST_SHIFT 13
- +#define PHY_ADDR_LNKST_AUTO (0x0 << PHY_ADDR_LNKST_SHIFT)
- +#define PHY_ADDR_LNKST_UP (0x1 << PHY_ADDR_LNKST_SHIFT)
- +#define PHY_ADDR_LNKST_DOWN (0x2 << PHY_ADDR_LNKST_SHIFT)
- +#define PHY_ADDR_SPEED_SHIFT 11
- +#define PHY_ADDR_SPEED_M10 (0x0 << PHY_ADDR_SPEED_SHIFT)
- +#define PHY_ADDR_SPEED_M100 (0x1 << PHY_ADDR_SPEED_SHIFT)
- +#define PHY_ADDR_SPEED_G1 (0x2 << PHY_ADDR_SPEED_SHIFT)
- +#define PHY_ADDR_SPEED_AUTO (0x3 << PHY_ADDR_SPEED_SHIFT)
- +#define PHY_ADDR_FDUP_SHIFT 9
- +#define PHY_ADDR_FDUP_AUTO (0x0 << PHY_ADDR_FDUP_SHIFT)
- +#define PHY_ADDR_FDUP_EN (0x1 << PHY_ADDR_FDUP_SHIFT)
- +#define PHY_ADDR_FDUP_DIS (0x3 << PHY_ADDR_FDUP_SHIFT)
- +#define PHY_ADDR_FCONTX_SHIFT 7
- +#define PHY_ADDR_FCONTX_AUTO (0x0 << PHY_ADDR_FCONTX_SHIFT)
- +#define PHY_ADDR_FCONTX_EN (0x1 << PHY_ADDR_FCONTX_SHIFT)
- +#define PHY_ADDR_FCONTX_DIS (0x3 << PHY_ADDR_FCONTX_SHIFT)
- +#define PHY_ADDR_FCONRX_SHIFT 5
- +#define PHY_ADDR_FCONRX_AUTO (0x0 << PHY_ADDR_FCONRX_SHIFT)
- +#define PHY_ADDR_FCONRX_EN (0x1 << PHY_ADDR_FCONRX_SHIFT)
- +#define PHY_ADDR_FCONRX_DIS (0x3 << PHY_ADDR_FCONRX_SHIFT)
- +
- +#define MII_CFG_RES (1 << 15)
- +#define MII_CFG_EN (1 << 14)
- +#define MII_CFG_LDCLKDIS (1 << 12)
- +#define MII_CFG_MIIRATE_SHIFT 4
- +#define MII_CFG_MIIRATE_MASK (0x7 << MII_CFG_MIIRATE_SHIFT)
- +#define MII_CFG_MIIRATE_M2P5 (0x0 << MII_CFG_MIIRATE_SHIFT)
- +#define MII_CFG_MIIRATE_M25 (0x1 << MII_CFG_MIIRATE_SHIFT)
- +#define MII_CFG_MIIRATE_M125 (0x2 << MII_CFG_MIIRATE_SHIFT)
- +#define MII_CFG_MIIRATE_M50 (0x3 << MII_CFG_MIIRATE_SHIFT)
- +#define MII_CFG_MIIRATE_AUTO (0x4 << MII_CFG_MIIRATE_SHIFT)
- +#define MII_CFG_MIIMODE_MASK 0xf
- +#define MII_CFG_MIIMODE_MIIP 0x0
- +#define MII_CFG_MIIMODE_MIIM 0x1
- +#define MII_CFG_MIIMODE_RMIIP 0x2
- +#define MII_CFG_MIIMODE_RMIIM 0x3
- +#define MII_CFG_MIIMODE_RGMII 0x4
- +
- +#define PCDU_RXDLY_SHIFT 7
- +#define PCDU_RXDLY_MASK (0x7 << PCDU_RXDLY_SHIFT)
- +#define PCDU_TXDLY_MASK 0x7
- +
- +#define PMAC_HD_CTL_FC (1 << 10)
- +#define PMAC_HD_CTL_CCRC (1 << 9)
- +#define PMAC_HD_CTL_RST (1 << 8)
- +#define PMAC_HD_CTL_AST (1 << 7)
- +#define PMAC_HD_CTL_RXSH (1 << 6)
- +#define PMAC_HD_CTL_RC (1 << 4)
- +#define PMAC_HD_CTL_AS (1 << 3)
- +#define PMAC_HD_CTL_AC (1 << 2)
- +
- +#define PCE_PCTRL_0_IGSTEN (1 << 11)
- +
- +#define FDMA_PCTRL_STEN (1 << 1)
- +#define FDMA_PCTRL_EN (1 << 0)
- +
- +#define SDMA_PCTRL_EN (1 << 0)
- +
- +#define MDIO_GLOB_CTRL_SE (1 << 15)
- +
- +#define MDIO_MDC_CFG1_RES (1 << 15)
- +#define MDIO_MDC_CFG1_MCEN (1 << 8)
- +
- +#define MDIO_CTRL_MBUSY (1 << 12)
- +#define MDIO_CTRL_OP_READ (1 << 11)
- +#define MDIO_CTRL_OP_WRITE (1 << 10)
- +#define MDIO_CTRL_PHYAD_SHIFT 5
- +#define MDIO_CTRL_PHYAD_MASK (0x1f << MDIO_CTRL_PHYAD_SHIFT)
- +#define MDIO_CTRL_REGAD_MASK 0x1f
- +
- +#endif /* __VRX200_SWITCH_H__ */
- --- a/arch/mips/include/asm/asm.h
- +++ b/arch/mips/include/asm/asm.h
- @@ -53,6 +53,7 @@
- .align 2; \
- .type symbol, @function; \
- .ent symbol, 0; \
- + .section .text.symbol,"x"; \
- symbol: .frame sp, 0, ra
-
- /*
- @@ -62,7 +63,8 @@ symbol: .frame sp, 0, ra
- .globl symbol; \
- .align 2; \
- .type symbol, @function; \
- - .ent symbol, 0; \
- + .ent symbol, 0; \
- + .section .text.symbol,"x"; \
- symbol: .frame sp, framesize, rpc
-
- /*
- --- /dev/null
- +++ b/arch/mips/include/asm/gpio.h
- @@ -0,0 +1,6 @@
- +/*
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <asm/arch/gpio.h>
- +#include <asm-generic/gpio.h>
- --- /dev/null
- +++ b/arch/mips/include/asm/lantiq/chipid.h
- @@ -0,0 +1,73 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __LANTIQ_CHIPID_H__
- +#define __LANTIQ_CHIPID_H__
- +
- +enum ltq_chip_partnum {
- + LTQ_SOC_UNKNOWN = 0,
- + LTQ_SOC_VRX288_2 = 0x000B, /* VRX288 v1.2 */
- + LTQ_SOC_VRX268_2 = 0x000C, /* VRX268 v1.2 */
- + LTQ_SOC_GRX288_2 = 0x000D, /* GRX288 v1.2 */
- + LTQ_SOC_DANUBE = 0x0129,
- + LTQ_SOC_DANUBE_S = 0x012B,
- + LTQ_SOC_TWINPASS = 0x012D,
- + LTQ_SOC_VRX288 = 0x01C0, /* VRX288 v1.1 */
- + LTQ_SOC_VRX268 = 0x01C2, /* VRX268 v1.1 */
- + LTQ_SOC_GRX288 = 0x01C9, /* GRX288 v1.1 */
- +};
- +
- +extern unsigned int ltq_chip_version_get(void);
- +extern unsigned int ltq_chip_partnum_get(void);
- +extern const char *ltq_chip_partnum_str(void);
- +
- +extern void ltq_chip_print_info(void);
- +
- +#ifdef CONFIG_SOC_XWAY_DANUBE
- +static inline int ltq_soc_is_danube(void)
- +{
- + return 1;
- +}
- +#else
- +static inline int ltq_soc_is_danube(void)
- +{
- + return 0;
- +}
- +#endif
- +
- +#ifdef CONFIG_SOC_XWAY_VRX200
- +static inline int ltq_soc_is_vrx200(void)
- +{
- + return 1;
- +}
- +
- +static inline int ltq_soc_is_vrx200_v1(void)
- +{
- + return ltq_chip_version_get() == 1;
- +}
- +
- +static inline int ltq_soc_is_vrx200_v2(void)
- +{
- + return ltq_chip_version_get() == 2;
- +}
- +#else
- +static inline int ltq_soc_is_vrx200(void)
- +{
- + return 0;
- +}
- +
- +static inline int ltq_soc_is_vrx200_v1(void)
- +{
- + return 0;
- +}
- +
- +static inline int ltq_soc_is_vrx200_v2(void)
- +{
- + return 0;
- +}
- +#endif
- +
- +#endif /* __LANTIQ_CHIPID_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/lantiq/clk.h
- @@ -0,0 +1,30 @@
- +/*
- + * Copyright (C) 2007-2010 Lantiq Deutschland GmbH
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + * *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __LANTIQ_CLK_H__
- +#define __LANTIQ_CLK_H__
- +
- +/* Symbolic clock speeds */
- +enum ltq_clk {
- + CLOCK_83_MHZ = 83333333,
- + CLOCK_111_MHZ = 111111111,
- + CLOCK_125_MHZ = 125000000,
- + CLOCK_133_MHZ = 133333333,
- + CLOCK_166_MHZ = 166666667,
- + CLOCK_197_MHZ = 197000000,
- + CLOCK_333_MHZ = 333333333,
- + CLOCK_393_MHZ = 393219000,
- + CLOCK_500_MHZ = 500000000,
- + CLOCK_600_MHZ = 600000000,
- + CLOCK_1000_MHZ = 1000000000,
- +};
- +
- +extern unsigned long ltq_get_cpu_clock(void);
- +extern unsigned long ltq_get_bus_clock(void);
- +extern unsigned long ltq_get_io_region_clock(void);
- +
- +#endif /* __LANTIQ_CLK_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/lantiq/config.h
- @@ -0,0 +1,164 @@
- +/*
- + * Copyright (C) 2007-2010 Lantiq Deutschland GmbH
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __LANTIQ_CONFIG_H__
- +#define __LANTIQ_CONFIG_H__
- +
- +/* Memory usage */
- +#define CONFIG_SYS_MAXARGS 24
- +#define CONFIG_SYS_MALLOC_LEN 1024*1024
- +#define CONFIG_SYS_BOOTPARAMS_LEN 128*1024
- +
- +/* Command line */
- +#define CONFIG_SYS_PROMPT CONFIG_MACH_TYPE " # "
- +#define CONFIG_SYS_CBSIZE 512
- +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \
- + sizeof(CONFIG_SYS_PROMPT)+16)
- +
- +#define CONFIG_SYS_HUSH_PARSER
- +#define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
- +
- +/*
- + * Enable advanced console features on demand to reduce
- + * flash and RAM footprint
- + */
- +#if defined(CONFIG_LTQ_ADVANCED_CONSOLE)
- +#define CONFIG_SYS_LONGHELP
- +#define CONFIG_AUTO_COMPLETE
- +#define CONFIG_CMDLINE_EDITING
- +#endif
- +
- +/* SPI flash SPL */
- +#if defined(CONFIG_LTQ_SUPPORT_SPL_SPI_FLASH) && defined(CONFIG_SYS_BOOT_SFSPL)
- +#define CONFIG_SPL
- +#define CONFIG_SPL_SPI_SUPPORT
- +#define CONFIG_SPL_SPI_FLASH_SUPPORT
- +#define CONFIG_SPI_SPL_SIMPLE
- +#endif
- +
- +#if defined(CONFIG_LTQ_SUPPORT_SPL_NOR_FLASH) && defined(CONFIG_SYS_BOOT_NORSPL)
- +#define CONFIG_SPL
- +#endif
- +
- +/* Common SPL */
- +#if defined(CONFIG_SPL)
- +#define CONFIG_SKIP_LOWLEVEL_INIT
- +#define CONFIG_SPL_LIBGENERIC_SUPPORT
- +#define CONFIG_SPL_GPIO_SUPPORT
- +#define CONFIG_SPL_START_S_PATH \
- + "arch/mips/cpu/mips32/lantiq-common"
- +#define CONFIG_SPL_LDSCRIPT \
- + "arch/mips/cpu/mips32/lantiq-common/u-boot-spl.lds"
- +#endif
- +
- +#if defined(CONFIG_LTQ_SPL_CONSOLE)
- +#define CONFIG_SPL_SERIAL_SUPPORT
- +#define CONFIG_SPL_LIBCOMMON_SUPPORT
- +#endif
- +
- +#if defined(CONFIG_LTQ_SPL_COMP_LZMA)
- +#define CONFIG_LZMA
- +#define CONFIG_SPL_LZMA_SUPPORT
- +#endif
- +
- +#if defined(CONFIG_LTQ_SPL_COMP_LZO)
- +#define CONFIG_LZO
- +#define CONFIG_SPL_LZO_SUPPORT
- +#endif
- +
- +/* Basic commands */
- +#define CONFIG_CMD_BDI
- +#define CONFIG_CMD_EDITENV
- +#define CONFIG_CMD_IMI
- +#define CONFIG_CMD_MEMORY
- +#define CONFIG_CMD_RUN
- +#define CONFIG_CMD_SAVEENV
- +#define CONFIG_CMD_LOADB
- +
- +/* Other U-Boot settings */
- +#define CONFIG_TIMESTAMP
- +
- +/* Default environment */
- +#define CONFIG_ENV_CONSOLEDEV \
- + "consoledev=" CONFIG_CONSOLE_DEV "\0"
- +
- +#define CONFIG_ENV_ADDCONSOLE \
- + "addconsole=setenv bootargs $bootargs" \
- + " console=$consoledev,$baudrate\0"
- +
- +#if defined(CONFIG_NET_DEV)
- +#define CONFIG_ENV_NETDEV \
- + "netdev=" CONFIG_NET_DEV "\0"
- +#else
- +#define CONFIG_ENV_NETDEV \
- + "netdev=eth0\0"
- +#endif
- +
- +#define CONFIG_ENV_ADDIP \
- + "addip=setenv bootargs $bootargs" \
- + " ip=$ipaddr:$serverip::::$netdev:off\0"
- +
- +#define CONFIG_ENV_ADDETH \
- + "addeth=setenv bootargs $bootargs" \
- + " ethaddr=$ethaddr\0"
- +
- +#define CONFIG_ENV_ADDMACHTYPE \
- + "addmachtype=setenv bootargs $bootargs" \
- + " machtype=" CONFIG_MACH_TYPE "\0"
- +
- +#if defined(CONFIG_LTQ_SUPPORT_NOR_FLASH)
- +#define CONFIG_ENV_WRITE_UBOOT_NOR \
- + "write-uboot-nor=" \
- + "protect off " __stringify(CONFIG_SYS_FLASH_BASE) " +$filesize && " \
- + "erase " __stringify(CONFIG_SYS_FLASH_BASE) " +$filesize && " \
- + "cp.b $fileaddr " __stringify(CONFIG_SYS_FLASH_BASE) " $filesize\0"
- +
- +#define CONFIG_ENV_LOAD_UBOOT_NOR \
- + "load-uboot-nor=tftpboot u-boot.bin\0" \
- + "load-uboot-norspl=tftpboot u-boot.ltq.norspl\0" \
- + "load-uboot-norspl-lzo=tftpboot u-boot.ltq.lzo.norspl\0" \
- + "load-uboot-norspl-lzma=tftpboot u-boot.ltq.lzma.norspl\0"
- +#else
- +#define CONFIG_ENV_WRITE_UBOOT_NOR
- +#define CONFIG_ENV_LOAD_UBOOT_NOR
- +#endif
- +
- +#if defined(CONFIG_LTQ_SUPPORT_SPI_FLASH)
- +#define CONFIG_ENV_SF_PROBE \
- + "sf-probe=sf probe " __stringify(CONFIG_ENV_SPI_CS) " " \
- + __stringify(CONFIG_ENV_SPI_MAX_HZ) " " \
- + __stringify(CONFIG_ENV_SPI_MODE) " \0"
- +
- +#define CONFIG_ENV_WRITE_UBOOT_SF \
- + "write-uboot-sf=" \
- + "run sf-probe && sf erase 0 +$filesize && " \
- + "sf write $fileaddr 0 $filesize\0"
- +
- +#define CONFIG_ENV_LOAD_UBOOT_SF \
- + "load-uboot-sfspl=tftpboot u-boot.ltq.sfspl\0" \
- + "load-uboot-sfspl-lzo=tftpboot u-boot.ltq.lzo.sfspl\0" \
- + "load-uboot-sfspl-lzma=tftpboot u-boot.ltq.lzma.sfspl\0"
- +#else
- +#define CONFIG_ENV_SF_PROBE
- +#define CONFIG_ENV_WRITE_UBOOT_SF
- +#define CONFIG_ENV_LOAD_UBOOT_SF
- +#endif
- +
- +#define CONFIG_ENV_LANTIQ_DEFAULTS \
- + CONFIG_ENV_CONSOLEDEV \
- + CONFIG_ENV_ADDCONSOLE \
- + CONFIG_ENV_NETDEV \
- + CONFIG_ENV_ADDIP \
- + CONFIG_ENV_ADDETH \
- + CONFIG_ENV_ADDMACHTYPE \
- + CONFIG_ENV_WRITE_UBOOT_NOR \
- + CONFIG_ENV_LOAD_UBOOT_NOR \
- + CONFIG_ENV_SF_PROBE \
- + CONFIG_ENV_WRITE_UBOOT_SF \
- + CONFIG_ENV_LOAD_UBOOT_SF
- +
- +#endif /* __LANTIQ_CONFIG_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/lantiq/cpu.h
- @@ -0,0 +1,34 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __LANTIQ_CPU_H__
- +#define __LANTIQ_CPU_H__
- +
- +enum ltq_boot_select {
- + BOOT_NOR,
- + BOOT_NOR_NO_BOOTROM,
- + BOOT_UART,
- + BOOT_UART_NO_EEPROM,
- + BOOT_SPI,
- + BOOT_NAND,
- + BOOT_PCI,
- + BOOT_MII0,
- + BOOT_RMII0,
- + BOOT_RGMII1,
- + BOOT_UNKNOWN,
- +};
- +
- +enum ltq_boot_select ltq_boot_select(void);
- +const char *ltq_boot_select_str(void);
- +
- +void ltq_pmu_init(void);
- +void ltq_ebu_init(void);
- +void ltq_gpio_init(void);
- +
- +void ltq_pll_init(void);
- +void ltq_dcdc_init(unsigned int dig_ref);
- +
- +#endif /* __LANTIQ_CPU_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/lantiq/dma.h
- @@ -0,0 +1,94 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __LANTIQ_DMA_H__
- +#define __LANTIQ_DMA_H__
- +
- +enum ltq_dma_endianess {
- + LTQ_DMA_ENDIANESS_B0_B1_B2_B3, /* No byte swapping */
- + LTQ_DMA_ENDIANESS_B1_B0_B3_B2, /* B0B1B2B3 => B1B0B3B2 */
- + LTQ_DMA_ENDIANESS_B2_B3_B0_B1, /* B0B1B2B3 => B2B3B0B1 */
- + LTQ_DMA_ENDIANESS_B3_B2_B1_B0, /* B0B1B2B3 => B3B2B1B0 */
- +};
- +
- +enum ltq_dma_burst_len {
- + LTQ_DMA_BURST_2WORDS = 1,
- + LTQ_DMA_BURST_4WORDS = 2,
- + LTQ_DMA_BURST_8WORDS = 3,
- +};
- +
- +struct ltq_dma_desc {
- + u32 ctl;
- + u32 addr;
- +};
- +
- +struct ltq_dma_channel {
- + struct ltq_dma_device *dev;
- + u8 chan_no;
- + u8 class;
- + u16 num_desc;
- + struct ltq_dma_desc *desc_base;
- + void *mem_base;
- + u32 dma_addr;
- +};
- +
- +struct ltq_dma_device {
- + enum ltq_dma_endianess rx_endian_swap;
- + enum ltq_dma_endianess tx_endian_swap;
- + enum ltq_dma_burst_len rx_burst_len;
- + enum ltq_dma_burst_len tx_burst_len;
- + struct ltq_dma_channel rx_chan;
- + struct ltq_dma_channel tx_chan;
- + u8 port;
- +};
- +
- +/**
- + * Initialize DMA hardware and driver
- + */
- +void ltq_dma_init(void);
- +
- +/**
- + * Register given DMA client context
- + *
- + * @returns 0 on success, negative value otherwise
- + */
- +int ltq_dma_register(struct ltq_dma_device *dev);
- +
- +/**
- + * Reset and halt all channels related to given DMA client
- + */
- +void ltq_dma_reset(struct ltq_dma_device *dev);
- +void ltq_dma_enable(struct ltq_dma_device *dev);
- +void ltq_dma_disable(struct ltq_dma_device *dev);
- +
- +/**
- + * Map RX DMA descriptor to memory region
- + *
- + * @returns 0 on success, negative value otherwise
- + */
- +int ltq_dma_rx_map(struct ltq_dma_device *dev, int index, void *data, int len);
- +
- +/**
- + * Check if new data is available.
- + *
- + * @returns length of received data, 0 otherwise
- + */
- +int ltq_dma_rx_poll(struct ltq_dma_device *dev, int index);
- +
- +int ltq_dma_rx_length(struct ltq_dma_device *dev, int index);
- +
- +/**
- + * Map TX DMA descriptor to memory region
- + *
- + * @returns 0 on success, negative value otherwise
- + */
- +int ltq_dma_tx_map(struct ltq_dma_device *dev, int index, void *data, int len,
- + unsigned long timeout);
- +
- +int ltq_dma_tx_wait(struct ltq_dma_device *dev, int index,
- + unsigned long timeout);
- +
- +#endif /* __LANTIQ_DMA_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/lantiq/eth.h
- @@ -0,0 +1,35 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __LANTIQ_ETH_H__
- +#define __LANTIQ_ETH_H__
- +
- +#include <phy.h>
- +
- +enum LTQ_ETH_PORT_FLAGS {
- + LTQ_ETH_PORT_NONE = 0,
- + LTQ_ETH_PORT_PHY = 1,
- + LTQ_ETH_PORT_SWITCH = (1 << 1),
- + LTQ_ETH_PORT_MAC = (1 << 2),
- +};
- +
- +struct ltq_eth_port_config {
- + u8 num;
- + u8 phy_addr;
- + u16 flags;
- + phy_interface_t phy_if;
- + u8 rgmii_rx_delay;
- + u8 rgmii_tx_delay;
- +};
- +
- +struct ltq_eth_board_config {
- + const struct ltq_eth_port_config *ports;
- + int num_ports;
- +};
- +
- +extern int ltq_eth_initialize(const struct ltq_eth_board_config *board_config);
- +
- +#endif /* __LANTIQ_ETH_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/lantiq/gpio.h
- @@ -0,0 +1,50 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __LANTIQ_GPIO_H__
- +#define __LANTIQ_GPIO_H__
- +
- +enum ltq_gpio_dir {
- + GPIO_DIR_IN = 0,
- + GPIO_DIR_OUT
- +};
- +
- +enum ltq_gpio_od {
- + GPIO_OD_ACTIVE = 0,
- + GPIO_OD_NORMAL
- +};
- +
- +enum ltq_gpio_altsel {
- + GPIO_ALTSEL_CLR = 0,
- + GPIO_ALTSEL_SET
- +};
- +
- +extern int gpio_set_altfunc(unsigned gpio, int altsel0, int altsel1, int dir);
- +extern int gpio_set_opendrain(unsigned gpio, int od);
- +
- +static inline int gpio_to_port(unsigned gpio)
- +{
- + return gpio >> 4;
- +}
- +
- +static inline int gpio_to_pin(unsigned gpio)
- +{
- + return gpio & 0xF;
- +}
- +
- +static inline int gpio_to_bit(unsigned gpio)
- +{
- + return 1 << gpio_to_pin(gpio);
- +}
- +
- +static inline int gpio_to_gpio(unsigned port, unsigned pin)
- +{
- + return (port << 4) | (pin & 0xF);
- +}
- +
- +#include <asm-generic/gpio.h>
- +
- +#endif /* __LANTIQ_GPIO_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/lantiq/io.h
- @@ -0,0 +1,37 @@
- +/*
- + * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __LANTIQ_IO_H__
- +#define __LANTIQ_IO_H__
- +
- +#include <asm/io.h>
- +
- +#define ltq_readb(a) __raw_readb(a)
- +#define ltq_writeb(a, v) __raw_writeb(v, a)
- +
- +#define ltq_readl(a) __raw_readl(a)
- +#define ltq_writel(a, v) __raw_writel(v, a)
- +
- +#define ltq_clrbits(a, clear) \
- + ltq_writel(a, ltq_readl(a) & ~(clear))
- +
- +#define ltq_setbits(a, set) \
- + ltq_writel(a, ltq_readl(a) | (set))
- +
- +#define ltq_clrsetbits(a, clear, set) \
- + ltq_writel(a, (ltq_readl(a) & ~(clear)) | (set))
- +
- +static inline void ltq_reg_dump(const void *addr, const char *desc)
- +{
- + u32 data;
- +
- + data = ltq_readl(addr);
- + printf("ltq_reg_dump: %s 0x%p = 0x%08x\n",
- + desc, addr, data);
- +}
- +
- +#endif /* __LANTIQ_IO_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/lantiq/pm.h
- @@ -0,0 +1,21 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __LANTIQ_PM_H__
- +#define __LANTIQ_PM_H__
- +
- +enum ltq_pm_modules {
- + LTQ_PM_CORE,
- + LTQ_PM_DMA,
- + LTQ_PM_ETH,
- + LTQ_PM_SPI,
- +};
- +
- +u32 ltq_pm_map(enum ltq_pm_modules module);
- +int ltq_pm_enable(enum ltq_pm_modules module);
- +int ltq_pm_disable(enum ltq_pm_modules module);
- +
- +#endif /* __LANTIQ_PM_H__ */
- --- /dev/null
- +++ b/arch/mips/include/asm/lantiq/reset.h
- @@ -0,0 +1,37 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __LANTIQ_RESET_H__
- +#define __LANTIQ_RESET_H__
- +
- +enum ltq_reset_modules {
- + LTQ_RESET_CORE,
- + LTQ_RESET_DMA,
- + LTQ_RESET_ETH,
- + LTQ_RESET_PHY,
- + LTQ_RESET_HARD,
- + LTQ_RESET_SOFT,
- +};
- +
- +extern u32 ltq_reset_map(enum ltq_reset_modules module);
- +extern int ltq_reset_activate(enum ltq_reset_modules module);
- +extern int ltq_reset_deactivate(enum ltq_reset_modules module);
- +
- +static inline int ltq_reset_once(enum ltq_reset_modules module, ulong usec)
- +{
- + int ret;
- +
- + ret = ltq_reset_activate(module);
- + if (ret)
- + return ret;
- +
- + __udelay(usec);
- + ret = ltq_reset_deactivate(module);
- +
- + return ret;
- +}
- +
- +#endif /* __LANTIQ_RESET_H__ */
- --- a/arch/mips/include/asm/mipsregs.h
- +++ b/arch/mips/include/asm/mipsregs.h
- @@ -46,7 +46,10 @@
- #define CP0_ENTRYLO1 $3
- #define CP0_CONF $3
- #define CP0_CONTEXT $4
- +#define CP0_CONTEXTCONFIG $4,1
- +#define CP0_USERLOCAL $4,1
- #define CP0_PAGEMASK $5
- +#define CP0_PAGEGRAIN $5,1
- #define CP0_WIRED $6
- #define CP0_INFO $7
- #define CP0_BADVADDR $8
- @@ -54,10 +57,19 @@
- #define CP0_ENTRYHI $10
- #define CP0_COMPARE $11
- #define CP0_STATUS $12
- +#define CP0_INTCTL $12,1
- +#define CP0_SRSCTL $12,2
- +#define CP0_SRSMAP $12,3
- +#define CP0_SRSHIGH $12,4
- #define CP0_CAUSE $13
- #define CP0_EPC $14
- #define CP0_PRID $15
- +#define CP0_EBASE $15,1
- #define CP0_CONFIG $16
- +#define CP0_CONFIG1 $16,1
- +#define CP0_CONFIG2 $16,2
- +#define CP0_CONFIG3 $16,3
- +#define CP0_CONFIG7 $16,7
- #define CP0_LLADDR $17
- #define CP0_WATCHLO $18
- #define CP0_WATCHHI $19
- @@ -70,7 +82,17 @@
- #define CP0_ECC $26
- #define CP0_CACHEERR $27
- #define CP0_TAGLO $28
- +#define CP0_ITAGLO $28
- +#define CP0_IDATALO $28,1
- +#define CP0_DTAGLO $28,2
- +#define CP0_DDATALO $28,3
- +#define CP0_L23TAGLO $28,4
- +#define CP0_L23DATALO $28,5
- #define CP0_TAGHI $29
- +#define CP0_IDATAHI $29,1
- +#define CP0_DTAGHI $29,2
- +#define CP0_L23TAGHI $29,4
- +#define CP0_L23DATAHI $29,5
- #define CP0_ERROREPC $30
- #define CP0_DESAVE $31
-
- @@ -395,6 +417,12 @@
- #define CAUSEF_BD (_ULCAST_(1) << 31)
-
- /*
- + * Bits in the coprocessor 0 EBase register.
- + */
- +#define EBASEB_CPUNUM 0
- +#define EBASEF_CPUNUM (_ULCAST_(1023))
- +
- +/*
- * Bits in the coprocessor 0 config register.
- */
- /* Generic bits. */
- --- a/arch/mips/include/asm/u-boot-mips.h
- +++ b/arch/mips/include/asm/u-boot-mips.h
- @@ -23,3 +23,4 @@ static inline unsigned long image_copy_e
- }
-
- extern int incaip_set_cpuclk(void);
- +extern int arch_cpu_init(void);
- --- a/arch/mips/lib/board.c
- +++ b/arch/mips/lib/board.c
- @@ -33,6 +33,16 @@ static char *failed = "*** failed ***\n"
- */
- const unsigned long mips_io_port_base = -1;
-
- +int __arch_cpu_init(void)
- +{
- + /*
- + * Nothing to do in this dummy implementation
- + */
- + return 0;
- +}
- +int arch_cpu_init(void)
- + __attribute__((weak, alias("__arch_cpu_init")));
- +
- int __board_early_init_f(void)
- {
- /*
- @@ -106,6 +116,7 @@ static int init_baudrate(void)
- typedef int (init_fnc_t)(void);
-
- init_fnc_t *init_sequence[] = {
- + arch_cpu_init,
- board_early_init_f,
- timer_init,
- env_init, /* initialize environment */
- --- /dev/null
- +++ b/board/lantiq/easy50712/Makefile
- @@ -0,0 +1,27 @@
- +#
- +# Copyright (C) 2000-2011 Wolfgang Denk, DENX Software Engineering, wd@denx.de
- +#
- +# SPDX-License-Identifier: GPL-2.0+
- +#
- +
- +include $(TOPDIR)/config.mk
- +
- +LIB = $(obj)lib$(BOARD).o
- +
- +COBJS = $(BOARD).o
- +
- +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
- +OBJS := $(addprefix $(obj),$(COBJS))
- +SOBJS := $(addprefix $(obj),$(SOBJS))
- +
- +$(LIB): $(obj).depend $(OBJS) $(SOBJS)
- + $(call cmd_link_o_target, $(OBJS) $(SOBJS))
- +
- +#########################################################################
- +
- +# defines $(obj).depend target
- +include $(SRCTREE)/rules.mk
- +
- +sinclude $(obj).depend
- +
- +#########################################################################
- --- /dev/null
- +++ b/board/lantiq/easy50712/config.mk
- @@ -0,0 +1,7 @@
- +#
- +# Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- +#
- +# SPDX-License-Identifier: GPL-2.0+
- +#
- +
- +PLATFORM_CPPFLAGS += -I$(TOPDIR)/board/$(BOARDDIR)
- --- /dev/null
- +++ b/board/lantiq/easy50712/ddr_settings.h
- @@ -0,0 +1,54 @@
- +/*
- + * Copyright (C) 2007-2010 Lantiq Deutschland GmbH
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#define MC_DC00_VALUE 0x1B1B
- +#define MC_DC01_VALUE 0x0
- +#define MC_DC02_VALUE 0x0
- +#define MC_DC03_VALUE 0x0
- +#define MC_DC04_VALUE 0x0
- +#define MC_DC05_VALUE 0x200
- +#define MC_DC06_VALUE 0x605
- +#define MC_DC07_VALUE 0x303
- +#define MC_DC08_VALUE 0x102
- +#define MC_DC09_VALUE 0x70a
- +#define MC_DC10_VALUE 0x203
- +#define MC_DC11_VALUE 0xc02
- +#define MC_DC12_VALUE 0x1C8
- +#define MC_DC13_VALUE 0x1
- +#define MC_DC14_VALUE 0x0
- +#define MC_DC15_VALUE 0x13c
- +#define MC_DC16_VALUE 0xC800
- +#define MC_DC17_VALUE 0xd
- +#define MC_DC18_VALUE 0x300
- +#define MC_DC19_VALUE 0x200
- +#define MC_DC20_VALUE 0xA04
- +#define MC_DC21_VALUE 0xd00
- +#define MC_DC22_VALUE 0xd0d
- +#define MC_DC23_VALUE 0x0
- +#define MC_DC24_VALUE 0x62
- +#define MC_DC25_VALUE 0x0
- +#define MC_DC26_VALUE 0x0
- +#define MC_DC27_VALUE 0x0
- +#define MC_DC28_VALUE 0x510
- +#define MC_DC29_VALUE 0x2d89
- +#define MC_DC30_VALUE 0x8300
- +#define MC_DC31_VALUE 0x0
- +#define MC_DC32_VALUE 0x0
- +#define MC_DC33_VALUE 0x0
- +#define MC_DC34_VALUE 0x0
- +#define MC_DC35_VALUE 0x0
- +#define MC_DC36_VALUE 0x0
- +#define MC_DC37_VALUE 0x0
- +#define MC_DC38_VALUE 0x0
- +#define MC_DC39_VALUE 0x0
- +#define MC_DC40_VALUE 0x0
- +#define MC_DC41_VALUE 0x0
- +#define MC_DC42_VALUE 0x0
- +#define MC_DC43_VALUE 0x0
- +#define MC_DC44_VALUE 0x0
- +#define MC_DC45_VALUE 0x500
- +#define MC_DC46_VALUE 0x0
- --- /dev/null
- +++ b/board/lantiq/easy50712/easy50712.c
- @@ -0,0 +1,112 @@
- +/*
- + * Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <switch.h>
- +#include <spi.h>
- +#include <asm/gpio.h>
- +#include <asm/lantiq/eth.h>
- +#include <asm/lantiq/reset.h>
- +#include <asm/lantiq/chipid.h>
- +
- +static void gpio_init(void)
- +{
- + /* SPI/CS output (low-active) for serial flash */
- + gpio_direction_output(22, 1);
- +
- + /* EBU.FL_CS1 as output for NAND CE */
- + gpio_set_altfunc(23, GPIO_ALTSEL_SET, GPIO_ALTSEL_CLR, GPIO_DIR_OUT);
- + /* EBU.FL_A23 as output for NAND CLE */
- + gpio_set_altfunc(24, GPIO_ALTSEL_SET, GPIO_ALTSEL_CLR, GPIO_DIR_OUT);
- + /* EBU.FL_A24 as output for NAND ALE */
- + gpio_set_altfunc(13, GPIO_ALTSEL_SET, GPIO_ALTSEL_CLR, GPIO_DIR_OUT);
- +
- + /* enable CLK_OUT2 for external switch */
- + gpio_set_altfunc(3, GPIO_ALTSEL_SET, GPIO_ALTSEL_CLR, GPIO_DIR_OUT);
- +}
- +
- +int board_early_init_f(void)
- +{
- + gpio_init();
- +
- + return 0;
- +}
- +
- +int checkboard(void)
- +{
- + puts("Board: " CONFIG_BOARD_NAME "\n");
- + ltq_chip_print_info();
- +
- + return 0;
- +}
- +
- +static const struct ltq_eth_port_config eth_port_config[] = {
- + /* MAC0: Lantiq ADM6996I switch */
- + { 0, 0x0, LTQ_ETH_PORT_SWITCH, PHY_INTERFACE_MODE_RMII },
- +};
- +
- +static const struct ltq_eth_board_config eth_board_config = {
- + .ports = eth_port_config,
- + .num_ports = ARRAY_SIZE(eth_port_config),
- +};
- +
- +int board_eth_init(bd_t *bis)
- +{
- + return ltq_eth_initialize(ð_board_config);
- +}
- +
- +static struct switch_device adm6996i_dev = {
- + .name = "adm6996i",
- + .cpu_port = 5,
- + .port_mask = 0xF,
- +};
- +
- +int board_switch_init(void)
- +{
- + /* Deactivate HRST line to release reset of ADM6996I switch */
- + ltq_reset_once(LTQ_RESET_HARD, 200000);
- +
- + /* ADM6996I needs some time to come out of reset */
- + __udelay(50000);
- +
- + return switch_device_register(&adm6996i_dev);
- +}
- +
- +int spi_cs_is_valid(unsigned int bus, unsigned int cs)
- +{
- + if (bus)
- + return 0;
- +
- + switch (cs) {
- + case 2:
- + return 1;
- + default:
- + return 0;
- + }
- +}
- +
- +void spi_cs_activate(struct spi_slave *slave)
- +{
- + switch (slave->cs) {
- + case 2:
- + gpio_set_value(22, 0);
- + break;
- + default:
- + break;
- + }
- +}
- +
- +void spi_cs_deactivate(struct spi_slave *slave)
- +{
- + switch (slave->cs) {
- + case 2:
- + gpio_set_value(22, 1);
- + break;
- + default:
- + break;
- + }
- +}
- --- /dev/null
- +++ b/board/lantiq/easy80920/Makefile
- @@ -0,0 +1,27 @@
- +#
- +# Copyright (C) 2000-2011 Wolfgang Denk, DENX Software Engineering, wd@denx.de
- +#
- +# SPDX-License-Identifier: GPL-2.0+
- +#
- +
- +include $(TOPDIR)/config.mk
- +
- +LIB = $(obj)lib$(BOARD).o
- +
- +COBJS = $(BOARD).o
- +
- +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
- +OBJS := $(addprefix $(obj),$(COBJS))
- +SOBJS := $(addprefix $(obj),$(SOBJS))
- +
- +$(LIB): $(obj).depend $(OBJS) $(SOBJS)
- + $(call cmd_link_o_target, $(OBJS) $(SOBJS))
- +
- +#########################################################################
- +
- +# defines $(obj).depend target
- +include $(SRCTREE)/rules.mk
- +
- +sinclude $(obj).depend
- +
- +#########################################################################
- --- /dev/null
- +++ b/board/lantiq/easy80920/config.mk
- @@ -0,0 +1,7 @@
- +#
- +# Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- +#
- +# SPDX-License-Identifier: GPL-2.0+
- +#
- +
- +PLATFORM_CPPFLAGS += -I$(TOPDIR)/board/$(BOARDDIR)
- --- /dev/null
- +++ b/board/lantiq/easy80920/ddr_settings.h
- @@ -0,0 +1,69 @@
- +/*
- + * Copyright (C) 2007-2010 Lantiq Deutschland GmbH
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#define MC_CCR00_VALUE 0x101
- +#define MC_CCR01_VALUE 0x1000100
- +#define MC_CCR02_VALUE 0x1010000
- +#define MC_CCR03_VALUE 0x101
- +#define MC_CCR04_VALUE 0x1000000
- +#define MC_CCR05_VALUE 0x1000101
- +#define MC_CCR06_VALUE 0x1000100
- +#define MC_CCR07_VALUE 0x1010000
- +#define MC_CCR08_VALUE 0x1000101
- +#define MC_CCR09_VALUE 0x0
- +#define MC_CCR10_VALUE 0x2000100
- +#define MC_CCR11_VALUE 0x2000300
- +#define MC_CCR12_VALUE 0x30000
- +#define MC_CCR13_VALUE 0x202
- +#define MC_CCR14_VALUE 0x7080A0F
- +#define MC_CCR15_VALUE 0x2040F
- +#define MC_CCR16_VALUE 0x40000
- +#define MC_CCR17_VALUE 0x70102
- +#define MC_CCR18_VALUE 0x4020002
- +#define MC_CCR19_VALUE 0x30302
- +#define MC_CCR20_VALUE 0x8000700
- +#define MC_CCR21_VALUE 0x40F020A
- +#define MC_CCR22_VALUE 0x0
- +#define MC_CCR23_VALUE 0xC020000
- +#define MC_CCR24_VALUE 0x4401B04
- +#define MC_CCR25_VALUE 0x0
- +#define MC_CCR26_VALUE 0x0
- +#define MC_CCR27_VALUE 0x6420000
- +#define MC_CCR28_VALUE 0x0
- +#define MC_CCR29_VALUE 0x0
- +#define MC_CCR30_VALUE 0x798
- +#define MC_CCR31_VALUE 0x0
- +#define MC_CCR32_VALUE 0x0
- +#define MC_CCR33_VALUE 0x650000
- +#define MC_CCR34_VALUE 0x200C8
- +#define MC_CCR35_VALUE 0x1D445D
- +#define MC_CCR36_VALUE 0xC8
- +#define MC_CCR37_VALUE 0xC351
- +#define MC_CCR38_VALUE 0x0
- +#define MC_CCR39_VALUE 0x141F04
- +#define MC_CCR40_VALUE 0x142704
- +#define MC_CCR41_VALUE 0x141b42
- +#define MC_CCR42_VALUE 0x141b42
- +#define MC_CCR43_VALUE 0x566504
- +#define MC_CCR44_VALUE 0x566504
- +#define MC_CCR45_VALUE 0x565F17
- +#define MC_CCR46_VALUE 0x565F17
- +#define MC_CCR47_VALUE 0x0
- +#define MC_CCR48_VALUE 0x0
- +#define MC_CCR49_VALUE 0x0
- +#define MC_CCR50_VALUE 0x0
- +#define MC_CCR51_VALUE 0x0
- +#define MC_CCR52_VALUE 0x133
- +#define MC_CCR53_VALUE 0xF3014B27
- +#define MC_CCR54_VALUE 0xF3014B27
- +#define MC_CCR55_VALUE 0xF3014B27
- +#define MC_CCR56_VALUE 0xF3014B27
- +#define MC_CCR57_VALUE 0x7800301
- +#define MC_CCR58_VALUE 0x7800301
- +#define MC_CCR59_VALUE 0x7800301
- +#define MC_CCR60_VALUE 0x7800301
- +#define MC_CCR61_VALUE 0x4
- --- /dev/null
- +++ b/board/lantiq/easy80920/easy80920.c
- @@ -0,0 +1,138 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <spi.h>
- +#include <asm/gpio.h>
- +#include <asm/lantiq/eth.h>
- +#include <asm/lantiq/chipid.h>
- +#include <asm/lantiq/cpu.h>
- +#include <asm/arch/gphy.h>
- +
- +#if defined(CONFIG_SPL_BUILD)
- +#define do_gpio_init 1
- +#define do_pll_init 1
- +#define do_dcdc_init 0
- +#elif defined(CONFIG_SYS_BOOT_RAM)
- +#define do_gpio_init 1
- +#define do_pll_init 0
- +#define do_dcdc_init 1
- +#elif defined(CONFIG_SYS_BOOT_NOR)
- +#define do_gpio_init 1
- +#define do_pll_init 1
- +#define do_dcdc_init 1
- +#else
- +#define do_gpio_init 0
- +#define do_pll_init 0
- +#define do_dcdc_init 1
- +#endif
- +
- +static void gpio_init(void)
- +{
- + /* SPI CS 0.4 to serial flash */
- + gpio_direction_output(10, 1);
- +
- + /* EBU.FL_CS1 as output for NAND CE */
- + gpio_set_altfunc(23, GPIO_ALTSEL_SET, GPIO_ALTSEL_CLR, GPIO_DIR_OUT);
- + /* EBU.FL_A23 as output for NAND CLE */
- + gpio_set_altfunc(24, GPIO_ALTSEL_SET, GPIO_ALTSEL_CLR, GPIO_DIR_OUT);
- + /* EBU.FL_A24 as output for NAND ALE */
- + gpio_set_altfunc(13, GPIO_ALTSEL_SET, GPIO_ALTSEL_CLR, GPIO_DIR_OUT);
- + /* GPIO 3.0 as input for NAND Ready Busy */
- + gpio_set_altfunc(48, GPIO_ALTSEL_SET, GPIO_ALTSEL_CLR, GPIO_DIR_IN);
- + /* GPIO 3.1 as output for NAND Read */
- + gpio_set_altfunc(49, GPIO_ALTSEL_SET, GPIO_ALTSEL_CLR, GPIO_DIR_OUT);
- +}
- +
- +int board_early_init_f(void)
- +{
- + if (do_gpio_init)
- + gpio_init();
- +
- + if (do_pll_init)
- + ltq_pll_init();
- +
- + if (do_dcdc_init)
- + ltq_dcdc_init(0x7F);
- +
- + return 0;
- +}
- +
- +int checkboard(void)
- +{
- + puts("Board: " CONFIG_BOARD_NAME "\n");
- + ltq_chip_print_info();
- +
- + return 0;
- +}
- +
- +static const struct ltq_eth_port_config eth_port_config[] = {
- + /* GMAC0: external Lantiq PEF7071 10/100/1000 PHY for LAN port 0 */
- + { 0, 0x0, LTQ_ETH_PORT_PHY, PHY_INTERFACE_MODE_RGMII },
- + /* GMAC1: external Lantiq PEF7071 10/100/1000 PHY for LAN port 1 */
- + { 1, 0x1, LTQ_ETH_PORT_PHY, PHY_INTERFACE_MODE_RGMII },
- + /* GMAC2: internal GPHY0 with 10/100/1000 firmware for LAN port 2 */
- + { 2, 0x11, LTQ_ETH_PORT_PHY, PHY_INTERFACE_MODE_GMII },
- + /* GMAC3: unused */
- + { 3, 0x0, LTQ_ETH_PORT_NONE, PHY_INTERFACE_MODE_NONE },
- + /* GMAC4: internal GPHY1 with 10/100/1000 firmware for LAN port 3 */
- + { 4, 0x13, LTQ_ETH_PORT_PHY, PHY_INTERFACE_MODE_GMII },
- + /* GMAC5: external Lantiq PEF7071 10/100/1000 PHY for WANoE port */
- + { 5, 0x5, LTQ_ETH_PORT_PHY, PHY_INTERFACE_MODE_RGMII },
- +};
- +
- +static const struct ltq_eth_board_config eth_board_config = {
- + .ports = eth_port_config,
- + .num_ports = ARRAY_SIZE(eth_port_config),
- +};
- +
- +int board_eth_init(bd_t * bis)
- +{
- + const enum ltq_gphy_clk clk = LTQ_GPHY_CLK_25MHZ_PLL0;
- + const ulong fw_addr = 0x80FF0000;
- +
- + ltq_gphy_phy11g_a1x_load(fw_addr);
- +
- + ltq_cgu_gphy_clk_src(clk);
- +
- + ltq_rcu_gphy_boot(0, fw_addr);
- + ltq_rcu_gphy_boot(1, fw_addr);
- +
- + return ltq_eth_initialize(ð_board_config);
- +}
- +
- +int spi_cs_is_valid(unsigned int bus, unsigned int cs)
- +{
- + if (bus)
- + return 0;
- +
- + if (cs == 4)
- + return 1;
- +
- + return 0;
- +}
- +
- +void spi_cs_activate(struct spi_slave *slave)
- +{
- + switch (slave->cs) {
- + case 4:
- + gpio_set_value(10, 0);
- + break;
- + default:
- + break;
- + }
- +}
- +
- +void spi_cs_deactivate(struct spi_slave *slave)
- +{
- + switch (slave->cs) {
- + case 4:
- + gpio_set_value(10, 1);
- + break;
- + default:
- + break;
- + }
- +}
- --- a/boards.cfg
- +++ b/boards.cfg
- @@ -502,10 +502,17 @@ Active mips mips32 au1x0
- Active mips mips32 au1x00 - dbau1x00 dbau1550 dbau1x00:DBAU1550 Thomas Lange <thomas@corelatus.se>
- Active mips mips32 au1x00 - dbau1x00 dbau1550_el dbau1x00:DBAU1550,SYS_LITTLE_ENDIAN Thomas Lange <thomas@corelatus.se>
- Active mips mips32 au1x00 - pb1x00 pb1000 pb1x00:PB1000 -
- +Active mips mips32 danube lantiq easy50712 easy50712_nor easy50712:SYS_BOOT_NOR Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
- +Active mips mips32 danube lantiq easy50712 easy50712_norspl easy50712:SYS_BOOT_NORSPL Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
- +Active mips mips32 danube lantiq easy50712 easy50712_ram easy50712:SYS_BOOT_RAM Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
- Active mips mips32 incaip - incaip incaip - Wolfgang Denk <wd@denx.de>
- Active mips mips32 incaip - incaip incaip_100MHz incaip:CPU_CLOCK_RATE=100000000 Wolfgang Denk <wd@denx.de>
- Active mips mips32 incaip - incaip incaip_133MHz incaip:CPU_CLOCK_RATE=133000000 Wolfgang Denk <wd@denx.de>
- Active mips mips32 incaip - incaip incaip_150MHz incaip:CPU_CLOCK_RATE=150000000 Wolfgang Denk <wd@denx.de>
- +Active mips mips32 vrx200 lantiq easy80920 easy80920_nor easy80920:SYS_BOOT_NOR Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
- +Active mips mips32 vrx200 lantiq easy80920 easy80920_norspl easy80920:SYS_BOOT_NORSPL Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
- +Active mips mips32 vrx200 lantiq easy80920 easy80920_ram easy80920:SYS_BOOT_RAM Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
- +Active mips mips32 vrx200 lantiq easy80920 easy80920_sfspl easy80920:SYS_BOOT_SFSPL Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
- Active mips mips64 - - qemu-mips qemu_mips64 qemu-mips64:SYS_BIG_ENDIAN -
- Active mips mips64 - - qemu-mips qemu_mips64el qemu-mips64:SYS_LITTLE_ENDIAN -
- Active nds32 n1213 ag101 AndesTech adp-ag101 adp-ag101 - Andes <uboot@andestech.com>
- --- a/drivers/dma/Makefile
- +++ b/drivers/dma/Makefile
- @@ -12,6 +12,7 @@ LIB := $(obj)libdma.o
- COBJS-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
- COBJS-$(CONFIG_APBH_DMA) += apbh_dma.o
- COBJS-$(CONFIG_FSL_DMA) += fsl_dma.o
- +COBJS-$(CONFIG_LANTIQ_DMA) += lantiq_dma.o
- COBJS-$(CONFIG_OMAP3_DMA) += omap3_dma.o
-
- COBJS := $(COBJS-y)
- --- /dev/null
- +++ b/drivers/dma/lantiq_dma.c
- @@ -0,0 +1,387 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <malloc.h>
- +#include <watchdog.h>
- +#include <linux/compiler.h>
- +#include <asm/lantiq/io.h>
- +#include <asm/lantiq/dma.h>
- +#include <asm/lantiq/pm.h>
- +#include <asm/lantiq/reset.h>
- +#include <asm/arch/soc.h>
- +#include <asm/processor.h>
- +
- +#define DMA_CTRL_PKTARB (1 << 31)
- +#define DMA_CTRL_MBRSTARB (1 << 30)
- +#define DMA_CTRL_MBRSTCNT_SHIFT 16
- +#define DMA_CTRL_MBRSTCNT_MASK (0x3ff << DMA_CTRL_MBRSTCNT_SHIFT)
- +#define DMA_CTRL_DRB (1 << 8)
- +#define DMA_CTRL_RESET (1 << 0)
- +
- +#define DMA_CPOLL_EN (1 << 31)
- +#define DMA_CPOLL_CNT_SHIFT 4
- +#define DMA_CPOLL_CNT_MASK (0xFFF << DMA_CPOLL_CNT_SHIFT)
- +
- +#define DMA_CCTRL_TXWGT_SHIFT 16
- +#define DMA_CCTRL_TXWGT_MASK (0x3 << DMA_CCTRL_TXWGT_SHIFT)
- +#define DMA_CCTRL_CLASS_SHIFT 9
- +#define DMA_CCTRL_CLASS_MASK (0x3 << DMA_CCTRL_CLASS_SHIFT)
- +#define DMA_CCTRL_RST (1 << 1)
- +#define DMA_CCTRL_ONOFF (1 << 0)
- +
- +#define DMA_PCTRL_TXBL_SHIFT 4
- +#define DMA_PCTRL_TXBL_2WORDS (1 << DMA_PCTRL_TXBL_SHIFT)
- +#define DMA_PCTRL_TXBL_4WORDS (2 << DMA_PCTRL_TXBL_SHIFT)
- +#define DMA_PCTRL_TXBL_8WORDS (3 << DMA_PCTRL_TXBL_SHIFT)
- +#define DMA_PCTRL_RXBL_SHIFT 2
- +#define DMA_PCTRL_RXBL_2WORDS (1 << DMA_PCTRL_RXBL_SHIFT)
- +#define DMA_PCTRL_RXBL_4WORDS (2 << DMA_PCTRL_RXBL_SHIFT)
- +#define DMA_PCTRL_RXBL_8WORDS (3 << DMA_PCTRL_RXBL_SHIFT)
- +#define DMA_PCTRL_TXENDI_SHIFT 10
- +#define DMA_PCTRL_TXENDI_MASK (0x3 << DMA_PCTRL_TXENDI_SHIFT)
- +#define DMA_PCTRL_RXENDI_SHIFT 8
- +#define DMA_PCTRL_RXENDI_MASK (0x3 << DMA_PCTRL_RXENDI_SHIFT)
- +
- +#define DMA_DESC_OWN (1 << 31)
- +#define DMA_DESC_C (1 << 30)
- +#define DMA_DESC_SOP (1 << 29)
- +#define DMA_DESC_EOP (1 << 28)
- +#define DMA_DESC_TX_OFFSET(x) ((x & 0x1f) << 23)
- +#define DMA_DESC_RX_OFFSET(x) ((x & 0x3) << 23)
- +#define DMA_DESC_LENGTH(x) (x & 0xffff)
- +
- +#define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a)))
- +
- +struct ltq_dma_regs {
- + u32 clc; /* Clock control */
- + u32 rsvd0;
- + u32 id; /* Identification */
- + u32 rsvd1;
- + u32 ctrl; /* Control */
- + u32 cpoll; /* Channel polling */
- + u32 cs; /* Channel select */
- + u32 cctrl; /* Channel control */
- + u32 cdba; /* Channel descriptor base address */
- + u32 cdlen; /* Channel descriptor length */
- + u32 cis; /* Channel interrupt status */
- + u32 cie; /* Channel interrupt enable */
- + u32 cgbl; /* Channel global buffer length */
- + u32 cdptnrd; /* Current descriptor pointer */
- + u32 rsvd2[2];
- + u32 ps; /* Port select */
- + u32 pctrl; /* Port control */
- + u32 rsvd3[43];
- + u32 irnen; /* Interrupt node enable */
- + u32 irncr; /* Interrupt node control */
- + u32 irnicr; /* Interrupt capture */
- +};
- +
- +static struct ltq_dma_regs *ltq_dma_regs =
- + (struct ltq_dma_regs *) CKSEG1ADDR(LTQ_DMA_BASE);
- +
- +static inline unsigned long ltq_dma_addr_to_virt(u32 dma_addr)
- +{
- + return KSEG0ADDR(dma_addr);
- +}
- +
- +static inline u32 ltq_virt_to_dma_addr(void *addr)
- +{
- + return CPHYSADDR(addr);
- +}
- +
- +static inline int ltq_dma_burst_align(enum ltq_dma_burst_len burst_len)
- +{
- + switch (burst_len) {
- + case LTQ_DMA_BURST_2WORDS:
- + return 2 * 4;
- + case LTQ_DMA_BURST_4WORDS:
- + return 4 * 4;
- + case LTQ_DMA_BURST_8WORDS:
- + return 8 * 4;
- + }
- +
- + return 0;
- +}
- +
- +static inline void ltq_dma_sync(void)
- +{
- + __asm__ __volatile__("sync");
- +}
- +
- +static inline void ltq_dma_dcache_wb_inv(const void *ptr, size_t size)
- +{
- + unsigned long addr = (unsigned long) ptr;
- +
- + flush_dcache_range(addr, addr + size);
- + ltq_dma_sync();
- +}
- +
- +static inline void ltq_dma_dcache_inv(const void *ptr, size_t size)
- +{
- + unsigned long addr = (unsigned long) ptr;
- +
- + invalidate_dcache_range(addr, addr + size);
- +}
- +
- +void ltq_dma_init(void)
- +{
- + /* Power up DMA */
- + ltq_pm_enable(LTQ_PM_DMA);
- +
- + /* Reset DMA */
- + ltq_setbits(<q_dma_regs->ctrl, DMA_CTRL_RESET);
- +
- + /* Disable and clear all interrupts */
- + ltq_writel(<q_dma_regs->irnen, 0);
- + ltq_writel(<q_dma_regs->irncr, 0xFFFFF);
- +
- +#if 0
- + /* Enable packet arbitration */
- + ltq_setbits(<q_dma_regs->ctrl, DMA_CTRL_PKTARB);
- +#endif
- +
- +#if 0
- + /* Enable descriptor read back */
- + ltq_setbits(<q_dma_regs->ctrl, DMA_CTRL_DRB);
- +#endif
- +
- + /* Enable polling for descriptor fetching for all channels */
- + ltq_writel(<q_dma_regs->cpoll, DMA_CPOLL_EN |
- + (4 << DMA_CPOLL_CNT_SHIFT));
- +}
- +
- +static void ltq_dma_channel_reset(struct ltq_dma_channel *chan)
- +{
- + ltq_writel(<q_dma_regs->cs, chan->chan_no);
- + ltq_setbits(<q_dma_regs->cctrl, DMA_CCTRL_RST);
- +}
- +
- +static void ltq_dma_channel_enable(struct ltq_dma_channel *chan)
- +{
- + ltq_writel(<q_dma_regs->cs, chan->chan_no);
- + ltq_setbits(<q_dma_regs->cctrl, DMA_CCTRL_ONOFF);
- +}
- +
- +static void ltq_dma_channel_disable(struct ltq_dma_channel *chan)
- +{
- + ltq_writel(<q_dma_regs->cs, chan->chan_no);
- + ltq_clrbits(<q_dma_regs->cctrl, DMA_CCTRL_ONOFF);
- +}
- +
- +static void ltq_dma_port_init(struct ltq_dma_device *dev)
- +{
- + u32 pctrl;
- +
- + pctrl = dev->tx_endian_swap << DMA_PCTRL_TXENDI_SHIFT;
- + pctrl |= dev->rx_endian_swap << DMA_PCTRL_RXENDI_SHIFT;
- + pctrl |= dev->tx_burst_len << DMA_PCTRL_TXBL_SHIFT;
- + pctrl |= dev->rx_burst_len << DMA_PCTRL_RXBL_SHIFT;
- +
- + ltq_writel(<q_dma_regs->ps, dev->port);
- + ltq_writel(<q_dma_regs->pctrl, pctrl);
- +}
- +
- +static int ltq_dma_alloc_descriptors(struct ltq_dma_device *dev,
- + struct ltq_dma_channel *chan)
- +{
- + size_t size;
- + void *desc_base;
- +
- + size = ALIGN(sizeof(struct ltq_dma_desc) * chan->num_desc +
- + ARCH_DMA_MINALIGN, ARCH_DMA_MINALIGN);
- +
- + chan->mem_base = malloc(size);
- + if (!chan->mem_base)
- + return 1;
- +
- + memset(chan->mem_base, 0, size);
- + ltq_dma_dcache_wb_inv(chan->mem_base, size);
- +
- + desc_base = PTR_ALIGN(chan->mem_base, ARCH_DMA_MINALIGN);
- +
- + debug("DMA: mem %p, desc %p\n", chan->mem_base, desc_base);
- +
- + /* Align descriptor base to 8 bytes */
- + chan->desc_base = (void *) CKSEG1ADDR(desc_base);
- + chan->dma_addr = CPHYSADDR(desc_base);
- + chan->dev = dev;
- +
- + debug("DMA: desc_base %p, size %u\n", chan->desc_base, size);
- +
- + /* Configure hardware with location of descriptor list */
- + ltq_writel(<q_dma_regs->cs, chan->chan_no);
- + ltq_writel(<q_dma_regs->cdba, chan->dma_addr);
- + ltq_writel(<q_dma_regs->cdlen, chan->num_desc);
- + ltq_writel(<q_dma_regs->cctrl, (3 << DMA_CCTRL_TXWGT_SHIFT) |
- + (chan->class << DMA_CCTRL_CLASS_SHIFT));
- + ltq_writel(<q_dma_regs->cctrl, DMA_CCTRL_RST);
- +
- + return 0;
- +}
- +
- +static void ltq_dma_free_descriptors(struct ltq_dma_channel *chan)
- +{
- + ltq_writel(<q_dma_regs->cs, chan->chan_no);
- + ltq_writel(<q_dma_regs->cdba, 0);
- + ltq_writel(<q_dma_regs->cdlen, 0);
- +
- + ltq_dma_channel_reset(chan);
- +
- + free(chan->mem_base);
- +}
- +
- +int ltq_dma_register(struct ltq_dma_device *dev)
- +{
- + int ret;
- +
- + ltq_dma_port_init(dev);
- +
- + ret = ltq_dma_alloc_descriptors(dev, &dev->rx_chan);
- + if (ret)
- + return ret;
- +
- + ret = ltq_dma_alloc_descriptors(dev, &dev->tx_chan);
- + if (ret) {
- + ltq_dma_free_descriptors(&dev->rx_chan);
- + return ret;
- + }
- +
- + return 0;
- +}
- +
- +void ltq_dma_reset(struct ltq_dma_device *dev)
- +{
- + ltq_dma_channel_reset(&dev->rx_chan);
- + ltq_dma_channel_reset(&dev->tx_chan);
- +}
- +
- +void ltq_dma_enable(struct ltq_dma_device *dev)
- +{
- + ltq_dma_channel_enable(&dev->rx_chan);
- + ltq_dma_channel_enable(&dev->tx_chan);
- +}
- +
- +void ltq_dma_disable(struct ltq_dma_device *dev)
- +{
- + ltq_dma_channel_disable(&dev->rx_chan);
- + ltq_dma_channel_disable(&dev->tx_chan);
- +}
- +
- +int ltq_dma_rx_map(struct ltq_dma_device *dev, int index, void *data, int len)
- +{
- + struct ltq_dma_channel *chan = &dev->rx_chan;
- + struct ltq_dma_desc *desc = &chan->desc_base[index];
- + u32 dma_addr = ltq_virt_to_dma_addr(data);
- + unsigned int offset;
- +
- + offset = dma_addr % ltq_dma_burst_align(dev->rx_burst_len);
- +
- + ltq_dma_dcache_inv(data, len);
- +
- +#if 0
- + printf("%s: index %d, data %p, dma_addr %08x, offset %u, len %d\n",
- + __func__, index, data, dma_addr, offset, len);
- +#endif
- +
- +
- + desc->addr = dma_addr - offset;
- + desc->ctl = DMA_DESC_OWN | DMA_DESC_RX_OFFSET(offset) |
- + DMA_DESC_LENGTH(len);
- +
- +#if 0
- + printf("%s: index %d, desc %p, desc->ctl %08x\n",
- + __func__, index, desc, desc->ctl);
- +#endif
- +
- + return 0;
- +}
- +
- +int ltq_dma_rx_poll(struct ltq_dma_device *dev, int index)
- +{
- + struct ltq_dma_channel *chan = &dev->rx_chan;
- + struct ltq_dma_desc *desc = &chan->desc_base[index];
- +
- +#if 0
- + printf("%s: index %d, desc %p, desc->ctl %08x\n",
- + __func__, index, desc, desc->ctl);
- +#endif
- +
- + if (desc->ctl & DMA_DESC_OWN)
- + return 0;
- +
- + if (desc->ctl & DMA_DESC_C)
- + return 1;
- +
- + return 0;
- +}
- +
- +int ltq_dma_rx_length(struct ltq_dma_device *dev, int index)
- +{
- + struct ltq_dma_channel *chan = &dev->rx_chan;
- + struct ltq_dma_desc *desc = &chan->desc_base[index];
- +
- + return DMA_DESC_LENGTH(desc->ctl);
- +}
- +
- +int ltq_dma_tx_map(struct ltq_dma_device *dev, int index, void *data, int len,
- + unsigned long timeout)
- +{
- + struct ltq_dma_channel *chan = &dev->tx_chan;
- + struct ltq_dma_desc *desc = &chan->desc_base[index];
- + unsigned int offset;
- + unsigned long timebase = get_timer(0);
- + u32 dma_addr = ltq_virt_to_dma_addr(data);
- +
- + while (desc->ctl & DMA_DESC_OWN) {
- + WATCHDOG_RESET();
- +
- + if (get_timer(timebase) >= timeout) {
- +#if 0
- + printf("%s: timeout: index %d, desc %p, desc->ctl %08x\n",
- + __func__, index, desc, desc->ctl);
- +#endif
- + return -1;
- + }
- + }
- +
- + offset = dma_addr % ltq_dma_burst_align(dev->rx_burst_len);
- +
- +#if 0
- + printf("%s: index %d, desc %p, data %p, dma_addr %08x, offset %u, len %d\n",
- + __func__, index, desc, data, dma_addr, offset, len);
- +#endif
- +
- + ltq_dma_dcache_wb_inv(data, len);
- +
- + desc->addr = dma_addr - offset;
- + desc->ctl = DMA_DESC_OWN | DMA_DESC_SOP | DMA_DESC_EOP |
- + DMA_DESC_TX_OFFSET(offset) | DMA_DESC_LENGTH(len);
- +
- +#if 0
- + printf("%s: index %d, desc %p, desc->ctl %08x\n",
- + __func__, index, desc, desc->ctl);
- +#endif
- +
- + return 0;
- +}
- +
- +int ltq_dma_tx_wait(struct ltq_dma_device *dev, int index,
- + unsigned long timeout)
- +{
- + struct ltq_dma_channel *chan = &dev->tx_chan;
- + struct ltq_dma_desc *desc = &chan->desc_base[index];
- + unsigned long timebase = get_timer(0);
- +
- + while ((desc->ctl & (DMA_DESC_OWN | DMA_DESC_C)) != DMA_DESC_C) {
- + WATCHDOG_RESET();
- +
- + if (get_timer(timebase) >= timeout)
- + return -1;
- + }
- +
- + return 0;
- +}
- --- a/drivers/gpio/Makefile
- +++ b/drivers/gpio/Makefile
- @@ -12,6 +12,7 @@ LIB := $(obj)libgpio.o
- COBJS-$(CONFIG_AT91_GPIO) += at91_gpio.o
- COBJS-$(CONFIG_INTEL_ICH6_GPIO) += intel_ich6_gpio.o
- COBJS-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o
- +COBJS-$(CONFIG_LANTIQ_GPIO) += lantiq_gpio.o
- COBJS-$(CONFIG_MARVELL_GPIO) += mvgpio.o
- COBJS-$(CONFIG_MARVELL_MFP) += mvmfp.o
- COBJS-$(CONFIG_MXC_GPIO) += mxc_gpio.o
- --- /dev/null
- +++ b/drivers/gpio/lantiq_gpio.c
- @@ -0,0 +1,329 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <asm/arch/soc.h>
- +#include <asm/arch/gpio.h>
- +#include <asm/lantiq/io.h>
- +
- +#define SSIO_GPIO_BASE 64
- +
- +#define SSIO_CON0_SWU (1 << 31)
- +#define SSIO_CON0_RZFL (1 << 26)
- +#define SSIO_CON0_GPHY1_SHIFT 27
- +#define SSIO_CON0_GPHY1_CONFIG ((CONFIG_LTQ_SSIO_GPHY1_MODE & 0x7) << 27)
- +
- +#define SSIO_CON1_US_FPI (2 << 30)
- +#define SSIO_CON1_FPID_2HZ (0 << 23)
- +#define SSIO_CON1_FPID_4HZ (1 << 23)
- +#define SSIO_CON1_FPID_8HZ (2 << 23)
- +#define SSIO_CON1_FPID_10HZ (3 << 23)
- +#define SSIO_CON1_FPIS_1_2 (1 << 20)
- +#define SSIO_CON1_FPIS_1_32 (2 << 20)
- +#define SSIO_CON1_FPIS_1_64 (3 << 20)
- +
- +#define SSIO_CON1_GPHY2_SHIFT 15
- +#define SSIO_CON1_GPHY2_CONFIG ((CONFIG_LTQ_SSIO_GPHY2_MODE & 0x7) << 15)
- +
- +#define SSIO_CON1_GROUP2 (1 << 2)
- +#define SSIO_CON1_GROUP1 (1 << 1)
- +#define SSIO_CON1_GROUP0 (1 << 0)
- +#define SSIO_CON1_GROUP_CONFIG (0x3)
- +
- +#ifdef CONFIG_LTQ_SSIO_SHIFT_REGS
- +#define enable_ssio 1
- +#else
- +#define enable_ssio 0
- +
- +#define CONFIG_LTQ_SSIO_GPHY1_MODE 0
- +#define CONFIG_LTQ_SSIO_GPHY2_MODE 0
- +#define CONFIG_LTQ_SSIO_INIT_VALUE 0
- +#endif
- +
- +#ifdef CONFIG_LTQ_SSIO_EDGE_FALLING
- +#define SSIO_RZFL_CONFIG SSIO_CON0_RZFL
- +#else
- +#define SSIO_RZFL_CONFIG 0
- +#endif
- +
- +struct ltq_gpio_port_regs {
- + __be32 out;
- + __be32 in;
- + __be32 dir;
- + __be32 altsel0;
- + __be32 altsel1;
- + __be32 od;
- + __be32 stoff;
- + __be32 pudsel;
- + __be32 puden;
- + __be32 rsvd1[3];
- +};
- +
- +struct ltq_gpio_regs {
- + u32 rsvd[4];
- + struct ltq_gpio_port_regs ports[CONFIG_LTQ_GPIO_MAX_BANKS];
- +};
- +
- +struct ltq_gpio3_regs {
- + u32 rsvd0[13];
- + __be32 od;
- + __be32 pudsel;
- + __be32 puden;
- + u32 rsvd1[9];
- + __be32 altsel1;
- + u32 rsvd2[14];
- + __be32 out;
- + __be32 in;
- + __be32 dir;
- + __be32 altsel0;
- +};
- +
- +struct ltq_ssio_regs {
- + __be32 con0;
- + __be32 con1;
- + __be32 cpu0;
- + __be32 cpu1;
- + __be32 ar;
- +};
- +
- +static struct ltq_gpio_regs *ltq_gpio_regs =
- + (struct ltq_gpio_regs *) CKSEG1ADDR(LTQ_GPIO_BASE);
- +
- +static struct ltq_gpio3_regs *ltq_gpio3_regs =
- + (struct ltq_gpio3_regs *) CKSEG1ADDR(LTQ_GPIO_BASE);
- +
- +static struct ltq_ssio_regs *ltq_ssio_regs =
- + (struct ltq_ssio_regs *) CKSEG1ADDR(LTQ_SSIO_BASE);
- +
- +static int is_gpio_bank3(unsigned int port)
- +{
- +#ifdef CONFIG_LTQ_HAS_GPIO_BANK3
- + return port == 3;
- +#else
- + return 0;
- +#endif
- +}
- +
- +static int is_gpio_ssio(unsigned int gpio)
- +{
- +#ifdef CONFIG_LTQ_SSIO_SHIFT_REGS
- + return gpio >= SSIO_GPIO_BASE;
- +#else
- + return 0;
- +#endif
- +}
- +
- +static inline int ssio_gpio_to_bit(unsigned gpio)
- +{
- + return 1 << (gpio - SSIO_GPIO_BASE);
- +}
- +
- +int ltq_gpio_init(void)
- +{
- + ltq_writel(<q_ssio_regs->ar, 0);
- + ltq_writel(<q_ssio_regs->cpu0, CONFIG_LTQ_SSIO_INIT_VALUE);
- + ltq_writel(<q_ssio_regs->cpu1, 0);
- + ltq_writel(<q_ssio_regs->con0, SSIO_CON0_SWU);
- +
- + if (enable_ssio) {
- + ltq_writel(<q_ssio_regs->con0, SSIO_CON0_GPHY1_CONFIG |
- + SSIO_RZFL_CONFIG);
- + ltq_writel(<q_ssio_regs->con1, SSIO_CON1_US_FPI |
- + SSIO_CON1_FPID_8HZ | SSIO_CON1_GPHY2_CONFIG |
- + SSIO_CON1_GROUP_CONFIG);
- + }
- +
- + return 0;
- +}
- +
- +int gpio_request(unsigned gpio, const char *label)
- +{
- + return 0;
- +}
- +
- +int gpio_free(unsigned gpio)
- +{
- + return 0;
- +}
- +
- +int gpio_direction_input(unsigned gpio)
- +{
- + unsigned port = gpio_to_port(gpio);
- + const void *gpio_od = <q_gpio_regs->ports[port].od;
- + const void *gpio_altsel0 = <q_gpio_regs->ports[port].altsel0;
- + const void *gpio_altsel1 = <q_gpio_regs->ports[port].altsel1;
- + const void *gpio_dir = <q_gpio_regs->ports[port].dir;
- +
- + if (is_gpio_ssio(gpio))
- + return 0;
- +
- + if (is_gpio_bank3(port)) {
- + gpio_od = <q_gpio3_regs->od;
- + gpio_altsel0 = <q_gpio3_regs->altsel0;
- + gpio_altsel1 = <q_gpio3_regs->altsel1;
- + gpio_dir = <q_gpio3_regs->dir;
- + }
- +
- + /*
- + * Reset open drain and altsel configs to workaround improper
- + * reset values or unwanted modifications by BootROM
- + */
- + ltq_clrbits(gpio_od, gpio_to_bit(gpio));
- + ltq_clrbits(gpio_altsel0, gpio_to_bit(gpio));
- + ltq_clrbits(gpio_altsel1, gpio_to_bit(gpio));
- +
- + /* Switch to input */
- + ltq_clrbits(gpio_dir, gpio_to_bit(gpio));
- +
- + return 0;
- +}
- +
- +int gpio_direction_output(unsigned gpio, int value)
- +{
- + unsigned port = gpio_to_port(gpio);
- + const void *gpio_od = <q_gpio_regs->ports[port].od;
- + const void *gpio_altsel0 = <q_gpio_regs->ports[port].altsel0;
- + const void *gpio_altsel1 = <q_gpio_regs->ports[port].altsel1;
- + const void *gpio_dir = <q_gpio_regs->ports[port].dir;
- + const void *gpio_out = <q_gpio_regs->ports[port].out;
- + u32 data = gpio_to_bit(gpio);
- +
- + if (is_gpio_ssio(gpio)) {
- + data = ssio_gpio_to_bit(gpio);
- + if (value)
- + ltq_setbits(<q_ssio_regs->cpu0, data);
- + else
- + ltq_clrbits(<q_ssio_regs->cpu0, data);
- +
- + return 0;
- + }
- +
- + if (is_gpio_bank3(port)) {
- + gpio_od = <q_gpio3_regs->od;
- + gpio_altsel0 = <q_gpio3_regs->altsel0;
- + gpio_altsel1 = <q_gpio3_regs->altsel1;
- + gpio_dir = <q_gpio3_regs->dir;
- + gpio_out = <q_gpio3_regs->out;
- + }
- +
- + /*
- + * Reset open drain and altsel configs to workaround improper
- + * reset values or unwanted modifications by BootROM
- + */
- + ltq_setbits(gpio_od, data);
- + ltq_clrbits(gpio_altsel0, data);
- + ltq_clrbits(gpio_altsel1, data);
- +
- + if (value)
- + ltq_setbits(gpio_out, data);
- + else
- + ltq_clrbits(gpio_out, data);
- +
- + /* Switch to output */
- + ltq_setbits(gpio_dir, data);
- +
- + return 0;
- +}
- +
- +int gpio_get_value(unsigned gpio)
- +{
- + unsigned port = gpio_to_port(gpio);
- + const void *gpio_in = <q_gpio_regs->ports[port].in;
- + u32 data = gpio_to_bit(gpio);
- + u32 val;
- +
- + if (is_gpio_ssio(gpio)) {
- + gpio_in = <q_ssio_regs->cpu0;
- + data = ssio_gpio_to_bit(gpio);
- + }
- +
- + if (is_gpio_bank3(port))
- + gpio_in = <q_gpio3_regs->in;
- +
- + val = ltq_readl(gpio_in);
- +
- + return !!(val & data);
- +}
- +
- +int gpio_set_value(unsigned gpio, int value)
- +{
- + unsigned port = gpio_to_port(gpio);
- + const void *gpio_out = <q_gpio_regs->ports[port].out;
- + u32 data = gpio_to_bit(gpio);
- +
- + if (is_gpio_ssio(gpio)) {
- + gpio_out = <q_ssio_regs->cpu0;
- + data = ssio_gpio_to_bit(gpio);
- + }
- +
- + if (is_gpio_bank3(port))
- + gpio_out = <q_gpio3_regs->out;
- +
- + if (value)
- + ltq_setbits(gpio_out, data);
- + else
- + ltq_clrbits(gpio_out, data);
- +
- + return 0;
- +}
- +
- +int gpio_set_altfunc(unsigned gpio, int altsel0, int altsel1, int dir)
- +{
- + unsigned port = gpio_to_port(gpio);
- + const void *gpio_od = <q_gpio_regs->ports[port].od;
- + const void *gpio_altsel0 = <q_gpio_regs->ports[port].altsel0;
- + const void *gpio_altsel1 = <q_gpio_regs->ports[port].altsel1;
- + const void *gpio_dir = <q_gpio_regs->ports[port].dir;
- +
- + if (is_gpio_ssio(gpio))
- + return 0;
- +
- + if (is_gpio_bank3(port)) {
- + gpio_od = <q_gpio3_regs->od;
- + gpio_altsel0 = <q_gpio3_regs->altsel0;
- + gpio_altsel1 = <q_gpio3_regs->altsel1;
- + gpio_dir = <q_gpio3_regs->dir;
- + }
- +
- + if (altsel0)
- + ltq_setbits(gpio_altsel0, gpio_to_bit(gpio));
- + else
- + ltq_clrbits(gpio_altsel0, gpio_to_bit(gpio));
- +
- + if (altsel1)
- + ltq_setbits(gpio_altsel1, gpio_to_bit(gpio));
- + else
- + ltq_clrbits(gpio_altsel1, gpio_to_bit(gpio));
- +
- + if (dir) {
- + ltq_setbits(gpio_od, gpio_to_bit(gpio));
- + ltq_setbits(gpio_dir, gpio_to_bit(gpio));
- + } else {
- + ltq_clrbits(gpio_od, gpio_to_bit(gpio));
- + ltq_clrbits(gpio_dir, gpio_to_bit(gpio));
- + }
- +
- + return 0;
- +}
- +
- +int gpio_set_opendrain(unsigned gpio, int od)
- +{
- + unsigned port = gpio_to_port(gpio);
- + const void *gpio_od = <q_gpio_regs->ports[port].od;
- +
- + if (is_gpio_ssio(gpio))
- + return 0;
- +
- + if (is_gpio_bank3(port))
- + gpio_od = <q_gpio3_regs->od;
- +
- + if (od)
- + ltq_setbits(gpio_od, gpio_to_bit(gpio));
- + else
- + ltq_clrbits(gpio_od, gpio_to_bit(gpio));
- +
- + return 0;
- +}
- --- a/drivers/mtd/cfi_flash.c
- +++ b/drivers/mtd/cfi_flash.c
- @@ -161,6 +161,18 @@ u64 flash_read64(void *addr)__attribute_
- #define flash_read64 __flash_read64
- #endif
-
- +static inline void *__flash_swap_addr(unsigned long addr)
- +{
- + return (void *) addr;
- +}
- +
- +#ifdef CONFIG_CFI_FLASH_USE_WEAK_ADDR_SWAP
- +void *flash_swap_addr(unsigned long addr)
- + __attribute__((weak, alias("__flash_swap_addr")));
- +#else
- +#define flash_swap_addr __flash_swap_addr
- +#endif
- +
- /*-----------------------------------------------------------------------
- */
- #if defined(CONFIG_ENV_IS_IN_FLASH) || defined(CONFIG_ENV_ADDR_REDUND) || (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE)
- @@ -196,7 +208,7 @@ flash_map (flash_info_t * info, flash_se
- {
- unsigned int byte_offset = offset * info->portwidth;
-
- - return (void *)(info->start[sect] + byte_offset);
- + return flash_swap_addr(info->start[sect] + byte_offset);
- }
-
- static inline void flash_unmap(flash_info_t *info, flash_sect_t sect,
- --- a/drivers/mtd/nand/Makefile
- +++ b/drivers/mtd/nand/Makefile
- @@ -53,6 +53,7 @@ COBJS-$(CONFIG_NAND_JZ4740) += jz4740_na
- COBJS-$(CONFIG_NAND_KB9202) += kb9202_nand.o
- COBJS-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o
- COBJS-$(CONFIG_NAND_KMETER1) += kmeter1_nand.o
- +COBJS-$(CONFIG_NAND_LANTIQ) += lantiq_nand.o
- COBJS-$(CONFIG_NAND_MPC5121_NFC) += mpc5121_nfc.o
- COBJS-$(CONFIG_NAND_MXC) += mxc_nand.o
- COBJS-$(CONFIG_NAND_MXS) += mxs_nand.o
- --- /dev/null
- +++ b/drivers/mtd/nand/lantiq_nand.c
- @@ -0,0 +1,126 @@
- +/*
- + * Copyright (C) 2012-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <linux/mtd/nand.h>
- +#include <linux/compiler.h>
- +#include <asm/arch/soc.h>
- +#include <asm/arch/nand.h>
- +#include <asm/lantiq/io.h>
- +
- +#define NAND_CON_ECC_ON (1 << 31)
- +#define NAND_CON_LATCH_PRE (1 << 23)
- +#define NAND_CON_LATCH_WP (1 << 22)
- +#define NAND_CON_LATCH_SE (1 << 21)
- +#define NAND_CON_LATCH_CS (1 << 20)
- +#define NAND_CON_LATCH_CLE (1 << 19)
- +#define NAND_CON_LATCH_ALE (1 << 18)
- +#define NAND_CON_OUT_CS1 (1 << 10)
- +#define NAND_CON_IN_CS1 (1 << 8)
- +#define NAND_CON_PRE_P (1 << 7)
- +#define NAND_CON_WP_P (1 << 6)
- +#define NAND_CON_SE_P (1 << 5)
- +#define NAND_CON_CS_P (1 << 4)
- +#define NAND_CON_CLE_P (1 << 3)
- +#define NAND_CON_ALE_P (1 << 2)
- +#define NAND_CON_CSMUX (1 << 1)
- +#define NAND_CON_NANDM (1 << 0)
- +
- +#define NAND_WAIT_WR_C (1 << 3)
- +#define NAND_WAIT_RDBY (1 << 0)
- +
- +#define NAND_CMD_ALE (1 << 2)
- +#define NAND_CMD_CLE (1 << 3)
- +#define NAND_CMD_CS (1 << 4)
- +#define NAND_CMD_SE (1 << 5)
- +#define NAND_CMD_WP (1 << 6)
- +#define NAND_CMD_PRE (1 << 7)
- +
- +struct ltq_nand_regs {
- + __be32 con; /* NAND controller control */
- + __be32 wait; /* NAND Flash Device RD/BY State */
- + __be32 ecc0; /* NAND Flash ECC Register 0 */
- + __be32 ecc_ac; /* NAND Flash ECC Register address counter */
- + __be32 ecc_cr; /* NAND Flash ECC Comparison */
- +};
- +
- +static struct ltq_nand_regs *ltq_nand_regs =
- + (struct ltq_nand_regs *) CKSEG1ADDR(LTQ_EBU_NAND_BASE);
- +
- +static void ltq_nand_wait_ready(void)
- +{
- + while ((ltq_readl(<q_nand_regs->wait) & NAND_WAIT_WR_C) == 0)
- + ;
- +}
- +
- +static int ltq_nand_dev_ready(struct mtd_info *mtd)
- +{
- + u32 data = ltq_readl(<q_nand_regs->wait);
- + return data & NAND_WAIT_RDBY;
- +}
- +
- +static void ltq_nand_select_chip(struct mtd_info *mtd, int chip)
- +{
- + if (chip == 0) {
- + ltq_setbits(<q_nand_regs->con, NAND_CON_NANDM);
- + ltq_setbits(<q_nand_regs->con, NAND_CON_LATCH_CS);
- + } else {
- + ltq_clrbits(<q_nand_regs->con, NAND_CON_LATCH_CS);
- + ltq_clrbits(<q_nand_regs->con, NAND_CON_NANDM);
- + }
- +}
- +
- +static void ltq_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
- +{
- + struct nand_chip *chip = mtd->priv;
- + unsigned long addr = (unsigned long) chip->IO_ADDR_W;
- +
- + if (ctrl & NAND_CTRL_CHANGE) {
- + if (ctrl & NAND_ALE)
- + addr |= NAND_CMD_ALE;
- + else
- + addr &= ~NAND_CMD_ALE;
- +
- + if (ctrl & NAND_CLE)
- + addr |= NAND_CMD_CLE;
- + else
- + addr &= ~NAND_CMD_CLE;
- +
- + chip->IO_ADDR_W = (void __iomem *) addr;
- + }
- +
- + if (cmd != NAND_CMD_NONE) {
- + writeb(cmd, chip->IO_ADDR_W);
- + ltq_nand_wait_ready();
- + }
- +}
- +
- +int ltq_nand_init(struct nand_chip *nand)
- +{
- + /* Enable NAND, set NAND CS to EBU CS1, enable EBU CS mux */
- + ltq_writel(<q_nand_regs->con, NAND_CON_OUT_CS1 | NAND_CON_IN_CS1 |
- + NAND_CON_PRE_P | NAND_CON_WP_P | NAND_CON_SE_P |
- + NAND_CON_CS_P | NAND_CON_CSMUX);
- +
- + nand->dev_ready = ltq_nand_dev_ready;
- + nand->select_chip = ltq_nand_select_chip;
- + nand->cmd_ctrl = ltq_nand_cmd_ctrl;
- +
- + nand->chip_delay = 30;
- + nand->options = 0;
- + nand->ecc.mode = NAND_ECC_SOFT;
- +
- + /* Enable CS bit in address offset */
- + nand->IO_ADDR_R = nand->IO_ADDR_R + NAND_CMD_CS;
- + nand->IO_ADDR_W = nand->IO_ADDR_W + NAND_CMD_CS;
- +
- + return 0;
- +}
- +
- +__weak int board_nand_init(struct nand_chip *chip)
- +{
- + return ltq_nand_init(chip);
- +}
- --- a/drivers/net/Makefile
- +++ b/drivers/net/Makefile
- @@ -37,6 +37,8 @@ COBJS-$(CONFIG_INCA_IP_SWITCH) += inca-i
- COBJS-$(CONFIG_DRIVER_KS8695ETH) += ks8695eth.o
- COBJS-$(CONFIG_KS8851_MLL) += ks8851_mll.o
- COBJS-$(CONFIG_LAN91C96) += lan91c96.o
- +COBJS-$(CONFIG_LANTIQ_DANUBE_ETOP) += lantiq_danube_etop.o
- +COBJS-$(CONFIG_LANTIQ_VRX200_SWITCH) += lantiq_vrx200_switch.o
- COBJS-$(CONFIG_MACB) += macb.o
- COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
- COBJS-$(CONFIG_MPC5xxx_FEC) += mpc5xxx_fec.o
- --- /dev/null
- +++ b/drivers/net/lantiq_danube_etop.c
- @@ -0,0 +1,410 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <malloc.h>
- +#include <netdev.h>
- +#include <miiphy.h>
- +#include <switch.h>
- +#include <asm/lantiq/io.h>
- +#include <asm/lantiq/eth.h>
- +#include <asm/lantiq/pm.h>
- +#include <asm/lantiq/reset.h>
- +#include <asm/lantiq/dma.h>
- +#include <asm/arch/soc.h>
- +
- +#define LTQ_PPE_ETOP_MDIO_ACC_RA (1 << 31)
- +#define LTQ_PPE_ETOP_MDIO_CFG_UMM1 (1 << 2)
- +#define LTQ_PPE_ETOP_MDIO_CFG_UMM0 (1 << 1)
- +
- +#define LTQ_PPE_ETOP_CFG_TCKINV1 (1 << 11)
- +#define LTQ_PPE_ETOP_CFG_TCKINV0 (1 << 10)
- +#define LTQ_PPE_ETOP_CFG_FEN1 (1 << 9)
- +#define LTQ_PPE_ETOP_CFG_FEN0 (1 << 8)
- +#define LTQ_PPE_ETOP_CFG_SEN1 (1 << 7)
- +#define LTQ_PPE_ETOP_CFG_SEN0 (1 << 6)
- +#define LTQ_PPE_ETOP_CFG_TURBO1 (1 << 5)
- +#define LTQ_PPE_ETOP_CFG_REMII1 (1 << 4)
- +#define LTQ_PPE_ETOP_CFG_OFF1 (1 << 3)
- +#define LTQ_PPE_ETOP_CFG_TURBO0 (1 << 2)
- +#define LTQ_PPE_ETOP_CFG_REMII0 (1 << 1)
- +#define LTQ_PPE_ETOP_CFG_OFF0 (1 << 0)
- +
- +#define LTQ_PPE_ENET0_MAC_CFG_CGEN (1 << 11)
- +#define LTQ_PPE_ENET0_MAC_CFG_DUPLEX (1 << 2)
- +#define LTQ_PPE_ENET0_MAC_CFG_SPEED (1 << 1)
- +#define LTQ_PPE_ENET0_MAC_CFG_LINK (1 << 0)
- +
- +#define LTQ_PPE_ENETS0_CFG_FTUC (1 << 28)
- +
- +#define LTQ_ETH_RX_BUFFER_CNT PKTBUFSRX
- +#define LTQ_ETH_TX_BUFFER_CNT 8
- +#define LTQ_ETH_RX_DATA_SIZE PKTSIZE_ALIGN
- +#define LTQ_ETH_IP_ALIGN 2
- +
- +#define LTQ_MDIO_DRV_NAME "ltq-mdio"
- +#define LTQ_ETH_DRV_NAME "ltq-eth"
- +
- +struct ltq_ppe_etop_regs {
- + u32 mdio_cfg; /* MDIO configuration */
- + u32 mdio_acc; /* MDIO access */
- + u32 cfg; /* ETOP configuration */
- + u32 ig_vlan_cos; /* IG VLAN priority CoS mapping */
- + u32 ig_dscp_cos3; /* IG DSCP CoS mapping 3 */
- + u32 ig_dscp_cos2; /* IG DSCP CoS mapping 2 */
- + u32 ig_dscp_cos1; /* IG DSCP CoS mapping 1 */
- + u32 ig_dscp_cos0; /* IG DSCP CoS mapping 0 */
- + u32 ig_plen_ctrl; /* IG frame length control */
- + u32 rsvd0[3];
- + u32 vpid; /* VLAN protocol ID */
- +};
- +
- +struct ltq_ppe_enet_regs {
- + u32 mac_cfg; /* MAC configuration */
- + u32 rsvd0[3];
- + u32 ig_cfg; /* Ingress configuration */
- + u32 ig_pgcnt; /* Ingress buffer used page count */
- + u32 rsvd1;
- + u32 ig_buf_ctrl; /* Ingress buffer backpressure ctrl */
- + u32 cos_cfg; /* Classification configuration */
- + u32 ig_drop; /* Total ingress drop frames */
- + u32 ig_err; /* Total ingress error frames */
- + u32 mac_da0; /* Ingress MAC address 0 */
- + u32 mac_da1; /* Ingress MAC address 1 */
- + u32 rsvd2[22];
- + u32 pgcnt; /* Page counter */
- + u32 rsvd3;
- + u32 hf_ctrl; /* Half duplex control */
- + u32 tx_ctrl; /* Transmit control */
- + u32 rsvd4;
- + u32 vlcos0; /* VLAN insertion config CoS 0 */
- + u32 vlcos1; /* VLAN insertion config CoS 1 */
- + u32 vlcos2; /* VLAN insertion config CoS 2 */
- + u32 vlcos3; /* VLAN insertion config CoS 3 */
- + u32 eg_col; /* Total egress collision frames */
- + u32 eg_drop; /* Total egress drop frames */
- +};
- +
- +struct ltq_eth_priv {
- + struct ltq_dma_device dma_dev;
- + struct mii_dev *bus;
- + struct eth_device *dev;
- + int rx_num;
- + int tx_num;
- +};
- +
- +struct ltq_mdio_access {
- + union {
- + struct {
- + unsigned ra:1;
- + unsigned rw:1;
- + unsigned rsvd:4;
- + unsigned phya:5;
- + unsigned rega:5;
- + unsigned phyd:16;
- + } reg;
- + u32 val;
- + };
- +};
- +
- +static struct ltq_ppe_etop_regs *ltq_ppe_etop_regs =
- + (struct ltq_ppe_etop_regs *) CKSEG1ADDR(LTQ_PPE_ETOP_BASE);
- +
- +static struct ltq_ppe_enet_regs *ltq_ppe_enet0_regs =
- + (struct ltq_ppe_enet_regs *) CKSEG1ADDR(LTQ_PPE_ENET0_BASE);
- +
- +static inline int ltq_mdio_poll(void)
- +{
- + struct ltq_mdio_access acc;
- + unsigned cnt = 10000;
- +
- + while (likely(cnt--)) {
- + acc.val = ltq_readl(<q_ppe_etop_regs->mdio_acc);
- + if (!acc.reg.ra)
- + return 0;
- + }
- +
- + return 1;
- +}
- +
- +static int ltq_mdio_read(struct mii_dev *bus, int addr, int dev_addr,
- + int regnum)
- +{
- + struct ltq_mdio_access acc;
- + int ret;
- +
- + acc.val = 0;
- + acc.reg.ra = 1;
- + acc.reg.rw = 1;
- + acc.reg.phya = addr;
- + acc.reg.rega = regnum;
- +
- + ret = ltq_mdio_poll();
- + if (ret)
- + return ret;
- +
- + ltq_writel(<q_ppe_etop_regs->mdio_acc, acc.val);
- +
- + ret = ltq_mdio_poll();
- + if (ret)
- + return ret;
- +
- + acc.val = ltq_readl(<q_ppe_etop_regs->mdio_acc);
- +
- + return acc.reg.phyd;
- +}
- +
- +static int ltq_mdio_write(struct mii_dev *bus, int addr, int dev_addr,
- + int regnum, u16 val)
- +{
- + struct ltq_mdio_access acc;
- + int ret;
- +
- + acc.val = 0;
- + acc.reg.ra = 1;
- + acc.reg.rw = 0;
- + acc.reg.phya = addr;
- + acc.reg.rega = regnum;
- + acc.reg.phyd = val;
- +
- + ret = ltq_mdio_poll();
- + if (ret)
- + return ret;
- +
- + ltq_writel(<q_ppe_etop_regs->mdio_acc, acc.val);
- +
- + return 0;
- +}
- +
- +static inline void ltq_eth_write_hwaddr(const struct eth_device *dev)
- +{
- + u32 da0, da1;
- +
- + da0 = (dev->enetaddr[0] << 24) + (dev->enetaddr[1] << 16) +
- + (dev->enetaddr[2] << 8) + dev->enetaddr[3];
- + da1 = (dev->enetaddr[4] << 24) + (dev->enetaddr[5] << 16);
- +
- + ltq_writel(<q_ppe_enet0_regs->mac_da0, da0);
- + ltq_writel(<q_ppe_enet0_regs->mac_da1, da1);
- +}
- +
- +static inline u8 *ltq_eth_rx_packet_align(int rx_num)
- +{
- + u8 *packet = (u8 *) NetRxPackets[rx_num];
- +
- + /*
- + * IP header needs
- + */
- + return packet + LTQ_ETH_IP_ALIGN;
- +}
- +
- +static int ltq_eth_init(struct eth_device *dev, bd_t *bis)
- +{
- + struct ltq_eth_priv *priv = dev->priv;
- + struct ltq_dma_device *dma_dev = &priv->dma_dev;
- + int i;
- +
- + ltq_eth_write_hwaddr(dev);
- +
- + for (i = 0; i < LTQ_ETH_RX_BUFFER_CNT; i++)
- + ltq_dma_rx_map(dma_dev, i, ltq_eth_rx_packet_align(i),
- + LTQ_ETH_RX_DATA_SIZE);
- +
- + ltq_dma_enable(dma_dev);
- +
- + priv->rx_num = 0;
- + priv->tx_num = 0;
- +
- + return 0;
- +}
- +
- +static void ltq_eth_halt(struct eth_device *dev)
- +{
- + struct ltq_eth_priv *priv = dev->priv;
- + struct ltq_dma_device *dma_dev = &priv->dma_dev;
- +
- + ltq_dma_reset(dma_dev);
- +}
- +
- +static int ltq_eth_send(struct eth_device *dev, void *packet, int length)
- +{
- + struct ltq_eth_priv *priv = dev->priv;
- + struct ltq_dma_device *dma_dev = &priv->dma_dev;
- + int err;
- +
- + /* Minimum payload length w/ CRC is 60 bytes */
- + if (length < 60)
- + length = 60;
- +
- + err = ltq_dma_tx_map(dma_dev, priv->tx_num, packet, length, 10);
- + if (err) {
- + puts("NET: timeout on waiting for TX descriptor\n");
- + return -1;
- + }
- +
- + priv->tx_num = (priv->tx_num + 1) % LTQ_ETH_TX_BUFFER_CNT;
- +
- + return err;
- +}
- +
- +static int ltq_eth_recv(struct eth_device *dev)
- +{
- + struct ltq_eth_priv *priv = dev->priv;
- + struct ltq_dma_device *dma_dev = &priv->dma_dev;
- + u8 *packet;
- + int len;
- +
- + if (!ltq_dma_rx_poll(dma_dev, priv->rx_num))
- + return 0;
- +
- +#if 0
- + printf("%s: rx_num %d\n", __func__, priv->rx_num);
- +#endif
- +
- + len = ltq_dma_rx_length(dma_dev, priv->rx_num);
- + packet = ltq_eth_rx_packet_align(priv->rx_num);
- +
- +#if 0
- + printf("%s: received: packet %p, len %u, rx_num %d\n",
- + __func__, packet, len, priv->rx_num);
- +#endif
- +
- + if (len)
- + NetReceive(packet, len);
- +
- + ltq_dma_rx_map(dma_dev, priv->rx_num, packet,
- + LTQ_ETH_RX_DATA_SIZE);
- +
- + priv->rx_num = (priv->rx_num + 1) % LTQ_ETH_RX_BUFFER_CNT;
- +
- + return 0;
- +}
- +
- +static void ltq_eth_hw_init(const struct ltq_eth_port_config *port)
- +{
- + u32 data;
- +
- + /* Power up ethernet subsystems */
- + ltq_pm_enable(LTQ_PM_ETH);
- +
- + /* Reset ethernet subsystems */
- + ltq_reset_once(LTQ_RESET_ETH, 1);
- +
- + /* Disable MDIO auto-detection */
- + ltq_clrbits(<q_ppe_etop_regs->mdio_cfg, LTQ_PPE_ETOP_MDIO_CFG_UMM1 |
- + LTQ_PPE_ETOP_MDIO_CFG_UMM0);
- +
- + /* Enable CRC generation, Full Duplex, 100Mbps, Link up */
- + ltq_writel(<q_ppe_enet0_regs->mac_cfg, LTQ_PPE_ENET0_MAC_CFG_CGEN |
- + LTQ_PPE_ENET0_MAC_CFG_DUPLEX |
- + LTQ_PPE_ENET0_MAC_CFG_SPEED |
- + LTQ_PPE_ENET0_MAC_CFG_LINK);
- +
- + /* Reset ETOP cfg and disable all */
- + data = LTQ_PPE_ETOP_CFG_OFF0 | LTQ_PPE_ETOP_CFG_OFF1;
- +
- + /* Enable ENET0, enable store and fetch */
- + data &= ~LTQ_PPE_ETOP_CFG_OFF0;
- + data |= LTQ_PPE_ETOP_CFG_SEN0 | LTQ_PPE_ETOP_CFG_FEN0;
- +
- + if (port->phy_if == PHY_INTERFACE_MODE_RMII)
- + data |= LTQ_PPE_ETOP_CFG_REMII0;
- + else
- + data &= ~LTQ_PPE_ETOP_CFG_REMII0;
- +
- + ltq_writel(<q_ppe_etop_regs->cfg, data);
- +
- + /* Set allowed packet length from 64 bytes to 1518 bytes */
- + ltq_writel(<q_ppe_etop_regs->ig_plen_ctrl, (64 << 16) | 1518);
- +
- + /* Enable filter for unicast packets */
- + ltq_setbits(<q_ppe_enet0_regs->ig_cfg, LTQ_PPE_ENETS0_CFG_FTUC);
- +}
- +
- +int ltq_eth_initialize(const struct ltq_eth_board_config *board_config)
- +{
- + struct eth_device *dev;
- + struct mii_dev *bus;
- + struct ltq_eth_priv *priv;
- + struct ltq_dma_device *dma_dev;
- + const struct ltq_eth_port_config *port = &board_config->ports[0];
- + struct phy_device *phy;
- + struct switch_device *sw;
- + int ret;
- +
- + ltq_dma_init();
- + ltq_eth_hw_init(port);
- +
- + dev = calloc(1, sizeof(*dev));
- + if (!dev)
- + return -1;
- +
- + priv = calloc(1, sizeof(*priv));
- + if (!priv)
- + return -1;
- +
- + bus = mdio_alloc();
- + if (!bus)
- + return -1;
- +
- + sprintf(dev->name, LTQ_ETH_DRV_NAME);
- + dev->priv = priv;
- + dev->init = ltq_eth_init;
- + dev->halt = ltq_eth_halt;
- + dev->recv = ltq_eth_recv;
- + dev->send = ltq_eth_send;
- +
- + sprintf(bus->name, LTQ_MDIO_DRV_NAME);
- + bus->read = ltq_mdio_read;
- + bus->write = ltq_mdio_write;
- + bus->priv = priv;
- +
- + dma_dev = &priv->dma_dev;
- + dma_dev->port = 0;
- + dma_dev->rx_chan.chan_no = 6;
- + dma_dev->rx_chan.class = 3;
- + dma_dev->rx_chan.num_desc = LTQ_ETH_RX_BUFFER_CNT;
- + dma_dev->rx_endian_swap = LTQ_DMA_ENDIANESS_B3_B2_B1_B0;
- + dma_dev->rx_burst_len = LTQ_DMA_BURST_2WORDS;
- + dma_dev->tx_chan.chan_no = 7;
- + dma_dev->tx_chan.class = 3;
- + dma_dev->tx_chan.num_desc = LTQ_ETH_TX_BUFFER_CNT;
- + dma_dev->tx_endian_swap = LTQ_DMA_ENDIANESS_B3_B2_B1_B0;
- + dma_dev->tx_burst_len = LTQ_DMA_BURST_2WORDS;
- +
- + priv->bus = bus;
- + priv->dev = dev;
- +
- + ret = ltq_dma_register(dma_dev);
- + if (ret)
- + return ret;
- +
- + ret = mdio_register(bus);
- + if (ret)
- + return ret;
- +
- + ret = eth_register(dev);
- + if (ret)
- + return ret;
- +
- + if (port->flags & LTQ_ETH_PORT_SWITCH) {
- + sw = switch_connect(bus);
- + if (!sw)
- + return -1;
- +
- + switch_setup(sw);
- + }
- +
- + if (port->flags & LTQ_ETH_PORT_PHY) {
- + phy = phy_connect(bus, port->phy_addr, dev, port->phy_if);
- + if (!phy)
- + return -1;
- +
- + phy_config(phy);
- + }
- +
- + return 0;
- +}
- --- /dev/null
- +++ b/drivers/net/lantiq_vrx200_switch.c
- @@ -0,0 +1,675 @@
- +/*
- + * Copyright (C) 2010-2011 Lantiq Deutschland GmbH
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#define DEBUG
- +
- +#include <common.h>
- +#include <malloc.h>
- +#include <netdev.h>
- +#include <miiphy.h>
- +#include <linux/compiler.h>
- +#include <asm/gpio.h>
- +#include <asm/processor.h>
- +#include <asm/lantiq/io.h>
- +#include <asm/lantiq/eth.h>
- +#include <asm/lantiq/pm.h>
- +#include <asm/lantiq/reset.h>
- +#include <asm/lantiq/dma.h>
- +#include <asm/arch/soc.h>
- +#include <asm/arch/switch.h>
- +
- +#define LTQ_ETH_RX_BUFFER_CNT PKTBUFSRX
- +#define LTQ_ETH_TX_BUFFER_CNT 8
- +#define LTQ_ETH_RX_DATA_SIZE PKTSIZE_ALIGN
- +#define LTQ_ETH_IP_ALIGN 2
- +
- +#define LTQ_MDIO_DRV_NAME "ltq-mdio"
- +#define LTQ_ETH_DRV_NAME "ltq-eth"
- +
- +#define LTQ_ETHSW_MAX_GMAC 6
- +#define LTQ_ETHSW_PMAC 6
- +
- +struct ltq_mdio_phy_addr_reg {
- + union {
- + struct {
- + unsigned rsvd:1;
- + unsigned lnkst:2; /* Link status control */
- + unsigned speed:2; /* Speed control */
- + unsigned fdup:2; /* Full duplex control */
- + unsigned fcontx:2; /* Flow control mode TX */
- + unsigned fconrx:2; /* Flow control mode RX */
- + unsigned addr:5; /* PHY address */
- + } bits;
- + u16 val;
- + };
- +};
- +
- +enum ltq_mdio_phy_addr_lnkst {
- + LTQ_MDIO_PHY_ADDR_LNKST_AUTO = 0,
- + LTQ_MDIO_PHY_ADDR_LNKST_UP = 1,
- + LTQ_MDIO_PHY_ADDR_LNKST_DOWN = 2,
- +};
- +
- +enum ltq_mdio_phy_addr_speed {
- + LTQ_MDIO_PHY_ADDR_SPEED_M10 = 0,
- + LTQ_MDIO_PHY_ADDR_SPEED_M100 = 1,
- + LTQ_MDIO_PHY_ADDR_SPEED_G1 = 2,
- + LTQ_MDIO_PHY_ADDR_SPEED_AUTO = 3,
- +};
- +
- +enum ltq_mdio_phy_addr_fdup {
- + LTQ_MDIO_PHY_ADDR_FDUP_AUTO = 0,
- + LTQ_MDIO_PHY_ADDR_FDUP_ENABLE = 1,
- + LTQ_MDIO_PHY_ADDR_FDUP_DISABLE = 3,
- +};
- +
- +enum ltq_mdio_phy_addr_fcon {
- + LTQ_MDIO_PHY_ADDR_FCON_AUTO = 0,
- + LTQ_MDIO_PHY_ADDR_FCON_ENABLE = 1,
- + LTQ_MDIO_PHY_ADDR_FCON_DISABLE = 3,
- +};
- +
- +struct ltq_mii_mii_cfg_reg {
- + union {
- + struct {
- + unsigned res:1; /* Hardware reset */
- + unsigned en:1; /* xMII interface enable */
- + unsigned isol:1; /* xMII interface isolate */
- + unsigned ldclkdis:1; /* Link down clock disable */
- + unsigned rsvd:1;
- + unsigned crs:2; /* CRS sensitivity config */
- + unsigned rgmii_ibs:1; /* RGMII In Band status */
- + unsigned rmii:1; /* RMII ref clock direction */
- + unsigned miirate:3; /* xMII interface clock rate */
- + unsigned miimode:4; /* xMII interface mode */
- + } bits;
- + u16 val;
- + };
- +};
- +
- +enum ltq_mii_mii_cfg_miirate {
- + LTQ_MII_MII_CFG_MIIRATE_M2P5 = 0,
- + LTQ_MII_MII_CFG_MIIRATE_M25 = 1,
- + LTQ_MII_MII_CFG_MIIRATE_M125 = 2,
- + LTQ_MII_MII_CFG_MIIRATE_M50 = 3,
- + LTQ_MII_MII_CFG_MIIRATE_AUTO = 4,
- +};
- +
- +enum ltq_mii_mii_cfg_miimode {
- + LTQ_MII_MII_CFG_MIIMODE_MIIP = 0,
- + LTQ_MII_MII_CFG_MIIMODE_MIIM = 1,
- + LTQ_MII_MII_CFG_MIIMODE_RMIIP = 2,
- + LTQ_MII_MII_CFG_MIIMODE_RMIIM = 3,
- + LTQ_MII_MII_CFG_MIIMODE_RGMII = 4,
- +};
- +
- +struct ltq_eth_priv {
- + struct ltq_dma_device dma_dev;
- + struct mii_dev *bus;
- + struct eth_device *dev;
- + struct phy_device *phymap[LTQ_ETHSW_MAX_GMAC];
- + int rx_num;
- + int tx_num;
- +};
- +
- +static struct vr9_switch_regs *switch_regs =
- + (struct vr9_switch_regs *) CKSEG1ADDR(LTQ_SWITCH_BASE);
- +
- +static inline void vr9_switch_sync(void)
- +{
- + __asm__("sync");
- +}
- +
- +static inline int vr9_switch_mdio_is_busy(void)
- +{
- + u32 mdio_ctrl = ltq_readl(&switch_regs->mdio.mdio_ctrl);
- +
- + return mdio_ctrl & MDIO_CTRL_MBUSY;
- +}
- +
- +static inline void vr9_switch_mdio_poll(void)
- +{
- + while (vr9_switch_mdio_is_busy())
- + cpu_relax();
- +}
- +
- +static int vr9_switch_mdio_read(struct mii_dev *bus, int phyad, int devad,
- + int regad)
- +{
- + u32 mdio_ctrl;
- + int retval;
- +
- + mdio_ctrl = MDIO_CTRL_OP_READ |
- + ((phyad << MDIO_CTRL_PHYAD_SHIFT) & MDIO_CTRL_PHYAD_MASK) |
- + (regad & MDIO_CTRL_REGAD_MASK);
- +
- + vr9_switch_mdio_poll();
- + ltq_writel(&switch_regs->mdio.mdio_ctrl, mdio_ctrl);
- + vr9_switch_mdio_poll();
- + retval = ltq_readl(&switch_regs->mdio.mdio_read);
- +
- + return retval;
- +}
- +
- +static int vr9_switch_mdio_write(struct mii_dev *bus, int phyad, int devad,
- + int regad, u16 val)
- +{
- + u32 mdio_ctrl;
- +
- + mdio_ctrl = MDIO_CTRL_OP_WRITE |
- + ((phyad << MDIO_CTRL_PHYAD_SHIFT) & MDIO_CTRL_PHYAD_MASK) |
- + (regad & MDIO_CTRL_REGAD_MASK);
- +
- + vr9_switch_mdio_poll();
- + ltq_writel(&switch_regs->mdio.mdio_write, val);
- + ltq_writel(&switch_regs->mdio.mdio_ctrl, mdio_ctrl);
- +
- + return 0;
- +}
- +
- +static void ltq_eth_gmac_update(struct phy_device *phydev, int num)
- +{
- + struct ltq_mdio_phy_addr_reg phy_addr_reg;
- + struct ltq_mii_mii_cfg_reg mii_cfg_reg;
- +
- + phy_addr_reg.val = ltq_readl(to_mdio_phyaddr(switch_regs, num));
- +
- + switch (num) {
- + case 0:
- + case 1:
- + case 5:
- + mii_cfg_reg.val = ltq_readl(to_mii_miicfg(switch_regs, num));
- + break;
- + default:
- + mii_cfg_reg.val = 0;
- + break;
- + }
- +
- + phy_addr_reg.bits.addr = phydev->addr;
- +
- + if (phydev->link)
- + phy_addr_reg.bits.lnkst = LTQ_MDIO_PHY_ADDR_LNKST_UP;
- + else
- + phy_addr_reg.bits.lnkst = LTQ_MDIO_PHY_ADDR_LNKST_DOWN;
- +
- + switch (phydev->speed) {
- + case SPEED_1000:
- + phy_addr_reg.bits.speed = LTQ_MDIO_PHY_ADDR_SPEED_G1;
- + mii_cfg_reg.bits.miirate = LTQ_MII_MII_CFG_MIIRATE_M125;
- + break;
- + case SPEED_100:
- + phy_addr_reg.bits.speed = LTQ_MDIO_PHY_ADDR_SPEED_M100;
- + switch (mii_cfg_reg.bits.miimode) {
- + case LTQ_MII_MII_CFG_MIIMODE_RMIIM:
- + case LTQ_MII_MII_CFG_MIIMODE_RMIIP:
- + mii_cfg_reg.bits.miirate = LTQ_MII_MII_CFG_MIIRATE_M50;
- + break;
- + default:
- + mii_cfg_reg.bits.miirate = LTQ_MII_MII_CFG_MIIRATE_M25;
- + break;
- + }
- + break;
- + default:
- + phy_addr_reg.bits.speed = LTQ_MDIO_PHY_ADDR_SPEED_M10;
- + mii_cfg_reg.bits.miirate = LTQ_MII_MII_CFG_MIIRATE_M2P5;
- + break;
- + }
- +
- + if (phydev->duplex == DUPLEX_FULL)
- + phy_addr_reg.bits.fdup = LTQ_MDIO_PHY_ADDR_FDUP_ENABLE;
- + else
- + phy_addr_reg.bits.fdup = LTQ_MDIO_PHY_ADDR_FDUP_DISABLE;
- +
- + ltq_writel(to_mdio_phyaddr(switch_regs, num), phy_addr_reg.val);
- +
- + switch (num) {
- + case 0:
- + case 1:
- + case 5:
- + ltq_writel(to_mii_miicfg(switch_regs, num), mii_cfg_reg.val);
- + break;
- + default:
- + break;
- + }
- +}
- +
- +static inline u8 *ltq_eth_rx_packet_align(int rx_num)
- +{
- + u8 *packet = (u8 *) NetRxPackets[rx_num];
- +
- + /*
- + * IP header needs
- + */
- + return packet + LTQ_ETH_IP_ALIGN;
- +}
- +
- +static int ltq_eth_init(struct eth_device *dev, bd_t *bis)
- +{
- + struct ltq_eth_priv *priv = dev->priv;
- + struct ltq_dma_device *dma_dev = &priv->dma_dev;
- + struct phy_device *phydev;
- + int i;
- +
- + for (i = 0; i < LTQ_ETHSW_MAX_GMAC; i++) {
- + phydev = priv->phymap[i];
- + if (!phydev)
- + continue;
- +
- + phy_startup(phydev);
- + ltq_eth_gmac_update(phydev, i);
- + }
- +
- + for (i = 0; i < LTQ_ETH_RX_BUFFER_CNT; i++)
- + ltq_dma_rx_map(dma_dev, i, ltq_eth_rx_packet_align(i),
- + LTQ_ETH_RX_DATA_SIZE);
- +
- + ltq_dma_enable(dma_dev);
- +
- + priv->rx_num = 0;
- + priv->tx_num = 0;
- +
- + return 0;
- +}
- +
- +static void ltq_eth_halt(struct eth_device *dev)
- +{
- + struct ltq_eth_priv *priv = dev->priv;
- + struct ltq_dma_device *dma_dev = &priv->dma_dev;
- + struct phy_device *phydev;
- + int i;
- +
- + ltq_dma_reset(dma_dev);
- +
- + for (i = 0; i < LTQ_ETHSW_MAX_GMAC; i++) {
- + phydev = priv->phymap[i];
- + if (!phydev)
- + continue;
- +
- + phy_shutdown(phydev);
- + phydev->link = 0;
- + ltq_eth_gmac_update(phydev, i);
- + }
- +}
- +
- +static int ltq_eth_send(struct eth_device *dev, void *packet, int length)
- +{
- + struct ltq_eth_priv *priv = dev->priv;
- + struct ltq_dma_device *dma_dev = &priv->dma_dev;
- +
- +#if 0
- + printf("%s: packet %p, len %d\n", __func__, packet, length);
- +#endif
- +
- + ltq_dma_tx_map(dma_dev, priv->tx_num, packet, length, 10);
- + priv->tx_num = (priv->tx_num + 1) % LTQ_ETH_TX_BUFFER_CNT;
- +
- + return 0;
- +}
- +
- +static int ltq_eth_recv(struct eth_device *dev)
- +{
- + struct ltq_eth_priv *priv = dev->priv;
- + struct ltq_dma_device *dma_dev = &priv->dma_dev;
- + u8 *packet;
- + int len;
- +
- + if (!ltq_dma_rx_poll(dma_dev, priv->rx_num))
- + return 0;
- +
- +#if 0
- + printf("%s: rx_num %d\n", __func__, priv->rx_num);
- +#endif
- +
- + len = ltq_dma_rx_length(dma_dev, priv->rx_num);
- + packet = ltq_eth_rx_packet_align(priv->rx_num);
- +
- +#if 0
- + printf("%s: received: packet %p, len %u, rx_num %d\n",
- + __func__, packet, len, priv->rx_num);
- +#endif
- +
- + if (len)
- + NetReceive(packet, len);
- +
- + ltq_dma_rx_map(dma_dev, priv->rx_num, packet,
- + LTQ_ETH_RX_DATA_SIZE);
- +
- + priv->rx_num = (priv->rx_num + 1) % LTQ_ETH_RX_BUFFER_CNT;
- +
- + return 0;
- +}
- +
- +static void ltq_eth_gmac_init(int num)
- +{
- + struct ltq_mdio_phy_addr_reg phy_addr_reg;
- + struct ltq_mii_mii_cfg_reg mii_cfg_reg;
- +
- + /* Reset PHY status to link down */
- + phy_addr_reg.val = ltq_readl(to_mdio_phyaddr(switch_regs, num));
- + phy_addr_reg.bits.addr = num;
- + phy_addr_reg.bits.lnkst = LTQ_MDIO_PHY_ADDR_LNKST_DOWN;
- + phy_addr_reg.bits.speed = LTQ_MDIO_PHY_ADDR_SPEED_M10;
- + phy_addr_reg.bits.fdup = LTQ_MDIO_PHY_ADDR_FDUP_DISABLE;
- + ltq_writel(to_mdio_phyaddr(switch_regs, num), phy_addr_reg.val);
- +
- + /* Reset and disable MII interface */
- + switch (num) {
- + case 0:
- + case 1:
- + case 5:
- + mii_cfg_reg.val = ltq_readl(to_mii_miicfg(switch_regs, num));
- + mii_cfg_reg.bits.en = 0;
- + mii_cfg_reg.bits.res = 1;
- + mii_cfg_reg.bits.miirate = LTQ_MII_MII_CFG_MIIRATE_M2P5;
- + ltq_writel(to_mii_miicfg(switch_regs, num), mii_cfg_reg.val);
- + break;
- + default:
- + break;
- + }
- +
- + /*
- + * - enable frame checksum generation
- + * - enable padding of short frames
- + * - disable flow control
- + */
- + ltq_writel(to_mac_ctrl(switch_regs, num, 0),
- + MAC_CTRL0_PADEN | MAC_CTRL0_FCS | MAC_CTRL0_FCON_NONE);
- +
- + vr9_switch_sync();
- +}
- +
- +static void ltq_eth_pmac_init(void)
- +{
- + /*
- + * WAR: buffer congestion:
- + * - shorten preambel to 1 byte
- + * - set TX IPG to 7 bytes
- + */
- +#if 1
- + ltq_writel(to_mac_ctrl(switch_regs, LTQ_ETHSW_PMAC, 1),
- + MAC_CTRL1_SHORTPRE | 7);
- +#endif
- +
- + /*
- + * WAR: systematical concept weakness ACM bug
- + * - set maximum number of used buffer segments to 254
- + * - soft-reset BM FSQM
- + */
- +#if 1
- + ltq_writel(&switch_regs->bm.core.fsqm_gctrl, 253);
- + ltq_setbits(&switch_regs->bm.core.gctrl, BM_GCTRL_F_SRES);
- + ltq_clrbits(&switch_regs->bm.core.gctrl, BM_GCTRL_F_SRES);
- +#endif
- +
- + /*
- + * WAR: switch MAC drop bug
- + */
- +#if 1
- + ltq_writel(to_pce_tbl_key(switch_regs, 0), 0xf);
- + ltq_writel(to_pce_tbl_value(switch_regs, 0), 0x40);
- + ltq_writel(&switch_regs->pce.core.tbl_addr, 0x3);
- + ltq_writel(&switch_regs->pce.core.tbl_ctrl, 0x902f);
- +#endif
- +
- + /*
- + * Configure frame header control:
- + * - enable flow control
- + * - enable CRC check for packets from DMA to PMAC
- + * - remove special tag from packets from PMAC to DMA
- + * - add CRC for packets from DMA to PMAC
- + */
- + ltq_writel(&switch_regs->pmac.hd_ctl, /*PMAC_HD_CTL_FC |*/
- + PMAC_HD_CTL_CCRC | PMAC_HD_CTL_RST | PMAC_HD_CTL_AC |
- + PMAC_HD_CTL_RC);
- +
- +#if 1
- + ltq_writel(&switch_regs->pmac.rx_ipg, 0x8b);
- +#endif
- +
- + /*
- + * - enable frame checksum generation
- + * - enable padding of short frames
- + * - disable flow control
- + */
- + ltq_writel(to_mac_ctrl(switch_regs, LTQ_ETHSW_PMAC, 0),
- + MAC_CTRL0_PADEN | MAC_CTRL0_FCS | MAC_CTRL0_FCON_NONE);
- +
- + vr9_switch_sync();
- +}
- +
- +static void ltq_eth_hw_init(void)
- +{
- + int i;
- +
- + /* Power up ethernet and switch subsystems */
- + ltq_pm_enable(LTQ_PM_ETH);
- +
- + /* Reset ethernet and switch subsystems */
- +#if 0
- + ltq_reset_once(LTQ_RESET_ETH, 10);
- +#endif
- +
- + /* Enable switch macro */
- + ltq_setbits(&switch_regs->mdio.glob_ctrl, MDIO_GLOB_CTRL_SE);
- +
- + /* Disable MDIO auto-polling for all ports */
- + ltq_writel(&switch_regs->mdio.mdc_cfg_0, 0);
- +
- + /*
- + * Enable and set MDIO management clock to 2.5 MHz. This is the
- + * maximum clock for FE PHYs.
- + * Formula for clock is:
- + *
- + * 50 MHz
- + * x = ----------- - 1
- + * 2 * f_MDC
- + */
- + ltq_writel(&switch_regs->mdio.mdc_cfg_1, MDIO_MDC_CFG1_RES |
- + MDIO_MDC_CFG1_MCEN | 5);
- +
- + vr9_switch_sync();
- +
- + /* Init MAC connected to CPU */
- + ltq_eth_pmac_init();
- +
- + /* Init MACs connected to external MII interfaces */
- + for (i = 0; i < LTQ_ETHSW_MAX_GMAC; i++)
- + ltq_eth_gmac_init(i);
- +}
- +
- +static void ltq_eth_port_config(struct ltq_eth_priv *priv,
- + const struct ltq_eth_port_config *port)
- +{
- + struct ltq_mii_mii_cfg_reg mii_cfg_reg;
- + struct phy_device *phydev;
- + int setup_gpio = 0;
- +
- + switch (port->num) {
- + case 0: /* xMII0 */
- + case 1: /* xMII1 */
- + mii_cfg_reg.val = ltq_readl(to_mii_miicfg(switch_regs,
- + port->num));
- + mii_cfg_reg.bits.en = port->flags ? 1 : 0;
- +
- + switch (port->phy_if) {
- + case PHY_INTERFACE_MODE_MII:
- + if (port->flags & LTQ_ETH_PORT_PHY)
- + /* MII MAC mode, connected to external PHY */
- + mii_cfg_reg.bits.miimode =
- + LTQ_MII_MII_CFG_MIIMODE_MIIM;
- + else
- + /* MII PHY mode, connected to external MAC */
- + mii_cfg_reg.bits.miimode =
- + LTQ_MII_MII_CFG_MIIMODE_MIIP;
- + setup_gpio = 1;
- + break;
- + case PHY_INTERFACE_MODE_RMII:
- + if (port->flags & LTQ_ETH_PORT_PHY)
- + /* RMII MAC mode, connected to external PHY */
- + mii_cfg_reg.bits.miimode =
- + LTQ_MII_MII_CFG_MIIMODE_RMIIM;
- + else
- + /* RMII PHY mode, connected to external MAC */
- + mii_cfg_reg.bits.miimode =
- + LTQ_MII_MII_CFG_MIIMODE_RMIIP;
- + setup_gpio = 1;
- + break;
- + case PHY_INTERFACE_MODE_RGMII:
- + /* RGMII MAC mode, connected to external PHY */
- + mii_cfg_reg.bits.miimode =
- + LTQ_MII_MII_CFG_MIIMODE_RGMII;
- + setup_gpio = 1;
- +
- + /* RGMII clock delays */
- + ltq_writel(to_mii_pcdu(switch_regs, port->num),
- + port->rgmii_rx_delay << PCDU_RXDLY_SHIFT |
- + port->rgmii_tx_delay);
- + break;
- + default:
- + break;
- + }
- +
- + ltq_writel(to_mii_miicfg(switch_regs, port->num),
- + mii_cfg_reg.val);
- + break;
- + case 2: /* internal GPHY0 */
- + case 3: /* internal GPHY0 */
- + case 4: /* internal GPHY1 */
- + switch (port->phy_if) {
- + case PHY_INTERFACE_MODE_MII:
- + case PHY_INTERFACE_MODE_GMII:
- + setup_gpio = 1;
- + break;
- + default:
- + break;
- + }
- + break;
- + case 5: /* internal GPHY1 or xMII2 */
- + mii_cfg_reg.val = ltq_readl(to_mii_miicfg(switch_regs,
- + port->num));
- + mii_cfg_reg.bits.en = port->flags ? 1 : 0;
- +
- + switch (port->phy_if) {
- + case PHY_INTERFACE_MODE_MII:
- + /* MII MAC mode, connected to internal GPHY */
- + mii_cfg_reg.bits.miimode =
- + LTQ_MII_MII_CFG_MIIMODE_MIIM;
- + setup_gpio = 1;
- + break;
- + case PHY_INTERFACE_MODE_RGMII:
- + /* RGMII MAC mode, connected to external PHY */
- + mii_cfg_reg.bits.miimode =
- + LTQ_MII_MII_CFG_MIIMODE_RGMII;
- + setup_gpio = 1;
- +
- + /* RGMII clock delays */
- + ltq_writel(to_mii_pcdu(switch_regs, port->num),
- + port->rgmii_rx_delay << PCDU_RXDLY_SHIFT |
- + port->rgmii_tx_delay);
- + break;
- + default:
- + break;
- + }
- +
- + ltq_writel(to_mii_miicfg(switch_regs, port->num),
- + mii_cfg_reg.val);
- + break;
- + default:
- + break;
- + }
- +
- + /* Setup GPIOs for MII with external PHYs/MACs */
- + if (setup_gpio) {
- + /* MII/MDIO */
- + gpio_set_altfunc(42, GPIO_ALTSEL_SET, GPIO_ALTSEL_CLR,
- + GPIO_DIR_OUT);
- + /* MII/MDC */
- + gpio_set_altfunc(43, GPIO_ALTSEL_SET, GPIO_ALTSEL_CLR,
- + GPIO_DIR_OUT);
- + }
- +
- + /* Connect to internal/external PHYs */
- + if (port->flags & LTQ_ETH_PORT_PHY) {
- + phydev = phy_connect(priv->bus, port->phy_addr, priv->dev,
- + port->phy_if);
- + if (phydev)
- + phy_config(phydev);
- +
- + priv->phymap[port->num] = phydev;
- + }
- +}
- +
- +int ltq_eth_initialize(const struct ltq_eth_board_config *board_config)
- +{
- + struct eth_device *dev;
- + struct mii_dev *bus;
- + struct ltq_eth_priv *priv;
- + struct ltq_dma_device *dma_dev;
- + int i, ret;
- +
- + build_check_vr9_registers();
- +
- + ltq_dma_init();
- + ltq_eth_hw_init();
- +
- + dev = calloc(1, sizeof(struct eth_device));
- + if (!dev)
- + return -1;
- +
- + priv = calloc(1, sizeof(struct ltq_eth_priv));
- + if (!priv)
- + return -1;
- +
- + bus = mdio_alloc();
- + if (!bus)
- + return -1;
- +
- + sprintf(dev->name, LTQ_ETH_DRV_NAME);
- + dev->priv = priv;
- + dev->init = ltq_eth_init;
- + dev->halt = ltq_eth_halt;
- + dev->recv = ltq_eth_recv;
- + dev->send = ltq_eth_send;
- +
- + sprintf(bus->name, LTQ_MDIO_DRV_NAME);
- + bus->read = vr9_switch_mdio_read;
- + bus->write = vr9_switch_mdio_write;
- + bus->priv = priv;
- +
- + dma_dev = &priv->dma_dev;
- + dma_dev->port = 0;
- + dma_dev->rx_chan.chan_no = 0;
- + dma_dev->rx_chan.class = 0;
- + dma_dev->rx_chan.num_desc = LTQ_ETH_RX_BUFFER_CNT;
- + dma_dev->rx_endian_swap = LTQ_DMA_ENDIANESS_B3_B2_B1_B0;
- + dma_dev->rx_burst_len = LTQ_DMA_BURST_2WORDS;
- + dma_dev->tx_chan.chan_no = 1;
- + dma_dev->tx_chan.class = 0;
- + dma_dev->tx_chan.num_desc = LTQ_ETH_TX_BUFFER_CNT;
- + dma_dev->tx_endian_swap = LTQ_DMA_ENDIANESS_B3_B2_B1_B0;
- + dma_dev->tx_burst_len = LTQ_DMA_BURST_2WORDS;
- +
- + priv->bus = bus;
- + priv->dev = dev;
- +
- + ret = ltq_dma_register(dma_dev);
- + if (ret)
- + return -1;
- +
- + ret = mdio_register(bus);
- + if (ret)
- + return -1;
- +
- + ret = eth_register(dev);
- + if (ret)
- + return -1;
- +
- + for (i = 0; i < board_config->num_ports; i++)
- + ltq_eth_port_config(priv, &board_config->ports[i]);
- +
- + return 0;
- +}
- --- a/drivers/net/phy/Makefile
- +++ b/drivers/net/phy/Makefile
- @@ -20,6 +20,7 @@ COBJS-$(CONFIG_PHY_BROADCOM) += broadcom
- COBJS-$(CONFIG_PHY_DAVICOM) += davicom.o
- COBJS-$(CONFIG_PHY_ET1011C) += et1011c.o
- COBJS-$(CONFIG_PHY_ICPLUS) += icplus.o
- +COBJS-$(CONFIG_PHY_LANTIQ) += lantiq.o
- COBJS-$(CONFIG_PHY_LXT) += lxt.o
- COBJS-$(CONFIG_PHY_MARVELL) += marvell.o
- COBJS-$(CONFIG_PHY_MICREL) += micrel.o
- --- /dev/null
- +++ b/drivers/net/phy/lantiq.c
- @@ -0,0 +1,238 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#define DEBUG
- +
- +#include <common.h>
- +#include <miiphy.h>
- +
- +#define ADVERTIZE_MPD (1 << 10)
- +
- +DECLARE_GLOBAL_DATA_PTR;
- +
- +/*
- + * Update link status.
- + *
- + * Based on genphy_update_link in phylib.c
- + */
- +static int ltq_phy_update_link(struct phy_device *phydev)
- +{
- + unsigned int mii_reg;
- +
- + mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
- +
- + /*
- + * If we already saw the link up, and it hasn't gone down, then
- + * we don't need to wait for autoneg again
- + */
- + if (phydev->link && mii_reg & BMSR_LSTATUS)
- + return 0;
- +
- + if ((mii_reg & BMSR_ANEGCAPABLE) && !(mii_reg & BMSR_ANEGCOMPLETE)) {
- + phydev->link = 0;
- + return 0;
- + } else {
- + /* Read the link a second time to clear the latched state */
- + mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
- +
- + if (mii_reg & BMSR_LSTATUS)
- + phydev->link = 1;
- + else
- + phydev->link = 0;
- + }
- +
- + return 0;
- +}
- +
- +/*
- + * Update speed and duplex.
- + *
- + * Based on genphy_parse_link in phylib.c
- + */
- +static int ltq_phy_parse_link(struct phy_device *phydev)
- +{
- + unsigned int mii_reg;
- +
- + mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
- +
- + /* We're using autonegotiation */
- + if (mii_reg & BMSR_ANEGCAPABLE) {
- + u32 lpa = 0;
- + u32 gblpa = 0;
- +
- + /* Check for gigabit capability */
- + if (mii_reg & BMSR_ERCAP) {
- + /* We want a list of states supported by
- + * both PHYs in the link
- + */
- + gblpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_STAT1000);
- + gblpa &= phy_read(phydev,
- + MDIO_DEVAD_NONE, MII_CTRL1000) << 2;
- + }
- +
- + /* Set the baseline so we only have to set them
- + * if they're different
- + */
- + phydev->speed = SPEED_10;
- + phydev->duplex = DUPLEX_HALF;
- +
- + /* Check the gigabit fields */
- + if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) {
- + phydev->speed = SPEED_1000;
- +
- + if (gblpa & PHY_1000BTSR_1000FD)
- + phydev->duplex = DUPLEX_FULL;
- +
- + /* We're done! */
- + return 0;
- + }
- +
- + lpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE);
- + lpa &= phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA);
- +
- + if (lpa & (LPA_100FULL | LPA_100HALF)) {
- + phydev->speed = SPEED_100;
- +
- + if (lpa & LPA_100FULL)
- + phydev->duplex = DUPLEX_FULL;
- +
- + } else if (lpa & LPA_10FULL)
- + phydev->duplex = DUPLEX_FULL;
- + } else {
- + u32 bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
- +
- + phydev->speed = SPEED_10;
- + phydev->duplex = DUPLEX_HALF;
- +
- + if (bmcr & BMCR_FULLDPLX)
- + phydev->duplex = DUPLEX_FULL;
- +
- + if (bmcr & BMCR_SPEED1000)
- + phydev->speed = SPEED_1000;
- + else if (bmcr & BMCR_SPEED100)
- + phydev->speed = SPEED_100;
- + }
- +
- + return 0;
- +}
- +
- +static int ltq_phy_config(struct phy_device *phydev)
- +{
- + u16 val;
- +
- + /* Advertise as Multi-port device */
- + val = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000);
- + val |= ADVERTIZE_MPD;
- + phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, val);
- +
- + genphy_config_aneg(phydev);
- +
- + return 0;
- +}
- +
- +static int ltq_phy_startup(struct phy_device *phydev)
- +{
- + /*
- + * Update PHY status immediately without any delays as genphy_startup
- + * does because VRX200 switch needs to be configured dependent
- + * on this information.
- + */
- + ltq_phy_update_link(phydev);
- + ltq_phy_parse_link(phydev);
- +
- + debug("ltq_phy: addr %d, link %d, speed %d, duplex %d\n",
- + phydev->addr, phydev->link, phydev->speed, phydev->duplex);
- +
- + return 0;
- +}
- +
- +static struct phy_driver xrx_11g_13_driver = {
- + .name = "Lantiq XWAY XRX PHY11G v1.3 and earlier",
- + .uid = 0x030260D0,
- + .mask = 0xFFFFFFF0,
- + .features = PHY_GBIT_FEATURES,
- + .config = ltq_phy_config,
- + .startup = ltq_phy_startup,
- + .shutdown = genphy_shutdown,
- +};
- +
- +static struct phy_driver xrx_11g_14_driver = {
- + .name = "Lantiq XWAY XRX PHY11G v1.4 and later",
- + .uid = 0xd565a408,
- + .mask = 0xFFFFFFF8,
- + .features = PHY_GBIT_FEATURES,
- + .config = ltq_phy_config,
- + .startup = ltq_phy_startup,
- + .shutdown = genphy_shutdown,
- +};
- +
- +static struct phy_driver xrx_22f_14_driver = {
- + .name = "Lantiq XWAY XRX PHY22F v1.4 and later",
- + .uid = 0xd565a418,
- + .mask = 0xFFFFFFF8,
- + .features = PHY_BASIC_FEATURES,
- + .config = ltq_phy_config,
- + .startup = ltq_phy_startup,
- + .shutdown = genphy_shutdown,
- +};
- +
- +static struct phy_driver pef7071_driver = {
- + .name = "Lantiq XWAY PEF7071",
- + .uid = 0xd565a400,
- + .mask = 0xFFFFFFFF,
- + .features = PHY_GBIT_FEATURES,
- + .config = ltq_phy_config,
- + .startup = ltq_phy_startup,
- + .shutdown = genphy_shutdown,
- +};
- +
- +static struct phy_driver xrx_genphy_driver = {
- + .name = "Generic PHY at Lantiq XWAY XRX switch",
- + .uid = 0,
- + .mask = 0,
- + .features = 0,
- + .config = genphy_config,
- + .startup = ltq_phy_startup,
- + .shutdown = genphy_shutdown,
- +};
- +
- +int phy_lantiq_init(void)
- +{
- +#ifdef CONFIG_NEEDS_MANUAL_RELOC
- + xrx_11g_13_driver.config = ltq_phy_config;
- + xrx_11g_13_driver.startup = ltq_phy_startup;
- + xrx_11g_13_driver.shutdown = genphy_shutdown;
- + xrx_11g_13_driver.name += gd->reloc_off;
- +
- + xrx_11g_14_driver.config = ltq_phy_config;
- + xrx_11g_14_driver.startup = ltq_phy_startup;
- + xrx_11g_14_driver.shutdown = genphy_shutdown;
- + xrx_11g_14_driver.name += gd->reloc_off;
- +
- + xrx_22f_14_driver.config = ltq_phy_config;
- + xrx_22f_14_driver.startup = ltq_phy_startup;
- + xrx_22f_14_driver.shutdown = genphy_shutdown;
- + xrx_22f_14_driver.name += gd->reloc_off;
- +
- + pef7071_driver.config = ltq_phy_config;
- + pef7071_driver.startup = ltq_phy_startup;
- + pef7071_driver.shutdown = genphy_shutdown;
- + pef7071_driver.name += gd->reloc_off;
- +
- + xrx_genphy_driver.config = genphy_config;
- + xrx_genphy_driver.startup = ltq_phy_startup;
- + xrx_genphy_driver.shutdown = genphy_shutdown;
- + xrx_genphy_driver.name += gd->reloc_off;
- +#endif
- +
- + phy_register(&xrx_11g_13_driver);
- + phy_register(&xrx_11g_14_driver);
- + phy_register(&xrx_22f_14_driver);
- + phy_register(&pef7071_driver);
- + phy_register(&xrx_genphy_driver);
- +
- + return 0;
- +}
- --- a/drivers/net/phy/phy.c
- +++ b/drivers/net/phy/phy.c
- @@ -16,9 +16,10 @@
- #include <command.h>
- #include <miiphy.h>
- #include <phy.h>
- -#include <errno.h>
- #include <linux/err.h>
-
- +DECLARE_GLOBAL_DATA_PTR;
- +
- /* Generic PHY support and helper functions */
-
- /**
- @@ -440,6 +441,16 @@ static LIST_HEAD(phy_drivers);
-
- int phy_init(void)
- {
- +#ifdef CONFIG_NEEDS_MANUAL_RELOC
- + INIT_LIST_HEAD(&phy_drivers);
- +
- + genphy_driver.config = genphy_config;
- + genphy_driver.startup = genphy_startup;
- + genphy_driver.shutdown = genphy_shutdown;
- +
- + genphy_driver.name += gd->reloc_off;
- +#endif
- +
- #ifdef CONFIG_PHY_ATHEROS
- phy_atheros_init();
- #endif
- @@ -455,6 +466,9 @@ int phy_init(void)
- #ifdef CONFIG_PHY_ICPLUS
- phy_icplus_init();
- #endif
- +#ifdef CONFIG_PHY_LANTIQ
- + phy_lantiq_init();
- +#endif
- #ifdef CONFIG_PHY_LXT
- phy_lxt_init();
- #endif
- --- a/drivers/serial/Makefile
- +++ b/drivers/serial/Makefile
- @@ -24,6 +24,7 @@ COBJS-$(CONFIG_SYS_NS16550_SERIAL) += se
- COBJS-$(CONFIG_IMX_SERIAL) += serial_imx.o
- COBJS-$(CONFIG_IXP_SERIAL) += serial_ixp.o
- COBJS-$(CONFIG_KS8695_SERIAL) += serial_ks8695.o
- +COBJS-$(CONFIG_LANTIQ_SERIAL) += serial_lantiq.o
- COBJS-$(CONFIG_MAX3100_SERIAL) += serial_max3100.o
- COBJS-$(CONFIG_MXC_UART) += serial_mxc.o
- COBJS-$(CONFIG_PL010_SERIAL) += serial_pl01x.o
- --- a/drivers/serial/serial.c
- +++ b/drivers/serial/serial.c
- @@ -160,6 +160,7 @@ serial_initfunc(sa1100_serial_initialize
- serial_initfunc(sh_serial_initialize);
- serial_initfunc(arm_dcc_initialize);
- serial_initfunc(mxs_auart_initialize);
- +serial_initfunc(ltq_serial_initialize);
-
- /**
- * serial_register() - Register serial driver with serial driver core
- @@ -253,6 +254,7 @@ void serial_initialize(void)
- sh_serial_initialize();
- arm_dcc_initialize();
- mxs_auart_initialize();
- + ltq_serial_initialize();
-
- serial_assign(default_serial_console()->name);
- }
- --- /dev/null
- +++ b/drivers/serial/serial_lantiq.c
- @@ -0,0 +1,263 @@
- +/*
- + * Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <serial.h>
- +#include <asm/errno.h>
- +#include <asm/arch/soc.h>
- +#include <asm/lantiq/clk.h>
- +#include <asm/lantiq/io.h>
- +
- +#if CONFIG_CONSOLE_ASC == 0
- +#define LTQ_ASC_BASE LTQ_ASC0_BASE
- +#else
- +#define LTQ_ASC_BASE LTQ_ASC1_BASE
- +#endif
- +
- +#define LTQ_ASC_ID_TXFS_SHIFT 24
- +#define LTQ_ASC_ID_TXFS_MASK (0x3F << LTQ_ASC_ID_TXFS_SHIFT)
- +#define LTQ_ASC_ID_RXFS_SHIFT 16
- +#define LTQ_ASC_ID_RXFS_MASK (0x3F << LTQ_ASC_ID_RXFS_SHIFT)
- +
- +#define LTQ_ASC_MCON_R (1 << 15)
- +#define LTQ_ASC_MCON_FDE (1 << 9)
- +
- +#define LTQ_ASC_WHBSTATE_SETREN (1 << 1)
- +#define LTQ_ASC_WHBSTATE_CLRREN (1 << 0)
- +
- +#define LTQ_ASC_RXFCON_RXFITL_SHIFT 8
- +#define LTQ_ASC_RXFCON_RXFITL_MASK (0x3F << LTQ_ASC_RXFCON_RXFITL_SHIFT)
- +#define LTQ_ASC_RXFCON_RXFITL_RXFFLU (1 << 1)
- +#define LTQ_ASC_RXFCON_RXFITL_RXFEN (1 << 0)
- +
- +#define LTQ_ASC_TXFCON_TXFITL_SHIFT 8
- +#define LTQ_ASC_TXFCON_TXFITL_MASK (0x3F << LTQ_ASC_TXFCON_TXFITL_SHIFT)
- +#define LTQ_ASC_TXFCON_TXFITL_TXFFLU (1 << 1)
- +#define LTQ_ASC_TXFCON_TXFITL_TXFEN (1 << 0)
- +
- +#define LTQ_ASC_FSTAT_TXFREE_SHIFT 24
- +#define LTQ_ASC_FSTAT_TXFREE_MASK (0x3F << LTQ_ASC_FSTAT_TXFREE_SHIFT)
- +#define LTQ_ASC_FSTAT_RXFREE_SHIFT 16
- +#define LTQ_ASC_FSTAT_RXFREE_MASK (0x3F << LTQ_ASC_FSTAT_RXFREE_SHIFT)
- +#define LTQ_ASC_FSTAT_TXFFL_SHIFT 8
- +#define LTQ_ASC_FSTAT_TXFFL_MASK (0x3F << LTQ_ASC_FSTAT_TXFFL_SHIFT)
- +#define LTQ_ASC_FSTAT_RXFFL_MASK 0x3F
- +
- +#ifdef __BIG_ENDIAN
- +#define LTQ_ASC_RBUF_OFFSET 3
- +#define LTQ_ASC_TBUF_OFFSET 3
- +#else
- +#define LTQ_ASC_RBUF_OFFSET 0
- +#define LTQ_ASC_TBUF_OFFSET 0
- +#endif
- +
- +struct ltq_asc_regs {
- + u32 clc;
- + u32 pisel;
- + u32 id;
- + u32 rsvd0;
- + u32 mcon;
- + u32 state;
- + u32 whbstate;
- + u32 rsvd1;
- + u8 tbuf[4];
- + u8 rbuf[4];
- + u32 rsvd2[2];
- + u32 abcon;
- + u32 abstat;
- + u32 whbabcon;
- + u32 whbabstat;
- + u32 rxfcon;
- + u32 txfcon;
- + u32 fstat;
- + u32 rsvd3;
- + u32 bg;
- + u32 bg_timer;
- + u32 fdv;
- + u32 pmw;
- + u32 modcon;
- + u32 modstat;
- +};
- +
- +DECLARE_GLOBAL_DATA_PTR;
- +
- +static struct ltq_asc_regs *ltq_asc_regs =
- + (struct ltq_asc_regs *) CKSEG1ADDR(LTQ_ASC_BASE);
- +
- +static int ltq_serial_init(void)
- +{
- + /* Set clock divider for normal run mode to 1 and enable module */
- + ltq_writel(<q_asc_regs->clc, 0x100);
- +
- + /* Reset MCON register */
- + ltq_writel(<q_asc_regs->mcon, 0);
- +
- + /* Use Port A as receiver input */
- + ltq_writel(<q_asc_regs->pisel, 0);
- +
- + /* Enable and flush RX/TX FIFOs */
- + ltq_setbits(<q_asc_regs->rxfcon,
- + LTQ_ASC_RXFCON_RXFITL_RXFFLU | LTQ_ASC_RXFCON_RXFITL_RXFEN);
- + ltq_setbits(<q_asc_regs->txfcon,
- + LTQ_ASC_TXFCON_TXFITL_TXFFLU | LTQ_ASC_TXFCON_TXFITL_TXFEN);
- +
- + serial_setbrg();
- +
- + /* Disable error flags, enable receiver */
- + ltq_writel(<q_asc_regs->whbstate, LTQ_ASC_WHBSTATE_SETREN);
- +
- + return 0;
- +}
- +
- +/*
- + * fdv asc_clk
- + * Baudrate = ----- * -------------
- + * 512 16 * (bg + 1)
- + */
- +static void ltq_serial_calc_br_fdv(unsigned long asc_clk,
- + unsigned long baudrate, u16 *fdv,
- + u16 *bg)
- +{
- + const u32 c = asc_clk / (16 * 512);
- + u32 diff1, diff2;
- + u32 bg_calc, br_calc, i;
- +
- + diff1 = baudrate;
- + for (i = 512; i > 0; i--) {
- + /* Calc bg for current fdv value */
- + bg_calc = i * c / baudrate;
- +
- + /* Impossible baudrate */
- + if (!bg_calc)
- + return;
- +
- + /*
- + * Calc diff to target baudrate dependent on current
- + * bg and fdv values
- + */
- + br_calc = i * c / bg_calc;
- + if (br_calc > baudrate)
- + diff2 = br_calc - baudrate;
- + else
- + diff2 = baudrate - br_calc;
- +
- + /* Perfect values found */
- + if (diff2 == 0) {
- + *fdv = i;
- + *bg = bg_calc - 1;
- + return;
- + }
- +
- + if (diff2 < diff1) {
- + *fdv = i;
- + *bg = bg_calc - 1;
- + diff1 = diff2;
- + }
- + }
- +}
- +
- +static void ltq_serial_setbrg(void)
- +{
- + unsigned long asc_clk, baudrate;
- + u16 bg = 0;
- + u16 fdv = 511;
- +
- + /* ASC clock is same as FPI clock with CLC.RMS = 1 */
- + asc_clk = ltq_get_bus_clock();
- + baudrate = gd->baudrate;
- +
- + /* Calculate FDV and BG values */
- + ltq_serial_calc_br_fdv(asc_clk, baudrate, &fdv, &bg);
- +
- + /* Disable baudrate generator */
- + ltq_clrbits(<q_asc_regs->mcon, LTQ_ASC_MCON_R);
- +
- + /* Enable fractional divider */
- + ltq_setbits(<q_asc_regs->mcon, LTQ_ASC_MCON_FDE);
- +
- + /* Set fdv and bg values */
- + ltq_writel(<q_asc_regs->fdv, fdv);
- + ltq_writel(<q_asc_regs->bg, bg);
- +
- + /* Enable baudrate generator */
- + ltq_setbits(<q_asc_regs->mcon, LTQ_ASC_MCON_R);
- +}
- +
- +static unsigned int ltq_serial_tx_free(void)
- +{
- + unsigned int txfree;
- +
- + txfree = (ltq_readl(<q_asc_regs->fstat) &
- + LTQ_ASC_FSTAT_TXFREE_MASK) >>
- + LTQ_ASC_FSTAT_TXFREE_SHIFT;
- +
- + return txfree;
- +}
- +
- +static unsigned int ltq_serial_rx_fill(void)
- +{
- + unsigned int rxffl;
- +
- + rxffl = ltq_readl(<q_asc_regs->fstat) & LTQ_ASC_FSTAT_RXFFL_MASK;
- +
- + return rxffl;
- +}
- +
- +static void ltq_serial_tx(const char c)
- +{
- + ltq_writeb(<q_asc_regs->tbuf[LTQ_ASC_TBUF_OFFSET], c);
- +}
- +
- +static u8 ltq_serial_rx(void)
- +{
- + return ltq_readb(<q_asc_regs->rbuf[LTQ_ASC_RBUF_OFFSET]);
- +}
- +
- +static void ltq_serial_putc(const char c)
- +{
- + if (c == '\n')
- + ltq_serial_putc('\r');
- +
- + while (!ltq_serial_tx_free())
- + ;
- +
- + ltq_serial_tx(c);
- +}
- +
- +static int ltq_serial_getc(void)
- +{
- + while (!ltq_serial_rx_fill())
- + ;
- +
- + return ltq_serial_rx();
- +}
- +
- +static int ltq_serial_tstc(void)
- +{
- + return (0 != ltq_serial_rx_fill());
- +}
- +
- +static struct serial_device ltq_serial_drv = {
- + .name = "ltq_serial",
- + .start = ltq_serial_init,
- + .stop = NULL,
- + .setbrg = ltq_serial_setbrg,
- + .putc = ltq_serial_putc,
- + .puts = default_serial_puts,
- + .getc = ltq_serial_getc,
- + .tstc = ltq_serial_tstc,
- +};
- +
- +void ltq_serial_initialize(void)
- +{
- + serial_register(<q_serial_drv);
- +}
- +
- +__weak struct serial_device *default_serial_console(void)
- +{
- + return <q_serial_drv;
- +}
- --- a/drivers/spi/Makefile
- +++ b/drivers/spi/Makefile
- @@ -25,6 +25,7 @@ COBJS-$(CONFIG_DAVINCI_SPI) += davinci_s
- COBJS-$(CONFIG_EXYNOS_SPI) += exynos_spi.o
- COBJS-$(CONFIG_ICH_SPI) += ich.o
- COBJS-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
- +COBJS-$(CONFIG_LANTIQ_SPI) += lantiq_spi.o
- COBJS-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
- COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
- COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o
- --- /dev/null
- +++ b/drivers/spi/lantiq_spi.c
- @@ -0,0 +1,666 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <common.h>
- +#include <spi.h>
- +#include <malloc.h>
- +#include <watchdog.h>
- +#include <asm/gpio.h>
- +#include <asm/lantiq/io.h>
- +#include <asm/lantiq/clk.h>
- +#include <asm/lantiq/pm.h>
- +#include <asm/arch/soc.h>
- +
- +#define LTQ_SPI_CLC_RMC_SHIFT 8
- +#define LTQ_SPI_CLC_RMC_MASK (0xFF << LTQ_SPI_CLC_RMC_SHIFT)
- +#define LTQ_SPI_CLC_DISS (1 << 1)
- +#define LTQ_SPI_CLC_DISR 1
- +
- +#define LTQ_SPI_ID_TXFS_SHIFT 24
- +#define LTQ_SPI_ID_TXFS_MASK (0x3F << LTQ_SPI_ID_TXFS_SHIFT)
- +#define LTQ_SPI_ID_RXFS_SHIFT 16
- +#define LTQ_SPI_ID_RXFS_MASK (0x3F << LTQ_SPI_ID_RXFS_SHIFT)
- +
- +#define LTQ_SPI_CON_ENBV (1 << 22)
- +#define LTQ_SPI_CON_BM_SHIFT 16
- +#define LTQ_SPI_CON_BM_MASK (0x1F << LTQ_SPI_CON_BM_SHIFT)
- +#define LTQ_SPI_CON_IDLE (1 << 23)
- +#define LTQ_SPI_CON_RUEN (1 << 12)
- +#define LTQ_SPI_CON_AEN (1 << 10)
- +#define LTQ_SPI_CON_REN (1 << 9)
- +#define LTQ_SPI_CON_TEN (1 << 8)
- +#define LTQ_SPI_CON_LB (1 << 7)
- +#define LTQ_SPI_CON_PO (1 << 6)
- +#define LTQ_SPI_CON_PH (1 << 5)
- +#define LTQ_SPI_CON_HB (1 << 4)
- +#define LTQ_SPI_CON_RXOFF (1 << 1)
- +#define LTQ_SPI_CON_TXOFF 1
- +
- +#define LTQ_SPI_STAT_RXBV_SHIFT 28
- +#define LTQ_SPI_STAT_RXBV_MASK (0x7 << LTQ_SPI_STAT_RXBV_SHIFT)
- +#define LTQ_SPI_STAT_BSY (1 << 13)
- +
- +#define LTQ_SPI_WHBSTATE_SETMS (1 << 3)
- +#define LTQ_SPI_WHBSTATE_CLRMS (1 << 2)
- +#define LTQ_SPI_WHBSTATE_SETEN (1 << 1)
- +#define LTQ_SPI_WHBSTATE_CLREN 1
- +#define LTQ_SPI_WHBSTATE_CLR_ERRORS 0x0F50
- +
- +#define LTQ_SPI_TXFCON_TXFLU (1 << 1)
- +#define LTQ_SPI_TXFCON_TXFEN 1
- +
- +#define LTQ_SPI_RXFCON_RXFLU (1 << 1)
- +#define LTQ_SPI_RXFCON_RXFEN 1
- +
- +#define LTQ_SPI_FSTAT_RXFFL_MASK 0x3f
- +#define LTQ_SPI_FSTAT_TXFFL_SHIFT 8
- +#define LTQ_SPI_FSTAT_TXFFL_MASK (0x3f << LTQ_SPI_FSTAT_TXFFL_SHIFT)
- +
- +#define LTQ_SPI_RXREQ_RXCNT_MASK 0xFFFF
- +#define LTQ_SPI_RXCNT_TODO_MASK 0xFFFF
- +
- +#define LTQ_SPI_GPIO_DIN 16
- +#define LTQ_SPI_GPIO_DOUT 17
- +#define LTQ_SPI_GPIO_CLK 18
- +
- +struct ltq_spi_regs {
- + __be32 clc; /* Clock control */
- + __be32 pisel; /* Port input select */
- + __be32 id; /* Identification */
- + __be32 rsvd0;
- + __be32 con; /* Control */
- + __be32 stat; /* Status */
- + __be32 whbstate; /* Write HW modified state */
- + __be32 rsvd1;
- + __be32 tb; /* Transmit buffer */
- + __be32 rb; /* Receive buffer */
- + __be32 rsvd2[2];
- + __be32 rxfcon; /* Recevie FIFO control */
- + __be32 txfcon; /* Transmit FIFO control */
- + __be32 fstat; /* FIFO status */
- + __be32 rsvd3;
- + __be32 brt; /* Baudrate timer */
- + __be32 brstat; /* Baudrate timer status */
- + __be32 rsvd4[6];
- + __be32 sfcon; /* Serial frame control */
- + __be32 sfstat; /* Serial frame status */
- + __be32 rsvd5[2];
- + __be32 gpocon; /* General purpose output control */
- + __be32 gpostat; /* General purpose output status */
- + __be32 fgpo; /* Force general purpose output */
- + __be32 rsvd6;
- + __be32 rxreq; /* Receive request */
- + __be32 rxcnt; /* Receive count */
- + __be32 rsvd7[25];
- + __be32 dmacon; /* DMA control */
- + __be32 rsvd8;
- + __be32 irnen; /* Interrupt node enable */
- + __be32 irnicr; /* Interrupt node interrupt capture */
- + __be32 irncr; /* Interrupt node control */
- +};
- +
- +struct ltq_spi_drv_data {
- + struct ltq_spi_regs __iomem *regs;
- +
- + struct spi_slave slave;
- + unsigned int max_hz;
- + unsigned int mode;
- + unsigned int tx_todo;
- + unsigned int rx_todo;
- + unsigned int rx_req;
- + unsigned int bits_per_word;
- + unsigned int speed_hz;
- + const u8 *tx;
- + u8 *rx;
- + int status;
- +};
- +
- +static struct ltq_spi_drv_data *to_ltq_spi_slave(struct spi_slave *slave)
- +{
- + return container_of(slave, struct ltq_spi_drv_data, slave);
- +}
- +
- +#ifdef CONFIG_SPL_BUILD
- +/*
- + * We do not have or want malloc in a SPI flash SPL.
- + * Neither we have to support multiple SPI slaves. Thus we put the
- + * SPI slave context in BSS for SPL builds.
- + */
- +static struct ltq_spi_drv_data ltq_spi_slave;
- +
- +static struct ltq_spi_drv_data *ltq_spi_slave_alloc(unsigned int bus,
- + unsigned int cs)
- +{
- + ltq_spi_slave.slave.bus = bus;
- + ltq_spi_slave.slave.cs = cs;
- +
- + return <q_spi_slave;
- +}
- +
- +static void ltq_spi_slave_free(struct spi_slave *slave)
- +{
- +}
- +#else
- +static struct ltq_spi_drv_data *ltq_spi_slave_alloc(unsigned int bus,
- + unsigned int cs)
- +{
- + return spi_alloc_slave(struct ltq_spi_drv_data, bus, cs);
- +}
- +
- +static void ltq_spi_slave_free(struct spi_slave *slave)
- +{
- + struct ltq_spi_drv_data *drv;
- +
- + if (slave) {
- + drv = to_ltq_spi_slave(slave);
- + free(drv);
- + }
- +}
- +#endif
- +
- +static unsigned int tx_fifo_size(struct ltq_spi_drv_data *drv)
- +{
- + u32 id = ltq_readl(&drv->regs->id);
- +
- + return (id & LTQ_SPI_ID_TXFS_MASK) >> LTQ_SPI_ID_TXFS_SHIFT;
- +}
- +
- +static unsigned int rx_fifo_size(struct ltq_spi_drv_data *drv)
- +{
- + u32 id = ltq_readl(&drv->regs->id);
- +
- + return (id & LTQ_SPI_ID_RXFS_MASK) >> LTQ_SPI_ID_RXFS_SHIFT;
- +}
- +
- +static unsigned int tx_fifo_level(struct ltq_spi_drv_data *drv)
- +{
- + u32 fstat = ltq_readl(&drv->regs->fstat);
- +
- + return (fstat & LTQ_SPI_FSTAT_TXFFL_MASK) >> LTQ_SPI_FSTAT_TXFFL_SHIFT;
- +}
- +
- +static unsigned int rx_fifo_level(struct ltq_spi_drv_data *drv)
- +{
- + u32 fstat = ltq_readl(&drv->regs->fstat);
- +
- + return fstat & LTQ_SPI_FSTAT_RXFFL_MASK;
- +}
- +
- +static unsigned int tx_fifo_free(struct ltq_spi_drv_data *drv)
- +{
- + return tx_fifo_size(drv) - tx_fifo_level(drv);
- +}
- +
- +static void hw_power_on(struct ltq_spi_drv_data *drv)
- +{
- + u32 clc;
- +
- + /* Power-up mdule */
- + ltq_pm_enable(LTQ_PM_SPI);
- +
- + /*
- + * Set clock divider for run mode to 1 to
- + * run at same frequency as FPI bus
- + */
- + clc = (1 << LTQ_SPI_CLC_RMC_SHIFT);
- + ltq_writel(&drv->regs->clc, clc);
- +}
- +
- +static void hw_reset_fifos(struct ltq_spi_drv_data *drv)
- +{
- + u32 val;
- +
- + val = LTQ_SPI_TXFCON_TXFEN | LTQ_SPI_TXFCON_TXFLU;
- + ltq_writel(&drv->regs->txfcon, val);
- +
- + val = LTQ_SPI_RXFCON_RXFEN | LTQ_SPI_RXFCON_RXFLU;
- + ltq_writel(&drv->regs->rxfcon, val);
- +}
- +
- +static int hw_is_busy(struct ltq_spi_drv_data *drv)
- +{
- + u32 stat = ltq_readl(&drv->regs->stat);
- +
- + return stat & LTQ_SPI_STAT_BSY;
- +}
- +
- +static void hw_enter_config_mode(struct ltq_spi_drv_data *drv)
- +{
- + ltq_writel(&drv->regs->whbstate, LTQ_SPI_WHBSTATE_CLREN);
- +}
- +
- +static void hw_enter_active_mode(struct ltq_spi_drv_data *drv)
- +{
- + ltq_writel(&drv->regs->whbstate, LTQ_SPI_WHBSTATE_SETEN);
- +}
- +
- +static void hw_setup_speed_hz(struct ltq_spi_drv_data *drv,
- + unsigned int max_speed_hz)
- +{
- + unsigned int spi_hz, speed_hz, brt;
- +
- + /*
- + * SPI module clock is derived from FPI bus clock dependent on
- + * divider value in CLC.RMS which is always set to 1.
- + *
- + * f_SPI
- + * baudrate = --------------
- + * 2 * (BR + 1)
- + */
- + spi_hz = ltq_get_bus_clock() / 2;
- +
- + /* TODO: optimize baudrate calculation */
- + for (brt = 0; brt < 0xFFFF; brt++) {
- + speed_hz = spi_hz / (brt + 1);
- + if (speed_hz <= max_speed_hz)
- + break;
- + }
- +
- + ltq_writel(&drv->regs->brt, brt);
- +}
- +
- +static void hw_setup_bits_per_word(struct ltq_spi_drv_data *drv,
- + unsigned int bits_per_word)
- +{
- + u32 bm;
- +
- + /* CON.BM value = bits_per_word - 1 */
- + bm = (bits_per_word - 1) << LTQ_SPI_CON_BM_SHIFT;
- +
- + ltq_clrsetbits(&drv->regs->con, LTQ_SPI_CON_BM_MASK, bm);
- +}
- +
- +static void hw_setup_clock_mode(struct ltq_spi_drv_data *drv, unsigned int mode)
- +{
- + u32 con_set = 0, con_clr = 0;
- +
- + /*
- + * SPI mode mapping in CON register:
- + * Mode CPOL CPHA CON.PO CON.PH
- + * 0 0 0 0 1
- + * 1 0 1 0 0
- + * 2 1 0 1 1
- + * 3 1 1 1 0
- + */
- + if (mode & SPI_CPHA)
- + con_clr |= LTQ_SPI_CON_PH;
- + else
- + con_set |= LTQ_SPI_CON_PH;
- +
- + if (mode & SPI_CPOL)
- + con_set |= LTQ_SPI_CON_PO | LTQ_SPI_CON_IDLE;
- + else
- + con_clr |= LTQ_SPI_CON_PO | LTQ_SPI_CON_IDLE;
- +
- + /* Set heading control */
- + if (mode & SPI_LSB_FIRST)
- + con_clr |= LTQ_SPI_CON_HB;
- + else
- + con_set |= LTQ_SPI_CON_HB;
- +
- + /* Set loopback mode */
- + if (mode & SPI_LOOP)
- + con_set |= LTQ_SPI_CON_LB;
- + else
- + con_clr |= LTQ_SPI_CON_LB;
- +
- + ltq_clrsetbits(&drv->regs->con, con_clr, con_set);
- +}
- +
- +static void hw_set_rxtx(struct ltq_spi_drv_data *drv)
- +{
- + u32 con;
- +
- + /* Configure transmitter and receiver */
- + con = ltq_readl(&drv->regs->con);
- + if (drv->tx)
- + con &= ~LTQ_SPI_CON_TXOFF;
- + else
- + con |= LTQ_SPI_CON_TXOFF;
- +
- + if (drv->rx)
- + con &= ~LTQ_SPI_CON_RXOFF;
- + else
- + con |= LTQ_SPI_CON_RXOFF;
- +
- + ltq_writel(&drv->regs->con, con);
- +}
- +
- +static void hw_init(struct ltq_spi_drv_data *drv)
- +{
- + hw_power_on(drv);
- +
- + /* Put controller into config mode */
- + hw_enter_config_mode(drv);
- +
- + /* Disable all interrupts */
- + ltq_writel(&drv->regs->irnen, 0);
- +
- + /* Clear error flags */
- + ltq_clrsetbits(&drv->regs->whbstate, 0, LTQ_SPI_WHBSTATE_CLR_ERRORS);
- +
- + /* Enable error checking, disable TX/RX */
- + ltq_writel(&drv->regs->con, LTQ_SPI_CON_RUEN | LTQ_SPI_CON_AEN |
- + LTQ_SPI_CON_TEN | LTQ_SPI_CON_REN | LTQ_SPI_CON_TXOFF |
- + LTQ_SPI_CON_RXOFF);
- +
- + /* Setup default SPI mode */
- + drv->bits_per_word = 8;
- + drv->speed_hz = 0;
- + hw_setup_bits_per_word(drv, drv->bits_per_word);
- + hw_setup_clock_mode(drv, SPI_MODE_0);
- +
- + /* Enable master mode and clear error flags */
- + ltq_writel(&drv->regs->whbstate, LTQ_SPI_WHBSTATE_SETMS |
- + LTQ_SPI_WHBSTATE_CLR_ERRORS);
- +
- + /* Reset GPIO/CS registers */
- + ltq_writel(&drv->regs->gpocon, 0);
- + ltq_writel(&drv->regs->fgpo, 0xFF00);
- +
- + /* Enable and flush FIFOs */
- + hw_reset_fifos(drv);
- +
- + /* SPI/DIN input */
- + gpio_set_altfunc(16, GPIO_ALTSEL_SET, GPIO_ALTSEL_CLR, GPIO_DIR_IN);
- + /* SPI/DOUT output */
- + gpio_set_altfunc(17, GPIO_ALTSEL_SET, GPIO_ALTSEL_CLR, GPIO_DIR_OUT);
- + /* SPI/CLK output */
- + gpio_set_altfunc(18, GPIO_ALTSEL_SET, GPIO_ALTSEL_CLR, GPIO_DIR_OUT);
- +}
- +
- +static void tx_fifo_write(struct ltq_spi_drv_data *drv)
- +{
- + const u8 *tx8;
- + const u16 *tx16;
- + const u32 *tx32;
- + u32 data;
- + unsigned int tx_free = tx_fifo_free(drv);
- +
- + while (drv->tx_todo && tx_free) {
- + switch (drv->bits_per_word) {
- + case 8:
- + tx8 = drv->tx;
- + data = *tx8;
- + drv->tx_todo--;
- + drv->tx++;
- + break;
- + case 16:
- + tx16 = (u16 *) drv->tx;
- + data = *tx16;
- + drv->tx_todo -= 2;
- + drv->tx += 2;
- + break;
- + case 32:
- + tx32 = (u32 *) drv->tx;
- + data = *tx32;
- + drv->tx_todo -= 4;
- + drv->tx += 4;
- + break;
- + default:
- + return;
- + }
- +
- + ltq_writel(&drv->regs->tb, data);
- + tx_free--;
- + }
- +}
- +
- +static void rx_fifo_read_full_duplex(struct ltq_spi_drv_data *drv)
- +{
- + u8 *rx8;
- + u16 *rx16;
- + u32 *rx32;
- + u32 data;
- + unsigned int rx_fill = rx_fifo_level(drv);
- +
- + while (rx_fill) {
- + data = ltq_readl(&drv->regs->rb);
- +
- + switch (drv->bits_per_word) {
- + case 8:
- + rx8 = drv->rx;
- + *rx8 = data;
- + drv->rx_todo--;
- + drv->rx++;
- + break;
- + case 16:
- + rx16 = (u16 *) drv->rx;
- + *rx16 = data;
- + drv->rx_todo -= 2;
- + drv->rx += 2;
- + break;
- + case 32:
- + rx32 = (u32 *) drv->rx;
- + *rx32 = data;
- + drv->rx_todo -= 4;
- + drv->rx += 4;
- + break;
- + default:
- + return;
- + }
- +
- + rx_fill--;
- + }
- +}
- +
- +static void rx_fifo_read_half_duplex(struct ltq_spi_drv_data *drv)
- +{
- + u32 data, *rx32;
- + u8 *rx8;
- + unsigned int rxbv, shift;
- + unsigned int rx_fill = rx_fifo_level(drv);
- +
- + /*
- + * In RX-only mode the bits per word value is ignored by HW. A value
- + * of 32 is used instead. Thus all 4 bytes per FIFO must be read.
- + * If remaining RX bytes are less than 4, the FIFO must be read
- + * differently. The amount of received and valid bytes is indicated
- + * by STAT.RXBV register value.
- + */
- + while (rx_fill) {
- + if (drv->rx_todo < 4) {
- + rxbv = (ltq_readl(&drv->regs->stat) &
- + LTQ_SPI_STAT_RXBV_MASK) >>
- + LTQ_SPI_STAT_RXBV_SHIFT;
- + data = ltq_readl(&drv->regs->rb);
- +
- + shift = (rxbv - 1) * 8;
- + rx8 = drv->rx;
- +
- + while (rxbv) {
- + *rx8++ = (data >> shift) & 0xFF;
- + rxbv--;
- + shift -= 8;
- + drv->rx_todo--;
- + drv->rx++;
- +
- + if (drv->rx_req)
- + drv->rx_req --;
- + }
- + } else {
- + data = ltq_readl(&drv->regs->rb);
- + rx32 = (u32 *) drv->rx;
- +
- + *rx32++ = data;
- + drv->rx_todo -= 4;
- + drv->rx += 4;
- +
- + if (drv->rx_req >= 4)
- + drv->rx_req -= 4;
- + }
- + rx_fill--;
- + }
- +}
- +
- +static void rx_request(struct ltq_spi_drv_data *drv)
- +{
- + unsigned int rxreq, rxreq_max;
- +
- + if (drv->rx_req)
- + return;
- +
- + /*
- + * To avoid receive overflows at high clocks it is better to request
- + * only the amount of bytes that fits into all FIFOs. This value
- + * depends on the FIFO size implemented in hardware.
- + */
- + rxreq = drv->rx_todo;
- + rxreq_max = rx_fifo_size(drv) * 4;
- + if (rxreq > rxreq_max)
- + rxreq = rxreq_max;
- +
- + drv->rx_req = rxreq;
- + ltq_writel(&drv->regs->rxreq, rxreq);
- +}
- +
- +void spi_init(void)
- +{
- +}
- +
- +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
- + unsigned int max_hz, unsigned int mode)
- +{
- + struct ltq_spi_drv_data *drv;
- +
- + if (!spi_cs_is_valid(bus, cs))
- + return NULL;
- +
- + drv = ltq_spi_slave_alloc(bus, cs);
- + if (!drv)
- + return NULL;
- +
- + drv->regs = (struct ltq_spi_regs *) CKSEG1ADDR(LTQ_SPI_BASE);
- +
- + hw_init(drv);
- +
- + drv->max_hz = max_hz;
- + drv->mode = mode;
- +
- + return &drv->slave;
- +}
- +
- +void spi_free_slave(struct spi_slave *slave)
- +{
- + ltq_spi_slave_free(slave);
- +}
- +
- +static int ltq_spi_wait_ready(struct ltq_spi_drv_data *drv)
- +{
- + const unsigned long timeout = 20000;
- + unsigned long timebase;
- +
- + timebase = get_timer(0);
- +
- + do {
- + WATCHDOG_RESET();
- +
- + if (!hw_is_busy(drv))
- + return 0;
- + } while (get_timer(timebase) < timeout);
- +
- + return 1;
- +}
- +
- +int spi_claim_bus(struct spi_slave *slave)
- +{
- + struct ltq_spi_drv_data *drv = to_ltq_spi_slave(slave);
- + int ret;
- +
- + ret = ltq_spi_wait_ready(drv);
- + if (ret) {
- + debug("cannot claim bus\n");
- + return ret;
- + }
- +
- + hw_enter_config_mode(drv);
- + hw_setup_clock_mode(drv, drv->mode);
- + hw_setup_speed_hz(drv, drv->max_hz);
- + hw_setup_bits_per_word(drv, drv->bits_per_word);
- + hw_enter_active_mode(drv);
- +
- + return 0;
- +}
- +
- +void spi_release_bus(struct spi_slave *slave)
- +{
- + struct ltq_spi_drv_data *drv = to_ltq_spi_slave(slave);
- +
- + hw_enter_config_mode(drv);
- +}
- +
- +int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
- + const void *dout, void *din, unsigned long flags)
- +{
- +
- + struct ltq_spi_drv_data *drv = to_ltq_spi_slave(slave);
- + int ret = 0;
- +
- + if (bitlen % 8)
- + return 1;
- +
- + if (!bitlen) {
- + ret = 0;
- + goto done;
- + }
- +
- + if (flags & SPI_XFER_BEGIN)
- + spi_cs_activate(slave);
- +
- + drv->tx = dout;
- + drv->tx_todo = 0;
- + drv->rx = din;
- + drv->rx_todo = 0;
- + hw_set_rxtx(drv);
- +
- + if (drv->tx) {
- + drv->tx_todo = bitlen / 8;
- +
- + tx_fifo_write(drv);
- + }
- +
- + if (drv->rx) {
- + drv->rx_todo = bitlen / 8;
- +
- + if (!drv->tx)
- + rx_request(drv);
- + }
- +
- + for (;;) {
- + if (drv->tx) {
- + if (drv->rx && drv->rx_todo)
- + rx_fifo_read_full_duplex(drv);
- +
- + if (drv->tx_todo)
- + tx_fifo_write(drv);
- + else
- + goto done;
- + } else if (drv->rx) {
- + if (drv->rx_todo) {
- + rx_fifo_read_half_duplex(drv);
- +
- + if (drv->rx_todo)
- + rx_request(drv);
- + else
- + goto done;
- + } else {
- + goto done;
- + }
- + }
- + }
- +
- +done:
- + ret = ltq_spi_wait_ready(drv);
- +
- + drv->rx = NULL;
- + drv->tx = NULL;
- + hw_set_rxtx(drv);
- +
- + if (flags & SPI_XFER_END)
- + spi_cs_deactivate(slave);
- +
- + return ret;
- +}
- --- /dev/null
- +++ b/include/configs/easy50712.h
- @@ -0,0 +1,79 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __CONFIG_H
- +#define __CONFIG_H
- +
- +#define CONFIG_MACH_TYPE "EASY50712"
- +#define CONFIG_IDENT_STRING " "CONFIG_MACH_TYPE
- +#define CONFIG_BOARD_NAME "Lantiq EASY50712 Danube Reference Board"
- +
- +/* Configure SoC */
- +#define CONFIG_LTQ_SUPPORT_UART /* Enable ASC and UART */
- +
- +#define CONFIG_LTQ_SUPPORT_ETHERNET /* Enable ethernet */
- +
- +#define CONFIG_LTQ_SUPPORT_NOR_FLASH /* Have a parallel NOR flash */
- +
- +#define CONFIG_LTQ_SUPPORT_SPI_FLASH
- +#define CONFIG_SPI_FLASH_ATMEL /* Have an AT45DB321D serial flash */
- +
- +#define CONFIG_LTQ_SUPPORT_NAND_FLASH
- +
- +#define CONFIG_LTQ_SUPPORT_SPL_NOR_FLASH /* Build NOR flash SPL */
- +
- +#define CONFIG_LTQ_SPL_COMP_LZO
- +#define CONFIG_LTQ_SPL_CONSOLE
- +
- +/* Switch devices */
- +#define CONFIG_SWITCH_MULTI
- +#define CONFIG_SWITCH_ADM6996I
- +
- +/* Environment */
- +#define CONFIG_ENV_SPI_BUS 0
- +#define CONFIG_ENV_SPI_CS 2
- +#define CONFIG_ENV_SPI_MAX_HZ 20000000
- +#define CONFIG_ENV_SPI_MODE 0
- +
- +#if defined(CONFIG_SYS_BOOT_NOR)
- +#define CONFIG_ENV_IS_IN_FLASH
- +#define CONFIG_ENV_OVERWRITE
- +#define CONFIG_ENV_OFFSET (256 * 1024)
- +#define CONFIG_ENV_SECT_SIZE (64 * 1024)
- +#elif defined(CONFIG_SYS_BOOT_NORSPL)
- +#define CONFIG_ENV_IS_IN_FLASH
- +#define CONFIG_ENV_OVERWRITE
- +#define CONFIG_ENV_OFFSET (128 * 1024)
- +#define CONFIG_ENV_SECT_SIZE (64 * 1024)
- +#else
- +#define CONFIG_ENV_IS_NOWHERE
- +#endif
- +
- +#define CONFIG_ENV_SIZE (8 * 1024)
- +
- +#define CONFIG_LOADADDR CONFIG_SYS_LOAD_ADDR
- +
- +/* Console */
- +#define CONFIG_LTQ_ADVANCED_CONSOLE
- +#define CONFIG_BAUDRATE 115200
- +#define CONFIG_CONSOLE_ASC 1
- +#define CONFIG_CONSOLE_DEV "ttyLTQ1"
- +
- +/* Commands */
- +#define CONFIG_CMD_PING
- +
- +/* Pull in default board configs for Lantiq XWAY Danube */
- +#include <asm/lantiq/config.h>
- +#include <asm/arch/config.h>
- +
- +#define CONFIG_ENV_UPDATE_UBOOT_NOR \
- + "update-uboot-nor=run load-uboot-norspl-lzo write-uboot-nor\0"
- +
- +#define CONFIG_EXTRA_ENV_SETTINGS \
- + CONFIG_ENV_LANTIQ_DEFAULTS \
- + CONFIG_ENV_UPDATE_UBOOT_NOR
- +
- +#endif /* __CONFIG_H */
- --- /dev/null
- +++ b/include/configs/easy80920.h
- @@ -0,0 +1,92 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#ifndef __CONFIG_H
- +#define __CONFIG_H
- +
- +#define CONFIG_MACH_TYPE "EASY80920"
- +#define CONFIG_IDENT_STRING " "CONFIG_MACH_TYPE
- +#define CONFIG_BOARD_NAME "Lantiq EASY80920 VRX200 Family Board"
- +
- +/* Configure SoC */
- +#define CONFIG_LTQ_SUPPORT_UART /* Enable ASC and UART */
- +
- +#define CONFIG_LTQ_SUPPORT_ETHERNET /* Enable ethernet */
- +
- +#define CONFIG_LTQ_SUPPORT_NOR_FLASH /* Have a parallel NOR flash */
- +
- +#define CONFIG_LTQ_SUPPORT_SPI_FLASH
- +#define CONFIG_SPI_FLASH_MACRONIX /* Have a MX29LV620 serial flash */
- +
- +#define CONFIG_LTQ_SUPPORT_NAND_FLASH
- +
- +#define CONFIG_LTQ_SUPPORT_SPL_SPI_FLASH /* Build SPI flash SPL */
- +#define CONFIG_SPL_SPI_BUS 0
- +#define CONFIG_SPL_SPI_CS 4
- +#define CONFIG_SPL_SPI_MAX_HZ 25000000
- +#define CONFIG_SPL_SPI_MODE 0
- +
- +#define CONFIG_LTQ_SUPPORT_SPL_NOR_FLASH /* Build NOR flash SPL */
- +
- +#define CONFIG_LTQ_SPL_COMP_LZO
- +#define CONFIG_LTQ_SPL_CONSOLE
- +
- +#define CONFIG_SYS_DRAM_PROBE
- +
- +/* Environment */
- +#define CONFIG_ENV_SPI_BUS CONFIG_SPL_SPI_BUS
- +#define CONFIG_ENV_SPI_CS CONFIG_SPL_SPI_CS
- +#define CONFIG_ENV_SPI_MAX_HZ CONFIG_SPL_SPI_MAX_HZ
- +#define CONFIG_ENV_SPI_MODE CONFIG_SPL_SPI_MODE
- +
- +#if defined(CONFIG_SYS_BOOT_NOR)
- +#define CONFIG_ENV_IS_IN_FLASH
- +#define CONFIG_ENV_OVERWRITE
- +#define CONFIG_ENV_OFFSET (384 * 1024)
- +#define CONFIG_ENV_SECT_SIZE (64 * 1024)
- +#elif defined(CONFIG_SYS_BOOT_NORSPL)
- +#define CONFIG_ENV_IS_IN_FLASH
- +#define CONFIG_ENV_OVERWRITE
- +#define CONFIG_ENV_OFFSET (192 * 1024)
- +#define CONFIG_ENV_SECT_SIZE (64 * 1024)
- +#elif defined(CONFIG_SYS_BOOT_SFSPL)
- +#define CONFIG_ENV_IS_IN_SPI_FLASH
- +#define CONFIG_ENV_OVERWRITE
- +#define CONFIG_ENV_OFFSET (192 * 1024)
- +#define CONFIG_ENV_SECT_SIZE (64 * 1024)
- +#else
- +#define CONFIG_ENV_IS_NOWHERE
- +#endif
- +
- +#define CONFIG_ENV_SIZE (8 * 1024)
- +
- +#define CONFIG_LOADADDR CONFIG_SYS_LOAD_ADDR
- +
- +/* Console */
- +#define CONFIG_LTQ_ADVANCED_CONSOLE
- +#define CONFIG_BAUDRATE 115200
- +#define CONFIG_CONSOLE_ASC 1
- +#define CONFIG_CONSOLE_DEV "ttyLTQ1"
- +
- +/* Commands */
- +#define CONFIG_CMD_PING
- +
- +/* Pull in default board configs for Lantiq XWAY VRX200 */
- +#include <asm/lantiq/config.h>
- +#include <asm/arch/config.h>
- +
- +#define CONFIG_ENV_UPDATE_UBOOT_NOR \
- + "update-uboot-nor=run load-uboot-norspl-lzo write-uboot-nor\0"
- +
- +#define CONFIG_ENV_UPDATE_UBOOT_SF \
- + "update-uboot-sf=run load-uboot-sfspl-lzo write-uboot-sf\0"
- +
- +#define CONFIG_EXTRA_ENV_SETTINGS \
- + CONFIG_ENV_LANTIQ_DEFAULTS \
- + CONFIG_ENV_UPDATE_UBOOT_NOR \
- + CONFIG_ENV_UPDATE_UBOOT_SF
- +
- +#endif /* __CONFIG_H */
- --- a/include/phy.h
- +++ b/include/phy.h
- @@ -214,6 +214,7 @@ int phy_atheros_init(void);
- int phy_broadcom_init(void);
- int phy_davicom_init(void);
- int phy_et1011c_init(void);
- +int phy_lantiq_init(void);
- int phy_lxt_init(void);
- int phy_marvell_init(void);
- int phy_micrel_init(void);
- --- a/spl/Makefile
- +++ b/spl/Makefile
- @@ -100,6 +100,8 @@ LIBS-$(CONFIG_SPL_USBETH_SUPPORT) += dri
- LIBS-$(CONFIG_SPL_MUSB_NEW_SUPPORT) += drivers/usb/musb-new/libusb_musb-new.o
- LIBS-$(CONFIG_SPL_USBETH_SUPPORT) += drivers/usb/gadget/libusb_gadget.o
- LIBS-$(CONFIG_SPL_WATCHDOG_SUPPORT) += drivers/watchdog/libwatchdog.o
- +LIBS-$(CONFIG_SPL_LZMA_SUPPORT) += lib/lzma/liblzma.o
- +LIBS-$(CONFIG_SPL_LZO_SUPPORT) += lib/lzo/liblzo.o
-
- ifneq ($(CONFIG_OMAP_COMMON),)
- LIBS-y += $(CPUDIR)/omap-common/libomap-common.o
- --- a/tools/.gitignore
- +++ b/tools/.gitignore
- @@ -2,6 +2,7 @@
- /envcrc
- /gen_eth_addr
- /img2srec
- +/ltq-boot-image
- /kwboot
- /mkenvimage
- /mkimage
- --- a/tools/Makefile
- +++ b/tools/Makefile
- @@ -49,6 +49,7 @@ BIN_FILES-$(CONFIG_VIDEO_LOGO) += bmp_lo
- BIN_FILES-$(CONFIG_BUILD_ENVCRC) += envcrc$(SFX)
- BIN_FILES-$(CONFIG_CMD_NET) += gen_eth_addr$(SFX)
- BIN_FILES-$(CONFIG_CMD_LOADS) += img2srec$(SFX)
- +BIN_FILES-$(CONFIG_SOC_LANTIQ) += ltq-boot-image$(SFX)
- BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX)
- BIN_FILES-y += mkenvimage$(SFX)
- BIN_FILES-y += mkimage$(SFX)
- @@ -95,6 +96,7 @@ OBJ_FILES-$(CONFIG_MX28) += mxsboot.o
- OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o
- OBJ_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1.o
- OBJ_FILES-$(CONFIG_SMDK5250) += mkexynosspl.o
- +OBJ_FILES-$(CONFIG_SOC_LANTIQ) += ltq-boot-image.o
- OBJ_FILES-$(CONFIG_VIDEO_LOGO) += bmp_logo.o
- OBJ_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes.o
-
- @@ -195,6 +197,10 @@ $(obj)img2srec$(SFX): $(obj)img2srec.o
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
- $(HOSTSTRIP) $@
-
- +$(obj)ltq-boot-image$(SFX): $(obj)ltq-boot-image.o
- + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
- + $(HOSTSTRIP) $@
- +
- $(obj)xway-swap-bytes$(SFX): $(obj)xway-swap-bytes.o
- $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
- $(HOSTSTRIP) $@
- --- /dev/null
- +++ b/tools/ltq-boot-image.c
- @@ -0,0 +1,315 @@
- +/*
- + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
- + *
- + * SPDX-License-Identifier: GPL-2.0+
- + */
- +
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <string.h>
- +#include <unistd.h>
- +#include <getopt.h>
- +#include <compiler.h>
- +#include <sys/stat.h>
- +
- +enum image_types {
- + IMAGE_NONE,
- + IMAGE_SFSPL
- +};
- +
- +/* Lantiq non-volatile bootstrap command IDs */
- +enum nvb_cmd_ids {
- + NVB_CMD_DEBUG = 0x11,
- + NVB_CMD_REGCFG = 0x22,
- + NVB_CMD_IDWNLD = 0x33,
- + NVB_CMD_CDWNLD = 0x44,
- + NVB_CMD_DWNLD = 0x55,
- + NVB_CMD_IFCFG = 0x66,
- + NVB_CMD_START = 0x77
- +};
- +
- +/* Lantiq non-volatile bootstrap command flags */
- +enum nvb_cmd_flags {
- + NVB_FLAG_START = 1,
- + NVB_FLAG_DEC = (1 << 1),
- + NVB_FLAG_DBG = (1 << 2),
- + NVB_FLAG_SDBG = (1 << 3),
- + NVB_FLAG_CFG0 = (1 << 4),
- + NVB_FLAG_CFG1 = (1 << 5),
- + NVB_FLAG_CFG2 = (1 << 6),
- + NVB_FLAG_RST = (1 << 7)
- +};
- +
- +struct args {
- + enum image_types type;
- + __u32 entry_addr;
- + const char *uboot_bin;
- + const char *spl_bin;
- + const char *out_bin;
- +};
- +
- +static void usage_msg(const char *name)
- +{
- + fprintf(stderr, "%s: [-h] -t type -e entry-addr -u uboot-bin [-s spl-bin] -o out-bin\n",
- + name);
- + fprintf(stderr, " Image types:\n"
- + " sfspl - SPL + [compressed] U-Boot for SPI flash\n");
- +}
- +
- +static enum image_types parse_image_type(const char *type)
- +{
- + if (!type)
- + return IMAGE_NONE;
- +
- + if (!strncmp(type, "sfspl", 6))
- + return IMAGE_SFSPL;
- +
- + return IMAGE_NONE;
- +}
- +
- +static int parse_args(int argc, char *argv[], struct args *arg)
- +{
- + int opt;
- +
- + memset(arg, 0, sizeof(*arg));
- +
- + while ((opt = getopt(argc, argv, "ht:e:u:s:o:")) != -1) {
- + switch (opt) {
- + case 'h':
- + usage_msg(argv[0]);
- + return 1;
- + case 't':
- + arg->type = parse_image_type(optarg);
- + break;
- + case 'e':
- + arg->entry_addr = strtoul(optarg, NULL, 16);
- + break;
- + case 'u':
- + arg->uboot_bin = optarg;
- + break;
- + case 's':
- + arg->spl_bin = optarg;
- + break;
- + case 'o':
- + arg->out_bin = optarg;
- + break;
- + default:
- + fprintf(stderr, "Invalid option -%c\n", opt);
- + goto parse_error;
- + }
- + }
- +
- + if (arg->type == IMAGE_NONE) {
- + fprintf(stderr, "Invalid image type\n");
- + goto parse_error;
- + }
- +
- + if (!arg->uboot_bin) {
- + fprintf(stderr, "Missing U-Boot binary\n");
- + goto parse_error;
- + }
- +
- + if (!arg->out_bin) {
- + fprintf(stderr, "Missing output binary\n");
- + goto parse_error;
- + }
- +
- + if (arg->type == IMAGE_SFSPL && !arg->spl_bin) {
- + fprintf(stderr, "Missing SPL binary\n");
- + goto parse_error;
- + }
- +
- + return 0;
- +
- +parse_error:
- + usage_msg(argv[0]);
- + return -1;
- +}
- +
- +static __u32 build_nvb_command(unsigned cmdid, unsigned cmdflags)
- +{
- + __u32 cmd;
- + __u16 tag;
- +
- + tag = (cmdid << 8) | cmdflags;
- + cmd = (tag << 16) | (0xFFFF - tag);
- +
- + return cpu_to_be32(cmd);
- +}
- +
- +static int write_header(int fd, const void *hdr, size_t size)
- +{
- + ssize_t n;
- +
- + n = write(fd, hdr, size);
- + if (n != size) {
- + fprintf(stderr, "Cannot write header: %s\n",
- + strerror(errno));
- + return -1;
- + }
- +
- + return 0;
- +}
- +
- +static int write_nvb_dwnld_header(int fd, size_t size, __u32 addr)
- +{
- + __u32 hdr[3];
- +
- + hdr[0] = build_nvb_command(NVB_CMD_DWNLD, NVB_FLAG_START |
- + NVB_FLAG_SDBG);
- + hdr[1] = cpu_to_be32(size + 4);
- + hdr[2] = cpu_to_be32(addr);
- +
- + return write_header(fd, hdr, sizeof(hdr));
- +}
- +
- +static int write_nvb_start_header(int fd, __u32 addr)
- +{
- + __u32 hdr[3];
- +
- + hdr[0] = build_nvb_command(NVB_CMD_START, NVB_FLAG_SDBG);
- + hdr[1] = cpu_to_be32(4);
- + hdr[2] = cpu_to_be32(addr);
- +
- + return write_header(fd, hdr, sizeof(hdr));
- +}
- +
- +static int open_input_bin(const char *name, void **ptr, size_t *size)
- +{
- + struct stat sbuf;
- + int ret, fd;
- +
- + fd = open(name, O_RDONLY | O_BINARY);
- + if (0 > fd) {
- + fprintf(stderr, "Cannot open %s: %s\n", name,
- + strerror(errno));
- + return -1;
- + }
- +
- + ret = fstat(fd, &sbuf);
- + if (0 > ret) {
- + fprintf(stderr, "Cannot fstat %s: %s\n", name,
- + strerror(errno));
- + return -1;
- + }
- +
- + *ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
- + if (*ptr == MAP_FAILED) {
- + fprintf(stderr, "Cannot mmap %s: %s\n", name,
- + strerror(errno));
- + return -1;
- + }
- +
- + *size = sbuf.st_size;
- +
- + return fd;
- +}
- +
- +static void close_input_bin(int fd, void *ptr, size_t size)
- +{
- + munmap(ptr, size);
- + close(fd);
- +}
- +
- +static int copy_bin(int fd, void *ptr, size_t size)
- +{
- + ssize_t n;
- +
- + n = write(fd, ptr, size);
- + if (n != size) {
- + fprintf(stderr, "Cannot copy binary: %s\n", strerror(errno));
- + return -1;
- + }
- +
- + return 0;
- +}
- +
- +static int open_output_bin(const char *name)
- +{
- + int fd;
- +
- + fd = open(name, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0666);
- + if (0 > fd) {
- + fprintf(stderr, "Cannot open %s: %s\n", name,
- + strerror(errno));
- + return -1;
- + }
- +
- + return fd;
- +}
- +
- +static int create_sfspl(const struct args *arg)
- +{
- + int out_fd, uboot_fd, spl_fd, ret;
- + void *uboot_ptr, *spl_ptr;
- + size_t uboot_size, spl_size;
- +
- + out_fd = open_output_bin(arg->out_bin);
- + if (0 > out_fd)
- + goto err;
- +
- + spl_fd = open_input_bin(arg->spl_bin, &spl_ptr, &spl_size);
- + if (0 > spl_fd)
- + goto err_spl;
- +
- + uboot_fd = open_input_bin(arg->uboot_bin, &uboot_ptr, &uboot_size);
- + if (0 > uboot_fd)
- + goto err_uboot;
- +
- + ret = write_nvb_dwnld_header(out_fd, spl_size, arg->entry_addr);
- + if (ret)
- + goto err_write;
- +
- + ret = copy_bin(out_fd, spl_ptr, spl_size);
- + if (ret)
- + goto err_write;
- +
- + ret = write_nvb_start_header(out_fd, arg->entry_addr);
- + if (ret)
- + goto err_write;
- +
- + ret = copy_bin(out_fd, uboot_ptr, uboot_size);
- + if (ret)
- + goto err_write;
- +
- + close_input_bin(uboot_fd, uboot_ptr, uboot_size);
- + close_input_bin(spl_fd, spl_ptr, spl_size);
- + close(out_fd);
- +
- + return 0;
- +
- +err_write:
- + close_input_bin(uboot_fd, uboot_ptr, uboot_size);
- +err_uboot:
- + close_input_bin(spl_fd, spl_ptr, spl_size);
- +err_spl:
- + close(out_fd);
- +err:
- + return -1;
- +}
- +
- +int main(int argc, char *argv[])
- +{
- + int ret;
- + struct args arg;
- +
- + ret = parse_args(argc, argv, &arg);
- + if (ret)
- + goto done;
- +
- + switch (arg.type) {
- + case IMAGE_SFSPL:
- + ret = create_sfspl(&arg);
- + break;
- + default:
- + fprintf(stderr, "Image type not implemented\n");
- + ret = -1;
- + break;
- + }
- +
- +done:
- + if (ret >= 0)
- + return EXIT_SUCCESS;
- +
- + return EXIT_FAILURE;
- +}
|