1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258 |
- --- a/include/linux/stmmac.h
- +++ b/include/linux/stmmac.h
- @@ -99,6 +99,7 @@ struct plat_stmmacenet_data {
- int phy_addr;
- int interface;
- struct stmmac_mdio_bus_data *mdio_bus_data;
- + struct device_node *phy_node;
- struct stmmac_dma_cfg *dma_cfg;
- int clk_csr;
- int has_gmac;
- @@ -114,32 +115,12 @@ struct plat_stmmacenet_data {
- int maxmtu;
- int multicast_filter_bins;
- int unicast_filter_entries;
- + int tx_fifo_size;
- + int rx_fifo_size;
- void (*fix_mac_speed)(void *priv, unsigned int speed);
- void (*bus_setup)(void __iomem *ioaddr);
- - void *(*setup)(struct platform_device *pdev);
- - void (*free)(struct platform_device *pdev, void *priv);
- int (*init)(struct platform_device *pdev, void *priv);
- void (*exit)(struct platform_device *pdev, void *priv);
- - void *custom_cfg;
- - void *custom_data;
- void *bsp_priv;
- };
- -
- -/* of_data for SoC glue layer device tree bindings */
- -
- -struct stmmac_of_data {
- - int has_gmac;
- - int enh_desc;
- - int tx_coe;
- - int rx_coe;
- - int bugged_jumbo;
- - int pmt;
- - int riwt_off;
- - void (*fix_mac_speed)(void *priv, unsigned int speed);
- - void (*bus_setup)(void __iomem *ioaddr);
- - void *(*setup)(struct platform_device *pdev);
- - void (*free)(struct platform_device *pdev, void *priv);
- - int (*init)(struct platform_device *pdev, void *priv);
- - void (*exit)(struct platform_device *pdev, void *priv);
- -};
- #endif
- --- a/drivers/net/ethernet/stmicro/Kconfig
- +++ b/drivers/net/ethernet/stmicro/Kconfig
- @@ -7,9 +7,7 @@ config NET_VENDOR_STMICRO
- default y
- depends on HAS_IOMEM
- ---help---
- - If you have a network (Ethernet) card belonging to this class, say Y
- - and read the Ethernet-HOWTO, available from
- - <http://www.tldp.org/docs.html#howto>.
- + If you have a network (Ethernet) card belonging to this class, say Y.
-
- Note that the answer to this question doesn't directly affect the
- kernel: saying N will just cause the configurator to skip all
- --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
- +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
- @@ -14,21 +14,54 @@ config STMMAC_ETH
- if STMMAC_ETH
-
- config STMMAC_PLATFORM
- - bool "STMMAC Platform bus support"
- + tristate "STMMAC Platform bus support"
- depends on STMMAC_ETH
- + select MFD_SYSCON
- default y
- ---help---
- - This selects the platform specific bus support for
- - the stmmac device driver. This is the driver used
- - on many embedded STM platforms based on ARM and SuperH
- - processors.
- + This selects the platform specific bus support for the stmmac driver.
- + This is the driver used on several SoCs:
- + STi, Allwinner, Amlogic Meson, Altera SOCFPGA.
- +
- If you have a controller with this interface, say Y or M here.
-
- If unsure, say N.
-
- +if STMMAC_PLATFORM
- +
- +config DWMAC_GENERIC
- + tristate "Generic driver for DWMAC"
- + default STMMAC_PLATFORM
- + ---help---
- + Generic DWMAC driver for platforms that don't require any
- + platform specific code to function or is using platform
- + data for setup.
- +
- +config DWMAC_IPQ806X
- + tristate "QCA IPQ806x DWMAC support"
- + default ARCH_QCOM
- + depends on OF
- + select MFD_SYSCON
- + help
- + Support for QCA IPQ806X DWMAC Ethernet.
- +
- + This selects the IPQ806x SoC glue layer support for the stmmac
- + device driver. This driver does not use any of the hardware
- + acceleration features available on this SoC. Network devices
- + will behave like standard non-accelerated ethernet interfaces.
- +
- +config DWMAC_LPC18XX
- + tristate "NXP LPC18xx/43xx DWMAC support"
- + default ARCH_LPC18XX
- + depends on OF
- + select MFD_SYSCON
- + ---help---
- + Support for NXP LPC18xx/43xx DWMAC Ethernet.
- +
- config DWMAC_MESON
- - bool "Amlogic Meson dwmac support"
- - depends on STMMAC_PLATFORM && ARCH_MESON
- + tristate "Amlogic Meson dwmac support"
- + default ARCH_MESON
- + depends on OF
- help
- Support for Ethernet controller on Amlogic Meson SoCs.
-
- @@ -36,9 +69,22 @@ config DWMAC_MESON
- the stmmac device driver. This driver is used for Meson6 and
- Meson8 SoCs.
-
- +config DWMAC_ROCKCHIP
- + tristate "Rockchip dwmac support"
- + default ARCH_ROCKCHIP
- + depends on OF
- + select MFD_SYSCON
- + help
- + Support for Ethernet controller on Rockchip RK3288 SoC.
- +
- + This selects the Rockchip RK3288 SoC glue layer support for
- + the stmmac device driver.
- +
- config DWMAC_SOCFPGA
- - bool "SOCFPGA dwmac support"
- - depends on STMMAC_PLATFORM && MFD_SYSCON && (ARCH_SOCFPGA || COMPILE_TEST)
- + tristate "SOCFPGA dwmac support"
- + default ARCH_SOCFPGA
- + depends on OF
- + select MFD_SYSCON
- help
- Support for ethernet controller on Altera SOCFPGA
-
- @@ -46,21 +92,11 @@ config DWMAC_SOCFPGA
- for the stmmac device driver. This driver is used for
- arria5 and cyclone5 FPGA SoCs.
-
- -config DWMAC_SUNXI
- - bool "Allwinner GMAC support"
- - depends on STMMAC_PLATFORM && ARCH_SUNXI
- - default y
- - ---help---
- - Support for Allwinner A20/A31 GMAC ethernet controllers.
- -
- - This selects Allwinner SoC glue layer support for the
- - stmmac device driver. This driver is used for A20/A31
- - GMAC ethernet controller.
- -
- config DWMAC_STI
- - bool "STi GMAC support"
- - depends on STMMAC_PLATFORM && ARCH_STI
- - default y
- + tristate "STi GMAC support"
- + default ARCH_STI
- + depends on OF
- + select MFD_SYSCON
- ---help---
- Support for ethernet controller on STi SOCs.
-
- @@ -68,8 +104,20 @@ config DWMAC_STI
- device driver. This driver is used on for the STi series
- SOCs GMAC ethernet controller.
-
- +config DWMAC_SUNXI
- + tristate "Allwinner GMAC support"
- + default ARCH_SUNXI
- + depends on OF
- + ---help---
- + Support for Allwinner A20/A31 GMAC ethernet controllers.
- +
- + This selects Allwinner SoC glue layer support for the
- + stmmac device driver. This driver is used for A20/A31
- + GMAC ethernet controller.
- +endif
- +
- config STMMAC_PCI
- - bool "STMMAC PCI bus support"
- + tristate "STMMAC PCI bus support"
- depends on STMMAC_ETH && PCI
- ---help---
- This is to select the Synopsys DWMAC available on PCI devices,
- @@ -79,22 +127,4 @@ config STMMAC_PCI
- D1215994A VIRTEX FPGA board.
-
- If unsure, say N.
- -
- -config STMMAC_DEBUG_FS
- - bool "Enable monitoring via sysFS "
- - default n
- - depends on STMMAC_ETH && DEBUG_FS
- - ---help---
- - The stmmac entry in /sys reports DMA TX/RX rings
- - or (if supported) the HW cap register.
- -
- -config STMMAC_DA
- - bool "STMMAC DMA arbitration scheme"
- - default n
- - ---help---
- - Selecting this option, rx has priority over Tx (only for Giga
- - Ethernet device).
- - By default, the DMA arbitration scheme is based on Round-robin
- - (rx:tx priority is 1:1).
- -
- endif
- --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
- +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
- @@ -1,11 +1,20 @@
- obj-$(CONFIG_STMMAC_ETH) += stmmac.o
- -stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
- -stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
- -stmmac-$(CONFIG_DWMAC_MESON) += dwmac-meson.o
- -stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
- -stmmac-$(CONFIG_DWMAC_STI) += dwmac-sti.o
- -stmmac-$(CONFIG_DWMAC_SOCFPGA) += dwmac-socfpga.o
- stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
- - chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
- - dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
- + chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
- + dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
- mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o $(stmmac-y)
- +
- +# Ordering matters. Generic driver must be last.
- +obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o
- +obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o
- +obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o
- +obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o
- +obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o
- +obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-socfpga.o
- +obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o
- +obj-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
- +obj-$(CONFIG_DWMAC_GENERIC) += dwmac-generic.o
- +stmmac-platform-objs:= stmmac_platform.o
- +
- +obj-$(CONFIG_STMMAC_PCI) += stmmac-pci.o
- +stmmac-pci-objs:= stmmac_pci.o
- --- a/drivers/net/ethernet/stmicro/stmmac/common.h
- +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
- @@ -44,6 +44,7 @@
- #undef FRAME_FILTER_DEBUG
- /* #define FRAME_FILTER_DEBUG */
-
- +/* Extra statistic and debug information exposed by ethtool */
- struct stmmac_extra_stats {
- /* Transmit errors */
- unsigned long tx_underflow ____cacheline_aligned;
- @@ -149,7 +150,7 @@ struct stmmac_extra_stats {
- #define MAC_CSR_H_FRQ_MASK 0x20
-
- #define HASH_TABLE_SIZE 64
- -#define PAUSE_TIME 0x200
- +#define PAUSE_TIME 0xffff
-
- /* Flow Control defines */
- #define FLOW_OFF 0
- @@ -220,6 +221,7 @@ enum dma_irq_status {
- handle_tx = 0x8,
- };
-
- +/* EEE and LPI defines */
- #define CORE_IRQ_TX_PATH_IN_LPI_MODE (1 << 0)
- #define CORE_IRQ_TX_PATH_EXIT_LPI_MODE (1 << 1)
- #define CORE_IRQ_RX_PATH_IN_LPI_MODE (1 << 2)
- @@ -229,6 +231,7 @@ enum dma_irq_status {
- #define CORE_PCS_LINK_STATUS (1 << 6)
- #define CORE_RGMII_IRQ (1 << 7)
-
- +/* Physical Coding Sublayer */
- struct rgmii_adv {
- unsigned int pause;
- unsigned int duplex;
- @@ -294,6 +297,7 @@ struct dma_features {
-
- #define JUMBO_LEN 9000
-
- +/* Descriptors helpers */
- struct stmmac_desc_ops {
- /* DMA RX descriptor ring initialization */
- void (*init_rx_desc) (struct dma_desc *p, int disable_rx_ic, int mode,
- @@ -341,6 +345,10 @@ struct stmmac_desc_ops {
- int (*get_rx_timestamp_status) (void *desc, u32 ats);
- };
-
- +extern const struct stmmac_desc_ops enh_desc_ops;
- +extern const struct stmmac_desc_ops ndesc_ops;
- +
- +/* Specific DMA helpers */
- struct stmmac_dma_ops {
- /* DMA core initialization */
- int (*init) (void __iomem *ioaddr, int pbl, int fb, int mb,
- @@ -349,7 +357,8 @@ struct stmmac_dma_ops {
- void (*dump_regs) (void __iomem *ioaddr);
- /* Set tx/rx threshold in the csr6 register
- * An invalid value enables the store-and-forward mode */
- - void (*dma_mode) (void __iomem *ioaddr, int txmode, int rxmode);
- + void (*dma_mode)(void __iomem *ioaddr, int txmode, int rxmode,
- + int rxfifosz);
- /* To track extra statistic (if supported) */
- void (*dma_diagnostic_fr) (void *data, struct stmmac_extra_stats *x,
- void __iomem *ioaddr);
- @@ -370,6 +379,7 @@ struct stmmac_dma_ops {
-
- struct mac_device_info;
-
- +/* Helpers to program the MAC core */
- struct stmmac_ops {
- /* MAC core initialization */
- void (*core_init)(struct mac_device_info *hw, int mtu);
- @@ -400,6 +410,7 @@ struct stmmac_ops {
- void (*get_adv)(struct mac_device_info *hw, struct rgmii_adv *adv);
- };
-
- +/* PTP and HW Timer helpers */
- struct stmmac_hwtimestamp {
- void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data);
- void (*config_sub_second_increment) (void __iomem *ioaddr);
- @@ -410,6 +421,8 @@ struct stmmac_hwtimestamp {
- u64(*get_systime) (void __iomem *ioaddr);
- };
-
- +extern const struct stmmac_hwtimestamp stmmac_ptp;
- +
- struct mac_link {
- int port;
- int duplex;
- @@ -421,6 +434,7 @@ struct mii_regs {
- unsigned int data; /* MII Data */
- };
-
- +/* Helpers to manage the descriptors for chain and ring modes */
- struct stmmac_mode_ops {
- void (*init) (void *des, dma_addr_t phy_addr, unsigned int size,
- unsigned int extend_desc);
- --- /dev/null
- +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
- @@ -0,0 +1,81 @@
- +/*
- + * Generic DWMAC platform driver
- + *
- + * Copyright (C) 2007-2011 STMicroelectronics Ltd
- + * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
- + *
- + * This file is licensed under the terms of the GNU General Public
- + * License version 2. This program is licensed "as is" without any
- + * warranty of any kind, whether express or implied.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/of.h>
- +#include <linux/platform_device.h>
- +
- +#include "stmmac.h"
- +#include "stmmac_platform.h"
- +
- +static int dwmac_generic_probe(struct platform_device *pdev)
- +{
- + struct plat_stmmacenet_data *plat_dat;
- + struct stmmac_resources stmmac_res;
- + int ret;
- +
- + ret = stmmac_get_platform_resources(pdev, &stmmac_res);
- + if (ret)
- + return ret;
- +
- + if (pdev->dev.of_node) {
- + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
- + if (IS_ERR(plat_dat)) {
- + dev_err(&pdev->dev, "dt configuration failed\n");
- + return PTR_ERR(plat_dat);
- + }
- + } else {
- + plat_dat = dev_get_platdata(&pdev->dev);
- + if (!plat_dat) {
- + dev_err(&pdev->dev, "no platform data provided\n");
- + return -EINVAL;
- + }
- +
- + /* Set default value for multicast hash bins */
- + plat_dat->multicast_filter_bins = HASH_TABLE_SIZE;
- +
- + /* Set default value for unicast filter entries */
- + plat_dat->unicast_filter_entries = 1;
- + }
- +
- + /* Custom initialisation (if needed) */
- + if (plat_dat->init) {
- + ret = plat_dat->init(pdev, plat_dat->bsp_priv);
- + if (ret)
- + return ret;
- + }
- +
- + return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
- +}
- +
- +static const struct of_device_id dwmac_generic_match[] = {
- + { .compatible = "st,spear600-gmac"},
- + { .compatible = "snps,dwmac-3.610"},
- + { .compatible = "snps,dwmac-3.70a"},
- + { .compatible = "snps,dwmac-3.710"},
- + { .compatible = "snps,dwmac"},
- + { }
- +};
- +MODULE_DEVICE_TABLE(of, dwmac_generic_match);
- +
- +static struct platform_driver dwmac_generic_driver = {
- + .probe = dwmac_generic_probe,
- + .remove = stmmac_pltfr_remove,
- + .driver = {
- + .name = STMMAC_RESOURCE_NAME,
- + .pm = &stmmac_pltfr_pm_ops,
- + .of_match_table = of_match_ptr(dwmac_generic_match),
- + },
- +};
- +module_platform_driver(dwmac_generic_driver);
- +
- +MODULE_DESCRIPTION("Generic dwmac driver");
- +MODULE_LICENSE("GPL v2");
- --- /dev/null
- +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
- @@ -0,0 +1,373 @@
- +/*
- + * Qualcomm Atheros IPQ806x GMAC glue layer
- + *
- + * Copyright (C) 2015 The Linux Foundation
- + *
- + * Permission to use, copy, modify, and/or distribute this software for any
- + * purpose with or without fee is hereby granted, provided that the above
- + * copyright notice and this permission notice appear in all copies.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- + */
- +
- +#include <linux/device.h>
- +#include <linux/platform_device.h>
- +#include <linux/phy.h>
- +#include <linux/regmap.h>
- +#include <linux/clk.h>
- +#include <linux/reset.h>
- +#include <linux/of_net.h>
- +#include <linux/mfd/syscon.h>
- +#include <linux/stmmac.h>
- +#include <linux/of_mdio.h>
- +#include <linux/module.h>
- +
- +#include "stmmac_platform.h"
- +
- +#define NSS_COMMON_CLK_GATE 0x8
- +#define NSS_COMMON_CLK_GATE_PTP_EN(x) BIT(0x10 + x)
- +#define NSS_COMMON_CLK_GATE_RGMII_RX_EN(x) BIT(0x9 + (x * 2))
- +#define NSS_COMMON_CLK_GATE_RGMII_TX_EN(x) BIT(0x8 + (x * 2))
- +#define NSS_COMMON_CLK_GATE_GMII_RX_EN(x) BIT(0x4 + x)
- +#define NSS_COMMON_CLK_GATE_GMII_TX_EN(x) BIT(0x0 + x)
- +
- +#define NSS_COMMON_CLK_DIV0 0xC
- +#define NSS_COMMON_CLK_DIV_OFFSET(x) (x * 8)
- +#define NSS_COMMON_CLK_DIV_MASK 0x7f
- +
- +#define NSS_COMMON_CLK_SRC_CTRL 0x14
- +#define NSS_COMMON_CLK_SRC_CTRL_OFFSET(x) (x)
- +/* Mode is coded on 1 bit but is different depending on the MAC ID:
- + * MAC0: QSGMII=0 RGMII=1
- + * MAC1: QSGMII=0 SGMII=0 RGMII=1
- + * MAC2 & MAC3: QSGMII=0 SGMII=1
- + */
- +#define NSS_COMMON_CLK_SRC_CTRL_RGMII(x) 1
- +#define NSS_COMMON_CLK_SRC_CTRL_SGMII(x) ((x >= 2) ? 1 : 0)
- +
- +#define NSS_COMMON_MACSEC_CTL 0x28
- +#define NSS_COMMON_MACSEC_CTL_EXT_BYPASS_EN(x) (1 << x)
- +
- +#define NSS_COMMON_GMAC_CTL(x) (0x30 + (x * 4))
- +#define NSS_COMMON_GMAC_CTL_CSYS_REQ BIT(19)
- +#define NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL BIT(16)
- +#define NSS_COMMON_GMAC_CTL_IFG_LIMIT_OFFSET 8
- +#define NSS_COMMON_GMAC_CTL_IFG_OFFSET 0
- +#define NSS_COMMON_GMAC_CTL_IFG_MASK 0x3f
- +
- +#define NSS_COMMON_CLK_DIV_RGMII_1000 1
- +#define NSS_COMMON_CLK_DIV_RGMII_100 9
- +#define NSS_COMMON_CLK_DIV_RGMII_10 99
- +#define NSS_COMMON_CLK_DIV_SGMII_1000 0
- +#define NSS_COMMON_CLK_DIV_SGMII_100 4
- +#define NSS_COMMON_CLK_DIV_SGMII_10 49
- +
- +#define QSGMII_PCS_MODE_CTL 0x68
- +#define QSGMII_PCS_MODE_CTL_AUTONEG_EN(x) BIT((x * 8) + 7)
- +
- +#define QSGMII_PCS_CAL_LCKDT_CTL 0x120
- +#define QSGMII_PCS_CAL_LCKDT_CTL_RST BIT(19)
- +
- +/* Only GMAC1/2/3 support SGMII and their CTL register are not contiguous */
- +#define QSGMII_PHY_SGMII_CTL(x) ((x == 1) ? 0x134 : \
- + (0x13c + (4 * (x - 2))))
- +#define QSGMII_PHY_CDR_EN BIT(0)
- +#define QSGMII_PHY_RX_FRONT_EN BIT(1)
- +#define QSGMII_PHY_RX_SIGNAL_DETECT_EN BIT(2)
- +#define QSGMII_PHY_TX_DRIVER_EN BIT(3)
- +#define QSGMII_PHY_QSGMII_EN BIT(7)
- +#define QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET 12
- +#define QSGMII_PHY_PHASE_LOOP_GAIN_MASK 0x7
- +#define QSGMII_PHY_RX_DC_BIAS_OFFSET 18
- +#define QSGMII_PHY_RX_DC_BIAS_MASK 0x3
- +#define QSGMII_PHY_RX_INPUT_EQU_OFFSET 20
- +#define QSGMII_PHY_RX_INPUT_EQU_MASK 0x3
- +#define QSGMII_PHY_CDR_PI_SLEW_OFFSET 22
- +#define QSGMII_PHY_CDR_PI_SLEW_MASK 0x3
- +#define QSGMII_PHY_TX_DRV_AMP_OFFSET 28
- +#define QSGMII_PHY_TX_DRV_AMP_MASK 0xf
- +
- +struct ipq806x_gmac {
- + struct platform_device *pdev;
- + struct regmap *nss_common;
- + struct regmap *qsgmii_csr;
- + uint32_t id;
- + struct clk *core_clk;
- + phy_interface_t phy_mode;
- +};
- +
- +static int get_clk_div_sgmii(struct ipq806x_gmac *gmac, unsigned int speed)
- +{
- + struct device *dev = &gmac->pdev->dev;
- + int div;
- +
- + switch (speed) {
- + case SPEED_1000:
- + div = NSS_COMMON_CLK_DIV_SGMII_1000;
- + break;
- +
- + case SPEED_100:
- + div = NSS_COMMON_CLK_DIV_SGMII_100;
- + break;
- +
- + case SPEED_10:
- + div = NSS_COMMON_CLK_DIV_SGMII_10;
- + break;
- +
- + default:
- + dev_err(dev, "Speed %dMbps not supported in SGMII\n", speed);
- + return -EINVAL;
- + }
- +
- + return div;
- +}
- +
- +static int get_clk_div_rgmii(struct ipq806x_gmac *gmac, unsigned int speed)
- +{
- + struct device *dev = &gmac->pdev->dev;
- + int div;
- +
- + switch (speed) {
- + case SPEED_1000:
- + div = NSS_COMMON_CLK_DIV_RGMII_1000;
- + break;
- +
- + case SPEED_100:
- + div = NSS_COMMON_CLK_DIV_RGMII_100;
- + break;
- +
- + case SPEED_10:
- + div = NSS_COMMON_CLK_DIV_RGMII_10;
- + break;
- +
- + default:
- + dev_err(dev, "Speed %dMbps not supported in RGMII\n", speed);
- + return -EINVAL;
- + }
- +
- + return div;
- +}
- +
- +static int ipq806x_gmac_set_speed(struct ipq806x_gmac *gmac, unsigned int speed)
- +{
- + uint32_t clk_bits, val;
- + int div;
- +
- + switch (gmac->phy_mode) {
- + case PHY_INTERFACE_MODE_RGMII:
- + div = get_clk_div_rgmii(gmac, speed);
- + clk_bits = NSS_COMMON_CLK_GATE_RGMII_RX_EN(gmac->id) |
- + NSS_COMMON_CLK_GATE_RGMII_TX_EN(gmac->id);
- + break;
- +
- + case PHY_INTERFACE_MODE_SGMII:
- + div = get_clk_div_sgmii(gmac, speed);
- + clk_bits = NSS_COMMON_CLK_GATE_GMII_RX_EN(gmac->id) |
- + NSS_COMMON_CLK_GATE_GMII_TX_EN(gmac->id);
- + break;
- +
- + default:
- + dev_err(&gmac->pdev->dev, "Unsupported PHY mode: \"%s\"\n",
- + phy_modes(gmac->phy_mode));
- + return -EINVAL;
- + }
- +
- + /* Disable the clocks */
- + regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
- + val &= ~clk_bits;
- + regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
- +
- + /* Set the divider */
- + regmap_read(gmac->nss_common, NSS_COMMON_CLK_DIV0, &val);
- + val &= ~(NSS_COMMON_CLK_DIV_MASK
- + << NSS_COMMON_CLK_DIV_OFFSET(gmac->id));
- + val |= div << NSS_COMMON_CLK_DIV_OFFSET(gmac->id);
- + regmap_write(gmac->nss_common, NSS_COMMON_CLK_DIV0, val);
- +
- + /* Enable the clock back */
- + regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
- + val |= clk_bits;
- + regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
- +
- + return 0;
- +}
- +
- +static void *ipq806x_gmac_of_parse(struct ipq806x_gmac *gmac)
- +{
- + struct device *dev = &gmac->pdev->dev;
- +
- + gmac->phy_mode = of_get_phy_mode(dev->of_node);
- + if (gmac->phy_mode < 0) {
- + dev_err(dev, "missing phy mode property\n");
- + return ERR_PTR(-EINVAL);
- + }
- +
- + if (of_property_read_u32(dev->of_node, "qcom,id", &gmac->id) < 0) {
- + dev_err(dev, "missing qcom id property\n");
- + return ERR_PTR(-EINVAL);
- + }
- +
- + /* The GMACs are called 1 to 4 in the documentation, but to simplify the
- + * code and keep it consistent with the Linux convention, we'll number
- + * them from 0 to 3 here.
- + */
- + if (gmac->id < 0 || gmac->id > 3) {
- + dev_err(dev, "invalid gmac id\n");
- + return ERR_PTR(-EINVAL);
- + }
- +
- + gmac->core_clk = devm_clk_get(dev, "stmmaceth");
- + if (IS_ERR(gmac->core_clk)) {
- + dev_err(dev, "missing stmmaceth clk property\n");
- + return gmac->core_clk;
- + }
- + clk_set_rate(gmac->core_clk, 266000000);
- +
- + /* Setup the register map for the nss common registers */
- + gmac->nss_common = syscon_regmap_lookup_by_phandle(dev->of_node,
- + "qcom,nss-common");
- + if (IS_ERR(gmac->nss_common)) {
- + dev_err(dev, "missing nss-common node\n");
- + return gmac->nss_common;
- + }
- +
- + /* Setup the register map for the qsgmii csr registers */
- + gmac->qsgmii_csr = syscon_regmap_lookup_by_phandle(dev->of_node,
- + "qcom,qsgmii-csr");
- + if (IS_ERR(gmac->qsgmii_csr)) {
- + dev_err(dev, "missing qsgmii-csr node\n");
- + return gmac->qsgmii_csr;
- + }
- +
- + return NULL;
- +}
- +
- +static void ipq806x_gmac_fix_mac_speed(void *priv, unsigned int speed)
- +{
- + struct ipq806x_gmac *gmac = priv;
- +
- + ipq806x_gmac_set_speed(gmac, speed);
- +}
- +
- +static int ipq806x_gmac_probe(struct platform_device *pdev)
- +{
- + struct plat_stmmacenet_data *plat_dat;
- + struct stmmac_resources stmmac_res;
- + struct device *dev = &pdev->dev;
- + struct ipq806x_gmac *gmac;
- + int val;
- + void *err;
- +
- + val = stmmac_get_platform_resources(pdev, &stmmac_res);
- + if (val)
- + return val;
- +
- + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
- + if (IS_ERR(plat_dat))
- + return PTR_ERR(plat_dat);
- +
- + gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
- + if (!gmac)
- + return -ENOMEM;
- +
- + gmac->pdev = pdev;
- +
- + err = ipq806x_gmac_of_parse(gmac);
- + if (IS_ERR(err)) {
- + dev_err(dev, "device tree parsing error\n");
- + return PTR_ERR(err);
- + }
- +
- + regmap_write(gmac->qsgmii_csr, QSGMII_PCS_CAL_LCKDT_CTL,
- + QSGMII_PCS_CAL_LCKDT_CTL_RST);
- +
- + /* Inter frame gap is set to 12 */
- + val = 12 << NSS_COMMON_GMAC_CTL_IFG_OFFSET |
- + 12 << NSS_COMMON_GMAC_CTL_IFG_LIMIT_OFFSET;
- + /* We also initiate an AXI low power exit request */
- + val |= NSS_COMMON_GMAC_CTL_CSYS_REQ;
- + switch (gmac->phy_mode) {
- + case PHY_INTERFACE_MODE_RGMII:
- + val |= NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL;
- + break;
- + case PHY_INTERFACE_MODE_SGMII:
- + val &= ~NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL;
- + break;
- + default:
- + dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
- + phy_modes(gmac->phy_mode));
- + return -EINVAL;
- + }
- + regmap_write(gmac->nss_common, NSS_COMMON_GMAC_CTL(gmac->id), val);
- +
- + /* Configure the clock src according to the mode */
- + regmap_read(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, &val);
- + val &= ~(1 << NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id));
- + switch (gmac->phy_mode) {
- + case PHY_INTERFACE_MODE_RGMII:
- + val |= NSS_COMMON_CLK_SRC_CTRL_RGMII(gmac->id) <<
- + NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
- + break;
- + case PHY_INTERFACE_MODE_SGMII:
- + val |= NSS_COMMON_CLK_SRC_CTRL_SGMII(gmac->id) <<
- + NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
- + break;
- + default:
- + dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
- + phy_modes(gmac->phy_mode));
- + return -EINVAL;
- + }
- + regmap_write(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, val);
- +
- + /* Enable PTP clock */
- + regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
- + val |= NSS_COMMON_CLK_GATE_PTP_EN(gmac->id);
- + regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
- +
- + if (gmac->phy_mode == PHY_INTERFACE_MODE_SGMII) {
- + regmap_write(gmac->qsgmii_csr, QSGMII_PHY_SGMII_CTL(gmac->id),
- + QSGMII_PHY_CDR_EN |
- + QSGMII_PHY_RX_FRONT_EN |
- + QSGMII_PHY_RX_SIGNAL_DETECT_EN |
- + QSGMII_PHY_TX_DRIVER_EN |
- + QSGMII_PHY_QSGMII_EN |
- + 0x4 << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET |
- + 0x3 << QSGMII_PHY_RX_DC_BIAS_OFFSET |
- + 0x1 << QSGMII_PHY_RX_INPUT_EQU_OFFSET |
- + 0x2 << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
- + 0xC << QSGMII_PHY_TX_DRV_AMP_OFFSET);
- + }
- +
- + plat_dat->has_gmac = true;
- + plat_dat->bsp_priv = gmac;
- + plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed;
- +
- + return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
- +}
- +
- +static const struct of_device_id ipq806x_gmac_dwmac_match[] = {
- + { .compatible = "qcom,ipq806x-gmac" },
- + { }
- +};
- +MODULE_DEVICE_TABLE(of, ipq806x_gmac_dwmac_match);
- +
- +static struct platform_driver ipq806x_gmac_dwmac_driver = {
- + .probe = ipq806x_gmac_probe,
- + .remove = stmmac_pltfr_remove,
- + .driver = {
- + .name = "ipq806x-gmac-dwmac",
- + .pm = &stmmac_pltfr_pm_ops,
- + .of_match_table = ipq806x_gmac_dwmac_match,
- + },
- +};
- +module_platform_driver(ipq806x_gmac_dwmac_driver);
- +
- +MODULE_AUTHOR("Mathieu Olivari <mathieu@codeaurora.org>");
- +MODULE_DESCRIPTION("Qualcomm Atheros IPQ806x DWMAC specific glue layer");
- +MODULE_LICENSE("Dual BSD/GPL");
- --- /dev/null
- +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c
- @@ -0,0 +1,86 @@
- +/*
- + * DWMAC glue for NXP LPC18xx/LPC43xx Ethernet
- + *
- + * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
- + *
- + * This file is licensed under the terms of the GNU General Public
- + * License version 2. This program is licensed "as is" without any
- + * warranty of any kind, whether express or implied.
- + */
- +
- +#include <linux/mfd/syscon.h>
- +#include <linux/module.h>
- +#include <linux/of.h>
- +#include <linux/of_net.h>
- +#include <linux/phy.h>
- +#include <linux/platform_device.h>
- +#include <linux/regmap.h>
- +#include <linux/stmmac.h>
- +
- +#include "stmmac_platform.h"
- +
- +/* Register defines for CREG syscon */
- +#define LPC18XX_CREG_CREG6 0x12c
- +# define LPC18XX_CREG_CREG6_ETHMODE_MASK 0x7
- +# define LPC18XX_CREG_CREG6_ETHMODE_MII 0x0
- +# define LPC18XX_CREG_CREG6_ETHMODE_RMII 0x4
- +
- +static int lpc18xx_dwmac_probe(struct platform_device *pdev)
- +{
- + struct plat_stmmacenet_data *plat_dat;
- + struct stmmac_resources stmmac_res;
- + struct regmap *reg;
- + u8 ethmode;
- + int ret;
- +
- + ret = stmmac_get_platform_resources(pdev, &stmmac_res);
- + if (ret)
- + return ret;
- +
- + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
- + if (IS_ERR(plat_dat))
- + return PTR_ERR(plat_dat);
- +
- + plat_dat->has_gmac = true;
- +
- + reg = syscon_regmap_lookup_by_compatible("nxp,lpc1850-creg");
- + if (IS_ERR(reg)) {
- + dev_err(&pdev->dev, "syscon lookup failed\n");
- + return PTR_ERR(reg);
- + }
- +
- + if (plat_dat->interface == PHY_INTERFACE_MODE_MII) {
- + ethmode = LPC18XX_CREG_CREG6_ETHMODE_MII;
- + } else if (plat_dat->interface == PHY_INTERFACE_MODE_RMII) {
- + ethmode = LPC18XX_CREG_CREG6_ETHMODE_RMII;
- + } else {
- + dev_err(&pdev->dev, "Only MII and RMII mode supported\n");
- + return -EINVAL;
- + }
- +
- + regmap_update_bits(reg, LPC18XX_CREG_CREG6,
- + LPC18XX_CREG_CREG6_ETHMODE_MASK, ethmode);
- +
- + return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
- +}
- +
- +static const struct of_device_id lpc18xx_dwmac_match[] = {
- + { .compatible = "nxp,lpc1850-dwmac" },
- + { }
- +};
- +MODULE_DEVICE_TABLE(of, lpc18xx_dwmac_match);
- +
- +static struct platform_driver lpc18xx_dwmac_driver = {
- + .probe = lpc18xx_dwmac_probe,
- + .remove = stmmac_pltfr_remove,
- + .driver = {
- + .name = "lpc18xx-dwmac",
- + .pm = &stmmac_pltfr_pm_ops,
- + .of_match_table = lpc18xx_dwmac_match,
- + },
- +};
- +module_platform_driver(lpc18xx_dwmac_driver);
- +
- +MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
- +MODULE_DESCRIPTION("DWMAC glue for LPC18xx/43xx Ethernet");
- +MODULE_LICENSE("GPL v2");
- --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
- +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
- @@ -15,9 +15,12 @@
- #include <linux/ethtool.h>
- #include <linux/io.h>
- #include <linux/ioport.h>
- +#include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/stmmac.h>
-
- +#include "stmmac_platform.h"
- +
- #define ETHMAC_SPEED_100 BIT(1)
-
- struct meson_dwmac {
- @@ -44,24 +47,54 @@ static void meson6_dwmac_fix_mac_speed(v
- writel(val, dwmac->reg);
- }
-
- -static void *meson6_dwmac_setup(struct platform_device *pdev)
- +static int meson6_dwmac_probe(struct platform_device *pdev)
- {
- + struct plat_stmmacenet_data *plat_dat;
- + struct stmmac_resources stmmac_res;
- struct meson_dwmac *dwmac;
- struct resource *res;
- + int ret;
- +
- + ret = stmmac_get_platform_resources(pdev, &stmmac_res);
- + if (ret)
- + return ret;
- +
- + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
- + if (IS_ERR(plat_dat))
- + return PTR_ERR(plat_dat);
-
- dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
- if (!dwmac)
- - return ERR_PTR(-ENOMEM);
- + return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- dwmac->reg = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(dwmac->reg))
- - return dwmac->reg;
- + return PTR_ERR(dwmac->reg);
- +
- + plat_dat->bsp_priv = dwmac;
- + plat_dat->fix_mac_speed = meson6_dwmac_fix_mac_speed;
-
- - return dwmac;
- + return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
- }
-
- -const struct stmmac_of_data meson6_dwmac_data = {
- - .setup = meson6_dwmac_setup,
- - .fix_mac_speed = meson6_dwmac_fix_mac_speed,
- +static const struct of_device_id meson6_dwmac_match[] = {
- + { .compatible = "amlogic,meson6-dwmac" },
- + { }
- };
- +MODULE_DEVICE_TABLE(of, meson6_dwmac_match);
- +
- +static struct platform_driver meson6_dwmac_driver = {
- + .probe = meson6_dwmac_probe,
- + .remove = stmmac_pltfr_remove,
- + .driver = {
- + .name = "meson6-dwmac",
- + .pm = &stmmac_pltfr_pm_ops,
- + .of_match_table = meson6_dwmac_match,
- + },
- +};
- +module_platform_driver(meson6_dwmac_driver);
- +
- +MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
- +MODULE_DESCRIPTION("Amlogic Meson DWMAC glue layer");
- +MODULE_LICENSE("GPL v2");
- --- /dev/null
- +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
- @@ -0,0 +1,626 @@
- +/**
- + * dwmac-rk.c - Rockchip RK3288 DWMAC specific glue layer
- + *
- + * Copyright (C) 2014 Chen-Zhi (Roger Chen)
- + *
- + * Chen-Zhi (Roger Chen) <roger.chen@rock-chips.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + */
- +
- +#include <linux/stmmac.h>
- +#include <linux/bitops.h>
- +#include <linux/clk.h>
- +#include <linux/phy.h>
- +#include <linux/of_net.h>
- +#include <linux/gpio.h>
- +#include <linux/module.h>
- +#include <linux/of_gpio.h>
- +#include <linux/of_device.h>
- +#include <linux/platform_device.h>
- +#include <linux/regulator/consumer.h>
- +#include <linux/delay.h>
- +#include <linux/mfd/syscon.h>
- +#include <linux/regmap.h>
- +
- +#include "stmmac_platform.h"
- +
- +struct rk_priv_data;
- +struct rk_gmac_ops {
- + void (*set_to_rgmii)(struct rk_priv_data *bsp_priv,
- + int tx_delay, int rx_delay);
- + void (*set_to_rmii)(struct rk_priv_data *bsp_priv);
- + void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed);
- + void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed);
- +};
- +
- +struct rk_priv_data {
- + struct platform_device *pdev;
- + int phy_iface;
- + struct regulator *regulator;
- + const struct rk_gmac_ops *ops;
- +
- + bool clk_enabled;
- + bool clock_input;
- +
- + struct clk *clk_mac;
- + struct clk *gmac_clkin;
- + struct clk *mac_clk_rx;
- + struct clk *mac_clk_tx;
- + struct clk *clk_mac_ref;
- + struct clk *clk_mac_refout;
- + struct clk *aclk_mac;
- + struct clk *pclk_mac;
- +
- + int tx_delay;
- + int rx_delay;
- +
- + struct regmap *grf;
- +};
- +
- +#define HIWORD_UPDATE(val, mask, shift) \
- + ((val) << (shift) | (mask) << ((shift) + 16))
- +
- +#define GRF_BIT(nr) (BIT(nr) | BIT(nr+16))
- +#define GRF_CLR_BIT(nr) (BIT(nr+16))
- +
- +#define RK3288_GRF_SOC_CON1 0x0248
- +#define RK3288_GRF_SOC_CON3 0x0250
- +
- +/*RK3288_GRF_SOC_CON1*/
- +#define RK3288_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(6) | GRF_CLR_BIT(7) | \
- + GRF_CLR_BIT(8))
- +#define RK3288_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | \
- + GRF_BIT(8))
- +#define RK3288_GMAC_FLOW_CTRL GRF_BIT(9)
- +#define RK3288_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(9)
- +#define RK3288_GMAC_SPEED_10M GRF_CLR_BIT(10)
- +#define RK3288_GMAC_SPEED_100M GRF_BIT(10)
- +#define RK3288_GMAC_RMII_CLK_25M GRF_BIT(11)
- +#define RK3288_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(11)
- +#define RK3288_GMAC_CLK_125M (GRF_CLR_BIT(12) | GRF_CLR_BIT(13))
- +#define RK3288_GMAC_CLK_25M (GRF_BIT(12) | GRF_BIT(13))
- +#define RK3288_GMAC_CLK_2_5M (GRF_CLR_BIT(12) | GRF_BIT(13))
- +#define RK3288_GMAC_RMII_MODE GRF_BIT(14)
- +#define RK3288_GMAC_RMII_MODE_CLR GRF_CLR_BIT(14)
- +
- +/*RK3288_GRF_SOC_CON3*/
- +#define RK3288_GMAC_TXCLK_DLY_ENABLE GRF_BIT(14)
- +#define RK3288_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(14)
- +#define RK3288_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15)
- +#define RK3288_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15)
- +#define RK3288_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7)
- +#define RK3288_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
- +
- +static void rk3288_set_to_rgmii(struct rk_priv_data *bsp_priv,
- + int tx_delay, int rx_delay)
- +{
- + struct device *dev = &bsp_priv->pdev->dev;
- +
- + if (IS_ERR(bsp_priv->grf)) {
- + dev_err(dev, "Missing rockchip,grf property\n");
- + return;
- + }
- +
- + regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
- + RK3288_GMAC_PHY_INTF_SEL_RGMII |
- + RK3288_GMAC_RMII_MODE_CLR);
- + regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON3,
- + RK3288_GMAC_RXCLK_DLY_ENABLE |
- + RK3288_GMAC_TXCLK_DLY_ENABLE |
- + RK3288_GMAC_CLK_RX_DL_CFG(rx_delay) |
- + RK3288_GMAC_CLK_TX_DL_CFG(tx_delay));
- +}
- +
- +static void rk3288_set_to_rmii(struct rk_priv_data *bsp_priv)
- +{
- + struct device *dev = &bsp_priv->pdev->dev;
- +
- + if (IS_ERR(bsp_priv->grf)) {
- + dev_err(dev, "Missing rockchip,grf property\n");
- + return;
- + }
- +
- + regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
- + RK3288_GMAC_PHY_INTF_SEL_RMII | RK3288_GMAC_RMII_MODE);
- +}
- +
- +static void rk3288_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
- +{
- + struct device *dev = &bsp_priv->pdev->dev;
- +
- + if (IS_ERR(bsp_priv->grf)) {
- + dev_err(dev, "Missing rockchip,grf property\n");
- + return;
- + }
- +
- + if (speed == 10)
- + regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
- + RK3288_GMAC_CLK_2_5M);
- + else if (speed == 100)
- + regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
- + RK3288_GMAC_CLK_25M);
- + else if (speed == 1000)
- + regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
- + RK3288_GMAC_CLK_125M);
- + else
- + dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
- +}
- +
- +static void rk3288_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
- +{
- + struct device *dev = &bsp_priv->pdev->dev;
- +
- + if (IS_ERR(bsp_priv->grf)) {
- + dev_err(dev, "Missing rockchip,grf property\n");
- + return;
- + }
- +
- + if (speed == 10) {
- + regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
- + RK3288_GMAC_RMII_CLK_2_5M |
- + RK3288_GMAC_SPEED_10M);
- + } else if (speed == 100) {
- + regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
- + RK3288_GMAC_RMII_CLK_25M |
- + RK3288_GMAC_SPEED_100M);
- + } else {
- + dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
- + }
- +}
- +
- +static const struct rk_gmac_ops rk3288_ops = {
- + .set_to_rgmii = rk3288_set_to_rgmii,
- + .set_to_rmii = rk3288_set_to_rmii,
- + .set_rgmii_speed = rk3288_set_rgmii_speed,
- + .set_rmii_speed = rk3288_set_rmii_speed,
- +};
- +
- +#define RK3368_GRF_SOC_CON15 0x043c
- +#define RK3368_GRF_SOC_CON16 0x0440
- +
- +/* RK3368_GRF_SOC_CON15 */
- +#define RK3368_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(9) | GRF_CLR_BIT(10) | \
- + GRF_CLR_BIT(11))
- +#define RK3368_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \
- + GRF_BIT(11))
- +#define RK3368_GMAC_FLOW_CTRL GRF_BIT(8)
- +#define RK3368_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(8)
- +#define RK3368_GMAC_SPEED_10M GRF_CLR_BIT(7)
- +#define RK3368_GMAC_SPEED_100M GRF_BIT(7)
- +#define RK3368_GMAC_RMII_CLK_25M GRF_BIT(3)
- +#define RK3368_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(3)
- +#define RK3368_GMAC_CLK_125M (GRF_CLR_BIT(4) | GRF_CLR_BIT(5))
- +#define RK3368_GMAC_CLK_25M (GRF_BIT(4) | GRF_BIT(5))
- +#define RK3368_GMAC_CLK_2_5M (GRF_CLR_BIT(4) | GRF_BIT(5))
- +#define RK3368_GMAC_RMII_MODE GRF_BIT(6)
- +#define RK3368_GMAC_RMII_MODE_CLR GRF_CLR_BIT(6)
- +
- +/* RK3368_GRF_SOC_CON16 */
- +#define RK3368_GMAC_TXCLK_DLY_ENABLE GRF_BIT(7)
- +#define RK3368_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(7)
- +#define RK3368_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15)
- +#define RK3368_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15)
- +#define RK3368_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8)
- +#define RK3368_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
- +
- +static void rk3368_set_to_rgmii(struct rk_priv_data *bsp_priv,
- + int tx_delay, int rx_delay)
- +{
- + struct device *dev = &bsp_priv->pdev->dev;
- +
- + if (IS_ERR(bsp_priv->grf)) {
- + dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
- + return;
- + }
- +
- + regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
- + RK3368_GMAC_PHY_INTF_SEL_RGMII |
- + RK3368_GMAC_RMII_MODE_CLR);
- + regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON16,
- + RK3368_GMAC_RXCLK_DLY_ENABLE |
- + RK3368_GMAC_TXCLK_DLY_ENABLE |
- + RK3368_GMAC_CLK_RX_DL_CFG(rx_delay) |
- + RK3368_GMAC_CLK_TX_DL_CFG(tx_delay));
- +}
- +
- +static void rk3368_set_to_rmii(struct rk_priv_data *bsp_priv)
- +{
- + struct device *dev = &bsp_priv->pdev->dev;
- +
- + if (IS_ERR(bsp_priv->grf)) {
- + dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
- + return;
- + }
- +
- + regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
- + RK3368_GMAC_PHY_INTF_SEL_RMII | RK3368_GMAC_RMII_MODE);
- +}
- +
- +static void rk3368_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
- +{
- + struct device *dev = &bsp_priv->pdev->dev;
- +
- + if (IS_ERR(bsp_priv->grf)) {
- + dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
- + return;
- + }
- +
- + if (speed == 10)
- + regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
- + RK3368_GMAC_CLK_2_5M);
- + else if (speed == 100)
- + regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
- + RK3368_GMAC_CLK_25M);
- + else if (speed == 1000)
- + regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
- + RK3368_GMAC_CLK_125M);
- + else
- + dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
- +}
- +
- +static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
- +{
- + struct device *dev = &bsp_priv->pdev->dev;
- +
- + if (IS_ERR(bsp_priv->grf)) {
- + dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
- + return;
- + }
- +
- + if (speed == 10) {
- + regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
- + RK3368_GMAC_RMII_CLK_2_5M |
- + RK3368_GMAC_SPEED_10M);
- + } else if (speed == 100) {
- + regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
- + RK3368_GMAC_RMII_CLK_25M |
- + RK3368_GMAC_SPEED_100M);
- + } else {
- + dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
- + }
- +}
- +
- +static const struct rk_gmac_ops rk3368_ops = {
- + .set_to_rgmii = rk3368_set_to_rgmii,
- + .set_to_rmii = rk3368_set_to_rmii,
- + .set_rgmii_speed = rk3368_set_rgmii_speed,
- + .set_rmii_speed = rk3368_set_rmii_speed,
- +};
- +
- +static int gmac_clk_init(struct rk_priv_data *bsp_priv)
- +{
- + struct device *dev = &bsp_priv->pdev->dev;
- +
- + bsp_priv->clk_enabled = false;
- +
- + bsp_priv->mac_clk_rx = devm_clk_get(dev, "mac_clk_rx");
- + if (IS_ERR(bsp_priv->mac_clk_rx))
- + dev_err(dev, "cannot get clock %s\n",
- + "mac_clk_rx");
- +
- + bsp_priv->mac_clk_tx = devm_clk_get(dev, "mac_clk_tx");
- + if (IS_ERR(bsp_priv->mac_clk_tx))
- + dev_err(dev, "cannot get clock %s\n",
- + "mac_clk_tx");
- +
- + bsp_priv->aclk_mac = devm_clk_get(dev, "aclk_mac");
- + if (IS_ERR(bsp_priv->aclk_mac))
- + dev_err(dev, "cannot get clock %s\n",
- + "aclk_mac");
- +
- + bsp_priv->pclk_mac = devm_clk_get(dev, "pclk_mac");
- + if (IS_ERR(bsp_priv->pclk_mac))
- + dev_err(dev, "cannot get clock %s\n",
- + "pclk_mac");
- +
- + bsp_priv->clk_mac = devm_clk_get(dev, "stmmaceth");
- + if (IS_ERR(bsp_priv->clk_mac))
- + dev_err(dev, "cannot get clock %s\n",
- + "stmmaceth");
- +
- + if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) {
- + bsp_priv->clk_mac_ref = devm_clk_get(dev, "clk_mac_ref");
- + if (IS_ERR(bsp_priv->clk_mac_ref))
- + dev_err(dev, "cannot get clock %s\n",
- + "clk_mac_ref");
- +
- + if (!bsp_priv->clock_input) {
- + bsp_priv->clk_mac_refout =
- + devm_clk_get(dev, "clk_mac_refout");
- + if (IS_ERR(bsp_priv->clk_mac_refout))
- + dev_err(dev, "cannot get clock %s\n",
- + "clk_mac_refout");
- + }
- + }
- +
- + if (bsp_priv->clock_input) {
- + dev_info(dev, "clock input from PHY\n");
- + } else {
- + if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
- + clk_set_rate(bsp_priv->clk_mac, 50000000);
- + }
- +
- + return 0;
- +}
- +
- +static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable)
- +{
- + int phy_iface = phy_iface = bsp_priv->phy_iface;
- +
- + if (enable) {
- + if (!bsp_priv->clk_enabled) {
- + if (phy_iface == PHY_INTERFACE_MODE_RMII) {
- + if (!IS_ERR(bsp_priv->mac_clk_rx))
- + clk_prepare_enable(
- + bsp_priv->mac_clk_rx);
- +
- + if (!IS_ERR(bsp_priv->clk_mac_ref))
- + clk_prepare_enable(
- + bsp_priv->clk_mac_ref);
- +
- + if (!IS_ERR(bsp_priv->clk_mac_refout))
- + clk_prepare_enable(
- + bsp_priv->clk_mac_refout);
- + }
- +
- + if (!IS_ERR(bsp_priv->aclk_mac))
- + clk_prepare_enable(bsp_priv->aclk_mac);
- +
- + if (!IS_ERR(bsp_priv->pclk_mac))
- + clk_prepare_enable(bsp_priv->pclk_mac);
- +
- + if (!IS_ERR(bsp_priv->mac_clk_tx))
- + clk_prepare_enable(bsp_priv->mac_clk_tx);
- +
- + /**
- + * if (!IS_ERR(bsp_priv->clk_mac))
- + * clk_prepare_enable(bsp_priv->clk_mac);
- + */
- + mdelay(5);
- + bsp_priv->clk_enabled = true;
- + }
- + } else {
- + if (bsp_priv->clk_enabled) {
- + if (phy_iface == PHY_INTERFACE_MODE_RMII) {
- + if (!IS_ERR(bsp_priv->mac_clk_rx))
- + clk_disable_unprepare(
- + bsp_priv->mac_clk_rx);
- +
- + if (!IS_ERR(bsp_priv->clk_mac_ref))
- + clk_disable_unprepare(
- + bsp_priv->clk_mac_ref);
- +
- + if (!IS_ERR(bsp_priv->clk_mac_refout))
- + clk_disable_unprepare(
- + bsp_priv->clk_mac_refout);
- + }
- +
- + if (!IS_ERR(bsp_priv->aclk_mac))
- + clk_disable_unprepare(bsp_priv->aclk_mac);
- +
- + if (!IS_ERR(bsp_priv->pclk_mac))
- + clk_disable_unprepare(bsp_priv->pclk_mac);
- +
- + if (!IS_ERR(bsp_priv->mac_clk_tx))
- + clk_disable_unprepare(bsp_priv->mac_clk_tx);
- + /**
- + * if (!IS_ERR(bsp_priv->clk_mac))
- + * clk_disable_unprepare(bsp_priv->clk_mac);
- + */
- + bsp_priv->clk_enabled = false;
- + }
- + }
- +
- + return 0;
- +}
- +
- +static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable)
- +{
- + struct regulator *ldo = bsp_priv->regulator;
- + int ret;
- + struct device *dev = &bsp_priv->pdev->dev;
- +
- + if (!ldo) {
- + dev_err(dev, "no regulator found\n");
- + return -1;
- + }
- +
- + if (enable) {
- + ret = regulator_enable(ldo);
- + if (ret)
- + dev_err(dev, "fail to enable phy-supply\n");
- + } else {
- + ret = regulator_disable(ldo);
- + if (ret)
- + dev_err(dev, "fail to disable phy-supply\n");
- + }
- +
- + return 0;
- +}
- +
- +static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
- + const struct rk_gmac_ops *ops)
- +{
- + struct rk_priv_data *bsp_priv;
- + struct device *dev = &pdev->dev;
- + int ret;
- + const char *strings = NULL;
- + int value;
- +
- + bsp_priv = devm_kzalloc(dev, sizeof(*bsp_priv), GFP_KERNEL);
- + if (!bsp_priv)
- + return ERR_PTR(-ENOMEM);
- +
- + bsp_priv->phy_iface = of_get_phy_mode(dev->of_node);
- + bsp_priv->ops = ops;
- +
- + bsp_priv->regulator = devm_regulator_get_optional(dev, "phy");
- + if (IS_ERR(bsp_priv->regulator)) {
- + if (PTR_ERR(bsp_priv->regulator) == -EPROBE_DEFER) {
- + dev_err(dev, "phy regulator is not available yet, deferred probing\n");
- + return ERR_PTR(-EPROBE_DEFER);
- + }
- + dev_err(dev, "no regulator found\n");
- + bsp_priv->regulator = NULL;
- + }
- +
- + ret = of_property_read_string(dev->of_node, "clock_in_out", &strings);
- + if (ret) {
- + dev_err(dev, "Can not read property: clock_in_out.\n");
- + bsp_priv->clock_input = true;
- + } else {
- + dev_info(dev, "clock input or output? (%s).\n",
- + strings);
- + if (!strcmp(strings, "input"))
- + bsp_priv->clock_input = true;
- + else
- + bsp_priv->clock_input = false;
- + }
- +
- + ret = of_property_read_u32(dev->of_node, "tx_delay", &value);
- + if (ret) {
- + bsp_priv->tx_delay = 0x30;
- + dev_err(dev, "Can not read property: tx_delay.");
- + dev_err(dev, "set tx_delay to 0x%x\n",
- + bsp_priv->tx_delay);
- + } else {
- + dev_info(dev, "TX delay(0x%x).\n", value);
- + bsp_priv->tx_delay = value;
- + }
- +
- + ret = of_property_read_u32(dev->of_node, "rx_delay", &value);
- + if (ret) {
- + bsp_priv->rx_delay = 0x10;
- + dev_err(dev, "Can not read property: rx_delay.");
- + dev_err(dev, "set rx_delay to 0x%x\n",
- + bsp_priv->rx_delay);
- + } else {
- + dev_info(dev, "RX delay(0x%x).\n", value);
- + bsp_priv->rx_delay = value;
- + }
- +
- + bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
- + "rockchip,grf");
- + bsp_priv->pdev = pdev;
- +
- + /*rmii or rgmii*/
- + if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) {
- + dev_info(dev, "init for RGMII\n");
- + bsp_priv->ops->set_to_rgmii(bsp_priv, bsp_priv->tx_delay,
- + bsp_priv->rx_delay);
- + } else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) {
- + dev_info(dev, "init for RMII\n");
- + bsp_priv->ops->set_to_rmii(bsp_priv);
- + } else {
- + dev_err(dev, "NO interface defined!\n");
- + }
- +
- + gmac_clk_init(bsp_priv);
- +
- + return bsp_priv;
- +}
- +
- +static int rk_gmac_init(struct platform_device *pdev, void *priv)
- +{
- + struct rk_priv_data *bsp_priv = priv;
- + int ret;
- +
- + ret = phy_power_on(bsp_priv, true);
- + if (ret)
- + return ret;
- +
- + ret = gmac_clk_enable(bsp_priv, true);
- + if (ret)
- + return ret;
- +
- + return 0;
- +}
- +
- +static void rk_gmac_exit(struct platform_device *pdev, void *priv)
- +{
- + struct rk_priv_data *gmac = priv;
- +
- + phy_power_on(gmac, false);
- + gmac_clk_enable(gmac, false);
- +}
- +
- +static void rk_fix_speed(void *priv, unsigned int speed)
- +{
- + struct rk_priv_data *bsp_priv = priv;
- + struct device *dev = &bsp_priv->pdev->dev;
- +
- + if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII)
- + bsp_priv->ops->set_rgmii_speed(bsp_priv, speed);
- + else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
- + bsp_priv->ops->set_rmii_speed(bsp_priv, speed);
- + else
- + dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface);
- +}
- +
- +static int rk_gmac_probe(struct platform_device *pdev)
- +{
- + struct plat_stmmacenet_data *plat_dat;
- + struct stmmac_resources stmmac_res;
- + const struct rk_gmac_ops *data;
- + int ret;
- +
- + data = of_device_get_match_data(&pdev->dev);
- + if (!data) {
- + dev_err(&pdev->dev, "no of match data provided\n");
- + return -EINVAL;
- + }
- +
- + ret = stmmac_get_platform_resources(pdev, &stmmac_res);
- + if (ret)
- + return ret;
- +
- + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
- + if (IS_ERR(plat_dat))
- + return PTR_ERR(plat_dat);
- +
- + plat_dat->has_gmac = true;
- + plat_dat->init = rk_gmac_init;
- + plat_dat->exit = rk_gmac_exit;
- + plat_dat->fix_mac_speed = rk_fix_speed;
- +
- + plat_dat->bsp_priv = rk_gmac_setup(pdev, data);
- + if (IS_ERR(plat_dat->bsp_priv))
- + return PTR_ERR(plat_dat->bsp_priv);
- +
- + ret = rk_gmac_init(pdev, plat_dat->bsp_priv);
- + if (ret)
- + return ret;
- +
- + return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
- +}
- +
- +static const struct of_device_id rk_gmac_dwmac_match[] = {
- + { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops },
- + { .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops },
- + { }
- +};
- +MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match);
- +
- +static struct platform_driver rk_gmac_dwmac_driver = {
- + .probe = rk_gmac_probe,
- + .remove = stmmac_pltfr_remove,
- + .driver = {
- + .name = "rk_gmac-dwmac",
- + .pm = &stmmac_pltfr_pm_ops,
- + .of_match_table = rk_gmac_dwmac_match,
- + },
- +};
- +module_platform_driver(rk_gmac_dwmac_driver);
- +
- +MODULE_AUTHOR("Chen-Zhi (Roger Chen) <roger.chen@rock-chips.com>");
- +MODULE_DESCRIPTION("Rockchip RK3288 DWMAC specific glue layer");
- +MODULE_LICENSE("GPL");
- --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
- +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
- @@ -23,7 +23,9 @@
- #include <linux/regmap.h>
- #include <linux/reset.h>
- #include <linux/stmmac.h>
- +
- #include "stmmac.h"
- +#include "stmmac_platform.h"
-
- #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
- #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
- @@ -89,7 +91,9 @@ static int socfpga_dwmac_parse_data(stru
- STMMAC_RESOURCE_NAME);
- if (IS_ERR(dwmac->stmmac_rst)) {
- dev_info(dev, "Could not get reset control!\n");
- - return -EINVAL;
- + if (PTR_ERR(dwmac->stmmac_rst) == -EPROBE_DEFER)
- + return -EPROBE_DEFER;
- + dwmac->stmmac_rst = NULL;
- }
-
- dwmac->interface = of_get_phy_mode(np);
- @@ -171,31 +175,6 @@ static int socfpga_dwmac_setup(struct so
- return 0;
- }
-
- -static void *socfpga_dwmac_probe(struct platform_device *pdev)
- -{
- - struct device *dev = &pdev->dev;
- - int ret;
- - struct socfpga_dwmac *dwmac;
- -
- - dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL);
- - if (!dwmac)
- - return ERR_PTR(-ENOMEM);
- -
- - ret = socfpga_dwmac_parse_data(dwmac, dev);
- - if (ret) {
- - dev_err(dev, "Unable to parse OF data\n");
- - return ERR_PTR(ret);
- - }
- -
- - ret = socfpga_dwmac_setup(dwmac);
- - if (ret) {
- - dev_err(dev, "couldn't setup SoC glue (%d)\n", ret);
- - return ERR_PTR(ret);
- - }
- -
- - return dwmac;
- -}
- -
- static void socfpga_dwmac_exit(struct platform_device *pdev, void *priv)
- {
- struct socfpga_dwmac *dwmac = priv;
- @@ -253,9 +232,65 @@ static int socfpga_dwmac_init(struct pla
- return ret;
- }
-
- -const struct stmmac_of_data socfpga_gmac_data = {
- - .setup = socfpga_dwmac_probe,
- - .init = socfpga_dwmac_init,
- - .exit = socfpga_dwmac_exit,
- - .fix_mac_speed = socfpga_dwmac_fix_mac_speed,
- +static int socfpga_dwmac_probe(struct platform_device *pdev)
- +{
- + struct plat_stmmacenet_data *plat_dat;
- + struct stmmac_resources stmmac_res;
- + struct device *dev = &pdev->dev;
- + int ret;
- + struct socfpga_dwmac *dwmac;
- +
- + ret = stmmac_get_platform_resources(pdev, &stmmac_res);
- + if (ret)
- + return ret;
- +
- + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
- + if (IS_ERR(plat_dat))
- + return PTR_ERR(plat_dat);
- +
- + dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL);
- + if (!dwmac)
- + return -ENOMEM;
- +
- + ret = socfpga_dwmac_parse_data(dwmac, dev);
- + if (ret) {
- + dev_err(dev, "Unable to parse OF data\n");
- + return ret;
- + }
- +
- + ret = socfpga_dwmac_setup(dwmac);
- + if (ret) {
- + dev_err(dev, "couldn't setup SoC glue (%d)\n", ret);
- + return ret;
- + }
- +
- + plat_dat->bsp_priv = dwmac;
- + plat_dat->init = socfpga_dwmac_init;
- + plat_dat->exit = socfpga_dwmac_exit;
- + plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed;
- +
- + ret = socfpga_dwmac_init(pdev, plat_dat->bsp_priv);
- + if (ret)
- + return ret;
- +
- + return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
- +}
- +
- +static const struct of_device_id socfpga_dwmac_match[] = {
- + { .compatible = "altr,socfpga-stmmac" },
- + { }
- };
- +MODULE_DEVICE_TABLE(of, socfpga_dwmac_match);
- +
- +static struct platform_driver socfpga_dwmac_driver = {
- + .probe = socfpga_dwmac_probe,
- + .remove = stmmac_pltfr_remove,
- + .driver = {
- + .name = "socfpga-dwmac",
- + .pm = &stmmac_pltfr_pm_ops,
- + .of_match_table = socfpga_dwmac_match,
- + },
- +};
- +module_platform_driver(socfpga_dwmac_driver);
- +
- +MODULE_LICENSE("GPL v2");
- --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
- +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
- @@ -1,4 +1,4 @@
- -/**
- +/*
- * dwmac-sti.c - STMicroelectronics DWMAC Specific Glue layer
- *
- * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited
- @@ -17,11 +17,15 @@
- #include <linux/stmmac.h>
- #include <linux/phy.h>
- #include <linux/mfd/syscon.h>
- +#include <linux/module.h>
- #include <linux/regmap.h>
- #include <linux/clk.h>
- #include <linux/of.h>
- +#include <linux/of_device.h>
- #include <linux/of_net.h>
-
- +#include "stmmac_platform.h"
- +
- #define DWMAC_125MHZ 125000000
- #define DWMAC_50MHZ 50000000
- #define DWMAC_25MHZ 25000000
- @@ -35,9 +39,8 @@
- #define IS_PHY_IF_MODE_GBIT(iface) (IS_PHY_IF_MODE_RGMII(iface) || \
- iface == PHY_INTERFACE_MODE_GMII)
-
- -/* STiH4xx register definitions (STiH415/STiH416/STiH407/STiH410 families) */
- -
- -/**
- +/* STiH4xx register definitions (STiH415/STiH416/STiH407/STiH410 families)
- + *
- * Below table summarizes the clock requirement and clock sources for
- * supported phy interface modes with link speeds.
- * ________________________________________________
- @@ -76,9 +79,7 @@
- #define STIH4XX_ETH_SEL_INTERNAL_NOTEXT_PHYCLK BIT(7)
- #define STIH4XX_ETH_SEL_TXCLK_NOT_CLK125 BIT(6)
-
- -/* STiD127 register definitions */
- -
- -/**
- +/* STiD127 register definitions
- *-----------------------
- * src |BIT(6)| BIT(7)|
- *-----------------------
- @@ -104,13 +105,13 @@
- #define EN_MASK GENMASK(1, 1)
- #define EN BIT(1)
-
- -/**
- +/*
- * 3 bits [4:2]
- * 000-GMII/MII
- * 001-RGMII
- * 010-SGMII
- * 100-RMII
- -*/
- + */
- #define MII_PHY_SEL_MASK GENMASK(4, 2)
- #define ETH_PHY_SEL_RMII BIT(4)
- #define ETH_PHY_SEL_SGMII BIT(3)
- @@ -123,11 +124,16 @@ struct sti_dwmac {
- bool ext_phyclk; /* Clock from external PHY */
- u32 tx_retime_src; /* TXCLK Retiming*/
- struct clk *clk; /* PHY clock */
- - int ctrl_reg; /* GMAC glue-logic control register */
- + u32 ctrl_reg; /* GMAC glue-logic control register */
- int clk_sel_reg; /* GMAC ext clk selection register */
- struct device *dev;
- struct regmap *regmap;
- u32 speed;
- + void (*fix_retime_src)(void *priv, unsigned int speed);
- +};
- +
- +struct sti_dwmac_of_data {
- + void (*fix_retime_src)(void *priv, unsigned int speed);
- };
-
- static u32 phy_intf_sels[] = {
- @@ -222,8 +228,9 @@ static void stid127_fix_retime_src(void
- regmap_update_bits(dwmac->regmap, reg, STID127_RETIME_SRC_MASK, val);
- }
-
- -static void sti_dwmac_ctrl_init(struct sti_dwmac *dwmac)
- +static int sti_dwmac_init(struct platform_device *pdev, void *priv)
- {
- + struct sti_dwmac *dwmac = priv;
- struct regmap *regmap = dwmac->regmap;
- int iface = dwmac->interface;
- struct device *dev = dwmac->dev;
- @@ -241,28 +248,8 @@ static void sti_dwmac_ctrl_init(struct s
-
- val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII;
- regmap_update_bits(regmap, reg, ENMII_MASK, val);
- -}
-
- -static int stix4xx_init(struct platform_device *pdev, void *priv)
- -{
- - struct sti_dwmac *dwmac = priv;
- - u32 spd = dwmac->speed;
- -
- - sti_dwmac_ctrl_init(dwmac);
- -
- - stih4xx_fix_retime_src(priv, spd);
- -
- - return 0;
- -}
- -
- -static int stid127_init(struct platform_device *pdev, void *priv)
- -{
- - struct sti_dwmac *dwmac = priv;
- - u32 spd = dwmac->speed;
- -
- - sti_dwmac_ctrl_init(dwmac);
- -
- - stid127_fix_retime_src(priv, spd);
- + dwmac->fix_retime_src(priv, dwmac->speed);
-
- return 0;
- }
- @@ -286,11 +273,6 @@ static int sti_dwmac_parse_data(struct s
- if (!np)
- return -EINVAL;
-
- - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-ethconf");
- - if (!res)
- - return -ENODATA;
- - dwmac->ctrl_reg = res->start;
- -
- /* clk selection from extra syscfg register */
- dwmac->clk_sel_reg = -ENXIO;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-clkconf");
- @@ -301,6 +283,12 @@ static int sti_dwmac_parse_data(struct s
- if (IS_ERR(regmap))
- return PTR_ERR(regmap);
-
- + err = of_property_read_u32_index(np, "st,syscon", 1, &dwmac->ctrl_reg);
- + if (err) {
- + dev_err(dev, "Can't get sysconfig ctrl offset (%d)\n", err);
- + return err;
- + }
- +
- dwmac->dev = dev;
- dwmac->interface = of_get_phy_mode(np);
- dwmac->regmap = regmap;
- @@ -310,16 +298,16 @@ static int sti_dwmac_parse_data(struct s
-
- if (IS_PHY_IF_MODE_GBIT(dwmac->interface)) {
- const char *rs;
- - dwmac->tx_retime_src = TX_RETIME_SRC_CLKGEN;
-
- err = of_property_read_string(np, "st,tx-retime-src", &rs);
- - if (err < 0)
- + if (err < 0) {
- dev_warn(dev, "Use internal clock source\n");
- -
- - if (!strcasecmp(rs, "clk_125"))
- + dwmac->tx_retime_src = TX_RETIME_SRC_CLKGEN;
- + } else if (!strcasecmp(rs, "clk_125")) {
- dwmac->tx_retime_src = TX_RETIME_SRC_CLK_125;
- - else if (!strcasecmp(rs, "txclk"))
- + } else if (!strcasecmp(rs, "txclk")) {
- dwmac->tx_retime_src = TX_RETIME_SRC_TXCLK;
- + }
-
- dwmac->speed = SPEED_1000;
- }
- @@ -333,34 +321,80 @@ static int sti_dwmac_parse_data(struct s
- return 0;
- }
-
- -static void *sti_dwmac_setup(struct platform_device *pdev)
- +static int sti_dwmac_probe(struct platform_device *pdev)
- {
- + struct plat_stmmacenet_data *plat_dat;
- + const struct sti_dwmac_of_data *data;
- + struct stmmac_resources stmmac_res;
- struct sti_dwmac *dwmac;
- int ret;
-
- + data = of_device_get_match_data(&pdev->dev);
- + if (!data) {
- + dev_err(&pdev->dev, "No OF match data provided\n");
- + return -EINVAL;
- + }
- +
- + ret = stmmac_get_platform_resources(pdev, &stmmac_res);
- + if (ret)
- + return ret;
- +
- + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
- + if (IS_ERR(plat_dat))
- + return PTR_ERR(plat_dat);
- +
- dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
- if (!dwmac)
- - return ERR_PTR(-ENOMEM);
- + return -ENOMEM;
-
- ret = sti_dwmac_parse_data(dwmac, pdev);
- if (ret) {
- dev_err(&pdev->dev, "Unable to parse OF data\n");
- - return ERR_PTR(ret);
- + return ret;
- }
-
- - return dwmac;
- + dwmac->fix_retime_src = data->fix_retime_src;
- +
- + plat_dat->bsp_priv = dwmac;
- + plat_dat->init = sti_dwmac_init;
- + plat_dat->exit = sti_dwmac_exit;
- + plat_dat->fix_mac_speed = data->fix_retime_src;
- +
- + ret = sti_dwmac_init(pdev, plat_dat->bsp_priv);
- + if (ret)
- + return ret;
- +
- + return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
- }
-
- -const struct stmmac_of_data stih4xx_dwmac_data = {
- - .fix_mac_speed = stih4xx_fix_retime_src,
- - .setup = sti_dwmac_setup,
- - .init = stix4xx_init,
- - .exit = sti_dwmac_exit,
- +static const struct sti_dwmac_of_data stih4xx_dwmac_data = {
- + .fix_retime_src = stih4xx_fix_retime_src,
- };
-
- -const struct stmmac_of_data stid127_dwmac_data = {
- - .fix_mac_speed = stid127_fix_retime_src,
- - .setup = sti_dwmac_setup,
- - .init = stid127_init,
- - .exit = sti_dwmac_exit,
- +static const struct sti_dwmac_of_data stid127_dwmac_data = {
- + .fix_retime_src = stid127_fix_retime_src,
- };
- +
- +static const struct of_device_id sti_dwmac_match[] = {
- + { .compatible = "st,stih415-dwmac", .data = &stih4xx_dwmac_data},
- + { .compatible = "st,stih416-dwmac", .data = &stih4xx_dwmac_data},
- + { .compatible = "st,stid127-dwmac", .data = &stid127_dwmac_data},
- + { .compatible = "st,stih407-dwmac", .data = &stih4xx_dwmac_data},
- + { }
- +};
- +MODULE_DEVICE_TABLE(of, sti_dwmac_match);
- +
- +static struct platform_driver sti_dwmac_driver = {
- + .probe = sti_dwmac_probe,
- + .remove = stmmac_pltfr_remove,
- + .driver = {
- + .name = "sti-dwmac",
- + .pm = &stmmac_pltfr_pm_ops,
- + .of_match_table = sti_dwmac_match,
- + },
- +};
- +module_platform_driver(sti_dwmac_driver);
- +
- +MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@st.com>");
- +MODULE_DESCRIPTION("STMicroelectronics DWMAC Specific Glue layer");
- +MODULE_LICENSE("GPL");
- --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
- +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
- @@ -1,4 +1,4 @@
- -/**
- +/*
- * dwmac-sunxi.c - Allwinner sunxi DWMAC specific glue layer
- *
- * Copyright (C) 2013 Chen-Yu Tsai
- @@ -18,10 +18,14 @@
-
- #include <linux/stmmac.h>
- #include <linux/clk.h>
- +#include <linux/module.h>
- #include <linux/phy.h>
- +#include <linux/platform_device.h>
- #include <linux/of_net.h>
- #include <linux/regulator/consumer.h>
-
- +#include "stmmac_platform.h"
- +
- struct sunxi_priv_data {
- int interface;
- int clk_enabled;
- @@ -29,35 +33,6 @@ struct sunxi_priv_data {
- struct regulator *regulator;
- };
-
- -static void *sun7i_gmac_setup(struct platform_device *pdev)
- -{
- - struct sunxi_priv_data *gmac;
- - struct device *dev = &pdev->dev;
- -
- - gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
- - if (!gmac)
- - return ERR_PTR(-ENOMEM);
- -
- - gmac->interface = of_get_phy_mode(dev->of_node);
- -
- - gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx");
- - if (IS_ERR(gmac->tx_clk)) {
- - dev_err(dev, "could not get tx clock\n");
- - return gmac->tx_clk;
- - }
- -
- - /* Optional regulator for PHY */
- - gmac->regulator = devm_regulator_get_optional(dev, "phy");
- - if (IS_ERR(gmac->regulator)) {
- - if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER)
- - return ERR_PTR(-EPROBE_DEFER);
- - dev_info(dev, "no regulator found\n");
- - gmac->regulator = NULL;
- - }
- -
- - return gmac;
- -}
- -
- #define SUN7I_GMAC_GMII_RGMII_RATE 125000000
- #define SUN7I_GMAC_MII_RATE 25000000
-
- @@ -128,13 +103,76 @@ static void sun7i_fix_speed(void *priv,
- }
- }
-
- -/* of_data specifying hardware features and callbacks.
- - * hardware features were copied from Allwinner drivers. */
- -const struct stmmac_of_data sun7i_gmac_data = {
- - .has_gmac = 1,
- - .tx_coe = 1,
- - .fix_mac_speed = sun7i_fix_speed,
- - .setup = sun7i_gmac_setup,
- - .init = sun7i_gmac_init,
- - .exit = sun7i_gmac_exit,
- +static int sun7i_gmac_probe(struct platform_device *pdev)
- +{
- + struct plat_stmmacenet_data *plat_dat;
- + struct stmmac_resources stmmac_res;
- + struct sunxi_priv_data *gmac;
- + struct device *dev = &pdev->dev;
- + int ret;
- +
- + ret = stmmac_get_platform_resources(pdev, &stmmac_res);
- + if (ret)
- + return ret;
- +
- + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
- + if (IS_ERR(plat_dat))
- + return PTR_ERR(plat_dat);
- +
- + gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
- + if (!gmac)
- + return -ENOMEM;
- +
- + gmac->interface = of_get_phy_mode(dev->of_node);
- +
- + gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx");
- + if (IS_ERR(gmac->tx_clk)) {
- + dev_err(dev, "could not get tx clock\n");
- + return PTR_ERR(gmac->tx_clk);
- + }
- +
- + /* Optional regulator for PHY */
- + gmac->regulator = devm_regulator_get_optional(dev, "phy");
- + if (IS_ERR(gmac->regulator)) {
- + if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER)
- + return -EPROBE_DEFER;
- + dev_info(dev, "no regulator found\n");
- + gmac->regulator = NULL;
- + }
- +
- + /* platform data specifying hardware features and callbacks.
- + * hardware features were copied from Allwinner drivers. */
- + plat_dat->tx_coe = 1;
- + plat_dat->has_gmac = true;
- + plat_dat->bsp_priv = gmac;
- + plat_dat->init = sun7i_gmac_init;
- + plat_dat->exit = sun7i_gmac_exit;
- + plat_dat->fix_mac_speed = sun7i_fix_speed;
- +
- + ret = sun7i_gmac_init(pdev, plat_dat->bsp_priv);
- + if (ret)
- + return ret;
- +
- + return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
- +}
- +
- +static const struct of_device_id sun7i_dwmac_match[] = {
- + { .compatible = "allwinner,sun7i-a20-gmac" },
- + { }
- };
- +MODULE_DEVICE_TABLE(of, sun7i_dwmac_match);
- +
- +static struct platform_driver sun7i_dwmac_driver = {
- + .probe = sun7i_gmac_probe,
- + .remove = stmmac_pltfr_remove,
- + .driver = {
- + .name = "sun7i-dwmac",
- + .pm = &stmmac_pltfr_pm_ops,
- + .of_match_table = sun7i_dwmac_match,
- + },
- +};
- +module_platform_driver(sun7i_dwmac_driver);
- +
- +MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
- +MODULE_DESCRIPTION("Allwinner sunxi DWMAC specific glue layer");
- +MODULE_LICENSE("GPL");
- --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
- +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
- @@ -172,6 +172,7 @@ enum inter_frame_gap {
- /* GMAC FLOW CTRL defines */
- #define GMAC_FLOW_CTRL_PT_MASK 0xffff0000 /* Pause Time Mask */
- #define GMAC_FLOW_CTRL_PT_SHIFT 16
- +#define GMAC_FLOW_CTRL_UP 0x00000008 /* Unicast pause frame enable */
- #define GMAC_FLOW_CTRL_RFE 0x00000004 /* Rx Flow Control Enable */
- #define GMAC_FLOW_CTRL_TFE 0x00000002 /* Tx Flow Control Enable */
- #define GMAC_FLOW_CTRL_FCB_BPA 0x00000001 /* Flow Control Busy ... */
- @@ -246,6 +247,56 @@ enum ttc_control {
- #define DMA_CONTROL_FEF 0x00000080
- #define DMA_CONTROL_FUF 0x00000040
-
- +/* Receive flow control activation field
- + * RFA field in DMA control register, bits 23,10:9
- + */
- +#define DMA_CONTROL_RFA_MASK 0x00800600
- +
- +/* Receive flow control deactivation field
- + * RFD field in DMA control register, bits 22,12:11
- + */
- +#define DMA_CONTROL_RFD_MASK 0x00401800
- +
- +/* RFD and RFA fields are encoded as follows
- + *
- + * Bit Field
- + * 0,00 - Full minus 1KB (only valid when rxfifo >= 4KB and EFC enabled)
- + * 0,01 - Full minus 2KB (only valid when rxfifo >= 4KB and EFC enabled)
- + * 0,10 - Full minus 3KB (only valid when rxfifo >= 4KB and EFC enabled)
- + * 0,11 - Full minus 4KB (only valid when rxfifo > 4KB and EFC enabled)
- + * 1,00 - Full minus 5KB (only valid when rxfifo > 8KB and EFC enabled)
- + * 1,01 - Full minus 6KB (only valid when rxfifo > 8KB and EFC enabled)
- + * 1,10 - Full minus 7KB (only valid when rxfifo > 8KB and EFC enabled)
- + * 1,11 - Reserved
- + *
- + * RFD should always be > RFA for a given FIFO size. RFD == RFA may work,
- + * but packet throughput performance may not be as expected.
- + *
- + * Be sure that bit 3 in GMAC Register 6 is set for Unicast Pause frame
- + * detection (IEEE Specification Requirement, Annex 31B, 31B.1, Pause
- + * Description).
- + *
- + * Be sure that DZPA (bit 7 in Flow Control Register, GMAC Register 6),
- + * is set to 0. This allows pause frames with a quanta of 0 to be sent
- + * as an XOFF message to the link peer.
- + */
- +
- +#define RFA_FULL_MINUS_1K 0x00000000
- +#define RFA_FULL_MINUS_2K 0x00000200
- +#define RFA_FULL_MINUS_3K 0x00000400
- +#define RFA_FULL_MINUS_4K 0x00000600
- +#define RFA_FULL_MINUS_5K 0x00800000
- +#define RFA_FULL_MINUS_6K 0x00800200
- +#define RFA_FULL_MINUS_7K 0x00800400
- +
- +#define RFD_FULL_MINUS_1K 0x00000000
- +#define RFD_FULL_MINUS_2K 0x00000800
- +#define RFD_FULL_MINUS_3K 0x00001000
- +#define RFD_FULL_MINUS_4K 0x00001800
- +#define RFD_FULL_MINUS_5K 0x00400000
- +#define RFD_FULL_MINUS_6K 0x00400800
- +#define RFD_FULL_MINUS_7K 0x00401000
- +
- enum rtc_control {
- DMA_CONTROL_RTC_64 = 0x00000000,
- DMA_CONTROL_RTC_32 = 0x00000008,
- --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
- +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
- @@ -201,7 +201,10 @@ static void dwmac1000_flow_ctrl(struct m
- unsigned int fc, unsigned int pause_time)
- {
- void __iomem *ioaddr = hw->pcsr;
- - unsigned int flow = 0;
- + /* Set flow such that DZPQ in Mac Register 6 is 0,
- + * and unicast pause detect is enabled.
- + */
- + unsigned int flow = GMAC_FLOW_CTRL_UP;
-
- pr_debug("GMAC Flow-Control:\n");
- if (fc & FLOW_RX) {
- --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
- +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
- @@ -70,10 +70,6 @@ static int dwmac1000_dma_init(void __iom
- if (mb)
- value |= DMA_BUS_MODE_MB;
-
- -#ifdef CONFIG_STMMAC_DA
- - value |= DMA_BUS_MODE_DA; /* Rx has priority over tx */
- -#endif
- -
- if (atds)
- value |= DMA_BUS_MODE_ATDS;
-
- @@ -110,8 +106,29 @@ static int dwmac1000_dma_init(void __iom
- return 0;
- }
-
- +static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
- +{
- + csr6 &= ~DMA_CONTROL_RFA_MASK;
- + csr6 &= ~DMA_CONTROL_RFD_MASK;
- +
- + /* Leave flow control disabled if receive fifo size is less than
- + * 4K or 0. Otherwise, send XOFF when fifo is 1K less than full,
- + * and send XON when 2K less than full.
- + */
- + if (rxfifosz < 4096) {
- + csr6 &= ~DMA_CONTROL_EFC;
- + pr_debug("GMAC: disabling flow control, rxfifo too small(%d)\n",
- + rxfifosz);
- + } else {
- + csr6 |= DMA_CONTROL_EFC;
- + csr6 |= RFA_FULL_MINUS_1K;
- + csr6 |= RFD_FULL_MINUS_2K;
- + }
- + return csr6;
- +}
- +
- static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode,
- - int rxmode)
- + int rxmode, int rxfifosz)
- {
- u32 csr6 = readl(ioaddr + DMA_CONTROL);
-
- @@ -157,6 +174,9 @@ static void dwmac1000_dma_operation_mode
- csr6 |= DMA_CONTROL_RTC_128;
- }
-
- + /* Configure flow control based on rx fifo size */
- + csr6 = dwmac1000_configure_fc(csr6, rxfifosz);
- +
- writel(csr6, ioaddr + DMA_CONTROL);
- }
-
- --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
- +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
- @@ -72,7 +72,7 @@ static int dwmac100_dma_init(void __iome
- * control register.
- */
- static void dwmac100_dma_operation_mode(void __iomem *ioaddr, int txmode,
- - int rxmode)
- + int rxmode, int rxfifosz)
- {
- u32 csr6 = readl(ioaddr + DMA_CONTROL);
-
- --- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
- +++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
- @@ -73,7 +73,7 @@
- #define MMC_RX_OCTETCOUNT_G 0x00000188
- #define MMC_RX_BROADCASTFRAME_G 0x0000018c
- #define MMC_RX_MULTICASTFRAME_G 0x00000190
- -#define MMC_RX_CRC_ERRROR 0x00000194
- +#define MMC_RX_CRC_ERROR 0x00000194
- #define MMC_RX_ALIGN_ERROR 0x00000198
- #define MMC_RX_RUN_ERROR 0x0000019C
- #define MMC_RX_JABBER_ERROR 0x000001A0
- @@ -196,7 +196,7 @@ void dwmac_mmc_read(void __iomem *ioaddr
- mmc->mmc_rx_octetcount_g += readl(ioaddr + MMC_RX_OCTETCOUNT_G);
- mmc->mmc_rx_broadcastframe_g += readl(ioaddr + MMC_RX_BROADCASTFRAME_G);
- mmc->mmc_rx_multicastframe_g += readl(ioaddr + MMC_RX_MULTICASTFRAME_G);
- - mmc->mmc_rx_crc_error += readl(ioaddr + MMC_RX_CRC_ERRROR);
- + mmc->mmc_rx_crc_error += readl(ioaddr + MMC_RX_CRC_ERROR);
- mmc->mmc_rx_align_error += readl(ioaddr + MMC_RX_ALIGN_ERROR);
- mmc->mmc_rx_run_error += readl(ioaddr + MMC_RX_RUN_ERROR);
- mmc->mmc_rx_jabber_error += readl(ioaddr + MMC_RX_JABBER_ERROR);
- --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
- +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
- @@ -34,6 +34,14 @@
- #include <linux/ptp_clock_kernel.h>
- #include <linux/reset.h>
-
- +struct stmmac_resources {
- + void __iomem *addr;
- + const char *mac;
- + int wol_irq;
- + int lpi_irq;
- + int irq;
- +};
- +
- struct stmmac_tx_info {
- dma_addr_t buf;
- bool map_as_page;
- @@ -97,6 +105,7 @@ struct stmmac_priv {
- int wolopts;
- int wol_irq;
- struct clk *stmmac_clk;
- + struct clk *pclk;
- struct reset_control *stmmac_rst;
- int clk_csr;
- struct timer_list eee_ctrl_timer;
- @@ -116,97 +125,28 @@ struct stmmac_priv {
- int use_riwt;
- int irq_wake;
- spinlock_t ptp_lock;
- +
- +#ifdef CONFIG_DEBUG_FS
- + struct dentry *dbgfs_dir;
- + struct dentry *dbgfs_rings_status;
- + struct dentry *dbgfs_dma_cap;
- +#endif
- };
-
- int stmmac_mdio_unregister(struct net_device *ndev);
- int stmmac_mdio_register(struct net_device *ndev);
- int stmmac_mdio_reset(struct mii_bus *mii);
- void stmmac_set_ethtool_ops(struct net_device *netdev);
- -extern const struct stmmac_desc_ops enh_desc_ops;
- -extern const struct stmmac_desc_ops ndesc_ops;
- -extern const struct stmmac_hwtimestamp stmmac_ptp;
- +
- int stmmac_ptp_register(struct stmmac_priv *priv);
- void stmmac_ptp_unregister(struct stmmac_priv *priv);
- int stmmac_resume(struct net_device *ndev);
- int stmmac_suspend(struct net_device *ndev);
- int stmmac_dvr_remove(struct net_device *ndev);
- -struct stmmac_priv *stmmac_dvr_probe(struct device *device,
- - struct plat_stmmacenet_data *plat_dat,
- - void __iomem *addr);
- +int stmmac_dvr_probe(struct device *device,
- + struct plat_stmmacenet_data *plat_dat,
- + struct stmmac_resources *res);
- void stmmac_disable_eee_mode(struct stmmac_priv *priv);
- bool stmmac_eee_init(struct stmmac_priv *priv);
-
- -#ifdef CONFIG_STMMAC_PLATFORM
- -#ifdef CONFIG_DWMAC_MESON
- -extern const struct stmmac_of_data meson6_dwmac_data;
- -#endif
- -#ifdef CONFIG_DWMAC_SUNXI
- -extern const struct stmmac_of_data sun7i_gmac_data;
- -#endif
- -#ifdef CONFIG_DWMAC_STI
- -extern const struct stmmac_of_data stih4xx_dwmac_data;
- -extern const struct stmmac_of_data stid127_dwmac_data;
- -#endif
- -#ifdef CONFIG_DWMAC_SOCFPGA
- -extern const struct stmmac_of_data socfpga_gmac_data;
- -#endif
- -extern struct platform_driver stmmac_pltfr_driver;
- -static inline int stmmac_register_platform(void)
- -{
- - int err;
- -
- - err = platform_driver_register(&stmmac_pltfr_driver);
- - if (err)
- - pr_err("stmmac: failed to register the platform driver\n");
- -
- - return err;
- -}
- -
- -static inline void stmmac_unregister_platform(void)
- -{
- - platform_driver_unregister(&stmmac_pltfr_driver);
- -}
- -#else
- -static inline int stmmac_register_platform(void)
- -{
- - pr_debug("stmmac: do not register the platf driver\n");
- -
- - return 0;
- -}
- -
- -static inline void stmmac_unregister_platform(void)
- -{
- -}
- -#endif /* CONFIG_STMMAC_PLATFORM */
- -
- -#ifdef CONFIG_STMMAC_PCI
- -extern struct pci_driver stmmac_pci_driver;
- -static inline int stmmac_register_pci(void)
- -{
- - int err;
- -
- - err = pci_register_driver(&stmmac_pci_driver);
- - if (err)
- - pr_err("stmmac: failed to register the PCI driver\n");
- -
- - return err;
- -}
- -
- -static inline void stmmac_unregister_pci(void)
- -{
- - pci_unregister_driver(&stmmac_pci_driver);
- -}
- -#else
- -static inline int stmmac_register_pci(void)
- -{
- - pr_debug("stmmac: do not register the PCI driver\n");
- -
- - return 0;
- -}
- -
- -static inline void stmmac_unregister_pci(void)
- -{
- -}
- -#endif /* CONFIG_STMMAC_PCI */
- -
- #endif /* __STMMAC_H__ */
- --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
- +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
- @@ -696,7 +696,7 @@ static int stmmac_set_coalesce(struct ne
- (ec->tx_max_coalesced_frames == 0))
- return -EINVAL;
-
- - if ((ec->tx_coalesce_usecs > STMMAC_COAL_TX_TIMER) ||
- + if ((ec->tx_coalesce_usecs > STMMAC_MAX_COAL_TX_TICK) ||
- (ec->tx_max_coalesced_frames > STMMAC_TX_MAX_FRAMES))
- return -EINVAL;
-
- --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
- +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
- @@ -44,14 +44,15 @@
- #include <linux/slab.h>
- #include <linux/prefetch.h>
- #include <linux/pinctrl/consumer.h>
- -#ifdef CONFIG_STMMAC_DEBUG_FS
- +#ifdef CONFIG_DEBUG_FS
- #include <linux/debugfs.h>
- #include <linux/seq_file.h>
- -#endif /* CONFIG_STMMAC_DEBUG_FS */
- +#endif /* CONFIG_DEBUG_FS */
- #include <linux/net_tstamp.h>
- #include "stmmac_ptp.h"
- #include "stmmac.h"
- #include <linux/reset.h>
- +#include <linux/of_mdio.h>
-
- #define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x)
-
- @@ -116,17 +117,17 @@ MODULE_PARM_DESC(chain_mode, "To use cha
-
- static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
-
- -#ifdef CONFIG_STMMAC_DEBUG_FS
- +#ifdef CONFIG_DEBUG_FS
- static int stmmac_init_fs(struct net_device *dev);
- -static void stmmac_exit_fs(void);
- +static void stmmac_exit_fs(struct net_device *dev);
- #endif
-
- #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
-
- /**
- * stmmac_verify_args - verify the driver parameters.
- - * Description: it verifies if some wrong parameter is passed to the driver.
- - * Note that wrong parameters are replaced with the default values.
- + * Description: it checks the driver parameters and set a default in case of
- + * errors.
- */
- static void stmmac_verify_args(void)
- {
- @@ -191,14 +192,8 @@ static void stmmac_clk_csr_set(struct st
-
- static void print_pkt(unsigned char *buf, int len)
- {
- - int j;
- - pr_debug("len = %d byte, buf addr: 0x%p", len, buf);
- - for (j = 0; j < len; j++) {
- - if ((j % 16) == 0)
- - pr_debug("\n %03x:", j);
- - pr_debug(" %02x", buf[j]);
- - }
- - pr_debug("\n");
- + pr_debug("len = %d byte, buf addr: 0x%p\n", len, buf);
- + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len);
- }
-
- /* minimum number of free TX descriptors required to wake up TX process */
- @@ -210,7 +205,7 @@ static inline u32 stmmac_tx_avail(struct
- }
-
- /**
- - * stmmac_hw_fix_mac_speed: callback for speed selection
- + * stmmac_hw_fix_mac_speed - callback for speed selection
- * @priv: driver private structure
- * Description: on some platforms (e.g. ST), some HW system configuraton
- * registers have to be set according to the link speed negotiated.
- @@ -224,9 +219,10 @@ static inline void stmmac_hw_fix_mac_spe
- }
-
- /**
- - * stmmac_enable_eee_mode: Check and enter in LPI mode
- + * stmmac_enable_eee_mode - check and enter in LPI mode
- * @priv: driver private structure
- - * Description: this function is to verify and enter in LPI mode for EEE.
- + * Description: this function is to verify and enter in LPI mode in case of
- + * EEE.
- */
- static void stmmac_enable_eee_mode(struct stmmac_priv *priv)
- {
- @@ -237,7 +233,7 @@ static void stmmac_enable_eee_mode(struc
- }
-
- /**
- - * stmmac_disable_eee_mode: disable/exit from EEE
- + * stmmac_disable_eee_mode - disable and exit from LPI mode
- * @priv: driver private structure
- * Description: this function is to exit and disable EEE in case of
- * LPI state is true. This is called by the xmit.
- @@ -250,7 +246,7 @@ void stmmac_disable_eee_mode(struct stmm
- }
-
- /**
- - * stmmac_eee_ctrl_timer: EEE TX SW timer.
- + * stmmac_eee_ctrl_timer - EEE TX SW timer.
- * @arg : data hook
- * Description:
- * if there is no data transfer and if we are not in LPI state,
- @@ -265,13 +261,12 @@ static void stmmac_eee_ctrl_timer(unsign
- }
-
- /**
- - * stmmac_eee_init: init EEE
- + * stmmac_eee_init - init EEE
- * @priv: driver private structure
- * Description:
- - * If the EEE support has been enabled while configuring the driver,
- - * if the GMAC actually supports the EEE (from the HW cap reg) and the
- - * phy can also manage EEE, so enable the LPI state and start the timer
- - * to verify if the tx path can enter in LPI state.
- + * if the GMAC supports the EEE (from the HW cap reg) and the phy device
- + * can also manage EEE, this function enable the LPI state and start related
- + * timer.
- */
- bool stmmac_eee_init(struct stmmac_priv *priv)
- {
- @@ -316,11 +311,11 @@ bool stmmac_eee_init(struct stmmac_priv
- spin_lock_irqsave(&priv->lock, flags);
- if (!priv->eee_active) {
- priv->eee_active = 1;
- - init_timer(&priv->eee_ctrl_timer);
- - priv->eee_ctrl_timer.function = stmmac_eee_ctrl_timer;
- - priv->eee_ctrl_timer.data = (unsigned long)priv;
- - priv->eee_ctrl_timer.expires = STMMAC_LPI_T(eee_timer);
- - add_timer(&priv->eee_ctrl_timer);
- + setup_timer(&priv->eee_ctrl_timer,
- + stmmac_eee_ctrl_timer,
- + (unsigned long)priv);
- + mod_timer(&priv->eee_ctrl_timer,
- + STMMAC_LPI_T(eee_timer));
-
- priv->hw->mac->set_eee_timer(priv->hw,
- STMMAC_DEFAULT_LIT_LS,
- @@ -338,7 +333,7 @@ out:
- return ret;
- }
-
- -/* stmmac_get_tx_hwtstamp: get HW TX timestamps
- +/* stmmac_get_tx_hwtstamp - get HW TX timestamps
- * @priv: driver private structure
- * @entry : descriptor index to be used.
- * @skb : the socket buffer
- @@ -380,7 +375,7 @@ static void stmmac_get_tx_hwtstamp(struc
- return;
- }
-
- -/* stmmac_get_rx_hwtstamp: get HW RX timestamps
- +/* stmmac_get_rx_hwtstamp - get HW RX timestamps
- * @priv: driver private structure
- * @entry : descriptor index to be used.
- * @skb : the socket buffer
- @@ -615,7 +610,7 @@ static int stmmac_hwtstamp_ioctl(struct
- * where, freq_div_ratio = clk_ptp_ref_i/50MHz
- * hence, addend = ((2^32) * 50MHz)/clk_ptp_ref_i;
- * NOTE: clk_ptp_ref_i should be >= 50MHz to
- - * achive 20ns accuracy.
- + * achieve 20ns accuracy.
- *
- * 2^x * y == (y << x), hence
- * 2^32 * 50000000 ==> (50000000 << 32)
- @@ -636,11 +631,11 @@ static int stmmac_hwtstamp_ioctl(struct
- }
-
- /**
- - * stmmac_init_ptp: init PTP
- + * stmmac_init_ptp - init PTP
- * @priv: driver private structure
- - * Description: this is to verify if the HW supports the PTPv1 or v2.
- + * Description: this is to verify if the HW supports the PTPv1 or PTPv2.
- * This is done by looking at the HW cap. register.
- - * Also it registers the ptp driver.
- + * This function also registers the ptp driver.
- */
- static int stmmac_init_ptp(struct stmmac_priv *priv)
- {
- @@ -682,9 +677,13 @@ static void stmmac_release_ptp(struct st
- }
-
- /**
- - * stmmac_adjust_link
- + * stmmac_adjust_link - adjusts the link parameters
- * @dev: net device structure
- - * Description: it adjusts the link parameters.
- + * Description: this is the helper called by the physical abstraction layer
- + * drivers to communicate the phy link status. According the speed and duplex
- + * this driver can invoke registered glue-logic as well.
- + * It also invoke the eee initialization because it could happen when switch
- + * on different networks (that are eee capable).
- */
- static void stmmac_adjust_link(struct net_device *dev)
- {
- @@ -774,7 +773,7 @@ static void stmmac_adjust_link(struct ne
- }
-
- /**
- - * stmmac_check_pcs_mode: verify if RGMII/SGMII is supported
- + * stmmac_check_pcs_mode - verify if RGMII/SGMII is supported
- * @priv: driver private structure
- * Description: this is to verify if the HW supports the PCS.
- * Physical Coding Sublayer (PCS) interface that can be used when the MAC is
- @@ -818,21 +817,31 @@ static int stmmac_init_phy(struct net_de
- priv->speed = 0;
- priv->oldduplex = -1;
-
- - if (priv->plat->phy_bus_name)
- - snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
- - priv->plat->phy_bus_name, priv->plat->bus_id);
- - else
- - snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
- - priv->plat->bus_id);
- + if (priv->plat->phy_node) {
- + phydev = of_phy_connect(dev, priv->plat->phy_node,
- + &stmmac_adjust_link, 0, interface);
- + } else {
- + if (priv->plat->phy_bus_name)
- + snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
- + priv->plat->phy_bus_name, priv->plat->bus_id);
- + else
- + snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
- + priv->plat->bus_id);
-
- - snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
- - priv->plat->phy_addr);
- - pr_debug("stmmac_init_phy: trying to attach to %s\n", phy_id_fmt);
- + snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
- + priv->plat->phy_addr);
- + pr_debug("stmmac_init_phy: trying to attach to %s\n",
- + phy_id_fmt);
-
- - phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, interface);
- + phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link,
- + interface);
- + }
-
- - if (IS_ERR(phydev)) {
- + if (IS_ERR_OR_NULL(phydev)) {
- pr_err("%s: Could not attach to PHY\n", dev->name);
- + if (!phydev)
- + return -ENODEV;
- +
- return PTR_ERR(phydev);
- }
-
- @@ -850,7 +859,7 @@ static int stmmac_init_phy(struct net_de
- * device as well.
- * Note: phydev->phy_id is the result of reading the UID PHY registers.
- */
- - if (phydev->phy_id == 0) {
- + if (!priv->plat->phy_node && phydev->phy_id == 0) {
- phy_disconnect(phydev);
- return -ENODEV;
- }
- @@ -863,7 +872,7 @@ static int stmmac_init_phy(struct net_de
- }
-
- /**
- - * stmmac_display_ring: display ring
- + * stmmac_display_ring - display ring
- * @head: pointer to the head of the ring passed.
- * @size: size of the ring.
- * @extend_desc: to verify if extended descriptors are used.
- @@ -931,7 +940,7 @@ static int stmmac_set_bfsize(int mtu, in
- }
-
- /**
- - * stmmac_clear_descriptors: clear descriptors
- + * stmmac_clear_descriptors - clear descriptors
- * @priv: driver private structure
- * Description: this function is called to clear the tx and rx descriptors
- * in case of both basic and extended descriptors are used.
- @@ -963,18 +972,25 @@ static void stmmac_clear_descriptors(str
- (i == txsize - 1));
- }
-
- +/**
- + * stmmac_init_rx_buffers - init the RX descriptor buffer.
- + * @priv: driver private structure
- + * @p: descriptor pointer
- + * @i: descriptor index
- + * @flags: gfp flag.
- + * Description: this function is called to allocate a receive buffer, perform
- + * the DMA mapping and init the descriptor.
- + */
- static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
- int i, gfp_t flags)
- {
- struct sk_buff *skb;
-
- - skb = __netdev_alloc_skb(priv->dev, priv->dma_buf_sz + NET_IP_ALIGN,
- - flags);
- + skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags);
- if (!skb) {
- pr_err("%s: Rx init fails; skb is NULL\n", __func__);
- return -ENOMEM;
- }
- - skb_reserve(skb, NET_IP_ALIGN);
- priv->rx_skbuff[i] = skb;
- priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
- priv->dma_buf_sz,
- @@ -1007,7 +1023,8 @@ static void stmmac_free_rx_buffers(struc
- /**
- * init_dma_desc_rings - init the RX/TX descriptor rings
- * @dev: net device structure
- - * Description: this function initializes the DMA RX/TX descriptors
- + * @flags: gfp flag.
- + * Description: this function initializes the DMA RX/TX descriptors
- * and allocates the socket buffers. It suppors the chained and ring
- * modes.
- */
- @@ -1089,6 +1106,7 @@ static int init_dma_desc_rings(struct ne
-
- priv->dirty_tx = 0;
- priv->cur_tx = 0;
- + netdev_reset_queue(priv->dev);
-
- stmmac_clear_descriptors(priv);
-
- @@ -1144,6 +1162,14 @@ static void dma_free_tx_skbufs(struct st
- }
- }
-
- +/**
- + * alloc_dma_desc_resources - alloc TX/RX resources.
- + * @priv: private structure
- + * Description: according to which descriptor can be used (extend or basic)
- + * this function allocates the resources for TX and RX paths. In case of
- + * reception, for example, it pre-allocated the RX socket buffer in order to
- + * allow zero-copy mechanism.
- + */
- static int alloc_dma_desc_resources(struct stmmac_priv *priv)
- {
- unsigned int txsize = priv->dma_tx_size;
- @@ -1255,13 +1281,15 @@ static void free_dma_desc_resources(stru
- /**
- * stmmac_dma_operation_mode - HW DMA operation mode
- * @priv: driver private structure
- - * Description: it sets the DMA operation mode: tx/rx DMA thresholds
- - * or Store-And-Forward capability.
- + * Description: it is used for configuring the DMA operation mode register in
- + * order to program the tx/rx DMA thresholds or Store-And-Forward mode.
- */
- static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
- {
- + int rxfifosz = priv->plat->rx_fifo_size;
- +
- if (priv->plat->force_thresh_dma_mode)
- - priv->hw->dma->dma_mode(priv->ioaddr, tc, tc);
- + priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, rxfifosz);
- else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) {
- /*
- * In case of GMAC, SF mode can be enabled
- @@ -1270,20 +1298,23 @@ static void stmmac_dma_operation_mode(st
- * 2) There is no bugged Jumbo frame support
- * that needs to not insert csum in the TDES.
- */
- - priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE);
- - tc = SF_DMA_MODE;
- + priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE,
- + rxfifosz);
- + priv->xstats.threshold = SF_DMA_MODE;
- } else
- - priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
- + priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE,
- + rxfifosz);
- }
-
- /**
- - * stmmac_tx_clean:
- + * stmmac_tx_clean - to manage the transmission completion
- * @priv: driver private structure
- - * Description: it reclaims resources after transmission completes.
- + * Description: it reclaims the transmit resources after transmission completes.
- */
- static void stmmac_tx_clean(struct stmmac_priv *priv)
- {
- unsigned int txsize = priv->dma_tx_size;
- + unsigned int bytes_compl = 0, pkts_compl = 0;
-
- spin_lock(&priv->tx_lock);
-
- @@ -1340,6 +1371,8 @@ static void stmmac_tx_clean(struct stmma
- priv->hw->mode->clean_desc3(priv, p);
-
- if (likely(skb != NULL)) {
- + pkts_compl++;
- + bytes_compl += skb->len;
- dev_consume_skb_any(skb);
- priv->tx_skbuff[entry] = NULL;
- }
- @@ -1348,6 +1381,9 @@ static void stmmac_tx_clean(struct stmma
-
- priv->dirty_tx++;
- }
- +
- + netdev_completed_queue(priv->dev, pkts_compl, bytes_compl);
- +
- if (unlikely(netif_queue_stopped(priv->dev) &&
- stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv))) {
- netif_tx_lock(priv->dev);
- @@ -1378,10 +1414,10 @@ static inline void stmmac_disable_dma_ir
- }
-
- /**
- - * stmmac_tx_err: irq tx error mng function
- + * stmmac_tx_err - to manage the tx error
- * @priv: driver private structure
- * Description: it cleans the descriptors and restarts the transmission
- - * in case of errors.
- + * in case of transmission errors.
- */
- static void stmmac_tx_err(struct stmmac_priv *priv)
- {
- @@ -1402,6 +1438,7 @@ static void stmmac_tx_err(struct stmmac_
- (i == txsize - 1));
- priv->dirty_tx = 0;
- priv->cur_tx = 0;
- + netdev_reset_queue(priv->dev);
- priv->hw->dma->start_tx(priv->ioaddr);
-
- priv->dev->stats.tx_errors++;
- @@ -1409,16 +1446,16 @@ static void stmmac_tx_err(struct stmmac_
- }
-
- /**
- - * stmmac_dma_interrupt: DMA ISR
- + * stmmac_dma_interrupt - DMA ISR
- * @priv: driver private structure
- * Description: this is the DMA ISR. It is called by the main ISR.
- - * It calls the dwmac dma routine to understand which type of interrupt
- - * happened. In case of there is a Normal interrupt and either TX or RX
- - * interrupt happened so the NAPI is scheduled.
- + * It calls the dwmac dma routine and schedule poll method in case of some
- + * work can be done.
- */
- static void stmmac_dma_interrupt(struct stmmac_priv *priv)
- {
- int status;
- + int rxfifosz = priv->plat->rx_fifo_size;
-
- status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
- if (likely((status & handle_rx)) || (status & handle_tx)) {
- @@ -1429,9 +1466,15 @@ static void stmmac_dma_interrupt(struct
- }
- if (unlikely(status & tx_hard_error_bump_tc)) {
- /* Try to bump up the dma threshold on this failure */
- - if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) {
- + if (unlikely(priv->xstats.threshold != SF_DMA_MODE) &&
- + (tc <= 256)) {
- tc += 64;
- - priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
- + if (priv->plat->force_thresh_dma_mode)
- + priv->hw->dma->dma_mode(priv->ioaddr, tc, tc,
- + rxfifosz);
- + else
- + priv->hw->dma->dma_mode(priv->ioaddr, tc,
- + SF_DMA_MODE, rxfifosz);
- priv->xstats.threshold = tc;
- }
- } else if (unlikely(status == tx_hard_error))
- @@ -1457,6 +1500,12 @@ static void stmmac_mmc_setup(struct stmm
- pr_info(" No MAC Management Counters available\n");
- }
-
- +/**
- + * stmmac_get_synopsys_id - return the SYINID.
- + * @priv: driver private structure
- + * Description: this simple function is to decode and return the SYINID
- + * starting from the HW core register.
- + */
- static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
- {
- u32 hwid = priv->hw->synopsys_uid;
- @@ -1475,11 +1524,11 @@ static u32 stmmac_get_synopsys_id(struct
- }
-
- /**
- - * stmmac_selec_desc_mode: to select among: normal/alternate/extend descriptors
- + * stmmac_selec_desc_mode - to select among: normal/alternate/extend descriptors
- * @priv: driver private structure
- * Description: select the Enhanced/Alternate or Normal descriptors.
- - * In case of Enhanced/Alternate, it looks at the extended descriptors are
- - * supported by the HW cap. register.
- + * In case of Enhanced/Alternate, it checks if the extended descriptors are
- + * supported by the HW capability register.
- */
- static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
- {
- @@ -1501,7 +1550,7 @@ static void stmmac_selec_desc_mode(struc
- }
-
- /**
- - * stmmac_get_hw_features: get MAC capabilities from the HW cap. register.
- + * stmmac_get_hw_features - get MAC capabilities from the HW cap. register.
- * @priv: driver private structure
- * Description:
- * new GMAC chip generations have a new register to indicate the
- @@ -1559,7 +1608,7 @@ static int stmmac_get_hw_features(struct
- }
-
- /**
- - * stmmac_check_ether_addr: check if the MAC addr is valid
- + * stmmac_check_ether_addr - check if the MAC addr is valid
- * @priv: driver private structure
- * Description:
- * it is to verify if the MAC address is valid, in case of failures it
- @@ -1578,7 +1627,7 @@ static void stmmac_check_ether_addr(stru
- }
-
- /**
- - * stmmac_init_dma_engine: DMA init.
- + * stmmac_init_dma_engine - DMA init.
- * @priv: driver private structure
- * Description:
- * It inits the DMA invoking the specific MAC/GMAC callback.
- @@ -1607,7 +1656,7 @@ static int stmmac_init_dma_engine(struct
- }
-
- /**
- - * stmmac_tx_timer: mitigation sw timer for tx.
- + * stmmac_tx_timer - mitigation sw timer for tx.
- * @data: data pointer
- * Description:
- * This is the timer handler to directly invoke the stmmac_tx_clean.
- @@ -1620,7 +1669,7 @@ static void stmmac_tx_timer(unsigned lon
- }
-
- /**
- - * stmmac_init_tx_coalesce: init tx mitigation options.
- + * stmmac_init_tx_coalesce - init tx mitigation options.
- * @priv: driver private structure
- * Description:
- * This inits the transmit coalesce parameters: i.e. timer rate,
- @@ -1639,15 +1688,18 @@ static void stmmac_init_tx_coalesce(stru
- }
-
- /**
- - * stmmac_hw_setup: setup mac in a usable state.
- + * stmmac_hw_setup - setup mac in a usable state.
- * @dev : pointer to the device structure.
- * Description:
- - * This function sets up the ip in a usable state.
- + * this is the main function to setup the HW in a usable state because the
- + * dma engine is reset, the core registers are configured (e.g. AXI,
- + * Checksum features, timers). The DMA is ready to start receiving and
- + * transmitting.
- * Return value:
- * 0 on success and an appropriate (-)ve integer as defined in errno.h
- * file on failure.
- */
- -static int stmmac_hw_setup(struct net_device *dev)
- +static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
- {
- struct stmmac_priv *priv = netdev_priv(dev);
- int ret;
- @@ -1684,11 +1736,13 @@ static int stmmac_hw_setup(struct net_de
-
- stmmac_mmc_setup(priv);
-
- - ret = stmmac_init_ptp(priv);
- - if (ret && ret != -EOPNOTSUPP)
- - pr_warn("%s: failed PTP initialisation\n", __func__);
- + if (init_ptp) {
- + ret = stmmac_init_ptp(priv);
- + if (ret && ret != -EOPNOTSUPP)
- + pr_warn("%s: failed PTP initialisation\n", __func__);
- + }
-
- -#ifdef CONFIG_STMMAC_DEBUG_FS
- +#ifdef CONFIG_DEBUG_FS
- ret = stmmac_init_fs(dev);
- if (ret < 0)
- pr_warn("%s: failed debugFS registration\n", __func__);
- @@ -1763,7 +1817,7 @@ static int stmmac_open(struct net_device
- goto init_error;
- }
-
- - ret = stmmac_hw_setup(dev);
- + ret = stmmac_hw_setup(dev, true);
- if (ret < 0) {
- pr_err("%s: Hw setup failed\n", __func__);
- goto init_error;
- @@ -1870,8 +1924,8 @@ static int stmmac_release(struct net_dev
-
- netif_carrier_off(dev);
-
- -#ifdef CONFIG_STMMAC_DEBUG_FS
- - stmmac_exit_fs();
- +#ifdef CONFIG_DEBUG_FS
- + stmmac_exit_fs(dev);
- #endif
-
- stmmac_release_ptp(priv);
- @@ -1880,7 +1934,7 @@ static int stmmac_release(struct net_dev
- }
-
- /**
- - * stmmac_xmit: Tx entry point of the driver
- + * stmmac_xmit - Tx entry point of the driver
- * @skb : the socket buffer
- * @dev : device pointer
- * Description : this is the tx entry point of the driver.
- @@ -2024,6 +2078,7 @@ static netdev_tx_t stmmac_xmit(struct sk
- if (!priv->hwts_tx_en)
- skb_tx_timestamp(skb);
-
- + netdev_sent_queue(dev, skb->len);
- priv->hw->dma->enable_dma_transmission(priv->ioaddr);
-
- spin_unlock(&priv->tx_lock);
- @@ -2055,7 +2110,7 @@ static void stmmac_rx_vlan(struct net_de
-
-
- /**
- - * stmmac_rx_refill: refill used skb preallocated buffers
- + * stmmac_rx_refill - refill used skb preallocated buffers
- * @priv: driver private structure
- * Description : this is to reallocate the skb for the reception process
- * that is based on zero-copy.
- @@ -2106,7 +2161,7 @@ static inline void stmmac_rx_refill(stru
- }
-
- /**
- - * stmmac_rx_refill: refill used skb preallocated buffers
- + * stmmac_rx - manage the receive process
- * @priv: driver private structure
- * @limit: napi bugget.
- * Description : this the function called by the napi poll method.
- @@ -2375,8 +2430,11 @@ static int stmmac_set_features(struct ne
- * @irq: interrupt number.
- * @dev_id: to pass the net device pointer.
- * Description: this is the main driver interrupt service routine.
- - * It calls the DMA ISR and also the core ISR to manage PMT, MMC, LPI
- - * interrupts.
- + * It can call:
- + * o DMA service routine (to manage incoming frame reception and transmission
- + * status)
- + * o Core interrupts to manage: remote wake-up, management counter, LPI
- + * interrupts.
- */
- static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
- {
- @@ -2457,10 +2515,8 @@ static int stmmac_ioctl(struct net_devic
- return ret;
- }
-
- -#ifdef CONFIG_STMMAC_DEBUG_FS
- +#ifdef CONFIG_DEBUG_FS
- static struct dentry *stmmac_fs_dir;
- -static struct dentry *stmmac_rings_status;
- -static struct dentry *stmmac_dma_cap;
-
- static void sysfs_display_ring(void *head, int size, int extend_desc,
- struct seq_file *seq)
- @@ -2599,36 +2655,39 @@ static const struct file_operations stmm
-
- static int stmmac_init_fs(struct net_device *dev)
- {
- - /* Create debugfs entries */
- - stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
- + struct stmmac_priv *priv = netdev_priv(dev);
-
- - if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
- - pr_err("ERROR %s, debugfs create directory failed\n",
- - STMMAC_RESOURCE_NAME);
- + /* Create per netdev entries */
- + priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir);
- +
- + if (!priv->dbgfs_dir || IS_ERR(priv->dbgfs_dir)) {
- + pr_err("ERROR %s/%s, debugfs create directory failed\n",
- + STMMAC_RESOURCE_NAME, dev->name);
-
- return -ENOMEM;
- }
-
- /* Entry to report DMA RX/TX rings */
- - stmmac_rings_status = debugfs_create_file("descriptors_status",
- - S_IRUGO, stmmac_fs_dir, dev,
- - &stmmac_rings_status_fops);
- + priv->dbgfs_rings_status =
- + debugfs_create_file("descriptors_status", S_IRUGO,
- + priv->dbgfs_dir, dev,
- + &stmmac_rings_status_fops);
-
- - if (!stmmac_rings_status || IS_ERR(stmmac_rings_status)) {
- + if (!priv->dbgfs_rings_status || IS_ERR(priv->dbgfs_rings_status)) {
- pr_info("ERROR creating stmmac ring debugfs file\n");
- - debugfs_remove(stmmac_fs_dir);
- + debugfs_remove_recursive(priv->dbgfs_dir);
-
- return -ENOMEM;
- }
-
- /* Entry to report the DMA HW features */
- - stmmac_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, stmmac_fs_dir,
- - dev, &stmmac_dma_cap_fops);
- + priv->dbgfs_dma_cap = debugfs_create_file("dma_cap", S_IRUGO,
- + priv->dbgfs_dir,
- + dev, &stmmac_dma_cap_fops);
-
- - if (!stmmac_dma_cap || IS_ERR(stmmac_dma_cap)) {
- + if (!priv->dbgfs_dma_cap || IS_ERR(priv->dbgfs_dma_cap)) {
- pr_info("ERROR creating stmmac MMC debugfs file\n");
- - debugfs_remove(stmmac_rings_status);
- - debugfs_remove(stmmac_fs_dir);
- + debugfs_remove_recursive(priv->dbgfs_dir);
-
- return -ENOMEM;
- }
- @@ -2636,13 +2695,13 @@ static int stmmac_init_fs(struct net_dev
- return 0;
- }
-
- -static void stmmac_exit_fs(void)
- +static void stmmac_exit_fs(struct net_device *dev)
- {
- - debugfs_remove(stmmac_rings_status);
- - debugfs_remove(stmmac_dma_cap);
- - debugfs_remove(stmmac_fs_dir);
- + struct stmmac_priv *priv = netdev_priv(dev);
- +
- + debugfs_remove_recursive(priv->dbgfs_dir);
- }
- -#endif /* CONFIG_STMMAC_DEBUG_FS */
- +#endif /* CONFIG_DEBUG_FS */
-
- static const struct net_device_ops stmmac_netdev_ops = {
- .ndo_open = stmmac_open,
- @@ -2663,11 +2722,10 @@ static const struct net_device_ops stmma
- /**
- * stmmac_hw_init - Init the MAC device
- * @priv: driver private structure
- - * Description: this function detects which MAC device
- - * (GMAC/MAC10-100) has to attached, checks the HW capability
- - * (if supported) and sets the driver's features (for example
- - * to use the ring or chaine mode or support the normal/enh
- - * descriptor structure).
- + * Description: this function is to configure the MAC device according to
- + * some platform parameters or the HW capability register. It prepares the
- + * driver to use either ring or chain modes and to setup either enhanced or
- + * normal descriptors.
- */
- static int stmmac_hw_init(struct stmmac_priv *priv)
- {
- @@ -2714,7 +2772,11 @@ static int stmmac_hw_init(struct stmmac_
- priv->plat->enh_desc = priv->dma_cap.enh_desc;
- priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
-
- - priv->plat->tx_coe = priv->dma_cap.tx_coe;
- + /* TXCOE doesn't work in thresh DMA mode */
- + if (priv->plat->force_thresh_dma_mode)
- + priv->plat->tx_coe = 0;
- + else
- + priv->plat->tx_coe = priv->dma_cap.tx_coe;
-
- if (priv->dma_cap.rx_coe_type2)
- priv->plat->rx_coe = STMMAC_RX_COE_TYPE2;
- @@ -2747,13 +2809,15 @@ static int stmmac_hw_init(struct stmmac_
- * stmmac_dvr_probe
- * @device: device pointer
- * @plat_dat: platform data pointer
- - * @addr: iobase memory address
- + * @res: stmmac resource pointer
- * Description: this is the main probe function used to
- * call the alloc_etherdev, allocate the priv structure.
- + * Return:
- + * returns 0 on success, otherwise errno.
- */
- -struct stmmac_priv *stmmac_dvr_probe(struct device *device,
- - struct plat_stmmacenet_data *plat_dat,
- - void __iomem *addr)
- +int stmmac_dvr_probe(struct device *device,
- + struct plat_stmmacenet_data *plat_dat,
- + struct stmmac_resources *res)
- {
- int ret = 0;
- struct net_device *ndev = NULL;
- @@ -2761,7 +2825,7 @@ struct stmmac_priv *stmmac_dvr_probe(str
-
- ndev = alloc_etherdev(sizeof(struct stmmac_priv));
- if (!ndev)
- - return NULL;
- + return -ENOMEM;
-
- SET_NETDEV_DEV(ndev, device);
-
- @@ -2772,8 +2836,17 @@ struct stmmac_priv *stmmac_dvr_probe(str
- stmmac_set_ethtool_ops(ndev);
- priv->pause = pause;
- priv->plat = plat_dat;
- - priv->ioaddr = addr;
- - priv->dev->base_addr = (unsigned long)addr;
- + priv->ioaddr = res->addr;
- + priv->dev->base_addr = (unsigned long)res->addr;
- +
- + priv->dev->irq = res->irq;
- + priv->wol_irq = res->wol_irq;
- + priv->lpi_irq = res->lpi_irq;
- +
- + if (res->mac)
- + memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN);
- +
- + dev_set_drvdata(device, priv->dev);
-
- /* Verify driver arguments */
- stmmac_verify_args();
- @@ -2800,6 +2873,16 @@ struct stmmac_priv *stmmac_dvr_probe(str
- }
- clk_prepare_enable(priv->stmmac_clk);
-
- + priv->pclk = devm_clk_get(priv->device, "pclk");
- + if (IS_ERR(priv->pclk)) {
- + if (PTR_ERR(priv->pclk) == -EPROBE_DEFER) {
- + ret = -EPROBE_DEFER;
- + goto error_pclk_get;
- + }
- + priv->pclk = NULL;
- + }
- + clk_prepare_enable(priv->pclk);
- +
- priv->stmmac_rst = devm_reset_control_get(priv->device,
- STMMAC_RESOURCE_NAME);
- if (IS_ERR(priv->stmmac_rst)) {
- @@ -2878,19 +2961,22 @@ struct stmmac_priv *stmmac_dvr_probe(str
- }
- }
-
- - return priv;
- + return 0;
-
- error_mdio_register:
- unregister_netdev(ndev);
- error_netdev_register:
- netif_napi_del(&priv->napi);
- error_hw_init:
- + clk_disable_unprepare(priv->pclk);
- +error_pclk_get:
- clk_disable_unprepare(priv->stmmac_clk);
- error_clk_get:
- free_netdev(ndev);
-
- - return ERR_PTR(ret);
- + return ret;
- }
- +EXPORT_SYMBOL_GPL(stmmac_dvr_probe);
-
- /**
- * stmmac_dvr_remove
- @@ -2908,20 +2994,28 @@ int stmmac_dvr_remove(struct net_device
- priv->hw->dma->stop_tx(priv->ioaddr);
-
- stmmac_set_mac(priv->ioaddr, false);
- - if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
- - priv->pcs != STMMAC_PCS_RTBI)
- - stmmac_mdio_unregister(ndev);
- netif_carrier_off(ndev);
- unregister_netdev(ndev);
- if (priv->stmmac_rst)
- reset_control_assert(priv->stmmac_rst);
- + clk_disable_unprepare(priv->pclk);
- clk_disable_unprepare(priv->stmmac_clk);
- + if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
- + priv->pcs != STMMAC_PCS_RTBI)
- + stmmac_mdio_unregister(ndev);
- free_netdev(ndev);
-
- return 0;
- }
- +EXPORT_SYMBOL_GPL(stmmac_dvr_remove);
-
- -#ifdef CONFIG_PM
- +/**
- + * stmmac_suspend - suspend callback
- + * @ndev: net device pointer
- + * Description: this is the function to suspend the device and it is called
- + * by the platform driver to stop the network queue, release the resources,
- + * program the PMT register (for WoL), clean and release driver resources.
- + */
- int stmmac_suspend(struct net_device *ndev)
- {
- struct stmmac_priv *priv = netdev_priv(ndev);
- @@ -2954,6 +3048,7 @@ int stmmac_suspend(struct net_device *nd
- stmmac_set_mac(priv->ioaddr, false);
- pinctrl_pm_select_sleep_state(priv->device);
- /* Disable clock in case of PWM is off */
- + clk_disable(priv->pclk);
- clk_disable(priv->stmmac_clk);
- }
- spin_unlock_irqrestore(&priv->lock, flags);
- @@ -2963,7 +3058,14 @@ int stmmac_suspend(struct net_device *nd
- priv->oldduplex = -1;
- return 0;
- }
- +EXPORT_SYMBOL_GPL(stmmac_suspend);
-
- +/**
- + * stmmac_resume - resume callback
- + * @ndev: net device pointer
- + * Description: when resume this function is invoked to setup the DMA and CORE
- + * in a usable state.
- + */
- int stmmac_resume(struct net_device *ndev)
- {
- struct stmmac_priv *priv = netdev_priv(ndev);
- @@ -2987,6 +3089,7 @@ int stmmac_resume(struct net_device *nde
- pinctrl_pm_select_default_state(priv->device);
- /* enable the clk prevously disabled */
- clk_enable(priv->stmmac_clk);
- + clk_enable(priv->pclk);
- /* reset the phy so that it's ready */
- if (priv->mii)
- stmmac_mdio_reset(priv->mii);
- @@ -2995,7 +3098,7 @@ int stmmac_resume(struct net_device *nde
- netif_device_attach(ndev);
-
- init_dma_desc_rings(ndev, GFP_ATOMIC);
- - stmmac_hw_setup(ndev);
- + stmmac_hw_setup(ndev, false);
- stmmac_init_tx_coalesce(priv);
-
- napi_enable(&priv->napi);
- @@ -3009,37 +3112,7 @@ int stmmac_resume(struct net_device *nde
-
- return 0;
- }
- -#endif /* CONFIG_PM */
- -
- -/* Driver can be configured w/ and w/ both PCI and Platf drivers
- - * depending on the configuration selected.
- - */
- -static int __init stmmac_init(void)
- -{
- - int ret;
- -
- - ret = stmmac_register_platform();
- - if (ret)
- - goto err;
- - ret = stmmac_register_pci();
- - if (ret)
- - goto err_pci;
- - return 0;
- -err_pci:
- - stmmac_unregister_platform();
- -err:
- - pr_err("stmmac: driver registration failed\n");
- - return ret;
- -}
- -
- -static void __exit stmmac_exit(void)
- -{
- - stmmac_unregister_platform();
- - stmmac_unregister_pci();
- -}
- -
- -module_init(stmmac_init);
- -module_exit(stmmac_exit);
- +EXPORT_SYMBOL_GPL(stmmac_resume);
-
- #ifndef MODULE
- static int __init stmmac_cmdline_opt(char *str)
- @@ -3094,6 +3167,35 @@ err:
- __setup("stmmaceth=", stmmac_cmdline_opt);
- #endif /* MODULE */
-
- +static int __init stmmac_init(void)
- +{
- +#ifdef CONFIG_DEBUG_FS
- + /* Create debugfs main directory if it doesn't exist yet */
- + if (!stmmac_fs_dir) {
- + stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
- +
- + if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
- + pr_err("ERROR %s, debugfs create directory failed\n",
- + STMMAC_RESOURCE_NAME);
- +
- + return -ENOMEM;
- + }
- + }
- +#endif
- +
- + return 0;
- +}
- +
- +static void __exit stmmac_exit(void)
- +{
- +#ifdef CONFIG_DEBUG_FS
- + debugfs_remove_recursive(stmmac_fs_dir);
- +#endif
- +}
- +
- +module_init(stmmac_init)
- +module_exit(stmmac_exit)
- +
- MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver");
- MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
- MODULE_LICENSE("GPL");
- --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
- +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
- @@ -161,11 +161,16 @@ int stmmac_mdio_reset(struct mii_bus *bu
-
- if (!gpio_request(reset_gpio, "mdio-reset")) {
- gpio_direction_output(reset_gpio, active_low ? 1 : 0);
- - udelay(data->delays[0]);
- + if (data->delays[0])
- + msleep(DIV_ROUND_UP(data->delays[0], 1000));
- +
- gpio_set_value(reset_gpio, active_low ? 0 : 1);
- - udelay(data->delays[1]);
- + if (data->delays[1])
- + msleep(DIV_ROUND_UP(data->delays[1], 1000));
- +
- gpio_set_value(reset_gpio, active_low ? 1 : 0);
- - udelay(data->delays[2]);
- + if (data->delays[2])
- + msleep(DIV_ROUND_UP(data->delays[2], 1000));
- }
- }
- #endif
- --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
- +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
- @@ -24,38 +24,128 @@
- *******************************************************************************/
-
- #include <linux/pci.h>
- +#include <linux/dmi.h>
- +
- #include "stmmac.h"
-
- -static struct plat_stmmacenet_data plat_dat;
- -static struct stmmac_mdio_bus_data mdio_data;
- -static struct stmmac_dma_cfg dma_cfg;
- -
- -static void stmmac_default_data(void)
- -{
- - memset(&plat_dat, 0, sizeof(struct plat_stmmacenet_data));
- -
- - plat_dat.bus_id = 1;
- - plat_dat.phy_addr = 0;
- - plat_dat.interface = PHY_INTERFACE_MODE_GMII;
- - plat_dat.clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
- - plat_dat.has_gmac = 1;
- - plat_dat.force_sf_dma_mode = 1;
- -
- - mdio_data.phy_reset = NULL;
- - mdio_data.phy_mask = 0;
- - plat_dat.mdio_bus_data = &mdio_data;
- -
- - dma_cfg.pbl = 32;
- - dma_cfg.burst_len = DMA_AXI_BLEN_256;
- - plat_dat.dma_cfg = &dma_cfg;
- +/*
- + * This struct is used to associate PCI Function of MAC controller on a board,
- + * discovered via DMI, with the address of PHY connected to the MAC. The
- + * negative value of the address means that MAC controller is not connected
- + * with PHY.
- + */
- +struct stmmac_pci_dmi_data {
- + const char *name;
- + unsigned int func;
- + int phy_addr;
- +};
- +
- +struct stmmac_pci_info {
- + struct pci_dev *pdev;
- + int (*setup)(struct plat_stmmacenet_data *plat,
- + struct stmmac_pci_info *info);
- + struct stmmac_pci_dmi_data *dmi;
- +};
- +
- +static int stmmac_pci_find_phy_addr(struct stmmac_pci_info *info)
- +{
- + const char *name = dmi_get_system_info(DMI_BOARD_NAME);
- + unsigned int func = PCI_FUNC(info->pdev->devfn);
- + struct stmmac_pci_dmi_data *dmi;
- +
- + /*
- + * Galileo boards with old firmware don't support DMI. We always return
- + * 1 here, so at least first found MAC controller would be probed.
- + */
- + if (!name)
- + return 1;
- +
- + for (dmi = info->dmi; dmi->name && *dmi->name; dmi++) {
- + if (!strcmp(dmi->name, name) && dmi->func == func)
- + return dmi->phy_addr;
- + }
- +
- + return -ENODEV;
- +}
- +
- +static void stmmac_default_data(struct plat_stmmacenet_data *plat)
- +{
- + plat->bus_id = 1;
- + plat->phy_addr = 0;
- + plat->interface = PHY_INTERFACE_MODE_GMII;
- + plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
- + plat->has_gmac = 1;
- + plat->force_sf_dma_mode = 1;
- +
- + plat->mdio_bus_data->phy_reset = NULL;
- + plat->mdio_bus_data->phy_mask = 0;
- +
- + plat->dma_cfg->pbl = 32;
- + plat->dma_cfg->burst_len = DMA_AXI_BLEN_256;
- +
- + /* Set default value for multicast hash bins */
- + plat->multicast_filter_bins = HASH_TABLE_SIZE;
- +
- + /* Set default value for unicast filter entries */
- + plat->unicast_filter_entries = 1;
- +}
- +
- +static int quark_default_data(struct plat_stmmacenet_data *plat,
- + struct stmmac_pci_info *info)
- +{
- + struct pci_dev *pdev = info->pdev;
- + int ret;
- +
- + /*
- + * Refuse to load the driver and register net device if MAC controller
- + * does not connect to any PHY interface.
- + */
- + ret = stmmac_pci_find_phy_addr(info);
- + if (ret < 0)
- + return ret;
- +
- + plat->bus_id = PCI_DEVID(pdev->bus->number, pdev->devfn);
- + plat->phy_addr = ret;
- + plat->interface = PHY_INTERFACE_MODE_RMII;
- + plat->clk_csr = 2;
- + plat->has_gmac = 1;
- + plat->force_sf_dma_mode = 1;
- +
- + plat->mdio_bus_data->phy_reset = NULL;
- + plat->mdio_bus_data->phy_mask = 0;
- +
- + plat->dma_cfg->pbl = 16;
- + plat->dma_cfg->burst_len = DMA_AXI_BLEN_256;
- + plat->dma_cfg->fixed_burst = 1;
-
- /* Set default value for multicast hash bins */
- - plat_dat.multicast_filter_bins = HASH_TABLE_SIZE;
- + plat->multicast_filter_bins = HASH_TABLE_SIZE;
-
- /* Set default value for unicast filter entries */
- - plat_dat.unicast_filter_entries = 1;
- + plat->unicast_filter_entries = 1;
- +
- + return 0;
- }
-
- +static struct stmmac_pci_dmi_data quark_pci_dmi_data[] = {
- + {
- + .name = "Galileo",
- + .func = 6,
- + .phy_addr = 1,
- + },
- + {
- + .name = "GalileoGen2",
- + .func = 6,
- + .phy_addr = 1,
- + },
- + {}
- +};
- +
- +static struct stmmac_pci_info quark_pci_info = {
- + .setup = quark_default_data,
- + .dmi = quark_pci_dmi_data,
- +};
- +
- /**
- * stmmac_pci_probe
- *
- @@ -71,64 +161,65 @@ static void stmmac_default_data(void)
- static int stmmac_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
- {
- - int ret = 0;
- - void __iomem *addr = NULL;
- - struct stmmac_priv *priv = NULL;
- + struct stmmac_pci_info *info = (struct stmmac_pci_info *)id->driver_data;
- + struct plat_stmmacenet_data *plat;
- + struct stmmac_resources res;
- int i;
- + int ret;
- +
- + plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
- + if (!plat)
- + return -ENOMEM;
- +
- + plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
- + sizeof(*plat->mdio_bus_data),
- + GFP_KERNEL);
- + if (!plat->mdio_bus_data)
- + return -ENOMEM;
- +
- + plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg),
- + GFP_KERNEL);
- + if (!plat->dma_cfg)
- + return -ENOMEM;
-
- /* Enable pci device */
- - ret = pci_enable_device(pdev);
- + ret = pcim_enable_device(pdev);
- if (ret) {
- - pr_err("%s : ERROR: failed to enable %s device\n", __func__,
- - pci_name(pdev));
- + dev_err(&pdev->dev, "%s: ERROR: failed to enable device\n",
- + __func__);
- return ret;
- }
- - if (pci_request_regions(pdev, STMMAC_RESOURCE_NAME)) {
- - pr_err("%s: ERROR: failed to get PCI region\n", __func__);
- - ret = -ENODEV;
- - goto err_out_req_reg_failed;
- - }
-
- /* Get the base address of device */
- - for (i = 0; i <= 5; i++) {
- + for (i = 0; i <= PCI_STD_RESOURCE_END; i++) {
- if (pci_resource_len(pdev, i) == 0)
- continue;
- - addr = pci_iomap(pdev, i, 0);
- - if (addr == NULL) {
- - pr_err("%s: ERROR: cannot map register memory aborting",
- - __func__);
- - ret = -EIO;
- - goto err_out_map_failed;
- - }
- + ret = pcim_iomap_regions(pdev, BIT(i), pci_name(pdev));
- + if (ret)
- + return ret;
- break;
- }
- - pci_set_master(pdev);
- -
- - stmmac_default_data();
-
- - priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat, addr);
- - if (IS_ERR(priv)) {
- - pr_err("%s: main driver probe failed", __func__);
- - ret = PTR_ERR(priv);
- - goto err_out;
- - }
- - priv->dev->irq = pdev->irq;
- - priv->wol_irq = pdev->irq;
- -
- - pci_set_drvdata(pdev, priv->dev);
- + pci_set_master(pdev);
-
- - pr_debug("STMMAC platform driver registration completed");
- + if (info) {
- + info->pdev = pdev;
- + if (info->setup) {
- + ret = info->setup(plat, info);
- + if (ret)
- + return ret;
- + }
- + } else
- + stmmac_default_data(plat);
-
- - return 0;
- + pci_enable_msi(pdev);
-
- -err_out:
- - pci_clear_master(pdev);
- -err_out_map_failed:
- - pci_release_regions(pdev);
- -err_out_req_reg_failed:
- - pci_disable_device(pdev);
- + memset(&res, 0, sizeof(res));
- + res.addr = pcim_iomap_table(pdev)[i];
- + res.wol_irq = pdev->irq;
- + res.irq = pdev->irq;
-
- - return ret;
- + return stmmac_dvr_probe(&pdev->dev, plat, &res);
- }
-
- /**
- @@ -141,61 +232,55 @@ err_out_req_reg_failed:
- static void stmmac_pci_remove(struct pci_dev *pdev)
- {
- struct net_device *ndev = pci_get_drvdata(pdev);
- - struct stmmac_priv *priv = netdev_priv(ndev);
-
- stmmac_dvr_remove(ndev);
- -
- - pci_iounmap(pdev, priv->ioaddr);
- - pci_release_regions(pdev);
- - pci_disable_device(pdev);
- }
-
- -#ifdef CONFIG_PM
- -static int stmmac_pci_suspend(struct pci_dev *pdev, pm_message_t state)
- +#ifdef CONFIG_PM_SLEEP
- +static int stmmac_pci_suspend(struct device *dev)
- {
- + struct pci_dev *pdev = to_pci_dev(dev);
- struct net_device *ndev = pci_get_drvdata(pdev);
- - int ret;
- -
- - ret = stmmac_suspend(ndev);
- - pci_save_state(pdev);
- - pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
- - return ret;
- + return stmmac_suspend(ndev);
- }
-
- -static int stmmac_pci_resume(struct pci_dev *pdev)
- +static int stmmac_pci_resume(struct device *dev)
- {
- + struct pci_dev *pdev = to_pci_dev(dev);
- struct net_device *ndev = pci_get_drvdata(pdev);
-
- - pci_set_power_state(pdev, PCI_D0);
- - pci_restore_state(pdev);
- -
- return stmmac_resume(ndev);
- }
- #endif
-
- +static SIMPLE_DEV_PM_OPS(stmmac_pm_ops, stmmac_pci_suspend, stmmac_pci_resume);
- +
- #define STMMAC_VENDOR_ID 0x700
- +#define STMMAC_QUARK_ID 0x0937
- #define STMMAC_DEVICE_ID 0x1108
-
- static const struct pci_device_id stmmac_id_table[] = {
- {PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)},
- {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_MAC)},
- + {PCI_VDEVICE(INTEL, STMMAC_QUARK_ID), (kernel_ulong_t)&quark_pci_info},
- {}
- };
-
- MODULE_DEVICE_TABLE(pci, stmmac_id_table);
-
- -struct pci_driver stmmac_pci_driver = {
- +static struct pci_driver stmmac_pci_driver = {
- .name = STMMAC_RESOURCE_NAME,
- .id_table = stmmac_id_table,
- .probe = stmmac_pci_probe,
- .remove = stmmac_pci_remove,
- -#ifdef CONFIG_PM
- - .suspend = stmmac_pci_suspend,
- - .resume = stmmac_pci_resume,
- -#endif
- + .driver = {
- + .pm = &stmmac_pm_ops,
- + },
- };
-
- +module_pci_driver(stmmac_pci_driver);
- +
- MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PCI driver");
- MODULE_AUTHOR("Rayagond Kokatanur <rayagond.kokatanur@vayavyalabs.com>");
- MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
- --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
- +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
- @@ -23,41 +23,23 @@
- *******************************************************************************/
-
- #include <linux/platform_device.h>
- +#include <linux/module.h>
- #include <linux/io.h>
- #include <linux/of.h>
- #include <linux/of_net.h>
- #include <linux/of_device.h>
- -#include "stmmac.h"
- +#include <linux/of_mdio.h>
-
- -static const struct of_device_id stmmac_dt_ids[] = {
- -#ifdef CONFIG_DWMAC_MESON
- - { .compatible = "amlogic,meson6-dwmac", .data = &meson6_dwmac_data},
- -#endif
- -#ifdef CONFIG_DWMAC_SUNXI
- - { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data},
- -#endif
- -#ifdef CONFIG_DWMAC_STI
- - { .compatible = "st,stih415-dwmac", .data = &stih4xx_dwmac_data},
- - { .compatible = "st,stih416-dwmac", .data = &stih4xx_dwmac_data},
- - { .compatible = "st,stid127-dwmac", .data = &stid127_dwmac_data},
- - { .compatible = "st,stih407-dwmac", .data = &stih4xx_dwmac_data},
- -#endif
- -#ifdef CONFIG_DWMAC_SOCFPGA
- - { .compatible = "altr,socfpga-stmmac", .data = &socfpga_gmac_data },
- -#endif
- - /* SoC specific glue layers should come before generic bindings */
- - { .compatible = "st,spear600-gmac"},
- - { .compatible = "snps,dwmac-3.610"},
- - { .compatible = "snps,dwmac-3.70a"},
- - { .compatible = "snps,dwmac-3.710"},
- - { .compatible = "snps,dwmac"},
- - { /* sentinel */ }
- -};
- -MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
- +#include "stmmac.h"
- +#include "stmmac_platform.h"
-
- #ifdef CONFIG_OF
-
- -/* This function validates the number of Multicast filtering bins specified
- +/**
- + * dwmac1000_validate_mcast_bins - validates the number of Multicast filter bins
- + * @mcast_bins: Multicast filtering bins
- + * Description:
- + * this function validates the number of Multicast filtering bins specified
- * by the configuration through the device tree. The Synopsys GMAC supports
- * 64 bins, 128 bins, or 256 bins. "bins" refer to the division of CRC
- * number space. 64 bins correspond to 6 bits of the CRC, 128 corresponds
- @@ -83,7 +65,11 @@ static int dwmac1000_validate_mcast_bins
- return x;
- }
-
- -/* This function validates the number of Unicast address entries supported
- +/**
- + * dwmac1000_validate_ucast_entries - validate the Unicast address entries
- + * @ucast_entries: number of Unicast address entries
- + * Description:
- + * This function validates the number of Unicast address entries supported
- * by a particular Synopsys 10/100/1000 controller. The Synopsys controller
- * supports 1, 32, 64, or 128 Unicast filter entries for it's Unicast filter
- * logic. This function validates a valid, supported configuration is
- @@ -109,37 +95,25 @@ static int dwmac1000_validate_ucast_entr
- return x;
- }
-
- -static int stmmac_probe_config_dt(struct platform_device *pdev,
- - struct plat_stmmacenet_data *plat,
- - const char **mac)
- +/**
- + * stmmac_probe_config_dt - parse device-tree driver parameters
- + * @pdev: platform_device structure
- + * @plat: driver data platform structure
- + * @mac: MAC address to use
- + * Description:
- + * this function is to read the driver parameters from device-tree and
- + * set some private fields that will be used by the main at runtime.
- + */
- +struct plat_stmmacenet_data *
- +stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
- {
- struct device_node *np = pdev->dev.of_node;
- + struct plat_stmmacenet_data *plat;
- struct stmmac_dma_cfg *dma_cfg;
- - const struct of_device_id *device;
-
- - if (!np)
- - return -ENODEV;
- -
- - device = of_match_device(stmmac_dt_ids, &pdev->dev);
- - if (!device)
- - return -ENODEV;
- -
- - if (device->data) {
- - const struct stmmac_of_data *data = device->data;
- - plat->has_gmac = data->has_gmac;
- - plat->enh_desc = data->enh_desc;
- - plat->tx_coe = data->tx_coe;
- - plat->rx_coe = data->rx_coe;
- - plat->bugged_jumbo = data->bugged_jumbo;
- - plat->pmt = data->pmt;
- - plat->riwt_off = data->riwt_off;
- - plat->fix_mac_speed = data->fix_mac_speed;
- - plat->bus_setup = data->bus_setup;
- - plat->setup = data->setup;
- - plat->free = data->free;
- - plat->init = data->init;
- - plat->exit = data->exit;
- - }
- + plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
- + if (!plat)
- + return ERR_PTR(-ENOMEM);
-
- *mac = of_get_mac_address(np);
- plat->interface = of_get_phy_mode(np);
- @@ -155,13 +129,24 @@ static int stmmac_probe_config_dt(struct
- /* Default to phy auto-detection */
- plat->phy_addr = -1;
-
- + /* If we find a phy-handle property, use it as the PHY */
- + plat->phy_node = of_parse_phandle(np, "phy-handle", 0);
- +
- + /* If phy-handle is not specified, check if we have a fixed-phy */
- + if (!plat->phy_node && of_phy_is_fixed_link(np)) {
- + if ((of_phy_register_fixed_link(np) < 0))
- + return ERR_PTR(-ENODEV);
- +
- + plat->phy_node = of_node_get(np);
- + }
- +
- /* "snps,phy-addr" is not a standard property. Mark it as deprecated
- * and warn of its use. Remove this when phy node support is added.
- */
- if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
- dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
-
- - if (plat->phy_bus_name)
- + if (plat->phy_node || plat->phy_bus_name)
- plat->mdio_bus_data = NULL;
- else
- plat->mdio_bus_data =
- @@ -169,6 +154,10 @@ static int stmmac_probe_config_dt(struct
- sizeof(struct stmmac_mdio_bus_data),
- GFP_KERNEL);
-
- + of_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size);
- +
- + of_property_read_u32(np, "rx-fifo-depth", &plat->rx_fifo_size);
- +
- plat->force_sf_dma_mode =
- of_property_read_bool(np, "snps,force_sf_dma_mode");
-
- @@ -177,6 +166,12 @@ static int stmmac_probe_config_dt(struct
- */
- plat->maxmtu = JUMBO_LEN;
-
- + /* Set default value for multicast hash bins */
- + plat->multicast_filter_bins = HASH_TABLE_SIZE;
- +
- + /* Set default value for unicast filter entries */
- + plat->unicast_filter_entries = 1;
- +
- /*
- * Currently only the properties needed on SPEAr600
- * are provided. All other properties should be added
- @@ -215,14 +210,19 @@ static int stmmac_probe_config_dt(struct
- if (of_find_property(np, "snps,pbl", NULL)) {
- dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
- GFP_KERNEL);
- - if (!dma_cfg)
- - return -ENOMEM;
- + if (!dma_cfg) {
- + of_node_put(np);
- + return ERR_PTR(-ENOMEM);
- + }
- plat->dma_cfg = dma_cfg;
- of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
- dma_cfg->fixed_burst =
- of_property_read_bool(np, "snps,fixed-burst");
- dma_cfg->mixed_burst =
- of_property_read_bool(np, "snps,mixed-burst");
- + of_property_read_u32(np, "snps,burst_len", &dma_cfg->burst_len);
- + if (dma_cfg->burst_len < 0 || dma_cfg->burst_len > 256)
- + dma_cfg->burst_len = 0;
- }
- plat->force_thresh_dma_mode = of_property_read_bool(np, "snps,force_thresh_dma_mode");
- if (plat->force_thresh_dma_mode) {
- @@ -230,123 +230,60 @@ static int stmmac_probe_config_dt(struct
- pr_warn("force_sf_dma_mode is ignored if force_thresh_dma_mode is set.");
- }
-
- - return 0;
- + return plat;
- }
- #else
- -static int stmmac_probe_config_dt(struct platform_device *pdev,
- - struct plat_stmmacenet_data *plat,
- - const char **mac)
- +struct plat_stmmacenet_data *
- +stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
- {
- - return -ENOSYS;
- + return ERR_PTR(-ENOSYS);
- }
- #endif /* CONFIG_OF */
- +EXPORT_SYMBOL_GPL(stmmac_probe_config_dt);
-
- -/**
- - * stmmac_pltfr_probe
- - * @pdev: platform device pointer
- - * Description: platform_device probe function. It allocates
- - * the necessary resources and invokes the main to init
- - * the net device, register the mdio bus etc.
- - */
- -static int stmmac_pltfr_probe(struct platform_device *pdev)
- +int stmmac_get_platform_resources(struct platform_device *pdev,
- + struct stmmac_resources *stmmac_res)
- {
- - int ret = 0;
- struct resource *res;
- - struct device *dev = &pdev->dev;
- - void __iomem *addr = NULL;
- - struct stmmac_priv *priv = NULL;
- - struct plat_stmmacenet_data *plat_dat = NULL;
- - const char *mac = NULL;
- -
- - res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- - addr = devm_ioremap_resource(dev, res);
- - if (IS_ERR(addr))
- - return PTR_ERR(addr);
- -
- - plat_dat = dev_get_platdata(&pdev->dev);
- -
- - if (!plat_dat)
- - plat_dat = devm_kzalloc(&pdev->dev,
- - sizeof(struct plat_stmmacenet_data),
- - GFP_KERNEL);
- - if (!plat_dat) {
- - pr_err("%s: ERROR: no memory", __func__);
- - return -ENOMEM;
- - }
- -
- - /* Set default value for multicast hash bins */
- - plat_dat->multicast_filter_bins = HASH_TABLE_SIZE;
- -
- - /* Set default value for unicast filter entries */
- - plat_dat->unicast_filter_entries = 1;
- -
- - if (pdev->dev.of_node) {
- - ret = stmmac_probe_config_dt(pdev, plat_dat, &mac);
- - if (ret) {
- - pr_err("%s: main dt probe failed", __func__);
- - return ret;
- - }
- - }
- -
- - /* Custom setup (if needed) */
- - if (plat_dat->setup) {
- - plat_dat->bsp_priv = plat_dat->setup(pdev);
- - if (IS_ERR(plat_dat->bsp_priv))
- - return PTR_ERR(plat_dat->bsp_priv);
- - }
- -
- - /* Custom initialisation (if needed)*/
- - if (plat_dat->init) {
- - ret = plat_dat->init(pdev, plat_dat->bsp_priv);
- - if (unlikely(ret))
- - return ret;
- - }
-
- - priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr);
- - if (IS_ERR(priv)) {
- - pr_err("%s: main driver probe failed", __func__);
- - return PTR_ERR(priv);
- - }
- + memset(stmmac_res, 0, sizeof(*stmmac_res));
-
- - /* Get MAC address if available (DT) */
- - if (mac)
- - memcpy(priv->dev->dev_addr, mac, ETH_ALEN);
- -
- - /* Get the MAC information */
- - priv->dev->irq = platform_get_irq_byname(pdev, "macirq");
- - if (priv->dev->irq < 0) {
- - if (priv->dev->irq != -EPROBE_DEFER) {
- - netdev_err(priv->dev,
- - "MAC IRQ configuration information not found\n");
- + /* Get IRQ information early to have an ability to ask for deferred
- + * probe if needed before we went too far with resource allocation.
- + */
- + stmmac_res->irq = platform_get_irq_byname(pdev, "macirq");
- + if (stmmac_res->irq < 0) {
- + if (stmmac_res->irq != -EPROBE_DEFER) {
- + dev_err(&pdev->dev,
- + "MAC IRQ configuration information not found\n");
- }
- - return priv->dev->irq;
- + return stmmac_res->irq;
- }
-
- - /*
- - * On some platforms e.g. SPEAr the wake up irq differs from the mac irq
- + /* On some platforms e.g. SPEAr the wake up irq differs from the mac irq
- * The external wake up irq can be passed through the platform code
- * named as "eth_wake_irq"
- *
- * In case the wake up interrupt is not passed from the platform
- * so the driver will continue to use the mac irq (ndev->irq)
- */
- - priv->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq");
- - if (priv->wol_irq < 0) {
- - if (priv->wol_irq == -EPROBE_DEFER)
- + stmmac_res->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq");
- + if (stmmac_res->wol_irq < 0) {
- + if (stmmac_res->wol_irq == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- - priv->wol_irq = priv->dev->irq;
- + stmmac_res->wol_irq = stmmac_res->irq;
- }
-
- - priv->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi");
- - if (priv->lpi_irq == -EPROBE_DEFER)
- + stmmac_res->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi");
- + if (stmmac_res->lpi_irq == -EPROBE_DEFER)
- return -EPROBE_DEFER;
-
- - platform_set_drvdata(pdev, priv->dev);
- -
- - pr_debug("STMMAC platform driver registration completed");
- + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- + stmmac_res->addr = devm_ioremap_resource(&pdev->dev, res);
-
- - return 0;
- + return PTR_ERR_OR_ZERO(stmmac_res->addr);
- }
- +EXPORT_SYMBOL_GPL(stmmac_get_platform_resources);
-
- /**
- * stmmac_pltfr_remove
- @@ -354,7 +291,7 @@ static int stmmac_pltfr_probe(struct pla
- * Description: this function calls the main to free the net resources
- * and calls the platforms hook and release the resources (e.g. mem).
- */
- -static int stmmac_pltfr_remove(struct platform_device *pdev)
- +int stmmac_pltfr_remove(struct platform_device *pdev)
- {
- struct net_device *ndev = platform_get_drvdata(pdev);
- struct stmmac_priv *priv = netdev_priv(ndev);
- @@ -363,13 +300,18 @@ static int stmmac_pltfr_remove(struct pl
- if (priv->plat->exit)
- priv->plat->exit(pdev, priv->plat->bsp_priv);
-
- - if (priv->plat->free)
- - priv->plat->free(pdev, priv->plat->bsp_priv);
- -
- return ret;
- }
- +EXPORT_SYMBOL_GPL(stmmac_pltfr_remove);
-
- -#ifdef CONFIG_PM
- +#ifdef CONFIG_PM_SLEEP
- +/**
- + * stmmac_pltfr_suspend
- + * @dev: device pointer
- + * Description: this function is invoked when suspend the driver and it direcly
- + * call the main suspend function and then, if required, on some platform, it
- + * can call an exit helper.
- + */
- static int stmmac_pltfr_suspend(struct device *dev)
- {
- int ret;
- @@ -384,6 +326,13 @@ static int stmmac_pltfr_suspend(struct d
- return ret;
- }
-
- +/**
- + * stmmac_pltfr_resume
- + * @dev: device pointer
- + * Description: this function is invoked when resume the driver before calling
- + * the main resume function, on some platforms, it can call own init helper
- + * if required.
- + */
- static int stmmac_pltfr_resume(struct device *dev)
- {
- struct net_device *ndev = dev_get_drvdata(dev);
- @@ -395,23 +344,12 @@ static int stmmac_pltfr_resume(struct de
-
- return stmmac_resume(ndev);
- }
- +#endif /* CONFIG_PM_SLEEP */
-
- -#endif /* CONFIG_PM */
- -
- -static SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops,
- - stmmac_pltfr_suspend, stmmac_pltfr_resume);
- -
- -struct platform_driver stmmac_pltfr_driver = {
- - .probe = stmmac_pltfr_probe,
- - .remove = stmmac_pltfr_remove,
- - .driver = {
- - .name = STMMAC_RESOURCE_NAME,
- - .owner = THIS_MODULE,
- - .pm = &stmmac_pltfr_pm_ops,
- - .of_match_table = of_match_ptr(stmmac_dt_ids),
- - },
- -};
- +SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, stmmac_pltfr_suspend,
- + stmmac_pltfr_resume);
- +EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops);
-
- -MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PLATFORM driver");
- +MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet platform support");
- MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
- MODULE_LICENSE("GPL");
- --- /dev/null
- +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
- @@ -0,0 +1,33 @@
- +/*******************************************************************************
- + Copyright (C) 2007-2009 STMicroelectronics Ltd
- +
- + This program is free software; you can redistribute it and/or modify it
- + under the terms and conditions of the GNU General Public License,
- + version 2, as published by the Free Software Foundation.
- +
- + This program is distributed in the hope it will be useful, but WITHOUT
- + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- + more details.
- +
- + The full GNU General Public License is included in this distribution in
- + the file called "COPYING".
- +
- + Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
- +*******************************************************************************/
- +
- +#ifndef __STMMAC_PLATFORM_H__
- +#define __STMMAC_PLATFORM_H__
- +
- +#include "stmmac.h"
- +
- +struct plat_stmmacenet_data *
- +stmmac_probe_config_dt(struct platform_device *pdev, const char **mac);
- +
- +int stmmac_get_platform_resources(struct platform_device *pdev,
- + struct stmmac_resources *stmmac_res);
- +
- +int stmmac_pltfr_remove(struct platform_device *pdev);
- +extern const struct dev_pm_ops stmmac_pltfr_pm_ops;
- +
- +#endif /* __STMMAC_PLATFORM_H__ */
|